/** * Dialog — headless primitive wrapping Radix Dialog. * * Radix's Dialog is best-in-class for focus trap, portal, scroll lock, * and `aria-modal` semantics (ARCHITECTURE §6). We wrap thinly: * - Permission gating on (canView=false → primitive returns null) * - Audit events on open / close * - `data-oshon-primitive="dialog-*"` styling hooks for Phase 4 * - i18n-ready `messages` prop on (for the "Close" aria-label) * * "use client" is mandatory here — Radix primitives use hooks + DOM APIs * internally, so our wrapper inherits the client boundary. See * `docs/adr/primitives/002-dialog-radix-wrap.md`. */ import * as RadixDialog from '@radix-ui/react-dialog'; import type { ComponentPropsWithoutRef, ReactNode } from 'react'; import { type PermissionContext } from '../context.js'; import { type MessageBag } from '../i18n.js'; export interface DialogRootProps extends Omit { /** * Called whenever the dialog's open state changes. The primitive fires * `dialog:open` / `dialog:close` audit events automatically before * this callback runs — consumers receive the same notification either * way. */ onOpenChange?: (open: boolean) => void; /** * Per-instance permission override. Merges over the ambient * `PermissionContext` (ARCHITECTURE §10). The primitive queries * `can('view', resource, attrs)` on mount; denied + `mode='hidden'` * returns `null`. Denied + `'disabled'` or `'readOnly'` still returns * `null` for a dialog (there is no useful visible-but-non-interactive * state for a modal) and emits a `permission:denied` audit. */ permissions?: Partial; /** * Resource name passed to `permissions.can('view', resource, attrs)`. * Default `'dialog'`. Override for specific semantics like * `resource="record:delete-confirmation"`. */ resource?: string; /** Attribute bag for attribute-based access control. */ permissionAttrs?: Record; children: ReactNode; } /** * Dialog root. Controls open state, gates on permissions, and fires * audit events. Must wrap every other `Dialog.*` sub-component. */ declare function Root({ children, open, defaultOpen, onOpenChange, permissions, resource, permissionAttrs, modal, }: DialogRootProps): import("react/jsx-runtime").JSX.Element | null; declare namespace Root { var displayName: string; } export type DialogTriggerProps = ComponentPropsWithoutRef; export type DialogPortalProps = RadixDialog.DialogPortalProps; /** * Portal. Radix handles the portal container itself; we pass through. */ declare function Portal(props: DialogPortalProps): import("react/jsx-runtime").JSX.Element; declare namespace Portal { var displayName: string; } export type DialogOverlayProps = ComponentPropsWithoutRef; export type DialogContentProps = ComponentPropsWithoutRef; export type DialogTitleProps = ComponentPropsWithoutRef; export type DialogDescriptionProps = ComponentPropsWithoutRef; export interface DialogCloseProps extends ComponentPropsWithoutRef { /** * i18n message bag. Reads `close` key for the default aria-label when * the consumer renders an icon-only close button. */ messages?: MessageBag; } /** * Compound Dialog primitive. Use as: * * * Open * * * * Confirm * Are you sure? * Cancel * * * */ export declare const Dialog: { Root: typeof Root; Trigger: import("react").ForwardRefExoticComponent, "ref"> & import("react").RefAttributes>; Portal: typeof Portal; Overlay: import("react").ForwardRefExoticComponent, "ref"> & import("react").RefAttributes>; Content: import("react").ForwardRefExoticComponent, "ref"> & import("react").RefAttributes>; Title: import("react").ForwardRefExoticComponent, "ref"> & import("react").RefAttributes>; Description: import("react").ForwardRefExoticComponent, "ref"> & import("react").RefAttributes>; Close: import("react").ForwardRefExoticComponent>; }; export type DialogProps = DialogRootProps; export {}; //# sourceMappingURL=dialog.d.ts.map