/** * Context shape for `` — consumed by every dialog sub-part. * * Mirrors Base UI React's `DialogRootContext` (`packages/react/src/dialog/ * root/DialogRootContext.ts`). The Solid port exposes every reactive field * as an `Accessor` so consumers can subscribe without wrapping. * * Context uses the `createContext(null)` + `== null` sentinel * pattern — `` wraps the subtree and every part * reads through `useDialogRootContext()`, which throws if no provider is * present (unless `optional: true` is passed). */ import { type Accessor } from "solid-js"; import type { BaseUIChangeEventDetails, REASONS } from "../internals/change-event-details.js"; import type { InteractionType } from "../internals/floating-ui/components/floating-focus-manager.js"; import type { FloatingRootStore } from "../internals/floating-ui/components/floating-root-store.js"; import type { UseInteractionsReturn } from "../internals/floating-ui/hooks/use-interactions.js"; import type { MutableRef } from "../internals/floating-ui/types.js"; import type { TransitionStatus } from "../internals/use-transition-status/use-transition-status.js"; import type { DialogStore } from "./store/dialog-store.js"; /** * Modal kind for ``: * * - `true` (default): focus-trap + scroll-lock + outside pointer block. * - `false`: none of the above (dialog is dismissable via the backdrop * click path but keyboard focus isn't trapped). * - `"trap-focus"`: focus is trapped but scroll isn't locked and outside * pointer interactions remain enabled. */ export type DialogModalKind = boolean | "trap-focus"; /** Change-event reason union for ``. */ export type DialogRootChangeEventReason = typeof REASONS.triggerPress | typeof REASONS.outsidePress | typeof REASONS.escapeKey | typeof REASONS.closePress | typeof REASONS.focusOut | typeof REASONS.imperativeAction | typeof REASONS.none; /** * `BaseUIChangeEventDetails` extended with the React Dialog-specific * `preventUnmountOnClose()` hook. When called from inside `onOpenChange`, * the dialog stays mounted after `open=false` — useful for consumers * controlling unmount timing through an external animation library. */ export type DialogRootChangeEventDetails = BaseUIChangeEventDetails void; }>; /** * Shared state surfaced on the dialog root context. Every field is a * signal/accessor except imperative writers. */ export interface DialogRootContextValue { /** Reactive open flag. */ open: Accessor; /** Whether the dialog's DOM is mounted (open OR animating out). */ mounted: Accessor; /** Enter/exit transition status, or `undefined` when settled. */ transitionStatus: Accessor; /** Modal kind. */ modal: Accessor; /** * When true, outside-press dismissal is disabled (the dialog only * closes via Escape / Close / imperative). */ disablePointerDismissal: Accessor; /** * The ARIA role applied to the popup. `"dialog"` for ``, * `"alertdialog"` for ``. Currently fixed to * `"dialog"` for the dialog compound; `alert-dialog` will override. */ role: Accessor<"dialog" | "alertdialog">; /** Whether the dialog has a parent dialog ancestor. */ nested: Accessor; /** Number of nested dialogs currently open underneath this root. */ nestedOpenDialogCount: Accessor; /** Number of nested drawers currently open underneath this root. */ nestedOpenDrawerCount: Accessor; /** * How the dialog was opened — reflects the interaction type captured * by `useOpenInteractionType`. Used by the popup to decide default * initial-focus behavior (touch → focus the popup element to avoid a * virtual keyboard flash). */ openMethod: Accessor; /** Title element id → consumed by popup's `aria-labelledby`. */ titleId: Accessor; setTitleId: (id: string | undefined) => void; /** Description element id → consumed by popup's `aria-describedby`. */ descriptionId: Accessor; setDescriptionId: (id: string | undefined) => void; /** * The shared `FloatingRootStore`. `useDismiss` / `useRole` write and * the popup / trigger read reactive signals off of it. */ floatingRootContext: FloatingRootStore; /** Prop-getter bundle from `useInteractions([dismiss, role])`. */ interactions: UseInteractionsReturn; /** * Imperative setOpen — used by trigger, close button, and the handle. */ setOpen: (next: boolean, details: DialogRootChangeEventDetails) => void; /** * Popup ref slot written by ``. The root reads it for * `useOpenChangeComplete`'s unmount timing and outside-press checks. */ popupRef: MutableRef; /** Backdrop ref slot, written by ``. */ backdropRef: MutableRef; /** Internal backdrop ref slot, written by ``. */ internalBackdropRef: MutableRef; /** * When `current` is `false`, `useDismiss`'s outside-press path is * suppressed. `` flips it off during an active * swipe-open gesture so the release doesn't dismiss the drawer it * just opened. */ outsidePressEnabledRef: MutableRef; /** Popup element accessor (reactive). */ popupElement: Accessor; setPopupElement: (el: HTMLElement | null) => void; /** Viewport element accessor (reactive). */ viewportElement: Accessor; setViewportElement: (el: HTMLElement | null) => void; /** Active trigger element. */ triggerElement: Accessor; setTriggerElement: (el: HTMLElement | null) => void; /** Active trigger id. */ activeTriggerId: Accessor; setActiveTriggerId: (id: string | null) => void; /** The dialog's store (handle registry + imperative wire). */ store: DialogStore; /** Payload written by the active trigger. */ payload: Accessor; setPayload: (payload: Payload | undefined) => void; /** * Parent-context callback invoked by a nested dialog/drawer when it * opens. The child passes its own nested counts (+1 for itself, * +(isDrawer ? 1 : 0) drawer delta). The receiving parent mirrors the * counts into its own `nestedOpenDialogCount` / `nestedOpenDrawerCount` * selectors so the parent's popup can flip `data-nested-dialog-open` * and `data-nested-drawer-open`. Mirrors React's `onNestedDialogOpen` * context callback. */ onNestedDialogOpen: (dialogCount: number, drawerCount: number) => void; /** * Parent-context callback invoked when a nested dialog/drawer closes. * Resets the parent's `nestedOpenDialogCount` / `nestedOpenDrawerCount` * to zero. Mirrors React's `onNestedDialogClose`. */ onNestedDialogClose: () => void; } /** * Context — `null` is the sentinel for "no provider". We don't use * `undefined` here. */ export declare const DialogRootContext: import("solid-js").Context | null>; /** * Read the current `` context. Throws unless `optional` is * `true`. Mirrors Base UI React's `useDialogRootContext` overloads. */ export declare function useDialogRootContext(): DialogRootContextValue; export declare function useDialogRootContext(optional: true): DialogRootContextValue | null; /** * Drawer detection context. Set to `true` by `` (not yet * ported), read here by `` to decide whether to count this * dialog as a drawer for the nested-open bookkeeping. Ships now so the * counting paths compose cleanly when drawer lands later. */ export declare const IsDrawerContext: import("solid-js").Context; //# sourceMappingURL=dialog-root-context.d.ts.map