@mortenbrudvik/waveui 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +454 -74
- package/dist/components/button/Link.cjs +1 -1
- package/dist/components/button/Link.cjs.map +1 -1
- package/dist/components/button/Link.mjs +4 -4
- package/dist/components/button/Toolbar.cjs +1 -1
- package/dist/components/button/Toolbar.cjs.map +1 -1
- package/dist/components/button/Toolbar.mjs +25 -30
- package/dist/components/button/Toolbar.mjs.map +1 -1
- package/dist/components/button/Toolbar.navigation.cjs +2 -0
- package/dist/components/button/Toolbar.navigation.cjs.map +1 -0
- package/dist/components/button/Toolbar.navigation.mjs +17 -0
- package/dist/components/button/Toolbar.navigation.mjs.map +1 -0
- package/dist/components/data-display/Avatar.cjs +1 -1
- package/dist/components/data-display/Avatar.cjs.map +1 -1
- package/dist/components/data-display/Avatar.context.cjs +2 -0
- package/dist/components/data-display/Avatar.context.cjs.map +1 -0
- package/dist/components/data-display/Avatar.context.mjs +9 -0
- package/dist/components/data-display/Avatar.context.mjs.map +1 -0
- package/dist/components/data-display/Avatar.mjs +66 -61
- package/dist/components/data-display/Avatar.mjs.map +1 -1
- package/dist/components/data-display/AvatarGroup.cjs +1 -1
- package/dist/components/data-display/AvatarGroup.cjs.map +1 -1
- package/dist/components/data-display/AvatarGroup.mjs +10 -10
- package/dist/components/data-display/InfoButton.cjs +1 -1
- package/dist/components/data-display/InfoButton.cjs.map +1 -1
- package/dist/components/data-display/InfoButton.mjs +12 -12
- package/dist/components/data-display/InteractionTag.cjs +2 -0
- package/dist/components/data-display/InteractionTag.cjs.map +1 -0
- package/dist/components/data-display/InteractionTag.mjs +234 -0
- package/dist/components/data-display/InteractionTag.mjs.map +1 -0
- package/dist/components/data-display/Tag.cjs +1 -1
- package/dist/components/data-display/Tag.cjs.map +1 -1
- package/dist/components/data-display/Tag.mjs +222 -90
- package/dist/components/data-display/Tag.mjs.map +1 -1
- package/dist/components/data-display/TagGroup.cjs +2 -0
- package/dist/components/data-display/TagGroup.cjs.map +1 -0
- package/dist/components/data-display/TagGroup.context.cjs +2 -0
- package/dist/components/data-display/TagGroup.context.cjs.map +1 -0
- package/dist/components/data-display/TagGroup.context.mjs +113 -0
- package/dist/components/data-display/TagGroup.context.mjs.map +1 -0
- package/dist/components/data-display/TagGroup.mjs +149 -0
- package/dist/components/data-display/TagGroup.mjs.map +1 -0
- package/dist/components/data-display/tagStyles.cjs +2 -0
- package/dist/components/data-display/tagStyles.cjs.map +1 -0
- package/dist/components/data-display/tagStyles.mjs +108 -0
- package/dist/components/data-display/tagStyles.mjs.map +1 -0
- package/dist/components/feedback/Toaster.cjs +1 -1
- package/dist/components/feedback/Toaster.cjs.map +1 -1
- package/dist/components/feedback/Toaster.mjs +287 -255
- package/dist/components/feedback/Toaster.mjs.map +1 -1
- package/dist/components/input/Combobox.cjs +1 -1
- package/dist/components/input/Combobox.cjs.map +1 -1
- package/dist/components/input/Combobox.expand.cjs +1 -1
- package/dist/components/input/Combobox.expand.cjs.map +1 -1
- package/dist/components/input/Combobox.expand.mjs +7 -7
- package/dist/components/input/Combobox.expand.mjs.map +1 -1
- package/dist/components/input/Combobox.mjs +176 -175
- package/dist/components/input/Combobox.mjs.map +1 -1
- package/dist/components/input/DatePicker.cjs +1 -1
- package/dist/components/input/DatePicker.cjs.map +1 -1
- package/dist/components/input/DatePicker.mjs +188 -187
- package/dist/components/input/DatePicker.mjs.map +1 -1
- package/dist/components/input/Dropdown.cjs +1 -1
- package/dist/components/input/Dropdown.cjs.map +1 -1
- package/dist/components/input/Dropdown.mjs +41 -40
- package/dist/components/input/Dropdown.mjs.map +1 -1
- package/dist/components/input/Option.cjs +1 -1
- package/dist/components/input/Option.cjs.map +1 -1
- package/dist/components/input/Option.mjs +101 -94
- package/dist/components/input/Option.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.cjs.map +1 -1
- package/dist/components/input/SwatchPicker.context.cjs.map +1 -1
- package/dist/components/input/SwatchPicker.context.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.mjs.map +1 -1
- package/dist/components/input/TagPicker.cjs +1 -1
- package/dist/components/input/TagPicker.cjs.map +1 -1
- package/dist/components/input/TagPicker.context.cjs +2 -0
- package/dist/components/input/TagPicker.context.cjs.map +1 -0
- package/dist/components/input/TagPicker.context.mjs +20 -0
- package/dist/components/input/TagPicker.context.mjs.map +1 -0
- package/dist/components/input/TagPicker.create.cjs +2 -0
- package/dist/components/input/TagPicker.create.cjs.map +1 -0
- package/dist/components/input/TagPicker.create.mjs +24 -0
- package/dist/components/input/TagPicker.create.mjs.map +1 -0
- package/dist/components/input/TagPicker.mjs +13 -279
- package/dist/components/input/TagPicker.mjs.map +1 -1
- package/dist/components/input/TagPicker.option.cjs +2 -0
- package/dist/components/input/TagPicker.option.cjs.map +1 -0
- package/dist/components/input/TagPicker.option.mjs +45 -0
- package/dist/components/input/TagPicker.option.mjs.map +1 -0
- package/dist/components/input/TagPicker.overflow.cjs +2 -0
- package/dist/components/input/TagPicker.overflow.cjs.map +1 -0
- package/dist/components/input/TagPicker.overflow.mjs +153 -0
- package/dist/components/input/TagPicker.overflow.mjs.map +1 -0
- package/dist/components/input/TagPicker.parts.cjs +2 -0
- package/dist/components/input/TagPicker.parts.cjs.map +1 -0
- package/dist/components/input/TagPicker.parts.mjs +425 -0
- package/dist/components/input/TagPicker.parts.mjs.map +1 -0
- package/dist/components/input/TagPicker.root.cjs +2 -0
- package/dist/components/input/TagPicker.root.cjs.map +1 -0
- package/dist/components/input/TagPicker.root.mjs +417 -0
- package/dist/components/input/TagPicker.root.mjs.map +1 -0
- package/dist/components/input/TimePicker.cjs +1 -1
- package/dist/components/input/TimePicker.cjs.map +1 -1
- package/dist/components/input/TimePicker.mjs +156 -154
- package/dist/components/input/TimePicker.mjs.map +1 -1
- package/dist/components/layout/Accordion.cjs.map +1 -1
- package/dist/components/layout/Accordion.mjs.map +1 -1
- package/dist/components/navigation/Hamburger.cjs +2 -0
- package/dist/components/navigation/Hamburger.cjs.map +1 -0
- package/dist/components/navigation/Hamburger.mjs +54 -0
- package/dist/components/navigation/Hamburger.mjs.map +1 -0
- package/dist/components/navigation/Menu.popover.cjs +1 -1
- package/dist/components/navigation/Menu.popover.cjs.map +1 -1
- package/dist/components/navigation/Menu.popover.mjs +137 -127
- package/dist/components/navigation/Menu.popover.mjs.map +1 -1
- package/dist/components/navigation/Menu.root.cjs +1 -1
- package/dist/components/navigation/Menu.root.cjs.map +1 -1
- package/dist/components/navigation/Menu.root.mjs +4 -4
- package/dist/components/navigation/Nav.cjs +1 -1
- package/dist/components/navigation/Nav.cjs.map +1 -1
- package/dist/components/navigation/Nav.context.cjs +2 -0
- package/dist/components/navigation/Nav.context.cjs.map +1 -0
- package/dist/components/navigation/Nav.context.mjs +137 -0
- package/dist/components/navigation/Nav.context.mjs.map +1 -0
- package/dist/components/navigation/Nav.mjs +151 -258
- package/dist/components/navigation/Nav.mjs.map +1 -1
- package/dist/components/navigation/Nav.parts.cjs +2 -0
- package/dist/components/navigation/Nav.parts.cjs.map +1 -0
- package/dist/components/navigation/Nav.parts.mjs +77 -0
- package/dist/components/navigation/Nav.parts.mjs.map +1 -0
- package/dist/components/navigation/Nav.root.cjs +2 -0
- package/dist/components/navigation/Nav.root.cjs.map +1 -0
- package/dist/components/navigation/Nav.root.mjs +78 -0
- package/dist/components/navigation/Nav.root.mjs.map +1 -0
- package/dist/components/navigation/NavDrawer.cjs +2 -0
- package/dist/components/navigation/NavDrawer.cjs.map +1 -0
- package/dist/components/navigation/NavDrawer.context.cjs +2 -0
- package/dist/components/navigation/NavDrawer.context.cjs.map +1 -0
- package/dist/components/navigation/NavDrawer.context.mjs +11 -0
- package/dist/components/navigation/NavDrawer.context.mjs.map +1 -0
- package/dist/components/navigation/NavDrawer.mjs +179 -0
- package/dist/components/navigation/NavDrawer.mjs.map +1 -0
- package/dist/components/overlays/Dialog.cjs +1 -1
- package/dist/components/overlays/Dialog.cjs.map +1 -1
- package/dist/components/overlays/Dialog.mjs +188 -123
- package/dist/components/overlays/Dialog.mjs.map +1 -1
- package/dist/components/overlays/Dialog.shared.cjs +1 -1
- package/dist/components/overlays/Dialog.shared.cjs.map +1 -1
- package/dist/components/overlays/Dialog.shared.mjs +157 -81
- package/dist/components/overlays/Dialog.shared.mjs.map +1 -1
- package/dist/components/overlays/Dialog.slots.cjs +2 -0
- package/dist/components/overlays/Dialog.slots.cjs.map +1 -0
- package/dist/components/overlays/Dialog.slots.mjs +129 -0
- package/dist/components/overlays/Dialog.slots.mjs.map +1 -0
- package/dist/components/overlays/Drawer.cjs +1 -1
- package/dist/components/overlays/Drawer.cjs.map +1 -1
- package/dist/components/overlays/Drawer.context.cjs +2 -0
- package/dist/components/overlays/Drawer.context.cjs.map +1 -0
- package/dist/components/overlays/Drawer.context.mjs +29 -0
- package/dist/components/overlays/Drawer.context.mjs.map +1 -0
- package/dist/components/overlays/Drawer.mjs +12 -187
- package/dist/components/overlays/Drawer.mjs.map +1 -1
- package/dist/components/overlays/Drawer.panel.cjs +2 -0
- package/dist/components/overlays/Drawer.panel.cjs.map +1 -0
- package/dist/components/overlays/Drawer.panel.mjs +159 -0
- package/dist/components/overlays/Drawer.panel.mjs.map +1 -0
- package/dist/components/overlays/Drawer.parts.cjs +2 -0
- package/dist/components/overlays/Drawer.parts.cjs.map +1 -0
- package/dist/components/overlays/Drawer.parts.mjs +152 -0
- package/dist/components/overlays/Drawer.parts.mjs.map +1 -0
- package/dist/components/overlays/Drawer.root.cjs +2 -0
- package/dist/components/overlays/Drawer.root.cjs.map +1 -0
- package/dist/components/overlays/Drawer.root.mjs +207 -0
- package/dist/components/overlays/Drawer.root.mjs.map +1 -0
- package/dist/components/overlays/Drawer.scroll.cjs +2 -0
- package/dist/components/overlays/Drawer.scroll.cjs.map +1 -0
- package/dist/components/overlays/Drawer.scroll.mjs +42 -0
- package/dist/components/overlays/Drawer.scroll.mjs.map +1 -0
- package/dist/components/overlays/Popover.cjs +1 -1
- package/dist/components/overlays/Popover.cjs.map +1 -1
- package/dist/components/overlays/Popover.mjs +173 -162
- package/dist/components/overlays/Popover.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.cjs +1 -1
- package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.mjs +96 -91
- package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
- package/dist/components/overlays/Tooltip.cjs +1 -1
- package/dist/components/overlays/Tooltip.cjs.map +1 -1
- package/dist/components/overlays/Tooltip.mjs +47 -47
- package/dist/components/overlays/Tooltip.mjs.map +1 -1
- package/dist/components/portal/Portal.cjs +1 -1
- package/dist/components/portal/Portal.cjs.map +1 -1
- package/dist/components/portal/Portal.mjs +5 -5
- package/dist/components/table/DataGrid.cjs +1 -1
- package/dist/components/table/DataGrid.cjs.map +1 -1
- package/dist/components/table/DataGrid.mjs +1 -1
- package/dist/hooks/useDismiss.cjs.map +1 -1
- package/dist/hooks/useDismiss.mjs.map +1 -1
- package/dist/hooks/useFocusTrap.cjs +1 -1
- package/dist/hooks/useFocusTrap.cjs.map +1 -1
- package/dist/hooks/useFocusTrap.mjs +115 -98
- package/dist/hooks/useFocusTrap.mjs.map +1 -1
- package/dist/hooks/useFocusVisible.cjs +2 -0
- package/dist/hooks/useFocusVisible.cjs.map +1 -0
- package/dist/hooks/useFocusVisible.mjs +49 -0
- package/dist/hooks/useFocusVisible.mjs.map +1 -0
- package/dist/hooks/useFocusableGroup.cjs +2 -0
- package/dist/hooks/useFocusableGroup.cjs.map +1 -0
- package/dist/hooks/useFocusableGroup.mjs +70 -0
- package/dist/hooks/useFocusableGroup.mjs.map +1 -0
- package/dist/hooks/useModalLayer.cjs +1 -1
- package/dist/hooks/useModalLayer.cjs.map +1 -1
- package/dist/hooks/useModalLayer.mjs +34 -21
- package/dist/hooks/useModalLayer.mjs.map +1 -1
- package/dist/hooks/useModalOpen.cjs +2 -0
- package/dist/hooks/useModalOpen.cjs.map +1 -0
- package/dist/hooks/useModalOpen.mjs +14 -0
- package/dist/hooks/useModalOpen.mjs.map +1 -0
- package/dist/hooks/usePopupPosition.cjs +1 -1
- package/dist/hooks/usePopupPosition.cjs.map +1 -1
- package/dist/hooks/usePopupPosition.mjs +82 -53
- package/dist/hooks/usePopupPosition.mjs.map +1 -1
- package/dist/hooks/useResolvedTarget.cjs +2 -0
- package/dist/hooks/useResolvedTarget.cjs.map +1 -0
- package/dist/hooks/useResolvedTarget.mjs +37 -0
- package/dist/hooks/useResolvedTarget.mjs.map +1 -0
- package/dist/hooks/useRestoreFocus.cjs +1 -1
- package/dist/hooks/useRestoreFocus.cjs.map +1 -1
- package/dist/hooks/useRestoreFocus.mjs +91 -78
- package/dist/hooks/useRestoreFocus.mjs.map +1 -1
- package/dist/hooks/useRovingGrid.cjs +1 -1
- package/dist/hooks/useRovingGrid.cjs.map +1 -1
- package/dist/hooks/useRovingGrid.mjs +8 -57
- package/dist/hooks/useRovingGrid.mjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.cjs +1 -1
- package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.mjs +180 -121
- package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3070 -269
- package/dist/index.d.ts +3070 -269
- package/dist/index.mjs +127 -107
- package/dist/lib/classNames.cjs +1 -1
- package/dist/lib/classNames.cjs.map +1 -1
- package/dist/lib/classNames.mjs +137 -77
- package/dist/lib/classNames.mjs.map +1 -1
- package/dist/lib/icons.cjs +1 -1
- package/dist/lib/icons.cjs.map +1 -1
- package/dist/lib/icons.mjs +13 -6
- package/dist/lib/icons.mjs.map +1 -1
- package/dist/lib/layers.cjs +1 -1
- package/dist/lib/layers.cjs.map +1 -1
- package/dist/lib/layers.mjs +120 -111
- package/dist/lib/layers.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/styles/tokens.css +25 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.mjs","names":["useId","useId$1","React","DialogContext","inertDialogContext","inertModalTrigger","useDialogContext","useRequiredContext","componentName","DialogRoot","openState","requestOpen","useModalOpenState","open","defaultOpen","onOpenChange","isClient","useIsClient","isOpen","trigger","useModalTrigger","contentId","setContentId","registerContentId","id","current","context","modalType","finalFocusRef","DialogTrigger","useModalTriggerPart","props","DialogClose","useModalClosePart","sizeClasses","DialogContent","rest","generatedId","propTitleId","titles","useTitleRegistry","surface","setSurface","surfaceRef","attachSurface","node","registerId","mergedRef","useMergedRefs","ref","closesOnBackdropPress","backdropPress","useBackdropPress","onDismiss","useModalDismiss","layer","useModalLayer","footerHeight","setFooterHeight","surfaceContext","hasTitle","slotRendersContent","title","Portal","cn","dialogContentClassNames","size","className","ModalSurfaceContext","dialogTitleClassNames","Button","DismissIcon","closeLabel","event","DialogTitle","titleId","titleRef","useModalTitle","stickyFooterClasses","footerRowClasses","DialogFooter","outsideContent","footer","setFooter","warnOnce","observer","entry","entries","dialogFooterClassNames","Dialog"],"sources":["../../../src/components/overlays/Dialog.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport {\n dialogContentClassNames,\n dialogFooterClassNames,\n dialogTitleClassNames,\n} from '../../lib/classNames';\nimport { warnOnce } from '../../lib/dev';\nimport { DismissIcon } from '../../lib/icons';\nimport { slotRendersContent } from '../../lib/slot';\nimport type { ModalOpenChangeReason, ModalType, OpenChangeDetails } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useModalLayer } from '../../hooks/useModalLayer';\nimport { Button } from '../button/Button';\nimport { Portal } from '../portal/Portal';\nimport {\n inertModalTrigger,\n ModalSurfaceContext,\n useBackdropPress,\n useModalClosePart,\n useModalDismiss,\n useModalOpenState,\n useModalTitle,\n useModalTrigger,\n useModalTriggerPart,\n useModalTriggerSession,\n useRequiredContext,\n useTitleRegistry,\n useUnnamedModalWarning,\n type ModalRequestOpen,\n type ModalSurfaceContextValue,\n type ModalTrigger,\n} from './Dialog.shared';\n\n/**\n * Why a {@link Dialog} asks to open or close: `trigger` (`Dialog.Trigger`), `close`\n * (`Dialog.Close`), `close-button` (the built-in Close button), `escape`, `outside-press` (the\n * backdrop). The shared `ModalOpenChangeReason`.\n */\nexport type DialogOpenChangeReason = ModalOpenChangeReason;\n\n/** The second argument of a {@link Dialog}'s `onOpenChange`: the reason and the DOM event. */\nexport type DialogOpenChangeDetails = OpenChangeDetails<DialogOpenChangeReason>;\n\n/**\n * How a {@link Dialog} blocks the page (the shared `ModalType`; Drawer reuses it when it gains\n * `modalType`).\n */\nexport type DialogModalType = ModalType;\n\n/** Properties for the Dialog component. */\nexport interface DialogProps {\n /**\n * Controlled open state of the dialog. The surface renders only in the browser: an open dialog\n * is closed in the server HTML and opens once it has hydrated.\n */\n open?: boolean;\n /**\n * Default open state for uncontrolled usage. The surface renders only in the browser: a dialog\n * open by default is closed in the server HTML and opens once it has hydrated.\n * @default false\n */\n defaultOpen?: boolean;\n /**\n * Called with the new open state when it changes. `details.reason` tells how — `trigger`,\n * `close` (a `.Close` part), `close-button` (the built-in Close button), `escape` or\n * `outside-press` (the backdrop) — so a controlled dialog can refuse only some ways of closing\n * (for example keep a form with unsaved changes open on `outside-press`); `details.event` is the\n * DOM event behind the request. WaveUI always passes `details`; it is typed optional until 1.0\n * so that code which calls this prop itself keeps compiling.\n *\n * Fires only when the value changes; a controlled dialog stays as it is until the parent updates\n * `open`.\n */\n onOpenChange?: (open: boolean, details?: DialogOpenChangeDetails) => void;\n /**\n * `modal`: a backdrop press, Escape, the Close button and `Dialog.Close` close it. `alert`: a\n * confirmation that needs an answer — `role=\"alertdialog\"`, and a backdrop press does not close\n * it (Escape still does). Initial focus goes to the first focusable element, the built-in Close\n * button; give the least destructive action `autoFocus` to focus it instead. (`'non-modal'` is\n * planned.)\n * @default 'modal'\n */\n modalType?: DialogModalType;\n /**\n * Where focus goes when the dialog closes, if it can take focus. Otherwise focus returns to the\n * element that had focus when the dialog opened, then to the trigger, then to an element next to\n * where that opener was (the next row's action after a confirm dialog deleted the row). Use it to\n * send focus somewhere else.\n */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /** `Dialog.Trigger` and `Dialog.Content`. */\n children: React.ReactNode;\n}\n\n/** Properties for the DialogContent sub-component. */\nexport interface DialogContentProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n /**\n * Title rendered as the dialog's heading; it names the dialog (`aria-labelledby`). Without it,\n * render a `Dialog.Title` or pass `aria-label`/`aria-labelledby`. A title that renders nothing\n * (`''`, `[]`, `true`) counts as none.\n */\n title?: React.ReactNode;\n /** Maximum width of the dialog: 400px (`small`) or 600px (`medium`); it never exceeds the viewport.\n * @default 'medium'\n */\n size?: 'small' | 'medium';\n /**\n * Accessible name of the built-in Close button (an icon-only button). Localize it with the\n * page's language.\n * @default 'Close'\n */\n closeLabel?: string;\n /** Content rendered inside the dialog body (put `Dialog.Footer` here as well). */\n children: React.ReactNode;\n /** Ref to the dialog surface (`role=\"dialog\"`, or `alertdialog` with `modalType=\"alert\"`). */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DialogFooter sub-component. */\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Footer content, typically action buttons (wrap closing buttons in `Dialog.Close`). */\n children: React.ReactNode;\n /** Ref to the footer element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DialogTitle sub-component. */\nexport interface DialogTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n /** The title; any content. */\n children: React.ReactNode;\n /** Ref to the heading element. */\n ref?: React.Ref<HTMLHeadingElement>;\n}\n\n/** Props a `Dialog.Trigger` puts on its element (and passes to a render-prop child). */\nexport interface DialogTriggerRenderProps extends React.HTMLAttributes<HTMLElement> {\n 'aria-haspopup': 'dialog';\n 'aria-expanded': boolean;\n /** The dialog surface's id, while the dialog is open. */\n 'aria-controls'?: string;\n onClick: React.MouseEventHandler<HTMLElement>;\n /** A callback ref, so the props spread onto any element type. */\n ref: React.RefCallback<HTMLElement>;\n}\n\n/** Properties for the DialogTrigger sub-component. */\nexport interface DialogTriggerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that opens the dialog. A single element receives the trigger props (merged with\n * its own: handlers composed, classes joined, its own `id` kept); a function receives them.\n */\n children: React.ReactNode | ((props: DialogTriggerRenderProps) => React.ReactNode);\n /**\n * `false` renders the 0.4 wrapper `<span>` around the children instead of merging the trigger\n * props onto the child. The span carries the click handler; `aria-haspopup`, `aria-expanded`\n * and `aria-controls` go to the first element in the tab order inside it.\n * @default true\n */\n asChild?: boolean;\n /** Ref to the trigger element (the child, or the wrapper span). */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** Props a `Dialog.Close` puts on its element (and passes to a render-prop child). */\nexport interface DialogCloseRenderProps extends React.HTMLAttributes<HTMLElement> {\n onClick: React.MouseEventHandler<HTMLElement>;\n /** A callback ref, so the props spread onto any element type. */\n ref: React.RefCallback<HTMLElement>;\n}\n\n/** Properties for the DialogClose sub-component. */\nexport interface DialogCloseProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that closes the dialog, typically a footer button. A single element receives an\n * `onClick` composed with its own (its handler runs first; `preventDefault()` keeps the dialog\n * open); a function receives the props.\n */\n children: React.ReactNode | ((props: DialogCloseRenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` that closes the dialog on click. @default true */\n asChild?: boolean;\n /** Ref to the close element (the child, or the wrapper span). */\n ref?: React.Ref<HTMLElement>;\n}\n\ninterface DialogContextValue {\n open: boolean;\n /** Asks the root to open or close, with the reason and event for `onOpenChange`. */\n requestOpen: ModalRequestOpen;\n /** The resolved `modalType`. */\n modalType: DialogModalType;\n /** The trigger element (`attach`) and the focus-restore target resolved from it (`focusRef`). */\n trigger: ModalTrigger;\n finalFocusRef: React.RefObject<HTMLElement | null> | undefined;\n /** The id of the open dialog surface (for the trigger's `aria-controls`), or `undefined`. */\n contentId: string | undefined;\n /** Registers the surface's id while it is mounted; returns the unregister function. */\n registerContentId: (id: string) => () => void;\n}\n\nconst DialogContext = React.createContext<DialogContextValue | null>(null);\nDialogContext.displayName = 'DialogContext';\n\nconst inertDialogContext: DialogContextValue = {\n open: false,\n requestOpen: () => {},\n modalType: 'modal',\n trigger: inertModalTrigger,\n finalFocusRef: undefined,\n contentId: undefined,\n registerContentId: () => () => {},\n};\n\nfunction useDialogContext(componentName: string): DialogContextValue {\n return useRequiredContext(DialogContext, componentName, 'Dialog', () => inertDialogContext);\n}\n\n// The root of `Dialog` (documented on the export below). A const arrow (like DrawerRoot): its type\n// can be named in consumers' declaration files, e.g. a story's `satisfies Meta<typeof Dialog>` (a\n// function declaration's `typeof` cannot, TS4023).\nconst DialogRoot = ({\n open,\n defaultOpen,\n onOpenChange,\n modalType = 'modal',\n finalFocusRef,\n children,\n}: DialogProps) => {\n const [openState, requestOpen] = useModalOpenState(open, defaultOpen, onOpenChange);\n // The surface lives in a portal, which renders only in the browser: until then (the server\n // HTML, hydration) the dialog reports itself closed, so the trigger's aria-expanded never\n // describes a dialog that is not there.\n const isClient = useIsClient();\n const isOpen = openState && isClient;\n const trigger = useModalTrigger();\n // After Dialog.Content's focus restore (a child's layout effects run first), start the trigger\n // session, or end it and forget the trigger that opened it.\n useModalTriggerSession(trigger, isOpen);\n const [contentId, setContentId] = React.useState<string | undefined>(undefined);\n const registerContentId = React.useCallback((id: string) => {\n setContentId(id);\n return () => setContentId((current) => (current === id ? undefined : current));\n }, []);\n\n const context = React.useMemo<DialogContextValue>(\n () => ({\n open: isOpen,\n requestOpen,\n modalType,\n trigger,\n finalFocusRef,\n contentId,\n registerContentId,\n }),\n [isOpen, requestOpen, modalType, trigger, finalFocusRef, contentId, registerContentId],\n );\n\n return <DialogContext.Provider value={context}>{children}</DialogContext.Provider>;\n};\nDialogRoot.displayName = 'Dialog';\n\n/**\n * Opens the dialog. Puts `aria-haspopup=\"dialog\"`, `aria-expanded`, `aria-controls` (while open), a\n * click handler and a ref on its single child (no wrapper element), or passes them to a\n * render-prop child. A custom child component must forward `ref` and spread its props; one that\n * does not is wrapped in a `<span>` automatically (with a development warning), the span that\n * `asChild={false}` renders. Focus returns to the trigger when the dialog closes (with several\n * triggers, to the one that opened it). On the span, the state ARIA goes to the first element in\n * the tab order inside it, and focus returns to that element (to the span when you made it the\n * trigger with a `role` such as `button` and `tabIndex={0}`, or when nothing inside it can take\n * focus).\n */\nexport const DialogTrigger = (props: DialogTriggerProps) => {\n const { open, requestOpen, trigger, contentId } = useDialogContext('Dialog.Trigger');\n return useModalTriggerPart<DialogTriggerRenderProps>(\n { open, requestOpen, trigger, controlsId: contentId },\n props,\n 'Dialog.Trigger',\n );\n};\nDialogTrigger.displayName = 'DialogTrigger';\n\n/**\n * Closes the dialog: composes a click handler onto its single child (its own `onClick` runs first;\n * calling `preventDefault()` there keeps the dialog open), or passes it to a render-prop child.\n *\n * @example\n * <Dialog.Close><Button appearance=\"subtle\">Cancel</Button></Dialog.Close>\n */\nexport const DialogClose = (props: DialogCloseProps) => {\n const { requestOpen } = useDialogContext('Dialog.Close');\n return useModalClosePart<DialogCloseRenderProps>(requestOpen, props, 'Dialog.Close');\n};\nDialogClose.displayName = 'DialogClose';\n\nconst sizeClasses: Record<'small' | 'medium', string> = {\n small: 'max-w-[400px]',\n medium: 'max-w-[600px]',\n};\n\n/**\n * The dialog surface, rendered in a portal (inheriting the WaveProvider theme) while the dialog is\n * open: backdrop, title, Close button and a scrolling body. It takes the full width up to its\n * `size` and never exceeds the viewport (the body scrolls, also sideways for content wider than\n * the dialog). Its 1rem gap to the viewport edges is its own margin, so a margin in `className`\n * replaces the gap: with the width and height caps lifted as well and its height set to the\n * viewport's, it fills the viewport (a full-screen dialog). It is `role=\"dialog\"`, or\n * `role=\"alertdialog\"` when the Dialog has `modalType=\"alert\"` (a `role` you pass wins), and\n * carries `data-modal-type` with the resolved type.\n */\nexport const DialogContent = ({\n title,\n size = 'medium',\n closeLabel = 'Close',\n children,\n className,\n id,\n ref,\n ...rest\n}: DialogContentProps) => {\n const { open, requestOpen, modalType, trigger, finalFocusRef, registerContentId } =\n useDialogContext('Dialog.Content');\n const generatedId = useId('wave-dialog');\n const contentId = id ?? generatedId;\n const propTitleId = useId('wave-dialog-title');\n const titles = useTitleRegistry();\n\n const [surface, setSurface] = React.useState<HTMLDivElement | null>(null);\n const surfaceRef = React.useRef<HTMLDivElement | null>(null);\n const attachSurface = React.useCallback((node: HTMLDivElement | null) => {\n surfaceRef.current = node;\n setSurface(node);\n }, []);\n // Reports the surface's id to the root (the trigger's `aria-controls`) while it is mounted. A new\n // `id` makes a new callback, which useMergedRefs re-attaches after the commit (re-registering).\n const registerId = React.useCallback(\n (node: HTMLDivElement | null) => (node ? registerContentId(contentId) : undefined),\n [registerContentId, contentId],\n );\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, attachSurface, registerId);\n\n // An alert dialog needs an answer: a backdrop press does not close it (Escape still does).\n const closesOnBackdropPress = modalType !== 'alert';\n const backdropPress = useBackdropPress(surfaceRef, closesOnBackdropPress);\n const onDismiss = useModalDismiss(requestOpen, 'Dialog', backdropPress.afterOutsidePress);\n const layer = useModalLayer({\n open,\n onDismiss,\n refs: [surfaceRef],\n outsidePress: closesOnBackdropPress,\n container: surface,\n triggerRef: trigger.focusRef,\n finalFocusRef,\n });\n useUnnamedModalWarning(open ? surface : null, titles.hasTitle, 'Dialog.Content', 'Dialog.Title');\n\n // The height of the sticky Dialog.Footer, reserved as the body's scroll padding.\n const [footerHeight, setFooterHeight] = React.useState<number | null>(null);\n const surfaceContext = React.useMemo<ModalSurfaceContextValue>(\n () => ({ ...titles.context, setFooterHeight }),\n [titles.context],\n );\n\n if (!open) return null;\n\n const hasTitle = slotRendersContent(title);\n\n return (\n <Portal layerId={layer.layerId}>\n <div\n className={cn(\n dialogContentClassNames.backdrop,\n 'fixed inset-0 flex items-center justify-center bg-backdrop',\n )}\n onMouseDown={backdropPress.onMouseDown}\n >\n <div\n ref={mergedRef}\n role={modalType === 'alert' ? 'alertdialog' : 'dialog'}\n id={contentId}\n aria-labelledby={hasTitle ? propTitleId : titles.titleId}\n tabIndex={-1}\n data-modal-type={modalType}\n {...rest}\n className={cn(\n dialogContentClassNames.root,\n // The border marks the surface where the shadow cannot: in high contrast the page,\n // the backdrop and the surface are black, and forced colors drop shadows. The 1rem gap\n // to the viewport edges is the surface's own margin, not the backdrop's padding, so a\n // margin in `className` replaces it and a full-screen dialog can reach the edges. Its\n // minimum width is zero, so content wider than the room inside the gap scrolls in the\n // body instead of pushing the surface over the gap.\n 'relative m-4 flex min-w-0 max-h-[calc(100dvh-2rem)] w-full flex-col rounded-lg border border-border bg-background p-6 text-foreground shadow-64',\n sizeClasses[size],\n className,\n )}\n >\n <ModalSurfaceContext.Provider value={surfaceContext}>\n {hasTitle && (\n <h2\n id={propTitleId}\n className={cn(dialogTitleClassNames.root, 'pe-8 text-subtitle-1 font-semibold')}\n >\n {title}\n </h2>\n )}\n <Button\n appearance=\"subtle\"\n size=\"small\"\n icon={<DismissIcon />}\n aria-label={closeLabel}\n onClick={(event) =>\n requestOpen(false, { reason: 'close-button', event: event.nativeEvent })\n }\n className={cn(\n dialogContentClassNames.closeButton,\n 'absolute end-4 top-4 text-muted-foreground',\n )}\n />\n <div\n // The scroll padding keeps a focused field above the sticky footer (WCAG 2.4.11).\n className={cn(\n dialogContentClassNames.body,\n '-mx-1 mt-1 min-h-0 flex-1 overflow-y-auto scroll-pb-(--wave-dialog-footer-height) p-1 text-body-1',\n )}\n style={\n footerHeight === null\n ? undefined\n : ({ '--wave-dialog-footer-height': `${footerHeight}px` } as React.CSSProperties)\n }\n >\n {children}\n </div>\n </ModalSurfaceContext.Provider>\n </div>\n </div>\n </Portal>\n );\n};\nDialogContent.displayName = 'DialogContent';\n\n/**\n * A heading that names the dialog (`aria-labelledby`), for rich titles or custom layouts. Render it\n * inside `Dialog.Content` (instead of the `title` prop). Like the `title` heading it reserves end\n * padding (`pe-8`) so a long first line stays clear of the Close button; a `className` padding wins.\n */\nexport const DialogTitle = ({ id, className, children, ref, ...rest }: DialogTitleProps) => {\n const { id: titleId, ref: titleRef } = useModalTitle('Dialog.Title', 'Dialog.Content', id, ref);\n return (\n <h2\n {...rest}\n id={titleId}\n ref={titleRef}\n className={cn(\n dialogTitleClassNames.root,\n 'pe-8 text-subtitle-1 font-semibold text-foreground',\n className,\n )}\n >\n {children}\n </h2>\n );\n};\nDialogTitle.displayName = 'DialogTitle';\n\n/**\n * `Dialog.Footer` inside `Dialog.Content`. The body is `p-1`, and sticky positioning stops at its\n * padding edge: `-bottom-1` with `-mb-1 pb-2` covers the body's bottom padding, `-mx-1 px-1` its\n * focus-ring inset, and `pt-3` separates the actions from the content scrolling under them.\n */\nconst stickyFooterClasses =\n 'sticky -bottom-1 z-10 -mx-1 -mb-1 mt-6 flex justify-end gap-2 bg-background px-1 pb-2 pt-3';\n\n/**\n * `Dialog.Footer` where no body reserves its height as scroll padding (a Drawer's body): a plain\n * action row, which never covers a focused field.\n */\nconst footerRowClasses = 'mt-6 flex justify-end gap-2';\n\n/**\n * Action row at the end of the dialog body. It stays where you render it in the DOM and sticks to\n * the bottom of the body while long content scrolls under it (with an opaque background); the body\n * reserves its height as scroll padding, so a focused field is never hidden behind it. Inside a\n * `<form>` that wraps the fields and the footer it sticks too: make it the form's last child.\n * Render it inside `Dialog.Content`: outside it, it would stay on the page while the dialog is\n * closed (a development warning says so). Inside a `Drawer`, whose body reserves no footer height,\n * it does not stick: it is an action row at the end of the content. Render one `Dialog.Footer` per\n * `Dialog.Content`: with two at once, the body reserves the height of the one measured last, and\n * unmounting either clears it until the other resizes (swapping one footer for another is fine).\n */\nexport const DialogFooter = ({ children, className, ref, ...rest }: DialogFooterProps) => {\n const surfaceContext = React.useContext(ModalSurfaceContext);\n const outsideContent = surfaceContext === null;\n const setFooterHeight = surfaceContext?.setFooterHeight;\n const [footer, setFooter] = React.useState<HTMLDivElement | null>(null);\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, setFooter);\n\n React.useEffect(() => {\n if (!outsideContent) return;\n warnOnce(\n 'Dialog.Footer:outside-content',\n 'Dialog.Footer must be rendered inside Dialog.Content. Outside it, the footer stays on the page while the dialog is closed.',\n );\n }, [outsideContent]);\n\n // Reports the footer's border-box height to Dialog.Content. The observer's first callback,\n // delivered before the next paint, supplies the first value; without ResizeObserver the body\n // keeps its default scroll padding.\n React.useLayoutEffect(() => {\n if (!footer || !setFooterHeight || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver((entries) => {\n const entry = entries[entries.length - 1];\n if (!entry) return;\n setFooterHeight(entry.borderBoxSize?.[0]?.blockSize ?? footer.offsetHeight);\n });\n observer.observe(footer, { box: 'border-box' });\n return () => {\n observer.disconnect();\n setFooterHeight(null);\n };\n }, [footer, setFooterHeight]);\n\n return (\n <div\n ref={mergedRef}\n {...rest}\n // Sticky only where the surface reserves the footer's height (Dialog.Content).\n className={cn(\n dialogFooterClassNames.root,\n setFooterHeight ? stickyFooterClasses : footerRowClasses,\n className,\n )}\n >\n {children}\n </div>\n );\n};\nDialogFooter.displayName = 'DialogFooter';\n\n/**\n * A modal dialog (Fluent UI v2 style): `Dialog` holds the open state; `Dialog.Trigger` opens it and\n * `Dialog.Content` renders the surface in a portal while open.\n *\n * - **Modal**: focus moves into the dialog and Tab stays inside it (toasts included), the rest of\n * the page is `inert` (instead of `aria-modal`, so toasts and live regions stay announced), and\n * the page does not scroll.\n * - **Closing**: Escape (only the topmost layer: a popup opened inside closes first), a click on\n * the backdrop (a drag that starts inside does not close it), the Close button and `Dialog.Close`.\n * `onOpenChange` gets the reason as its second argument (`details.reason`), so a controlled\n * dialog can refuse some of them. A backdrop press blurs the focused field before the dialog\n * closes, so a typed value is committed as with the Close button; when a controlled dialog\n * refuses the press, the field gets focus back (an alert dialog's press leaves focus where it\n * was). Focus returns to the first of these that can take focus: `finalFocusRef`, the element\n * that had focus when the dialog opened, the trigger, an element next to where that opener was.\n * - **Alert dialogs**: `modalType=\"alert\"` renders `role=\"alertdialog\"` for a confirmation that\n * needs an answer; a backdrop press does not close it.\n * - **Footer**: `Dialog.Footer` sticks to the bottom of the scrolling body, and the body keeps a\n * focused field above it.\n * - **Naming**: give `Dialog.Content` a `title`, a `Dialog.Title`, or `aria-label`.\n *\n * The sub-components are also exported under flat names (`DialogTrigger`, `DialogContent`,\n * `DialogFooter`, `DialogTitle`, `DialogClose`) for React Server Components, which cannot use the\n * dotted form; dotted access (`Dialog.Content`) needs a client file.\n *\n * @example\n * <Dialog>\n * <Dialog.Trigger><Button>Delete</Button></Dialog.Trigger>\n * <Dialog.Content title=\"Delete file?\">\n * This cannot be undone.\n * <Dialog.Footer>\n * <Dialog.Close><Button appearance=\"subtle\">Cancel</Button></Dialog.Close>\n * <Button appearance=\"primary\" onClick={remove}>Delete</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog>\n */\nexport const Dialog = /* @__PURE__ */ Object.assign(DialogRoot, {\n Trigger: DialogTrigger,\n Content: DialogContent,\n Footer: DialogFooter,\n Title: DialogTitle,\n Close: DialogClose,\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Dialog.mjs","names":["useId","_Fragment","useId$1","React","DialogContext","inertDialogContext","inertModalTrigger","useDialogContext","useRequiredContext","componentName","DialogRoot","openState","requestOpen","useModalOpenState","open","defaultOpen","onOpenChange","isClient","useIsClient","isOpen","trigger","useModalTrigger","contentId","setContentId","registerContentId","id","current","context","modalType","finalFocusRef","unmountOnClose","DialogTrigger","useModalTriggerPart","props","DialogClose","useModalClosePart","sizeClasses","fullTitleActionsClasses","TITLE_ACTIONS_GAP","BACKDROP_IGNORED_WARNING_KEY","BACKDROP_IGNORED_WARNING","NON_MODAL_FULL_WARNING_KEY","NON_MODAL_FULL_WARNING","useTitleActionsWidth","width","setWidth","area","observer","entry","entries","DialogContent","rest","presenceRef","usePresence","keptMounted","generatedId","propTitleId","titles","useTitleRegistry","surface","setSurface","surfaceRef","attachSurface","node","registerId","mergedRef","useMergedRefs","ref","portalRef","backdropPress","useBackdropPress","onDismiss","useModalDismiss","layer","useModalLayer","nonModal","opener","useModalOpener","onTabOrderKeyDown","usePopoverTabOrder","getTabbableThrough","useUnnamedModalWarning","useOpenInsideWarning","backdropIgnored","backdrop","warnOnce","coversUsablePage","size","titleActionsArea","setTitleActionsArea","titleActionsOutlet","setTitleActionsOutlet","titleActionsWidth","footerHeight","setFooterHeight","surfaceContext","isMounted","hasTitle","slotRendersContent","title","titleEndPadding","surfaceStyle","style","Portal","ModalBackdrop","dialogContentClassNames","presenceProps","cn","composeEventHandlers","onKeyDown","className","ModalSurfaceContext","dialogTitleClassNames","titleAction","renderSlot","ModalCloseButton","DialogTitle","titleId","titleRef","useModalTitle","outlet","heading","action","actionElement","Fragment","createPortal","stickyFooterClasses","footerRowClasses","DialogFooter","outsideContent","footer","setFooter","dialogFooterClassNames","Dialog"],"sources":["../../../src/components/overlays/Dialog.tsx"],"sourcesContent":["import * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { cn } from '../../lib/cn';\nimport {\n dialogContentClassNames,\n dialogFooterClassNames,\n dialogTitleClassNames,\n} from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { renderSlot, slotRendersContent, type Slot, type SlotObject } from '../../lib/slot';\nimport type {\n BackdropAppearance,\n ModalOpenChangeReason,\n ModalType,\n OpenChangeDetails,\n SurfaceSize,\n} from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useModalLayer } from '../../hooks/useModalLayer';\nimport { usePresence } from '../../hooks/usePresence';\nimport { Portal } from '../portal/Portal';\nimport {\n inertModalTrigger,\n ModalSurfaceContext,\n useBackdropPress,\n useModalClosePart,\n useModalDismiss,\n useModalOpener,\n useModalOpenState,\n useModalTitle,\n useModalTrigger,\n useModalTriggerPart,\n useModalTriggerSession,\n useOpenInsideWarning,\n useRaiseOnOpen,\n useRequiredContext,\n useTitleRegistry,\n useUnnamedModalWarning,\n type ModalRequestOpen,\n type ModalSurfaceContextValue,\n type ModalTrigger,\n} from './Dialog.shared';\nimport { ModalBackdrop, ModalCloseButton } from './Dialog.slots';\nimport { getTabbableThrough, usePopoverTabOrder } from './Popover.shared';\n\n/**\n * Why a {@link Dialog} asks to open or close: `trigger` (`Dialog.Trigger`), `close`\n * (`Dialog.Close`), `close-button` (the built-in Close button), `escape`, `outside-press` (the\n * backdrop). The shared `ModalOpenChangeReason`.\n */\nexport type DialogOpenChangeReason = ModalOpenChangeReason;\n\n/** The second argument of a {@link Dialog}'s `onOpenChange`: the reason and the DOM event. */\nexport type DialogOpenChangeDetails = OpenChangeDetails<DialogOpenChangeReason>;\n\n/**\n * How a {@link Dialog} relates to the page: `modal`, `alert` or `non-modal` (the shared\n * `ModalType`; `DrawerModalType` is the same type).\n */\nexport type DialogModalType = ModalType;\n\n/**\n * The width cap of a {@link Dialog}'s surface: `small` 400px, `medium` 600px, `large` 940px, or\n * `full`, the whole viewport (the shared `SurfaceSize`; `DrawerSize` is the same type).\n */\nexport type DialogSize = SurfaceSize;\n\n/** Properties for the Dialog component. */\nexport interface DialogProps {\n /**\n * Controlled open state of the dialog. The surface renders only in the browser: an open dialog\n * is closed in the server HTML and opens once it has hydrated.\n */\n open?: boolean;\n /**\n * Default open state for uncontrolled usage. The surface renders only in the browser: a dialog\n * open by default is closed in the server HTML and opens once it has hydrated.\n * @default false\n */\n defaultOpen?: boolean;\n /**\n * Called with the new open state when it changes. `details.reason` tells how — `trigger`,\n * `close` (a `.Close` part), `close-button` (the built-in Close button), `escape` or\n * `outside-press` (the backdrop) — so a controlled dialog can refuse only some ways of closing\n * (for example keep a form with unsaved changes open on `outside-press`); `details.event` is the\n * DOM event behind the request. WaveUI always passes `details`; it is typed optional until 1.0\n * so that code which calls this prop itself keeps compiling.\n *\n * Fires only when the value changes; a controlled dialog stays as it is until the parent updates\n * `open`.\n */\n onOpenChange?: (open: boolean, details?: DialogOpenChangeDetails) => void;\n /**\n * `modal`: the page behind is `inert` and does not scroll; a backdrop press, Escape, the Close\n * button and `Dialog.Close` close it. `alert`: a confirmation that needs an answer —\n * `role=\"alertdialog\"`, and a backdrop press does not close it (Escape still does). `non-modal`:\n * the page stays usable — no backdrop, no focus trap, nothing inert, the page scrolls; Tab and\n * Shift+Tab leave the dialog in the page's order right after the element that opened it, Escape\n * closes it while focus is inside it, presses on the page never close it, and focus returns to\n * the opener only when it was inside the dialog. A non-modal dialog covers the page under it\n * while Tab still reaches that page: keep the controls the user works with outside it, or use\n * `modal` (with `size=\"full\"` it covers everything, and a development warning says so). Every\n * type moves focus to the first focusable element on open (a title action, else the built-in\n * Close button); give another element `autoFocus` to start there (an alert dialog's least\n * destructive action). `Dialog.Trigger` toggles the dialog. Fluent's `modalType`.\n * @default 'modal'\n */\n modalType?: DialogModalType;\n /**\n * Where focus goes when the dialog closes, if it can take focus. Otherwise focus returns to the\n * element that had focus when the dialog opened, then to the trigger, then to an element next to\n * where that opener was (the next row's action after a confirm dialog deleted the row). Use it to\n * send focus somewhere else.\n */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * Removes `Dialog.Content` (the surface and everything in it) when the dialog closes. `false`\n * keeps it mounted while closed, `hidden` and `inert`, so a form inside keeps what was typed and\n * the components inside keep their state; the surface then mounts with the Dialog, closed (in\n * the browser only, as an open one), and an `autoFocus` inside it never applies (each open\n * focuses the first focusable element). A popup opened inside that is still open when the\n * dialog closes stays open over the page (a development warning says so): close it first.\n * Fluent's `unmountOnClose`.\n * @default true\n */\n unmountOnClose?: boolean;\n /** `Dialog.Trigger` and `Dialog.Content`. */\n children: React.ReactNode;\n}\n\n/** Properties for the DialogContent sub-component. */\nexport interface DialogContentProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n /**\n * Title rendered as the dialog's heading; it names the dialog (`aria-labelledby`). Without it,\n * render a `Dialog.Title` or pass `aria-label`/`aria-labelledby`. A title that renders nothing\n * (`''`, `[]`, `true`) counts as none.\n */\n title?: React.ReactNode;\n /**\n * Width cap: 400px (`small`), 600px (`medium`) or 940px (`large`), never wider than the viewport\n * (a 1rem margin). `full` covers the viewport: no margin, radius or border, the viewport's\n * dynamic height, and the safe-area insets as padding (with `viewport-fit=cover`); the body\n * scrolls under the sticky `Dialog.Footer`. Rendered as `data-size`. Fluent has no size. For\n * another width, put a width cap in `className` (it replaces the size's).\n * @default 'medium'\n */\n size?: DialogSize;\n /**\n * The backdrop of a modal or alert dialog: a `div` behind the dialog, `aria-hidden`. Shorthand\n * content renders inside it; a slot object's `className` (merged last), `style`, data\n * attributes, `ref` and handlers go to it, and its `appearance` (`'dimmed'` or `'transparent'`)\n * overrides the automatic one: while another modal Dialog or Drawer is open below this one the\n * backdrop is transparent, so the page is dimmed once. `null` renders no backdrop (the page stays\n * inert, and a press outside still closes a modal dialog); a boolean is no slot. Ignored with\n * `modalType=\"non-modal\"` (a development warning says so). Fluent's `backdrop`.\n */\n backdrop?: Slot<'div'> | (SlotObject<'div'> & { appearance?: BackdropAppearance });\n /**\n * Content of the built-in Close button (the dismiss glyph by default). It renders inside the\n * button, decorative (`aria-hidden`), so the button keeps the name `closeLabel`; a slot object's\n * `aria-label`, `aria-labelledby` or `title` names it instead, and its handlers run before the\n * close (`preventDefault()` keeps the dialog open). `null` hides the button (Escape and\n * `Dialog.Close` still close); a boolean is no slot, so `closeButton={cond && <MyIcon />}` keeps\n * the default; content that renders nothing keeps the default glyph. A `<button>` or Wave\n * `Button` passed here is merged into the built-in button, never nested (a development warning\n * says so): its props apply, its text label (`<button>Done</button>`) names the button instead\n * of `closeLabel`, and a Button's `icon`, `iconPosition` and `disabledFocusable` apply while\n * `appearance` and `size` are ignored. Fluent's `DialogTitle` `action` holds Fluent's close\n * button; WaveUI renders its own.\n */\n closeButton?: Slot<'span'>;\n /**\n * Header buttons for the `title` prop form, placed before the built-in Close button in the\n * dialog's top end corner, in DOM and Tab order (an expand toggle, a menu). The title's end\n * padding makes room for them. Interactive: name icon-only buttons. Renders nothing when empty.\n * See also `Dialog.Title`'s `action`. Fluent's `DialogTitle` `action`, for the `title` prop\n * form.\n */\n titleAction?: Slot<'span'>;\n /**\n * Accessible name of the built-in Close button (an icon-only button). Localize it with the\n * page's language. A text label of a button merged into `closeButton` names it instead.\n * @default 'Close'\n */\n closeLabel?: string;\n /** Content rendered inside the dialog body (put `Dialog.Footer` here as well). */\n children: React.ReactNode;\n /** Ref to the dialog surface (`role=\"dialog\"`, or `alertdialog` with `modalType=\"alert\"`). */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DialogFooter sub-component. */\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Footer content, typically action buttons (wrap closing buttons in `Dialog.Close`). */\n children: React.ReactNode;\n /** Ref to the footer element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DialogTitle sub-component. */\nexport interface DialogTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n /** The title; any content. */\n children: React.ReactNode;\n /**\n * Header buttons for this title, placed before the built-in Close button in the dialog's top end\n * corner (after `Dialog.Content`'s `titleAction`), not inside the heading, so they never become\n * part of the dialog's name. Outside `Dialog.Content` (in a Drawer) they render right after the\n * heading. Interactive: name icon-only buttons. Renders nothing when empty. Fluent's\n * `DialogTitle` `action`; unlike Fluent's, it is never filled by default (the Close button is\n * the Content's).\n */\n action?: Slot<'span'>;\n /** Ref to the heading element. */\n ref?: React.Ref<HTMLHeadingElement>;\n}\n\n/** Props a `Dialog.Trigger` puts on its element (and passes to a render-prop child). */\nexport interface DialogTriggerRenderProps extends React.HTMLAttributes<HTMLElement> {\n 'aria-haspopup': 'dialog';\n 'aria-expanded': boolean;\n /** The dialog surface's id, while the dialog is open. */\n 'aria-controls'?: string;\n onClick: React.MouseEventHandler<HTMLElement>;\n /** A callback ref, so the props spread onto any element type. */\n ref: React.RefCallback<HTMLElement>;\n}\n\n/** Properties for the DialogTrigger sub-component. */\nexport interface DialogTriggerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that opens and closes the dialog. A single element receives the trigger props\n * (merged with its own: handlers composed, classes joined, its own `id` kept); a function\n * receives them.\n */\n children: React.ReactNode | ((props: DialogTriggerRenderProps) => React.ReactNode);\n /**\n * `false` renders the 0.4 wrapper `<span>` around the children instead of merging the trigger\n * props onto the child. The span carries the click handler; `aria-haspopup`, `aria-expanded`\n * and `aria-controls` go to the first element in the tab order inside it.\n * @default true\n */\n asChild?: boolean;\n /** Ref to the trigger element (the child, or the wrapper span). */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** Props a `Dialog.Close` puts on its element (and passes to a render-prop child). */\nexport interface DialogCloseRenderProps extends React.HTMLAttributes<HTMLElement> {\n onClick: React.MouseEventHandler<HTMLElement>;\n /** A callback ref, so the props spread onto any element type. */\n ref: React.RefCallback<HTMLElement>;\n}\n\n/** Properties for the DialogClose sub-component. */\nexport interface DialogCloseProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that closes the dialog, typically a footer button. A single element receives an\n * `onClick` composed with its own (its handler runs first; `preventDefault()` keeps the dialog\n * open); a function receives the props.\n */\n children: React.ReactNode | ((props: DialogCloseRenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` that closes the dialog on click. @default true */\n asChild?: boolean;\n /** Ref to the close element (the child, or the wrapper span). */\n ref?: React.Ref<HTMLElement>;\n}\n\ninterface DialogContextValue {\n open: boolean;\n /** Asks the root to open or close, with the reason and event for `onOpenChange`. */\n requestOpen: ModalRequestOpen;\n /** The resolved `modalType`. */\n modalType: DialogModalType;\n /** The trigger element (`attach`) and the focus-restore target resolved from it (`focusRef`). */\n trigger: ModalTrigger;\n finalFocusRef: React.RefObject<HTMLElement | null> | undefined;\n /** The resolved `unmountOnClose`: `false` keeps `Dialog.Content` mounted while closed. */\n unmountOnClose: boolean;\n /** The id of the open dialog surface (for the trigger's `aria-controls`), or `undefined`. */\n contentId: string | undefined;\n /** Registers the surface's id while it is mounted; returns the unregister function. */\n registerContentId: (id: string) => () => void;\n}\n\nconst DialogContext = React.createContext<DialogContextValue | null>(null);\nDialogContext.displayName = 'DialogContext';\n\nconst inertDialogContext: DialogContextValue = {\n open: false,\n requestOpen: () => {},\n modalType: 'modal',\n trigger: inertModalTrigger,\n finalFocusRef: undefined,\n unmountOnClose: true,\n contentId: undefined,\n registerContentId: () => () => {},\n};\n\nfunction useDialogContext(componentName: string): DialogContextValue {\n return useRequiredContext(DialogContext, componentName, 'Dialog', () => inertDialogContext);\n}\n\n// The root of `Dialog` (documented on the export below). A const arrow (like DrawerRoot): its type\n// can be named in consumers' declaration files, e.g. a story's `satisfies Meta<typeof Dialog>` (a\n// function declaration's `typeof` cannot, TS4023).\nconst DialogRoot = ({\n open,\n defaultOpen,\n onOpenChange,\n modalType = 'modal',\n finalFocusRef,\n unmountOnClose = true,\n children,\n}: DialogProps) => {\n const [openState, requestOpen] = useModalOpenState(open, defaultOpen, onOpenChange);\n // The surface lives in a portal, which renders only in the browser: until then (the server\n // HTML, hydration) the dialog reports itself closed, so the trigger's aria-expanded never\n // describes a dialog that is not there.\n const isClient = useIsClient();\n const isOpen = openState && isClient;\n const trigger = useModalTrigger();\n // After Dialog.Content's focus restore (a child's layout effects run first), start the trigger\n // session, or end it and forget the trigger that opened it.\n useModalTriggerSession(trigger, isOpen);\n const [contentId, setContentId] = React.useState<string | undefined>(undefined);\n const registerContentId = React.useCallback((id: string) => {\n setContentId(id);\n return () => setContentId((current) => (current === id ? undefined : current));\n }, []);\n\n const context = React.useMemo<DialogContextValue>(\n () => ({\n open: isOpen,\n requestOpen,\n modalType,\n trigger,\n finalFocusRef,\n unmountOnClose,\n contentId,\n registerContentId,\n }),\n [\n isOpen,\n requestOpen,\n modalType,\n trigger,\n finalFocusRef,\n unmountOnClose,\n contentId,\n registerContentId,\n ],\n );\n\n return <DialogContext.Provider value={context}>{children}</DialogContext.Provider>;\n};\nDialogRoot.displayName = 'Dialog';\n\n/**\n * Opens and closes the dialog: a click while it is open asks it to close (reason `trigger`). Only a\n * non-modal dialog's trigger, or a trigger rendered inside the dialog's own content, can receive\n * one (a modal dialog makes the page inert). Fluent's `DialogTrigger` never toggles (outside the\n * surface it only opens, inside it only closes); this trigger always does. Puts\n * `aria-haspopup=\"dialog\"`, `aria-expanded`, `aria-controls` (while open), a click handler and a\n * ref on its single child (no wrapper element), or passes them to a render-prop child. A custom\n * child component must forward `ref` and spread its props; one that does not is wrapped in a\n * `<span>` automatically (with a development warning), the span that `asChild={false}` renders.\n * Focus returns to the trigger when the dialog closes (with several triggers, to the one that\n * opened it). On the span, the state ARIA goes to the first element in the tab order inside it,\n * and focus returns to that element (to the span when you made it the trigger with a `role` such\n * as `button` and `tabIndex={0}`, or when nothing inside it can take focus).\n */\nexport const DialogTrigger = (props: DialogTriggerProps) => {\n const { open, requestOpen, trigger, contentId } = useDialogContext('Dialog.Trigger');\n return useModalTriggerPart<DialogTriggerRenderProps>(\n { open, requestOpen, trigger, controlsId: contentId },\n props,\n 'Dialog.Trigger',\n );\n};\nDialogTrigger.displayName = 'DialogTrigger';\n\n/**\n * Closes the dialog: composes a click handler onto its single child (its own `onClick` runs first;\n * calling `preventDefault()` there keeps the dialog open), or passes it to a render-prop child.\n *\n * @example\n * <Dialog.Close><Button appearance=\"subtle\">Cancel</Button></Dialog.Close>\n */\nexport const DialogClose = (props: DialogCloseProps) => {\n const { requestOpen } = useDialogContext('Dialog.Close');\n return useModalClosePart<DialogCloseRenderProps>(requestOpen, props, 'Dialog.Close');\n};\nDialogClose.displayName = 'DialogClose';\n\n/**\n * The surface's width cap per size. `full` lifts the caps, the margin, the radius and the border,\n * takes the viewport's dynamic height and pads the safe-area insets (`max()` keeps the 24px\n * padding where there is no inset, and never adds the two). The side insets are physical (the\n * left inset pads the left side in either direction), so the side padding is too: one class per\n * side, with no direction override that a consumer's padding class would leave behind.\n */\nconst sizeClasses: Record<DialogSize, string> = {\n small: 'max-w-[400px]',\n medium: 'max-w-[600px]',\n large: 'max-w-[940px]',\n full: 'm-0 h-dvh max-h-none max-w-none rounded-none border-0 pt-[max(1.5rem,env(safe-area-inset-top))] pb-[max(1.5rem,env(safe-area-inset-bottom))] pl-[max(1.5rem,env(safe-area-inset-left))] pr-[max(1.5rem,env(safe-area-inset-right))]', // wave-allow-physical: the safe-area insets are physical sides\n};\n\n/** The title-actions area of a `full` dialog moves by the safe-area insets, as the padding does. */\nconst fullTitleActionsClasses =\n 'top-[max(1rem,env(safe-area-inset-top))] end-[max(1rem,env(safe-area-inset-right))] wave-rtl:end-[max(1rem,env(safe-area-inset-left))]';\n\n/** The gap (px) between the titles' text and the title-actions area. */\nconst TITLE_ACTIONS_GAP = 8;\n\nconst BACKDROP_IGNORED_WARNING_KEY = 'Dialog.Content:backdrop-ignored';\nconst BACKDROP_IGNORED_WARNING =\n 'Dialog.Content: `backdrop` is ignored with `modalType=\"non-modal\"`: a non-modal dialog has no backdrop, so the page behind it stays usable.';\n\nconst NON_MODAL_FULL_WARNING_KEY = 'Dialog.Content:non-modal-full';\nconst NON_MODAL_FULL_WARNING =\n 'Dialog.Content: `size=\"full\"` with `modalType=\"non-modal\"` covers the whole page while leaving it usable, so Tab reaches controls hidden behind the dialog. Use `modalType=\"modal\"`, or a smaller size with the page\\'s controls kept clear of it.';\n\n/**\n * The width (px) of the title-actions area, measured with a `ResizeObserver` (`null` until the\n * first measurement, and without `ResizeObserver`). The observer's first callback arrives before\n * the next paint.\n */\nfunction useTitleActionsWidth(area: HTMLElement | null): number | null {\n const [width, setWidth] = React.useState<number | null>(null);\n React.useLayoutEffect(() => {\n if (!area || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver((entries) => {\n const entry = entries[entries.length - 1];\n if (!entry) return;\n setWidth(entry.borderBoxSize?.[0]?.inlineSize ?? area.offsetWidth);\n });\n observer.observe(area, { box: 'border-box' });\n return () => {\n observer.disconnect();\n setWidth(null);\n };\n }, [area]);\n return width;\n}\n\n/**\n * The dialog surface, rendered in a portal (inheriting the WaveProvider theme) while the dialog is\n * open, and kept there while it is closed, `hidden` and `inert`, when the Dialog has\n * `unmountOnClose={false}`: the backdrop, and the surface centred in the positioner (the\n * backdrop's sibling) with the title, the title-actions area (title actions, then the Close\n * button) and a scrolling body. It takes the full width up to its `size` and never exceeds the\n * viewport (the body scrolls, also sideways for content wider than the dialog); `size=\"full\"`\n * fills the viewport. Its 1rem gap to the viewport edges is its own margin, so a margin in\n * `className` replaces the gap: with the width and height caps lifted as well and its height set\n * to the viewport's, it fills the viewport. It is `role=\"dialog\"`, or `role=\"alertdialog\"` when the\n * Dialog has `modalType=\"alert\"` (a `role` you pass wins), and carries `data-modal-type` and\n * `data-size` with the resolved values. A non-modal dialog has no backdrop: the positioner only\n * centres the surface and lets presses through to the page. The titles' end padding follows the\n * width of the title-actions area (`--wave-dialog-title-end-padding`, 2rem until it is measured).\n *\n * It mounts through the presence core: the backdrop, the positioner and the surface render\n * `data-presence` (`entered` while open, `exited` while kept closed; `entering` and `exiting`\n * only while a motion of yours runs on the surface), and the backdrop and the positioner are\n * `inert` while exiting and `hidden` and `inert` while kept closed. No motion ships: animate the\n * surface with `data-[presence=…]:` classes in `className` (an enter's start as\n * `data-[presence=entering]:starting:`, each with a `motion-reduce:` counterpart); a closed\n * surface waits for that motion before it unmounts or hides, while focus, the trap and the\n * isolation follow the open state at once.\n */\nexport const DialogContent = ({\n title,\n size = 'medium',\n backdrop,\n closeButton,\n titleAction,\n closeLabel = 'Close',\n children,\n className,\n style,\n id,\n onKeyDown,\n ref,\n ...rest\n}: DialogContentProps) => {\n const {\n open,\n requestOpen,\n modalType,\n trigger,\n finalFocusRef,\n unmountOnClose,\n registerContentId,\n } = useDialogContext('Dialog.Content');\n // Every surface mounts through the presence core (D5, D103), with no motion of its own: kept\n // mounted while closed with `unmountOnClose={false}`, else removed once it has exited.\n const {\n isMounted,\n ref: presenceRef,\n presenceProps,\n } = usePresence(open, { unmountOnExit: unmountOnClose });\n const keptMounted = !unmountOnClose;\n const generatedId = useId('wave-dialog');\n const contentId = id ?? generatedId;\n const propTitleId = useId('wave-dialog-title');\n const titles = useTitleRegistry();\n\n const [surface, setSurface] = React.useState<HTMLDivElement | null>(null);\n const surfaceRef = React.useRef<HTMLDivElement | null>(null);\n const attachSurface = React.useCallback((node: HTMLDivElement | null) => {\n surfaceRef.current = node;\n setSurface(node);\n }, []);\n // Reports the surface's id to the root (the trigger's `aria-controls`) while it is mounted. A new\n // `id` makes a new callback, which useMergedRefs re-attaches after the commit (re-registering).\n const registerId = React.useCallback(\n (node: HTMLDivElement | null) => (node ? registerContentId(contentId) : undefined),\n [registerContentId, contentId],\n );\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, attachSurface, registerId, presenceRef);\n // The portal wrapper: a kept-mounted surface moves to the top of its stack when it opens\n // (before the layer registers and the trap moves focus in).\n const portalRef = React.useRef<HTMLDivElement | null>(null);\n useRaiseOnOpen(open, keptMounted, portalRef);\n\n // An alert dialog needs an answer: a backdrop press does not close it (Escape still does;\n // useModalLayer registers its layer without outside presses).\n const backdropPress = useBackdropPress(surfaceRef, modalType !== 'alert');\n const onDismiss = useModalDismiss(requestOpen, 'Dialog', backdropPress.afterOutsidePress);\n const layer = useModalLayer({\n open,\n modalType,\n onDismiss,\n refs: [surfaceRef],\n container: surface,\n triggerRef: trigger.focusRef,\n finalFocusRef,\n });\n // A non-modal dialog keeps its place in the page's keyboard order right after its opener. The\n // opener is captured whenever the dialog opens, so a modal dialog that turns non-modal while open\n // (focus inside it by then) still knows it.\n const nonModal = modalType === 'non-modal';\n const opener = useModalOpener(open, trigger, surface);\n const onTabOrderKeyDown = usePopoverTabOrder({\n enabled: open && nonModal,\n surface,\n anchorRef: opener,\n getPreviousStop: getTabbableThrough,\n });\n useUnnamedModalWarning(open ? surface : null, titles.hasTitle, 'Dialog.Content', 'Dialog.Title');\n useOpenInsideWarning(open, keptMounted, layer.layerId, 'Dialog');\n\n // A non-modal dialog has no backdrop: a given slot (not undefined, null or a boolean) is ignored.\n const backdropIgnored =\n nonModal && backdrop !== undefined && backdrop !== null && typeof backdrop !== 'boolean';\n React.useEffect(() => {\n if (backdropIgnored) warnOnce(BACKDROP_IGNORED_WARNING_KEY, BACKDROP_IGNORED_WARNING);\n }, [backdropIgnored]);\n // A full non-modal dialog covers the page it leaves usable (D87.8).\n const coversUsablePage = open && nonModal && size === 'full';\n React.useEffect(() => {\n if (coversUsablePage) warnOnce(NON_MODAL_FULL_WARNING_KEY, NON_MODAL_FULL_WARNING);\n }, [coversUsablePage]);\n\n // The title-actions area (held in state) and the outlet `Dialog.Title` actions portal into. Both\n // attach in the commit that mounts the surface, so a title's action is in the DOM in the next\n // commit, the one in which the focus trap starts (it waits for the surface held in state). The\n // area is measured only while the dialog is open (a kept-mounted closed one measures nothing).\n const [titleActionsArea, setTitleActionsArea] = React.useState<HTMLDivElement | null>(null);\n const [titleActionsOutlet, setTitleActionsOutlet] = React.useState<HTMLSpanElement | null>(null);\n const titleActionsWidth = useTitleActionsWidth(open ? titleActionsArea : null);\n\n // The height of the sticky Dialog.Footer, reserved as the body's scroll padding.\n const [footerHeight, setFooterHeight] = React.useState<number | null>(null);\n const surfaceContext = React.useMemo<ModalSurfaceContextValue>(\n () => ({ ...titles.context, setFooterHeight, titleActionsOutlet }),\n [titles.context, titleActionsOutlet],\n );\n\n if (!isMounted) return null;\n\n const hasTitle = slotRendersContent(title);\n // The titles' end padding: the area's width and a gap while it has a size, none while it is\n // empty; unset (the 2rem fallback) until it is measured.\n const titleEndPadding =\n titleActionsWidth === null\n ? undefined\n : titleActionsWidth > 0\n ? `${titleActionsWidth + TITLE_ACTIONS_GAP}px`\n : '0px';\n const surfaceStyle =\n titleEndPadding === undefined\n ? style\n : ({ '--wave-dialog-title-end-padding': titleEndPadding, ...style } as React.CSSProperties);\n\n return (\n <Portal ref={portalRef} layerId={layer.layerId}>\n {/* Each top-level element carries the presence attributes (D7, D103): hidden and inert while\n kept closed, so a closed dialog leaves no backdrop over the page. */}\n {!nonModal && (\n <ModalBackdrop\n backdrop={backdrop}\n className={dialogContentClassNames.backdrop}\n layerId={layer.layerId}\n open={open}\n onMouseDown={backdropPress.onMouseDown}\n presenceProps={presenceProps}\n />\n )}\n <div\n {...presenceProps}\n // Centres the surface and lets presses through to the backdrop (modal) or the page\n // (non-modal) around it.\n className={cn(\n dialogContentClassNames.positioner,\n 'pointer-events-none fixed inset-0 flex items-center justify-center',\n )}\n >\n <div\n ref={mergedRef}\n role={modalType === 'alert' ? 'alertdialog' : 'dialog'}\n id={contentId}\n aria-labelledby={hasTitle ? propTitleId : titles.titleId}\n tabIndex={-1}\n data-modal-type={modalType}\n data-size={size}\n {...rest}\n data-presence={presenceProps['data-presence']}\n style={surfaceStyle}\n onKeyDown={composeEventHandlers(onKeyDown, onTabOrderKeyDown)}\n className={cn(\n dialogContentClassNames.root,\n // The border marks the surface where the shadow cannot: in high contrast the page,\n // the backdrop and the surface are black, and forced colors drop shadows. The 1rem gap\n // to the viewport edges is the surface's own margin, not the positioner's padding, so\n // a margin in `className` replaces it and a full-screen dialog can reach the edges.\n // Its minimum width is zero, so content wider than the room inside the gap scrolls in\n // the body instead of pushing the surface over the gap.\n 'pointer-events-auto relative m-4 flex min-w-0 max-h-[calc(100dvh-2rem)] w-full flex-col rounded-lg border border-border bg-background p-6 text-foreground shadow-64',\n sizeClasses[size],\n className,\n )}\n >\n <ModalSurfaceContext.Provider value={surfaceContext}>\n {hasTitle && (\n <h2\n id={propTitleId}\n className={cn(\n dialogTitleClassNames.root,\n 'pe-[var(--wave-dialog-title-end-padding,2rem)] text-subtitle-1 font-semibold',\n )}\n >\n {title}\n </h2>\n )}\n <div\n ref={setTitleActionsArea}\n className={cn(\n dialogContentClassNames.titleActions,\n 'absolute end-4 top-4 flex items-start gap-1',\n size === 'full' && fullTitleActionsClasses,\n )}\n >\n {slotRendersContent(titleAction)\n ? renderSlot(\n titleAction,\n 'span',\n cn(dialogContentClassNames.titleAction, 'inline-flex items-center gap-1'),\n )\n : null}\n {/* Each Dialog.Title action portals here, in mount order. */}\n <span ref={setTitleActionsOutlet} className=\"contents\" />\n <ModalCloseButton\n componentName=\"Dialog.Content\"\n closeButton={closeButton}\n closeLabel={closeLabel}\n onClose={(event) => requestOpen(false, { reason: 'close-button', event })}\n className={cn(dialogContentClassNames.closeButton, 'text-muted-foreground')}\n />\n </div>\n <div\n // The scroll padding keeps a focused field above the sticky footer (WCAG 2.4.11).\n className={cn(\n dialogContentClassNames.body,\n '-mx-1 mt-1 min-h-0 flex-1 overflow-y-auto scroll-pb-(--wave-dialog-footer-height) p-1 text-body-1',\n )}\n style={\n footerHeight === null\n ? undefined\n : ({ '--wave-dialog-footer-height': `${footerHeight}px` } as React.CSSProperties)\n }\n >\n {children}\n </div>\n </ModalSurfaceContext.Provider>\n </div>\n </div>\n </Portal>\n );\n};\nDialogContent.displayName = 'DialogContent';\n\n/**\n * A heading that names the dialog (`aria-labelledby`), for rich titles or custom layouts. Render it\n * inside `Dialog.Content` (instead of the `title` prop). Like the `title` heading, its end padding\n * follows the width of the dialog's title-actions area (2rem until it is measured), so a long first\n * line stays clear of the title actions and the Close button; a `className` padding wins. Its\n * `action` renders in that area, before the Close button, and never inside the heading.\n */\nexport const DialogTitle = ({\n id,\n action,\n className,\n children,\n ref,\n ...rest\n}: DialogTitleProps) => {\n const { id: titleId, ref: titleRef } = useModalTitle('Dialog.Title', 'Dialog.Content', id, ref);\n // `undefined` outside Dialog.Content (a Drawer), `null` until the content's outlet is attached.\n const outlet = React.useContext(ModalSurfaceContext)?.titleActionsOutlet;\n const heading = (\n <h2\n {...rest}\n id={titleId}\n ref={titleRef}\n className={cn(\n dialogTitleClassNames.root,\n 'pe-[var(--wave-dialog-title-end-padding,2rem)] text-subtitle-1 font-semibold text-foreground',\n className,\n )}\n >\n {children}\n </h2>\n );\n if (!slotRendersContent(action)) return heading;\n const actionElement = renderSlot(\n action,\n 'span',\n cn(dialogTitleClassNames.action, 'inline-flex items-center gap-1'),\n );\n return (\n <>\n {heading}\n {outlet === undefined ? actionElement : outlet && createPortal(actionElement, outlet)}\n </>\n );\n};\nDialogTitle.displayName = 'DialogTitle';\n\n/**\n * `Dialog.Footer` inside `Dialog.Content`. The body is `p-1`, and sticky positioning stops at its\n * padding edge: `-bottom-1` with `-mb-1 pb-2` covers the body's bottom padding, `-mx-1 px-1` its\n * focus-ring inset, and `pt-3` separates the actions from the content scrolling under them.\n */\nconst stickyFooterClasses =\n 'sticky -bottom-1 z-10 -mx-1 -mb-1 mt-6 flex justify-end gap-2 bg-background px-1 pb-2 pt-3';\n\n/**\n * `Dialog.Footer` where no body reserves its height as scroll padding (a Drawer's body): a plain\n * action row, which never covers a focused field.\n */\nconst footerRowClasses = 'mt-6 flex justify-end gap-2';\n\n/**\n * Action row at the end of the dialog body. It stays where you render it in the DOM and sticks to\n * the bottom of the body while long content scrolls under it (with an opaque background); the body\n * reserves its height as scroll padding, so a focused field is never hidden behind it. Inside a\n * `<form>` that wraps the fields and the footer it sticks too: make it the form's last child.\n * Render it inside `Dialog.Content`: outside it, it would stay on the page while the dialog is\n * closed (a development warning says so). Inside a `Drawer`, whose body reserves no footer height,\n * it does not stick: it is an action row at the end of the content. Render one `Dialog.Footer` per\n * `Dialog.Content`: with two at once, the body reserves the height of the one measured last, and\n * unmounting either clears it until the other resizes (swapping one footer for another is fine).\n */\nexport const DialogFooter = ({ children, className, ref, ...rest }: DialogFooterProps) => {\n const surfaceContext = React.useContext(ModalSurfaceContext);\n const outsideContent = surfaceContext === null;\n const setFooterHeight = surfaceContext?.setFooterHeight;\n const [footer, setFooter] = React.useState<HTMLDivElement | null>(null);\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, setFooter);\n\n React.useEffect(() => {\n if (!outsideContent) return;\n warnOnce(\n 'Dialog.Footer:outside-content',\n 'Dialog.Footer must be rendered inside Dialog.Content. Outside it, the footer stays on the page while the dialog is closed.',\n );\n }, [outsideContent]);\n\n // Reports the footer's border-box height to Dialog.Content. The observer's first callback,\n // delivered before the next paint, supplies the first value; without ResizeObserver the body\n // keeps its default scroll padding.\n React.useLayoutEffect(() => {\n if (!footer || !setFooterHeight || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver((entries) => {\n const entry = entries[entries.length - 1];\n if (!entry) return;\n setFooterHeight(entry.borderBoxSize?.[0]?.blockSize ?? footer.offsetHeight);\n });\n observer.observe(footer, { box: 'border-box' });\n return () => {\n observer.disconnect();\n setFooterHeight(null);\n };\n }, [footer, setFooterHeight]);\n\n return (\n <div\n ref={mergedRef}\n {...rest}\n // Sticky only where the surface reserves the footer's height (Dialog.Content).\n className={cn(\n dialogFooterClassNames.root,\n setFooterHeight ? stickyFooterClasses : footerRowClasses,\n className,\n )}\n >\n {children}\n </div>\n );\n};\nDialogFooter.displayName = 'DialogFooter';\n\n/**\n * A dialog (Fluent UI v2 style), modal by default: `Dialog` holds the open state; `Dialog.Trigger`\n * opens and closes it and `Dialog.Content` renders the surface in a portal while open (and, with\n * `unmountOnClose={false}`, keeps it there while closed, `hidden` and `inert`).\n *\n * - **Modal**: focus moves into the dialog and Tab stays inside it (toasts included), the rest of\n * the page is `inert` (instead of `aria-modal`, so toasts and live regions stay announced), and\n * the page does not scroll.\n * - **Closing**: Escape (only the topmost layer: a popup opened inside closes first), a click on\n * the backdrop (a drag that starts inside does not close it), the Close button and `Dialog.Close`.\n * `onOpenChange` gets the reason as its second argument (`details.reason`), so a controlled\n * dialog can refuse some of them. A backdrop press blurs the focused field before the dialog\n * closes, so a typed value is committed as with the Close button; when a controlled dialog\n * refuses the press, the field gets focus back (an alert dialog's press leaves focus where it\n * was). Focus returns to the first of these that can take focus: `finalFocusRef`, the element\n * that had focus when the dialog opened, the trigger, an element next to where that opener was.\n * - **Alert dialogs**: `modalType=\"alert\"` renders `role=\"alertdialog\"` for a confirmation that\n * needs an answer; a backdrop press does not close it.\n * - **Non-modal dialogs**: `modalType=\"non-modal\"` leaves the page usable (no backdrop, no focus\n * trap, nothing inert, the page scrolls). Focus moves in on open; Tab and Shift+Tab leave the\n * dialog in the page's order right after the element that opened it; Escape closes it only while\n * focus is inside it; presses on the page never close it; focus returns to the opener only from\n * inside. Keep the page's controls clear of the dialog, which covers the page under it.\n * - **Size**: `Dialog.Content` `size` caps the width at 400px (`small`), 600px (`medium`, the\n * default) or 940px (`large`); `full` covers the viewport and pads its safe-area insets.\n * - **Backdrop**: the backdrop is the surface's sibling and a slot (`backdrop`: `null` removes it,\n * `appearance` picks `dimmed` or `transparent`). A modal opened over another modal dims the page\n * once: its backdrop is transparent while the lower one is open.\n * - **Close button and title actions**: `closeButton` sets the built-in Close button's content, or\n * hides it (`null`); a button passed there is merged into it. `titleAction` and `Dialog.Title`'s\n * `action` place header buttons before the Close button in the top end corner, in DOM and Tab\n * order, and the titles' end padding makes room for them. Initial focus goes to the first\n * focusable element: a title action, else the Close button.\n * - **Footer**: `Dialog.Footer` sticks to the bottom of the scrolling body, and the body keeps a\n * focused field above it.\n * - **Kept mounted**: `unmountOnClose={false}` keeps the content mounted while the dialog is\n * closed, so a form keeps what was typed and the components inside keep their state; each open\n * focuses the first focusable element again (an `autoFocus` inside never applies), and a kept\n * dialog opened while another overlay is open stacks above it.\n * - **Presence**: the surface mounts through the presence core and renders `data-presence`; no\n * motion ships, and `data-[presence=…]:` classes on `Dialog.Content` animate it.\n * - **Naming**: give `Dialog.Content` a `title`, a `Dialog.Title`, or `aria-label`.\n *\n * The sub-components are also exported under flat names (`DialogTrigger`, `DialogContent`,\n * `DialogFooter`, `DialogTitle`, `DialogClose`) for React Server Components, which cannot use the\n * dotted form; dotted access (`Dialog.Content`) needs a client file.\n *\n * @example\n * <Dialog>\n * <Dialog.Trigger><Button>Delete</Button></Dialog.Trigger>\n * <Dialog.Content title=\"Delete file?\">\n * This cannot be undone.\n * <Dialog.Footer>\n * <Dialog.Close><Button appearance=\"subtle\">Cancel</Button></Dialog.Close>\n * <Button appearance=\"primary\" onClick={remove}>Delete</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog>\n */\nexport const Dialog = /* @__PURE__ */ Object.assign(DialogRoot, {\n Trigger: DialogTrigger,\n Content: DialogContent,\n Footer: DialogFooter,\n Title: DialogTitle,\n Close: DialogClose,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA+RA,IAAMI,IAAgBD,EAAM,cAAyC,IAAI;AACzE,EAAc,cAAc;AAE5B,IAAME,IAAyC;CAC7C,MAAM;CACN,mBAAmB,CAAC;CACpB,WAAW;CACX,SAASC;CACT,eAAe,KAAA;CACf,gBAAgB;CAChB,WAAW,KAAA;CACX,+BAA+B,CAAC;AAClC;AAEA,SAASC,EAAiB,GAA2C;CACnE,OAAOC,EAAmBJ,GAAeK,GAAe,gBAAgBJ,CAAkB;AAC5F;AAKA,IAAMK,KAAc,EAClB,SACA,gBACA,iBACA,eAAY,SACZ,kBACA,oBAAiB,IACjB,kBACiB;CACjB,IAAM,CAACC,GAAWC,KAAeC,EAAkBC,GAAMC,GAAaC,CAAY,GAI5EC,IAAWC,EAAY,GACvBC,IAASR,KAAaM,GACtBG,IAAUC,GAAgB;CAGhC,EAAuBD,GAASD,CAAM;CACtC,IAAM,CAACG,GAAWC,KAAgBpB,EAAM,SAA6B,KAAA,CAAS,GACxEqB,IAAoBrB,EAAM,aAAa,OAC3CoB,EAAaE,CAAE,SACFF,GAAc,MAAaG,MAAYD,IAAK,KAAA,IAAYC,CAAQ,IAC5E,CAAC,CAAC,GAECC,IAAUxB,EAAM,eACb;EACL,MAAMgB;EACN;EACA;EACA;EACA;EACA;EACA;EACA;CACF,IACA;EACEA;EACAP;EACAgB;EACAR;EACAS;EACAC;EACAR;EACAE;CACF,CACF;CAEA,OAAO,kBAACpB,EAAc,UAAf;EAAwB,OAAOuB;EAAU;CAAiC,CAAA;AACnF;AACA,EAAW,cAAc;AAgBzB,IAAaI,KAAiB,MAA8B;CAC1D,IAAM,EAAE,SAAM,gBAAa,YAAS,iBAAcxB,EAAiB,gBAAgB;CACnF,OAAOyB,GACL;EAAE;EAAM;EAAa;EAAS,YAAYV;CAAU,GACpDW,GACA,gBACF;AACF;AACA,EAAc,cAAc;AAS5B,IAAaC,KAAe,MAA4B;CACtD,IAAM,EAAE,mBAAgB3B,EAAiB,cAAc;CACvD,OAAO4B,GAA0CvB,GAAaqB,GAAO,cAAc;AACrF;AACA,EAAY,cAAc;AAS1B,IAAMG,KAA0C;CAC9C,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;AACR,GAGMC,KACJ,0IAGIC,KAAoB,GAEpBC,KAA+B,mCAC/BC,KACJ,iJAEIC,KAA6B,iCAC7BC,KACJ;AAOF,SAASC,GAAqB,GAAyC;CACrE,IAAM,CAACC,GAAOC,KAAY1C,EAAM,SAAwB,IAAI;CAc5D,OAbAA,EAAM,sBAAsB;EAC1B,IAAI,CAAC2C,KAAQ,OAAO,iBAAmB,KAAa;EACpD,IAAMC,IAAW,IAAI,gBAAgB,MAAY;GAC/C,IAAMC,IAAQC,EAAQA,EAAQ,SAAS;GACvC,AAAKD,KACLH,EAASG,EAAM,gBAAgB,EAAE,EAAE,cAAcF,EAAK,WAAW;EACnE,CAAC;EAED,OADAC,EAAS,QAAQD,GAAM,EAAE,KAAK,aAAa,CAAC,SAC/B;GAEX,AADAC,EAAS,WAAW,GACpBF,EAAS,IAAI;EACf;CACF,GAAG,CAACC,CAAI,CAAC,GACFF;AACT;AA0BA,IAAaM,KAAiB,EAC5B,UACA,UAAO,UACP,aACA,iBACA,gBACA,gBAAa,SACb,cACA,eACA,UACA,OACA,cACA,QACA,GAAGC,QACqB;CACxB,IAAM,EACJ,SACA,gBACA,cACA,YACA,kBACA,mBACA,yBACE5C,EAAiB,gBAAgB,GAG/B,EACJ,cACA,KAAK6C,GACL,qBACEC,EAAYvC,GAAM,EAAE,eAAegB,EAAe,CAAC,GACjDwB,IAAc,CAACxB,GACfyB,KAAcvD,EAAM,aAAa,GACjCsB,IAAYG,KAAM8B,IAClBC,IAAcxD,EAAM,mBAAmB,GACvCyD,IAASC,GAAiB,GAE1B,CAACC,GAASC,MAAczD,EAAM,SAAgC,IAAI,GAClE0D,IAAa1D,EAAM,OAA8B,IAAI,GACrD2D,KAAgB3D,EAAM,aAAa,MAAgC;EAEvE,AADA,EAAW,UAAU4D,GACrBH,GAAWG,CAAI;CACjB,GAAG,CAAC,CAAC,GAGCC,KAAa7D,EAAM,aACtB,MAAiC4D,IAAOvC,EAAkBF,CAAS,IAAI,KAAA,GACxE,CAACE,GAAmBF,CAAS,CAC/B,GACM2C,KAAYC,EAA8BC,GAAKL,IAAeE,IAAYZ,CAAW,GAGrFgB,IAAYjE,EAAM,OAA8B,IAAI;CAC1D,GAAeW,GAAMwC,GAAac,CAAS;CAI3C,IAAMC,IAAgBC,GAAiBT,GAAYjC,MAAc,OAAO,GAClE2C,KAAYC,GAAgB5D,GAAa,UAAUyD,EAAc,iBAAiB,GAClFI,IAAQC,EAAc;EAC1B;EACA;EACA;EACA,MAAM,CAACb,CAAU;EACjB,WAAWF;EACX,YAAYvC,EAAQ;EACpB;CACF,CAAC,GAIKuD,IAAW/C,MAAc,aACzBgD,KAASC,GAAe/D,GAAMM,GAASuC,CAAO,GAC9CmB,KAAoBC,EAAmB;EAC3C,SAASjE,KAAQ6D;EACjB;EACA,WAAWC;EACX,iBAAiBI;CACnB,CAAC;CAED,AADAC,GAAuBnE,IAAO6C,IAAU,MAAMF,EAAO,UAAU,kBAAkB,cAAc,GAC/FyB,GAAqBpE,GAAMwC,GAAamB,EAAM,SAAS,QAAQ;CAG/D,IAAMU,IACJR,KAAYS,KAAuC,QAAQ,OAAOA,KAAa;CACjF,EAAM,gBAAgB;EACpB,AAAID,KAAiBE,EAAS9C,IAA8BC,EAAwB;CACtF,GAAG,CAAC2C,CAAe,CAAC;CAEpB,IAAMG,IAAmBxE,KAAQ6D,KAAYY,MAAS;CACtD,EAAM,gBAAgB;EACpB,AAAID,KAAkBD,EAAS5C,IAA4BC,EAAsB;CACnF,GAAG,CAAC4C,CAAgB,CAAC;CAMrB,IAAM,CAACE,IAAkBC,MAAuBtF,EAAM,SAAgC,IAAI,GACpF,CAACuF,GAAoBC,MAAyBxF,EAAM,SAAiC,IAAI,GACzFyF,IAAoBjD,GAAqB7B,IAAO0E,KAAmB,IAAI,GAGvE,CAACK,IAAcC,MAAmB3F,EAAM,SAAwB,IAAI,GACpE4F,KAAiB5F,EAAM,eACpB;EAAE,GAAGsD,EAAO;EAAS;EAAiB;CAAmB,IAChE,CAACA,EAAO,SAASiC,CAAkB,CACrC;CAEA,IAAI,CAACM,GAAW,OAAO;CAEvB,IAAMC,KAAWC,EAAmBC,CAAK,GAGnCC,IACJR,MAAsB,OAClB,KAAA,IACAA,IAAoB,IAClB,GAAGA,IAAoBtD,GAAkB,MACzC,OACF+D,KACJD,MAAoB,KAAA,IAChBE,IACC;EAAE,mCAAmCF;EAAiB,GAAGE;CAAM;CAEtE,OACE,kBAACC,GAAD;EAAQ,KAAKnC;EAAW,SAASK,EAAM;EAAvC,UAAA,CAGG,CAACE,KACA,kBAAC6B,IAAD;GACY;GACV,WAAWC,EAAwB;GACnC,SAAShC,EAAM;GACT;GACN,aAAaJ,EAAc;GACZ;EAChB,CAAA,GAEH,kBAAC,OAAD;GACE,GAAIqC;GAGJ,WAAWC,EACTF,EAAwB,YACxB,oEACF;GAEA,UAAA,kBAAC,OAAD;IACE,KAAKxC;IACL,MAAMrC,MAAc,UAAU,gBAAgB;IAC9C,IAAIN;IACJ,mBAAiB2E,KAAWzC,IAAcC,EAAO;IACjD,UAAU;IACV,mBAAiB7B;IACjB,aAAW2D;IACX,GAAIpC;IACJ,iBAAeuD,EAAc;IAC7B,OAAOL;IACP,WAAWO,EAAqBC,GAAW/B,EAAiB;IAC5D,WAAW6B,EACTF,EAAwB,MAOxB,uKACArE,GAAYmD,IACZuB,EACF;IAEA,UAAA,kBAACC,EAAoB,UAArB;KAA8B,OAAOhB;KAArC,UAAA;MACGE,MACC,kBAAC,MAAD;OACE,IAAIzC;OACJ,WAAWmD,EACTK,EAAsB,MACtB,8EACF;OAEC,UAAAb;MACC,CAAA;MAEN,kBAAC,OAAD;OACE,KAAKV;OACL,WAAWkB,EACTF,EAAwB,cACxB,+CACAlB,MAAS,UAAUlD,EACrB;OANF,UAAA;QAQG6D,EAAmBe,CAAW,IAC3BC,EACED,GACA,QACAN,EAAGF,EAAwB,aAAa,gCAAgC,CAC1E,IACA;QAEJ,kBAAC,QAAD;SAAM,KAAKd;SAAuB,WAAU;QAAY,CAAA;QACxD,kBAACwB,IAAD;SACE,eAAc;SACD;SACD;SACZ,UAAU,MAAUvG,EAAY,IAAO;UAAE,QAAQ;UAAgB;SAAM,CAAC;SACxE,WAAW+F,EAAGF,EAAwB,aAAa,uBAAuB;QAC3E,CAAA;OACE;;MACL,kBAAC,OAAD;OAEE,WAAWE,EACTF,EAAwB,MACxB,mGACF;OACA,OACEZ,OAAiB,OACb,KAAA,IACC,EAAE,+BAA+B,GAAGA,GAAa,IAAI;OAG3D;MACE,CAAA;KACuB;;GAC3B,CAAA;EACF,CAAA,CACC;;AAEZ;AACA,EAAc,cAAc;AAS5B,IAAauB,KAAe,EAC1B,OACA,WACA,cACA,aACA,QACA,GAAGjE,QACmB;CACtB,IAAM,EAAE,IAAIkE,GAAS,KAAKC,MAAaC,EAAc,gBAAgB,kBAAkB9F,GAAI0C,CAAG,GAExFqD,IAASrH,EAAM,WAAW4G,CAAmB,CAAC,EAAE,oBAChDU,IACJ,kBAAC,MAAD;EACE,GAAItE;EACJ,IAAIkE;EACJ,KAAKC;EACL,WAAWX,EACTK,EAAsB,MACtB,gGACAF,CACF;EAEC;CACC,CAAA;CAEN,IAAI,CAACZ,EAAmBwB,CAAM,GAAG,OAAOD;CACxC,IAAME,IAAgBT,EACpBQ,GACA,QACAf,EAAGK,EAAsB,QAAQ,gCAAgC,CACnE;CACA,OACE,kBAAA/G,GAAA,EAAA,UAAA,CACGwH,GACAD,MAAW,KAAA,IAAYG,IAAgBH,KAAUK,EAAaF,GAAeH,CAAM,CACpF,EAAA,CAAA;AAEN;AACA,EAAY,cAAc;AAO1B,IAAMM,IACJ,8FAMIC,IAAmB,+BAaZC,KAAgB,EAAE,aAAU,cAAW,QAAK,GAAG7E,QAA8B;CACxF,IAAM4C,IAAiB5F,EAAM,WAAW4G,CAAmB,GACrDkB,IAAiBlC,MAAmB,MACpCD,IAAkBC,GAAgB,iBAClC,CAACmC,GAAQC,KAAahI,EAAM,SAAgC,IAAI,GAChE8D,IAAYC,EAA8BC,GAAKgE,CAAS;CA2B9D,OAzBAhI,EAAM,gBAAgB;EACpB,AAAK8H,KACL5C,EACE,iCACA,4HACF;CACF,GAAG,CAAC4C,CAAc,CAAC,GAKnB9H,EAAM,sBAAsB;EAC1B,IAAI,CAAC+H,KAAU,CAACpC,KAAmB,OAAO,iBAAmB,KAAa;EAC1E,IAAM/C,IAAW,IAAI,gBAAgB,MAAY;GAC/C,IAAMC,IAAQC,EAAQA,EAAQ,SAAS;GACvC,AAAKD,KACL8C,EAAgB9C,EAAM,gBAAgB,EAAE,EAAE,aAAakF,EAAO,YAAY;EAC5E,CAAC;EAED,OADAnF,EAAS,QAAQmF,GAAQ,EAAE,KAAK,aAAa,CAAC,SACjC;GAEX,AADAnF,EAAS,WAAW,GACpB+C,EAAgB,IAAI;EACtB;CACF,GAAG,CAACoC,GAAQpC,CAAe,CAAC,GAG1B,kBAAC,OAAD;EACE,KAAK7B;EACL,GAAId;EAEJ,WAAWwD,EACTyB,EAAuB,MACvBtC,IAAkBgC,IAAsBC,GACxCjB,CACF;EAEC;CACE,CAAA;AAET;AACA,EAAa,cAAc;AA6D3B,IAAauB,IAAyB,uBAAO,OAAO3H,GAAY;CAC9D,SAASqB;CACT,SAASmB;CACT,QAAQ8E;CACR,OAAOZ;CACP,OAAOlF;AACT,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/dev.cjs"),n=require("../../hooks/useControllable.cjs"),r=require("../../hooks/useId.cjs"),i=require("../../lib/focus.cjs"),a=require("../../hooks/useMergedRefs.cjs"),o=require("../../lib/
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/dev.cjs"),n=require("../../hooks/useControllable.cjs"),r=require("../../hooks/useId.cjs"),i=require("../../lib/focus.cjs"),a=require("../../hooks/useMergedRefs.cjs"),o=require("../../lib/layers.cjs"),s=require("../../lib/mergeProps.cjs"),c=require("../../lib/renderTrigger.cjs"),l=require("../../hooks/useTriggerElement.cjs");let u=require("react");u=e.__toESM(u,1);function d(e,t,r){let i=u.useRef(void 0),[a,o]=n.useControllable(e,t??!1,e=>r?.(e,i.current));return[a,u.useCallback((e,t)=>{i.current=t;try{o(e)}finally{i.current=void 0}},[o])]}function f(e,n,r){return u.useCallback((i,a)=>{switch(i){case`escape`:e(!1,{reason:i,event:a});break;case`outside-press`:e(!1,{reason:i,event:a}),r?.();break;case`focus-outside`:t.warnOnce(`${n}:focus-outside`,`${n} ignored a focus-outside dismissal: a modal surface does not close when focus leaves it.`);break;default:return i}},[e,n,r])}function p(e,t){let n=u.useRef(null);return{onMouseDown:u.useCallback(r=>{if(!r.currentTarget.contains(r.target))return;if(!t){r.preventDefault();return}let i=b();n.current=i&&e.current?.contains(i)?i:null},[t,e]),afterOutsidePress:u.useCallback(()=>{let t=n.current;n.current=null,t&&queueMicrotask(()=>{b()===null&&e.current?.contains(t)&&i.focusElement(t,{preventScroll:!0})})},[e])}}function m(e){return typeof e==`object`&&!!e&&typeof e.type==`string`&&typeof e.stopPropagation==`function`&&!(`nativeEvent`in e)}function h(e){let t=typeof e==`object`&&e?e.nativeEvent:void 0;return m(t)?t:m(e)?e:new Event(`click`)}var g={attach:()=>void 0,activate:()=>{},startSession:()=>{},endSession:()=>{},focusRef:{current:null}};function _(e){return typeof e==`object`&&!!e&&e.nodeType===1}function v(e){if(typeof e!=`object`||!e)return!1;let{currentTarget:t,target:n}=e;return!y(t)||!y(n)?!1:!t.contains(n)}function y(e){return typeof e==`object`&&!!e&&typeof e.nodeType==`number`&&typeof e.contains==`function`}function b(){if(typeof document>`u`)return null;let e=document.activeElement;return!e||e===document.body||e===document.documentElement?null:e.isConnected?e:null}function x(){let e=new Set,t=null,n=!1;return{attach:n=>{if(n)return e.add(n),()=>{e.delete(n),t===n&&(t=null)}},activate:e=>{_(e)&&(t=e,!n&&setTimeout(()=>{!n&&t===e&&(t=null)},0))},startSession:()=>{n=!0},endSession:()=>{n=!1,t=null},focusRef:{get current(){let n=b();if(n)return e.has(n)?l.getTriggerFocusTarget(n):null;if(t?.isConnected)return l.getTriggerFocusTarget(t);for(let t of e){if(!t.isConnected)continue;let e=l.getTriggerFocusTarget(t);if(e)return e}return null}}}}function S(){let[e]=u.useState(x);return e}function C(e){let t=null;return{attach:n=>{if(!n)return;t=n;let r=e.attach(n);return()=>{t===n&&(t=null),typeof r==`function`&&r()}},activate:n=>{let r=typeof n==`object`&&n?n.currentTarget:void 0;e.activate(t??r)}}}function w(e){return u.useMemo(()=>C(e),[e])}function T(e,{children:t,asChild:n,ref:r,...i},o){let{open:d,requestOpen:f,trigger:p,controlsId:m,popup:g=`dialog`}=e,{attach:_,activate:y}=w(p),b=a.useMergedRefs(_,r),x=u.useCallback(e=>{v(e)||(d||y(e),f(!d,{reason:`trigger`,event:h(e)}))},[d,y,f]),S={...g!==!1&&{"aria-haspopup":g},"aria-expanded":d,"aria-controls":d?m:void 0},C=s.mergeProps({...S,onClick:x,ref:b},i,{oursWin:c.STATE_ARIA});return l.useTriggerElement(t,C,{componentName:o,asChild:n})}function E(e,{children:t,asChild:n,ref:r,...i},o){let c=a.useMergedRefs(r),d=u.useCallback(t=>e(!1,{reason:`close`,event:h(t)}),[e]),f=s.mergeProps({onClick:d,ref:c},i);return l.useTriggerElement(t,f,{componentName:o,asChild:n})}function D(){let e=null;return{set:t=>{e=t},ref:{get current(){return e?.isConnected?e:null}}}}function O(e,t,n){let[r]=u.useState(D),i=u.useRef(!1);return u.useInsertionEffect(()=>{let a=i.current;if(i.current=e,e===a)return;if(!e){r.set(null);return}let o=t.focusRef.current;if(o){r.set(o);return}let s=b();r.set(s&&!n?.contains(s)?s:null)}),r.ref}function k(e,t){u.useLayoutEffect(()=>{t?e.startSession():e.endSession()},[e,t])}function A(e,t,n){let r=u.useRef(!1);u.useLayoutEffect(()=>{let i=r.current;if(r.current=e,!e||i||!t)return;let a=n.current,o=a?.parentElement;a&&o&&o.lastElementChild!==a&&o.appendChild(a)})}function j(e,n,r,i,a){let s=u.useRef(e);u.useEffect(()=>{let c=s.current;if(s.current=e,!t.isDev||e||!c||!n)return;let l=setTimeout(()=>{let e=a?.current??null;o.getOpenLayers().some(t=>{if(t.kind===`tooltip`)return!1;if(o.isDescendantLayer(t.id,r))return!0;let n=t.getAnchor();return!!e&&!!n&&e.contains(n)})&&t.warnOnce(`${i}:open-inside`,`${i} closed while a popup opened inside it is still open. With \`unmountOnClose={false}\` the popup stays open over the page: close it first, or keep the default \`unmountOnClose\`.`)},0);return()=>clearTimeout(l)},[e,n,r,i,a])}function M(e,n,r,i){let a=u.useContext(e);return a===null?(t.reportMissingContext(n,r),i()):a}var N=u.createContext(null);N.displayName=`ModalSurfaceContext`;var P={registerTitle:()=>()=>{}};function F(){let[e,t]=u.useState([]),n=u.useRef(0),r=u.useCallback(e=>{n.current+=1,t(t=>[...t,e]);let r=!0;return()=>{r&&(r=!1,--n.current,t(t=>{let n=t.indexOf(e);return n===-1?t:[...t.slice(0,n),...t.slice(n+1)]}))}},[]),i=u.useCallback(()=>n.current>0,[]),a=u.useMemo(()=>({registerTitle:r}),[r]);return{titleId:e[0],hasTitle:i,context:a}}function I(e,t,n,i){let{registerTitle:o}=M(N,e,t,()=>P),s=r.useId(`wave-modal-title`),c=n??s,l=u.useCallback(e=>e?o(c):void 0,[o,c]);return{id:c,ref:a.useMergedRefs(i,l)}}function L(e,n,r,i){u.useEffect(()=>{e&&(e.hasAttribute(`aria-label`)||e.hasAttribute(`aria-labelledby`)||n()||t.warnOnce(`${r}:unnamed`,`${r} has no accessible name. Pass \`title\`, render a ${i} inside it, or give it \`aria-label\` or \`aria-labelledby\`.`))},[e,n,r,i])}exports.ModalSurfaceContext=N,exports.getNativeEvent=h,exports.inertModalTrigger=g,exports.useBackdropPress=p,exports.useModalClosePart=E,exports.useModalDismiss=f,exports.useModalOpenState=d,exports.useModalOpener=O,exports.useModalTitle=I,exports.useModalTrigger=S,exports.useModalTriggerPart=T,exports.useModalTriggerSession=k,exports.useOpenInsideWarning=j,exports.useRaiseOnOpen=A,exports.useRequiredContext=M,exports.useTitleRegistry=F,exports.useUnnamedModalWarning=L;
|
|
2
2
|
//# sourceMappingURL=Dialog.shared.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.shared.cjs","names":["React","useControllable","unmapped","getTriggerFocusTarget","useMergedRefs","mergeProps","STATE_ARIA","useTriggerElement","useId","require_runtime","require_dev","require_useControllable","require_useId","require_focus","require_useMergedRefs","require_mergeProps","require_renderTrigger","require_useTriggerElement","react","useModalOpenState","detailsRef","value","setOpen","open","defaultOpen","onOpenChange","next","details","useModalDismiss","reason","requestOpen","afterOutsidePress","componentName","useBackdropPress","pressFocusRef","event","closesOnPress","focused","getFocusedElement","surfaceRef","element","isDomEvent","getNativeEvent","native","inertModalTrigger","isElementTarget","target","active","createModalTrigger","attached","activated","sessionOpen","useModalTrigger","trigger","createModalTriggerElement","node","detach","currentTarget","useModalTriggerElement","useModalTriggerPart","rest","modal","mergedRef","attach","ref","openModal","activate","triggerProps","controlsId","children","useModalClosePart","close","closeProps","useModalTriggerSession","useRequiredContext","context","parentName","getInert","ModalSurfaceContext","inertSurface","useTitleRegistry","ids","setIds","countRef","registerTitle","current","id","registered","index","hasTitle","useModalTitle","generatedId","idProp","register","useUnnamedModalWarning","surface","titleName"],"sources":["../../../src/components/overlays/Dialog.shared.tsx"],"sourcesContent":["import * as React from 'react';\nimport { reportMissingContext, warnOnce } from '../../lib/dev';\nimport { focusElement } from '../../lib/focus';\nimport type { DismissReason } from '../../lib/layers';\nimport { mergeProps } from '../../lib/mergeProps';\nimport { STATE_ARIA } from '../../lib/renderTrigger';\nimport type { ModalOpenChangeReason, OpenChangeDetails } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { getTriggerFocusTarget, useTriggerElement } from '../../hooks/useTriggerElement';\n\n/*\n * Internal helpers shared by Dialog and Drawer (P15). Not exported from the package.\n */\n\n/** Why a modal root asks to open or close, and the event (`DialogOpenChangeDetails`). */\nexport type ModalOpenChangeDetails = OpenChangeDetails<ModalOpenChangeReason>;\n\n/** Asks a modal root to open or close; see {@link useModalOpenState}. */\nexport type ModalRequestOpen = (open: boolean, details: ModalOpenChangeDetails) => void;\n\n/**\n * The open state of a modal root (`Dialog`, `Drawer`): `useControllable`, plus the details of the\n * request behind each change. Every internal path asks through `requestOpen(next, details)`, which\n * writes `details` to a ref, calls the setter and clears the ref once the setter returns.\n * `useControllable` calls its `onChange` synchronously inside the setter, only when the value\n * changes, and that `onChange` passes the ref's details on as `onOpenChange(next, details)`.\n * Clearing the ref afterwards means a change that no request caused can never report a stale\n * reason.\n */\nexport function useModalOpenState(\n open: boolean | undefined,\n defaultOpen: boolean | undefined,\n onOpenChange: ((open: boolean, details?: ModalOpenChangeDetails) => void) | undefined,\n): [open: boolean, requestOpen: ModalRequestOpen] {\n const detailsRef = React.useRef<ModalOpenChangeDetails | undefined>(undefined);\n const [value, setOpen] = useControllable(open, defaultOpen ?? false, (next: boolean) =>\n onOpenChange?.(next, detailsRef.current),\n );\n const requestOpen = React.useCallback<ModalRequestOpen>(\n (next, details) => {\n detailsRef.current = details;\n try {\n setOpen(next);\n } finally {\n detailsRef.current = undefined;\n }\n },\n [setOpen],\n );\n return [value, requestOpen];\n}\n\n/**\n * The `onDismiss` of a modal root's layer (`useModalLayer`): Escape and a backdrop press ask the\n * root to close, with their reason and event. `focus-outside` never reaches a modal layer (only a\n * layer registered with `focusOutside: true` gets it), so it is ignored with a development warning.\n *\n * @param requestOpen The root's request function, from {@link useModalOpenState}.\n * @param componentName The public name for the warning, e.g. `'Dialog'`.\n * @param afterOutsidePress Called right after an `outside-press` request (see\n * {@link useBackdropPress}).\n */\nexport function useModalDismiss(\n requestOpen: ModalRequestOpen,\n componentName: string,\n afterOutsidePress?: () => void,\n): (reason: DismissReason, event: Event) => void {\n return React.useCallback(\n (reason: DismissReason, event: Event) => {\n switch (reason) {\n case 'escape':\n requestOpen(false, { reason, event });\n break;\n case 'outside-press':\n requestOpen(false, { reason, event });\n afterOutsidePress?.();\n break;\n case 'focus-outside':\n warnOnce(\n `${componentName}:focus-outside`,\n `${componentName} ignored a focus-outside dismissal: a modal surface does not close when focus leaves it.`,\n );\n break;\n default: {\n // Exhaustive: a new DismissReason does not compile here until it is mapped.\n const unmapped: never = reason;\n return unmapped;\n }\n }\n },\n [requestOpen, componentName, afterOutsidePress],\n );\n}\n\n/** Returned by {@link useBackdropPress}. */\nexport interface BackdropPress {\n /** `onMouseDown` of the backdrop element. Stable while `closesOnPress` stays the same. */\n onMouseDown: (event: React.MouseEvent<HTMLElement>) => void;\n /** Pass it to {@link useModalDismiss}, which calls it after an `outside-press` request. Stable. */\n afterOutsidePress: () => void;\n}\n\n/**\n * What a press on a modal's backdrop does to focus (`Dialog.Content`, the Drawer panel). Presses\n * that start inside the surface bubble through unchanged.\n *\n * - When the press closes the modal (`closesOnPress`), the browser moves focus to `<body>` as\n * usual, so the focused control blurs while it is still mounted and its blur-time commit runs\n * (the typed text of a SpinButton or a picker, a consumer's `onBlur` autosave or validation)\n * before the click closes the surface. The element inside the surface that had focus is\n * remembered: when the surface is still open after the `outside-press` request (a controlled\n * modal refused it), it gets focus back, in a microtask that runs after React has committed the\n * request, and only while focus is still on `<body>` (a confirm dialog the refusal opened keeps\n * its focus).\n * - When the press never closes the modal (an alert dialog), the press does not move focus at all\n * (`preventDefault()`), so nothing blurs.\n *\n * @param surfaceRef The surface element (the dialog or the drawer panel).\n * @param closesOnPress Whether a backdrop press asks the modal to close (its layer's `outsidePress`).\n */\nexport function useBackdropPress(\n surfaceRef: React.RefObject<HTMLElement | null>,\n closesOnPress: boolean,\n): BackdropPress {\n // The element inside the surface that had focus when the last backdrop press started.\n const pressFocusRef = React.useRef<HTMLElement | null>(null);\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n if (event.target !== event.currentTarget) return;\n if (!closesOnPress) {\n event.preventDefault();\n return;\n }\n const focused = getFocusedElement();\n pressFocusRef.current = focused && surfaceRef.current?.contains(focused) ? focused : null;\n },\n [closesOnPress, surfaceRef],\n );\n\n const afterOutsidePress = React.useCallback(() => {\n const element = pressFocusRef.current;\n pressFocusRef.current = null;\n if (!element) return;\n // A close requested from the click is committed first (React flushes the update in a\n // microtask queued before this one), so a closed surface no longer contains the element.\n queueMicrotask(() => {\n if (getFocusedElement() !== null || !surfaceRef.current?.contains(element)) return;\n focusElement(element, { preventScroll: true });\n });\n }, [surfaceRef]);\n\n return { onMouseDown, afterOutsidePress };\n}\n\n/** Whether `value` is a DOM event (duck-typed, so an event from another window counts too). */\nfunction isDomEvent(value: unknown): value is Event {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<Event>).type === 'string' &&\n typeof (value as Partial<Event>).stopPropagation === 'function' &&\n !('nativeEvent' in value)\n );\n}\n\n/**\n * The DOM event behind a part's click handler call: a React event's `nativeEvent`, or a DOM event\n * passed as is. A render-prop child that calls the handler without its event (or with another\n * value) gets a new `click` event, so `details.event` is always an event.\n */\nexport function getNativeEvent(value: unknown): Event {\n const native =\n typeof value === 'object' && value !== null\n ? (value as { nativeEvent?: unknown }).nativeEvent\n : undefined;\n if (isDomEvent(native)) return native;\n if (isDomEvent(value)) return value;\n return new Event('click');\n}\n\n/** Returned by {@link useModalTrigger}. */\nexport interface ModalTrigger {\n /**\n * Callback ref for the element a trigger renders: the consumer's child, or the wrapper `<span>`\n * of `asChild={false}` and of the automatic fallback for a child that does not forward its ref.\n * Every trigger of the root attaches it (a root may have several). It returns a React 19 cleanup\n * that forgets that one element, so a trigger that unmounts never unregisters another. Stable.\n */\n attach: React.RefCallback<HTMLElement>;\n /**\n * Records the trigger that is opening the modal, for the open session that follows (anything that\n * is not an element is ignored). Focus returns to that trigger, not to another one of the same\n * root. Triggers call it through {@link useModalTriggerPart}.\n *\n * An activation the modal did not open for by the end of the task (a click that the parent of a\n * controlled modal rejected) is dropped, so it does not decide where focus returns after a later\n * open that no trigger started. React commits an accepted open within the same task.\n */\n activate: (target: unknown) => void;\n /**\n * Starts the open session: the activated trigger belongs to it until {@link endSession}.\n * {@link useModalTriggerSession} calls it when the modal opens.\n */\n startSession: () => void;\n /**\n * Ends the open session: forgets the activated trigger, so it does not decide where focus\n * returns after a later open that no trigger started. {@link useModalTriggerSession} calls it\n * when the modal closes.\n */\n endSession: () => void;\n /**\n * The focus-restore target, for the modal layer's `triggerRef`. Its `current` is resolved when it\n * is read (when the modal opens, and again on close if the opener captured then cannot take\n * focus any more):\n *\n * 1. `null` while an element other than `<body>` has focus: that element opened the modal (the\n * clicked trigger, the button inside a trigger's wrapper span, or the parent's own button of\n * a controlled modal), and the restore captures it. A trigger element itself with focus (a\n * `tabIndex={-1}` wrapper span that a press focused, as Safari does for a click on the button\n * inside it) resolves like any trigger instead.\n * 2. Otherwise (Safari does not focus a clicked button; a modal opened from code), the trigger\n * activated in this open session while it is still in the document.\n * 3. Otherwise the first mounted trigger that can take focus.\n *\n * A trigger resolves with `getTriggerFocusTarget`, the rule of every trigger's focus return: the\n * element that carries the state ARIA (the button inside a wrapper span, the span when you made\n * it the trigger), else the first tabbable element inside it, else itself when it can take\n * focus, else `null`. Read-only.\n */\n focusRef: React.RefObject<HTMLElement | null>;\n}\n\n/** A trigger for components rendered outside their root (C-CONTEXT inert fallback). */\nexport const inertModalTrigger: ModalTrigger = {\n attach: () => undefined,\n activate: () => {},\n startSession: () => {},\n endSession: () => {},\n focusRef: { current: null },\n};\n\nfunction isElementTarget(target: unknown): target is HTMLElement {\n return typeof target === 'object' && target !== null && (target as Partial<Node>).nodeType === 1;\n}\n\n/** The element that has focus, or `null` when focus is on `<body>` (or nowhere). */\nfunction getFocusedElement(): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n const active = document.activeElement;\n if (!active || active === document.body || active === document.documentElement) return null;\n return active.isConnected ? (active as HTMLElement) : null;\n}\n\nfunction createModalTrigger(): ModalTrigger {\n // Every mounted trigger element, in the order they attached.\n const attached = new Set<HTMLElement>();\n // The trigger clicked in the current open session (or in the task that is opening it);\n // forgotten when the modal closes, when the element detaches, or when no open followed the click.\n let activated: HTMLElement | null = null;\n // Whether an open session is running (between startSession and endSession).\n let sessionOpen = false;\n return {\n attach: (element) => {\n // Detaching runs the cleanup below (React 19 and useMergedRefs call it instead of passing\n // `null`), which knows which element leaves.\n if (!element) return undefined;\n attached.add(element);\n return () => {\n attached.delete(element);\n if (activated === element) activated = null;\n };\n },\n activate: (target) => {\n if (!isElementTarget(target)) return;\n activated = target;\n if (sessionOpen) return;\n // An accepted open commits before the next task starts; a rejected click leaves the modal\n // closed, and its activation must not outlive the task.\n setTimeout(() => {\n if (!sessionOpen && activated === target) activated = null;\n }, 0);\n },\n startSession: () => {\n sessionOpen = true;\n },\n endSession: () => {\n sessionOpen = false;\n activated = null;\n },\n focusRef: {\n get current() {\n // A focused element is the opener: the restore captures it (see ModalTrigger.focusRef),\n // unless it is a trigger element, which resolves like any trigger.\n const focused = getFocusedElement();\n if (focused) return attached.has(focused) ? getTriggerFocusTarget(focused) : null;\n // The trigger that opened the modal decides, also when it cannot take focus any more.\n if (activated?.isConnected) return getTriggerFocusTarget(activated);\n for (const element of attached) {\n if (!element.isConnected) continue;\n const target = getTriggerFocusTarget(element);\n if (target) return target;\n }\n return null;\n },\n },\n };\n}\n\n/**\n * The triggers of a modal root (`Dialog`, `Drawer`), overlays#9. Each `Dialog.Trigger`/\n * `Drawer.Trigger` attaches its element and activates it from its click handler through\n * {@link useModalTriggerPart}; the root passes `focusRef` to `useModalLayer` as its\n * `triggerRef` and scopes the activation to one open session with {@link useModalTriggerSession}.\n * Focus returns to the element that had focus when the modal opened; when nothing had focus, to\n * the trigger that opened it, else to the first mounted trigger. For a wrapper `<span>`, the\n * restore target is the element inside it that carries the state ARIA. Resolving when the ref is\n * read, not when it attaches, keeps a trigger that was disabled at mount (or whose content\n * changed) a valid target.\n */\nexport function useModalTrigger(): ModalTrigger {\n const [trigger] = React.useState(createModalTrigger);\n return trigger;\n}\n\n/** Returned by {@link useModalTriggerElement}. */\ninterface ModalTriggerElement {\n /**\n * Callback ref for the element one trigger renders (merge it with the consumer's ref): registers\n * it with the root's triggers and remembers it for `activate`. Stable.\n */\n attach: React.RefCallback<HTMLElement>;\n /**\n * Records this trigger as the one opening the modal: call it from the click handler, before\n * opening, with whatever the handler received. The element `attach` received wins, else the\n * event's `currentTarget`, so a render-prop child that calls `onClick()` without the event (or\n * with another value) is still recorded. Stable.\n */\n activate: (event?: unknown) => void;\n}\n\nfunction createModalTriggerElement(trigger: ModalTrigger): ModalTriggerElement {\n // The element this trigger rendered; a closure variable, not a React ref, so the click handler\n // that reads it can be passed around during render (C-HOOKS).\n let element: HTMLElement | null = null;\n return {\n attach: (node) => {\n if (!node) return undefined;\n element = node;\n const detach = trigger.attach(node);\n return () => {\n if (element === node) element = null;\n if (typeof detach === 'function') detach();\n };\n },\n activate: (event) => {\n const currentTarget =\n typeof event === 'object' && event !== null\n ? (event as { currentTarget?: unknown }).currentTarget\n : undefined;\n trigger.activate(element ?? currentTarget);\n },\n };\n}\n\n/**\n * One `Dialog.Trigger`/`Drawer.Trigger` of a modal root (overlays#9): attach `attach` to the\n * element the trigger renders and call `activate` from its click handler.\n */\nfunction useModalTriggerElement(trigger: ModalTrigger): ModalTriggerElement {\n return React.useMemo(() => createModalTriggerElement(trigger), [trigger]);\n}\n\n/** The props of a trigger or close part (`Dialog.Trigger`, `Drawer.Close`, …). */\nexport interface ModalPartProps<RenderProps> extends Omit<\n React.HTMLAttributes<HTMLElement>,\n 'children'\n> {\n /** A single element that receives the part's props, or a function that receives them. */\n children: React.ReactNode | ((props: RenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` carrying the click handler. */\n asChild?: boolean;\n /** Ref to the element the part renders. */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** What {@link useModalTriggerPart} reads from the modal root. */\nexport interface ModalTriggerState {\n open: boolean;\n /** Asks the root to open (reason `trigger`). */\n requestOpen: ModalRequestOpen;\n trigger: ModalTrigger;\n /** The surface's id for `aria-controls` while the modal is open. */\n controlsId: string | undefined;\n}\n\n/**\n * Renders a `Dialog.Trigger`/`Drawer.Trigger`: its element gets `aria-haspopup=\"dialog\"`,\n * `aria-expanded`, `aria-controls` (while open; these always win over the child's own), a click\n * handler that records the trigger (for the focus return) and asks the root to open (reason\n * `trigger`, with the click event), and a ref that registers it with the root's triggers. On a\n * wrapper span (`asChild={false}`, the automatic fallback), the state ARIA goes to the first\n * element in the tab order inside it (`useTriggerElement`).\n *\n * @param modal The root's state, from its context.\n * @param props The part's props.\n * @param componentName The public name for development warnings, e.g. `'Dialog.Trigger'`.\n */\nexport function useModalTriggerPart<RenderProps>(\n modal: ModalTriggerState,\n { children, asChild, ref, ...rest }: ModalPartProps<RenderProps>,\n componentName: string,\n): React.ReactNode {\n const { open, requestOpen, trigger, controlsId } = modal;\n const { attach, activate } = useModalTriggerElement(trigger);\n const mergedRef = useMergedRefs<HTMLElement>(attach, ref);\n const openModal = React.useCallback(\n (event?: React.MouseEvent<HTMLElement>) => {\n // Focus returns to this trigger, also when the root has several (overlays#9), and also when\n // a render-prop child calls `onClick()` without the event.\n activate(event);\n requestOpen(true, { reason: 'trigger', event: getNativeEvent(event) });\n },\n [activate, requestOpen],\n );\n\n const stateAria = {\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': open,\n 'aria-controls': open ? controlsId : undefined,\n };\n const triggerProps = mergeProps({ ...stateAria, onClick: openModal, ref: mergedRef }, rest, {\n oursWin: STATE_ARIA,\n });\n\n return useTriggerElement(children, triggerProps as RenderProps, { componentName, asChild });\n}\n\n/**\n * Renders a `Dialog.Close`/`Drawer.Close`: composes a click handler that asks the root to close\n * (reason `close`, with the click event) onto its element (the child's own `onClick` runs first;\n * `preventDefault()` there keeps the modal open).\n *\n * @param requestOpen The root's request function, from its context.\n * @param props The part's props.\n * @param componentName The public name for development warnings, e.g. `'Dialog.Close'`.\n */\nexport function useModalClosePart<RenderProps>(\n requestOpen: ModalRequestOpen,\n { children, asChild, ref, ...rest }: ModalPartProps<RenderProps>,\n componentName: string,\n): React.ReactNode {\n const mergedRef = useMergedRefs<HTMLElement>(ref);\n const close = React.useCallback(\n (event?: React.MouseEvent<HTMLElement>) =>\n requestOpen(false, { reason: 'close', event: getNativeEvent(event) }),\n [requestOpen],\n );\n const closeProps = mergeProps({ onClick: close, ref: mergedRef }, rest);\n return useTriggerElement(children, closeProps as RenderProps, { componentName, asChild });\n}\n\n/**\n * Scopes a trigger's activation to one open session (overlays#9): when the modal opens, the\n * activated trigger joins the session; when it closes, the trigger is forgotten, so a later open\n * that no trigger started (a controlled modal opened by the parent) does not return focus to it.\n *\n * It updates the session in a layout effect, after the modal's focus restore has used the\n * activation: call it in the root component (whose effects run after its children's) and, when\n * that component also calls `useModalLayer`, after that call (a component's effects run in order).\n */\nexport function useModalTriggerSession(trigger: ModalTrigger, open: boolean): void {\n React.useLayoutEffect(() => {\n if (open) trigger.startSession();\n else trigger.endSession();\n }, [trigger, open]);\n}\n\n/**\n * C-CONTEXT: reads a compound component's context. Outside its root it throws\n * `[WaveUI] <componentName> must be used within <parentName>` in development, and in production\n * logs the same message once per page (`reportMissingContext`) and returns the inert value from\n * `getInert`.\n */\nexport function useRequiredContext<T>(\n context: React.Context<T | null>,\n componentName: string,\n parentName: string,\n getInert: () => T,\n): T {\n const value = React.useContext(context);\n if (value !== null) return value;\n reportMissingContext(componentName, parentName);\n return getInert();\n}\n\n/** What a modal surface (`Dialog.Content`, the Drawer panel) provides to its descendants. */\nexport interface ModalSurfaceContextValue {\n /**\n * Registers the id of a title element (`Dialog.Title`, `Drawer.Title`) for the surface's\n * `aria-labelledby`. Returns the unregister function.\n */\n registerTitle: (id: string) => () => void;\n /**\n * Receives the measured border-box height of the surface's sticky footer (`Dialog.Footer`) in\n * px, or `null` once it unmounts; the surface reserves it as the scroll padding of its body.\n * Absent on a surface without a footer part (the Drawer panel).\n */\n setFooterHeight?: (px: number | null) => void;\n}\n\n/**\n * Provided by every modal surface; `null` outside one. Titles register with it, and\n * `Dialog.Footer` reads it to report its height and to warn when it is rendered outside\n * `Dialog.Content`.\n */\nexport const ModalSurfaceContext = React.createContext<ModalSurfaceContextValue | null>(null);\nModalSurfaceContext.displayName = 'ModalSurfaceContext';\n\nconst inertSurface: ModalSurfaceContextValue = { registerTitle: () => () => {} };\n\n/** Returned by {@link useTitleRegistry}. */\nexport interface TitleRegistry {\n /** The id of the first registered title, for `aria-labelledby`. */\n titleId: string | undefined;\n /** Whether a title is registered right now. Read it in effects and handlers, not during render. */\n hasTitle: () => boolean;\n /** The memoised value for `ModalSurfaceContext.Provider`. */\n context: ModalSurfaceContextValue;\n}\n\n/**\n * The title registry of a modal surface. A title registers its id from its ref callback (when its\n * element attaches), so the surface's `aria-labelledby` follows the title elements that are\n * actually rendered.\n */\nexport function useTitleRegistry(): TitleRegistry {\n const [ids, setIds] = React.useState<readonly string[]>([]);\n const countRef = React.useRef(0);\n\n const registerTitle = React.useCallback((id: string) => {\n countRef.current += 1;\n setIds((current) => [...current, id]);\n let registered = true;\n return () => {\n if (!registered) return;\n registered = false;\n countRef.current -= 1;\n setIds((current) => {\n const index = current.indexOf(id);\n return index === -1 ? current : [...current.slice(0, index), ...current.slice(index + 1)];\n });\n };\n }, []);\n\n const hasTitle = React.useCallback(() => countRef.current > 0, []);\n const context = React.useMemo(() => ({ registerTitle }), [registerTitle]);\n return { titleId: ids[0], hasTitle, context };\n}\n\n/**\n * The `id` and `ref` of a title sub-component (`Dialog.Title`, `Drawer.Title`): the consumer's\n * `id` (or a generated one), registered with the enclosing surface while the element is mounted.\n */\nexport function useModalTitle(\n componentName: string,\n parentName: string,\n idProp: string | undefined,\n ref: React.Ref<HTMLHeadingElement> | undefined,\n): { id: string; ref: React.RefCallback<HTMLHeadingElement> } {\n const { registerTitle } = useRequiredContext(\n ModalSurfaceContext,\n componentName,\n parentName,\n () => inertSurface,\n );\n const generatedId = useId('wave-modal-title');\n const id = idProp ?? generatedId;\n const register = React.useCallback(\n (node: HTMLHeadingElement | null) => (node ? registerTitle(id) : undefined),\n [registerTitle, id],\n );\n const mergedRef = useMergedRefs<HTMLHeadingElement>(ref, register);\n return { id, ref: mergedRef };\n}\n\n/**\n * Development warning (once per component) when an open modal surface has no accessible name:\n * no `title`, no registered title element, no `aria-label` and no `aria-labelledby`.\n *\n * @param surface The open surface element (`null` while closed).\n * @param hasTitle From {@link useTitleRegistry}.\n * @param componentName The public name, e.g. `'Dialog.Content'`.\n * @param titleName The title sub-component to recommend, e.g. `'Dialog.Title'`.\n */\nexport function useUnnamedModalWarning(\n surface: HTMLElement | null,\n hasTitle: () => boolean,\n componentName: string,\n titleName: string,\n): void {\n React.useEffect(() => {\n if (!surface) return;\n if (\n surface.hasAttribute('aria-label') ||\n surface.hasAttribute('aria-labelledby') ||\n hasTitle()\n ) {\n return;\n }\n warnOnce(\n `${componentName}:unnamed`,\n `${componentName} has no accessible name. Pass \\`title\\`, render a ${titleName} inside it, or give it \\`aria-label\\` or \\`aria-labelledby\\`.`,\n );\n }, [surface, hasTitle, componentName, titleName]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Dialog.shared.cjs","names":["React","useControllable","unmapped","getTriggerFocusTarget","useMergedRefs","mergeProps","STATE_ARIA","useTriggerElement","isDev","getOpenLayers","isDescendantLayer","useId","require_runtime","require_dev","require_useControllable","require_useId","require_focus","require_useMergedRefs","require_layers","require_mergeProps","require_renderTrigger","require_useTriggerElement","react","useModalOpenState","detailsRef","value","setOpen","open","defaultOpen","onOpenChange","next","details","useModalDismiss","reason","requestOpen","afterOutsidePress","componentName","useBackdropPress","pressFocusRef","event","closesOnPress","focused","getFocusedElement","surfaceRef","element","isDomEvent","getNativeEvent","native","inertModalTrigger","isElementTarget","target","isPortaledClick","isNode","currentTarget","active","createModalTrigger","attached","activated","sessionOpen","useModalTrigger","trigger","createModalTriggerElement","node","detach","useModalTriggerElement","useModalTriggerPart","rest","modal","mergedRef","attach","ref","toggleModal","activate","stateAria","popup","controlsId","triggerProps","children","useModalClosePart","close","closeProps","createModalOpener","useModalOpener","opener","enabledRef","wasEnabled","enabled","fromTrigger","surface","useModalTriggerSession","useRaiseOnOpen","wasOpenRef","wasOpen","keptMounted","wrapper","wrapperRef","container","useOpenInsideWarning","timer","layer","layerId","anchor","useRequiredContext","context","parentName","getInert","ModalSurfaceContext","inertSurface","useTitleRegistry","ids","setIds","countRef","registerTitle","current","id","registered","index","hasTitle","useModalTitle","generatedId","idProp","register","useUnnamedModalWarning","titleName"],"sources":["../../../src/components/overlays/Dialog.shared.tsx"],"sourcesContent":["import * as React from 'react';\nimport { isDev, reportMissingContext, warnOnce } from '../../lib/dev';\nimport { focusElement } from '../../lib/focus';\nimport { getOpenLayers, isDescendantLayer, type DismissReason } from '../../lib/layers';\nimport { mergeProps } from '../../lib/mergeProps';\nimport { STATE_ARIA } from '../../lib/renderTrigger';\nimport type { ModalOpenChangeReason, OpenChangeDetails } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { getTriggerFocusTarget, useTriggerElement } from '../../hooks/useTriggerElement';\n\n/*\n * Internal helpers shared by Dialog and Drawer (P15). Not exported from the package.\n */\n\n/** Why a modal root asks to open or close, and the event (`DialogOpenChangeDetails`). */\nexport type ModalOpenChangeDetails = OpenChangeDetails<ModalOpenChangeReason>;\n\n/** Asks a modal root to open or close; see {@link useModalOpenState}. */\nexport type ModalRequestOpen = (open: boolean, details: ModalOpenChangeDetails) => void;\n\n/**\n * The open state of a modal root (`Dialog`, `Drawer`): `useControllable`, plus the details of the\n * request behind each change. Every internal path asks through `requestOpen(next, details)`, which\n * writes `details` to a ref, calls the setter and clears the ref once the setter returns.\n * `useControllable` calls its `onChange` synchronously inside the setter, only when the value\n * changes, and that `onChange` passes the ref's details on as `onOpenChange(next, details)`.\n * Clearing the ref afterwards means a change that no request caused can never report a stale\n * reason.\n */\nexport function useModalOpenState(\n open: boolean | undefined,\n defaultOpen: boolean | undefined,\n onOpenChange: ((open: boolean, details?: ModalOpenChangeDetails) => void) | undefined,\n): [open: boolean, requestOpen: ModalRequestOpen] {\n const detailsRef = React.useRef<ModalOpenChangeDetails | undefined>(undefined);\n const [value, setOpen] = useControllable(open, defaultOpen ?? false, (next: boolean) =>\n onOpenChange?.(next, detailsRef.current),\n );\n const requestOpen = React.useCallback<ModalRequestOpen>(\n (next, details) => {\n detailsRef.current = details;\n try {\n setOpen(next);\n } finally {\n detailsRef.current = undefined;\n }\n },\n [setOpen],\n );\n return [value, requestOpen];\n}\n\n/**\n * The `onDismiss` of a modal root's layer (`useModalLayer`): Escape and a backdrop press ask the\n * root to close, with their reason and event. `focus-outside` never reaches a modal layer (only a\n * layer registered with `focusOutside: true` gets it), so it is ignored with a development warning.\n *\n * @param requestOpen The root's request function, from {@link useModalOpenState}.\n * @param componentName The public name for the warning, e.g. `'Dialog'`.\n * @param afterOutsidePress Called right after an `outside-press` request (see\n * {@link useBackdropPress}).\n */\nexport function useModalDismiss(\n requestOpen: ModalRequestOpen,\n componentName: string,\n afterOutsidePress?: () => void,\n): (reason: DismissReason, event: Event) => void {\n return React.useCallback(\n (reason: DismissReason, event: Event) => {\n switch (reason) {\n case 'escape':\n requestOpen(false, { reason, event });\n break;\n case 'outside-press':\n requestOpen(false, { reason, event });\n afterOutsidePress?.();\n break;\n case 'focus-outside':\n warnOnce(\n `${componentName}:focus-outside`,\n `${componentName} ignored a focus-outside dismissal: a modal surface does not close when focus leaves it.`,\n );\n break;\n default: {\n // Exhaustive: a new DismissReason does not compile here until it is mapped.\n const unmapped: never = reason;\n return unmapped;\n }\n }\n },\n [requestOpen, componentName, afterOutsidePress],\n );\n}\n\n/** Returned by {@link useBackdropPress}. */\nexport interface BackdropPress {\n /** `onMouseDown` of the backdrop element. Stable while `closesOnPress` stays the same. */\n onMouseDown: (event: React.MouseEvent<HTMLElement>) => void;\n /** Pass it to {@link useModalDismiss}, which calls it after an `outside-press` request. Stable. */\n afterOutsidePress: () => void;\n}\n\n/**\n * What a press on a modal's backdrop does to focus (`Dialog.Content`, the Drawer panel). The\n * backdrop is the surface's sibling, so every mouse press on it, its content included, is a\n * backdrop press (a press that a portal opened from the backdrop's content bubbles through the\n * React tree is not).\n *\n * - When the press closes the modal (`closesOnPress`), the browser moves focus to `<body>` as\n * usual, so the focused control blurs while it is still mounted and its blur-time commit runs\n * (the typed text of a SpinButton or a picker, a consumer's `onBlur` autosave or validation)\n * before the click closes the surface. The element inside the surface that had focus is\n * remembered: when the surface is still open after the `outside-press` request (a controlled\n * modal refused it), it gets focus back, in a microtask that runs after React has committed the\n * request, and only while focus is still on `<body>` (a confirm dialog the refusal opened keeps\n * its focus).\n * - When the press never closes the modal (an alert dialog), the press does not move focus at all\n * (`preventDefault()`), so nothing blurs.\n *\n * @param surfaceRef The surface element (the dialog or the drawer panel).\n * @param closesOnPress Whether a backdrop press asks the modal to close (its layer's `outsidePress`).\n */\nexport function useBackdropPress(\n surfaceRef: React.RefObject<HTMLElement | null>,\n closesOnPress: boolean,\n): BackdropPress {\n // The element inside the surface that had focus when the last backdrop press started.\n const pressFocusRef = React.useRef<HTMLElement | null>(null);\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n // C-COMPOSE: only presses on the backdrop element or its content in the DOM.\n if (!event.currentTarget.contains(event.target as Node)) return;\n if (!closesOnPress) {\n event.preventDefault();\n return;\n }\n const focused = getFocusedElement();\n pressFocusRef.current = focused && surfaceRef.current?.contains(focused) ? focused : null;\n },\n [closesOnPress, surfaceRef],\n );\n\n const afterOutsidePress = React.useCallback(() => {\n const element = pressFocusRef.current;\n pressFocusRef.current = null;\n if (!element) return;\n // A close requested from the click is committed first (React flushes the update in a\n // microtask queued before this one): a closed surface no longer contains the element, or\n // (exiting, or kept mounted) is inert, so the element cannot take focus.\n queueMicrotask(() => {\n if (getFocusedElement() !== null || !surfaceRef.current?.contains(element)) return;\n focusElement(element, { preventScroll: true });\n });\n }, [surfaceRef]);\n\n return { onMouseDown, afterOutsidePress };\n}\n\n/** Whether `value` is a DOM event (duck-typed, so an event from another window counts too). */\nfunction isDomEvent(value: unknown): value is Event {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<Event>).type === 'string' &&\n typeof (value as Partial<Event>).stopPropagation === 'function' &&\n !('nativeEvent' in value)\n );\n}\n\n/**\n * The DOM event behind a part's click handler call: a React event's `nativeEvent`, or a DOM event\n * passed as is. A render-prop child that calls the handler without its event (or with another\n * value) gets a new `click` event, so `details.event` is always an event.\n */\nexport function getNativeEvent(value: unknown): Event {\n const native =\n typeof value === 'object' && value !== null\n ? (value as { nativeEvent?: unknown }).nativeEvent\n : undefined;\n if (isDomEvent(native)) return native;\n if (isDomEvent(value)) return value;\n return new Event('click');\n}\n\n/** Returned by {@link useModalTrigger}. */\nexport interface ModalTrigger {\n /**\n * Callback ref for the element a trigger renders: the consumer's child, or the wrapper `<span>`\n * of `asChild={false}` and of the automatic fallback for a child that does not forward its ref.\n * Every trigger of the root attaches it (a root may have several). It returns a React 19 cleanup\n * that forgets that one element, so a trigger that unmounts never unregisters another. Stable.\n */\n attach: React.RefCallback<HTMLElement>;\n /**\n * Records the trigger that is opening the modal, for the open session that follows (anything that\n * is not an element is ignored). Focus returns to that trigger, not to another one of the same\n * root. Triggers call it through {@link useModalTriggerPart}.\n *\n * An activation the modal did not open for by the end of the task (a click that the parent of a\n * controlled modal rejected) is dropped, so it does not decide where focus returns after a later\n * open that no trigger started. React commits an accepted open within the same task.\n */\n activate: (target: unknown) => void;\n /**\n * Starts the open session: the activated trigger belongs to it until {@link endSession}.\n * {@link useModalTriggerSession} calls it when the modal opens.\n */\n startSession: () => void;\n /**\n * Ends the open session: forgets the activated trigger, so it does not decide where focus\n * returns after a later open that no trigger started. {@link useModalTriggerSession} calls it\n * when the modal closes.\n */\n endSession: () => void;\n /**\n * The focus-restore target, for the modal layer's `triggerRef`. Its `current` is resolved when it\n * is read (when the modal opens, and again on close if the opener captured then cannot take\n * focus any more):\n *\n * 1. `null` while an element other than `<body>` has focus: that element opened the modal (the\n * clicked trigger, the button inside a trigger's wrapper span, or the parent's own button of\n * a controlled modal), and the restore captures it. A trigger element itself with focus (a\n * `tabIndex={-1}` wrapper span that a press focused, as Safari does for a click on the button\n * inside it) resolves like any trigger instead.\n * 2. Otherwise (Safari does not focus a clicked button; a modal opened from code), the trigger\n * activated in this open session while it is still in the document.\n * 3. Otherwise the first mounted trigger that can take focus.\n *\n * A trigger resolves with `getTriggerFocusTarget`, the rule of every trigger's focus return: the\n * element that carries the state ARIA (the button inside a wrapper span, the span when you made\n * it the trigger), else the first tabbable element inside it, else itself when it can take\n * focus, else `null`. Read-only.\n */\n focusRef: React.RefObject<HTMLElement | null>;\n}\n\n/** A trigger for components rendered outside their root (C-CONTEXT inert fallback). */\nexport const inertModalTrigger: ModalTrigger = {\n attach: () => undefined,\n activate: () => {},\n startSession: () => {},\n endSession: () => {},\n focusRef: { current: null },\n};\n\nfunction isElementTarget(target: unknown): target is HTMLElement {\n return typeof target === 'object' && target !== null && (target as Partial<Node>).nodeType === 1;\n}\n\n/**\n * Whether a click handler's event came from outside its element in the DOM: it bubbled through the\n * React tree from a portal (a popup opened inside a trigger). `false` without an event (a\n * render-prop child that calls `onClick()` bare) or without DOM nodes to compare.\n */\nfunction isPortaledClick(event: unknown): boolean {\n if (typeof event !== 'object' || event === null) return false;\n const { currentTarget, target } = event as { currentTarget?: unknown; target?: unknown };\n if (!isNode(currentTarget) || !isNode(target)) return false;\n return !currentTarget.contains(target);\n}\n\nfunction isNode(value: unknown): value is Node {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<Node>).nodeType === 'number' &&\n typeof (value as Partial<Node>).contains === 'function'\n );\n}\n\n/** The element that has focus, or `null` when focus is on `<body>` (or nowhere). */\nfunction getFocusedElement(): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n const active = document.activeElement;\n if (!active || active === document.body || active === document.documentElement) return null;\n return active.isConnected ? (active as HTMLElement) : null;\n}\n\nfunction createModalTrigger(): ModalTrigger {\n // Every mounted trigger element, in the order they attached.\n const attached = new Set<HTMLElement>();\n // The trigger clicked in the current open session (or in the task that is opening it);\n // forgotten when the modal closes, when the element detaches, or when no open followed the click.\n let activated: HTMLElement | null = null;\n // Whether an open session is running (between startSession and endSession).\n let sessionOpen = false;\n return {\n attach: (element) => {\n // Detaching runs the cleanup below (React 19 and useMergedRefs call it instead of passing\n // `null`), which knows which element leaves.\n if (!element) return undefined;\n attached.add(element);\n return () => {\n attached.delete(element);\n if (activated === element) activated = null;\n };\n },\n activate: (target) => {\n if (!isElementTarget(target)) return;\n activated = target;\n if (sessionOpen) return;\n // An accepted open commits before the next task starts; a rejected click leaves the modal\n // closed, and its activation must not outlive the task.\n setTimeout(() => {\n if (!sessionOpen && activated === target) activated = null;\n }, 0);\n },\n startSession: () => {\n sessionOpen = true;\n },\n endSession: () => {\n sessionOpen = false;\n activated = null;\n },\n focusRef: {\n get current() {\n // A focused element is the opener: the restore captures it (see ModalTrigger.focusRef),\n // unless it is a trigger element, which resolves like any trigger.\n const focused = getFocusedElement();\n if (focused) return attached.has(focused) ? getTriggerFocusTarget(focused) : null;\n // The trigger that opened the modal decides, also when it cannot take focus any more.\n if (activated?.isConnected) return getTriggerFocusTarget(activated);\n for (const element of attached) {\n if (!element.isConnected) continue;\n const target = getTriggerFocusTarget(element);\n if (target) return target;\n }\n return null;\n },\n },\n };\n}\n\n/**\n * The triggers of a modal root (`Dialog`, `Drawer`), overlays#9. Each `Dialog.Trigger`/\n * `Drawer.Trigger` attaches its element and activates it from its click handler through\n * {@link useModalTriggerPart}; the root passes `focusRef` to `useModalLayer` as its\n * `triggerRef` and scopes the activation to one open session with {@link useModalTriggerSession}.\n * Focus returns to the element that had focus when the modal opened; when nothing had focus, to\n * the trigger that opened it, else to the first mounted trigger. For a wrapper `<span>`, the\n * restore target is the element inside it that carries the state ARIA. Resolving when the ref is\n * read, not when it attaches, keeps a trigger that was disabled at mount (or whose content\n * changed) a valid target.\n */\nexport function useModalTrigger(): ModalTrigger {\n const [trigger] = React.useState(createModalTrigger);\n return trigger;\n}\n\n/** Returned by {@link useModalTriggerElement}. */\ninterface ModalTriggerElement {\n /**\n * Callback ref for the element one trigger renders (merge it with the consumer's ref): registers\n * it with the root's triggers and remembers it for `activate`. Stable.\n */\n attach: React.RefCallback<HTMLElement>;\n /**\n * Records this trigger as the one opening the modal: call it from the click handler, before\n * opening, with whatever the handler received. The element `attach` received wins, else the\n * event's `currentTarget`, so a render-prop child that calls `onClick()` without the event (or\n * with another value) is still recorded. Stable.\n */\n activate: (event?: unknown) => void;\n}\n\nfunction createModalTriggerElement(trigger: ModalTrigger): ModalTriggerElement {\n // The element this trigger rendered; a closure variable, not a React ref, so the click handler\n // that reads it can be passed around during render (C-HOOKS).\n let element: HTMLElement | null = null;\n return {\n attach: (node) => {\n if (!node) return undefined;\n element = node;\n const detach = trigger.attach(node);\n return () => {\n if (element === node) element = null;\n if (typeof detach === 'function') detach();\n };\n },\n activate: (event) => {\n const currentTarget =\n typeof event === 'object' && event !== null\n ? (event as { currentTarget?: unknown }).currentTarget\n : undefined;\n trigger.activate(element ?? currentTarget);\n },\n };\n}\n\n/**\n * One `Dialog.Trigger`/`Drawer.Trigger` of a modal root (overlays#9): attach `attach` to the\n * element the trigger renders and call `activate` from its click handler.\n */\nfunction useModalTriggerElement(trigger: ModalTrigger): ModalTriggerElement {\n return React.useMemo(() => createModalTriggerElement(trigger), [trigger]);\n}\n\n/** The props of a trigger or close part (`Dialog.Trigger`, `Drawer.Close`, …). */\nexport interface ModalPartProps<RenderProps> extends Omit<\n React.HTMLAttributes<HTMLElement>,\n 'children'\n> {\n /** A single element that receives the part's props, or a function that receives them. */\n children: React.ReactNode | ((props: RenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` carrying the click handler. */\n asChild?: boolean;\n /** Ref to the element the part renders. */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** What {@link useModalTriggerPart} reads from the modal root. */\nexport interface ModalTriggerState {\n open: boolean;\n /**\n * Asks the root to open or close (reason `trigger`): to open while it is closed, to close while\n * it is open.\n */\n requestOpen: ModalRequestOpen;\n trigger: ModalTrigger;\n /** The surface's id for `aria-controls` while the modal is open. */\n controlsId: string | undefined;\n /**\n * `'dialog'` renders `aria-haspopup=\"dialog\"`; `false` renders none (an inline drawer, whose\n * trigger shows and hides a panel in place).\n * @default 'dialog'\n */\n popup?: 'dialog' | false;\n}\n\n/**\n * Renders a `Dialog.Trigger`/`Drawer.Trigger`: its element gets `aria-haspopup=\"dialog\"` (none\n * with `popup: false`, an inline drawer's trigger), `aria-expanded`, `aria-controls` (while open;\n * these always win over the child's own), a click handler that opens and closes the root (reason\n * `trigger`, with the click event: a click while it is open asks it to close) and records the\n * trigger that opens it (for the focus return), and a ref that registers it with the root's\n * triggers. On a wrapper span (`asChild={false}`, the automatic fallback), the state ARIA goes to\n * the first element in the tab order inside it (`useTriggerElement`).\n *\n * @param modal The root's state, from its context.\n * @param props The part's props.\n * @param componentName The public name for development warnings, e.g. `'Dialog.Trigger'`.\n */\nexport function useModalTriggerPart<RenderProps>(\n modal: ModalTriggerState,\n { children, asChild, ref, ...rest }: ModalPartProps<RenderProps>,\n componentName: string,\n): React.ReactNode {\n const { open, requestOpen, trigger, controlsId, popup = 'dialog' } = modal;\n const { attach, activate } = useModalTriggerElement(trigger);\n const mergedRef = useMergedRefs<HTMLElement>(attach, ref);\n const toggleModal = React.useCallback(\n (event?: React.MouseEvent<HTMLElement>) => {\n // A click that bubbled through the React tree from a portal opened inside the trigger (a\n // Popover in a wrapper span) is not a click on it (C-COMPOSE).\n if (isPortaledClick(event)) return;\n // Focus returns to this trigger, also when the root has several (overlays#9), and also when\n // a render-prop child calls `onClick()` without the event.\n if (!open) activate(event);\n requestOpen(!open, { reason: 'trigger', event: getNativeEvent(event) });\n },\n [open, activate, requestOpen],\n );\n\n // An inline drawer's trigger gets no `aria-haspopup` key at all, so a render-prop child that\n // spreads the props has none either.\n const stateAria = {\n ...(popup !== false && { 'aria-haspopup': popup }),\n 'aria-expanded': open,\n 'aria-controls': open ? controlsId : undefined,\n };\n const triggerProps = mergeProps({ ...stateAria, onClick: toggleModal, ref: mergedRef }, rest, {\n oursWin: STATE_ARIA,\n });\n\n return useTriggerElement(children, triggerProps as RenderProps, { componentName, asChild });\n}\n\n/**\n * Renders a `Dialog.Close`/`Drawer.Close`: composes a click handler that asks the root to close\n * (reason `close`, with the click event) onto its element (the child's own `onClick` runs first;\n * `preventDefault()` there keeps the modal open).\n *\n * @param requestOpen The root's request function, from its context.\n * @param props The part's props.\n * @param componentName The public name for development warnings, e.g. `'Dialog.Close'`.\n */\nexport function useModalClosePart<RenderProps>(\n requestOpen: ModalRequestOpen,\n { children, asChild, ref, ...rest }: ModalPartProps<RenderProps>,\n componentName: string,\n): React.ReactNode {\n const mergedRef = useMergedRefs<HTMLElement>(ref);\n const close = React.useCallback(\n (event?: React.MouseEvent<HTMLElement>) =>\n requestOpen(false, { reason: 'close', event: getNativeEvent(event) }),\n [requestOpen],\n );\n const closeProps = mergeProps({ onClick: close, ref: mergedRef }, rest);\n return useTriggerElement(children, closeProps as RenderProps, { componentName, asChild });\n}\n\n/** The element {@link useModalOpener} captured, while it is in the document. */\ninterface ModalOpener {\n /** Records the opener (or forgets it, `null`). */\n set: (element: HTMLElement | null) => void;\n /** The captured opener while it is in the document, else `null`. Read-only. */\n ref: React.RefObject<HTMLElement | null>;\n}\n\nfunction createModalOpener(): ModalOpener {\n let element: HTMLElement | null = null;\n return {\n set: (next) => {\n element = next;\n },\n ref: {\n get current() {\n return element?.isConnected ? element : null;\n },\n },\n };\n}\n\n/**\n * The element a non-modal surface takes its keyboard place after (`usePopoverTabOrder`'s\n * `anchorRef`). Pass the surface's open state as `enabled`, whatever its `modalType`, so a surface\n * that turns non-modal while open (focus already inside it) still knows its opener. It is\n * captured in the insertion phase of the commit in which `enabled` becomes true,\n * before focus moves in: `trigger.focusRef.current`, which with nothing focused is the activated\n * or first trigger's focus target and is `null` while an element other than `<body>` has focus\n * (`ModalTrigger.focusRef` rule 1; a focused `tabIndex={-1}` trigger wrapper span resolves as a\n * trigger), so a focused trigger, the button inside a trigger's span or a controlled surface's own\n * opener is taken by the next step: else the focused element when it is not `<body>` and not\n * inside `surface`, else `null`. Cleared when `enabled` becomes false. An opener removed from the\n * document since reads as `null`, so the surface keeps its portal's place (the end of the page).\n */\nexport function useModalOpener(\n enabled: boolean,\n trigger: ModalTrigger,\n surface: HTMLElement | null,\n): React.RefObject<HTMLElement | null> {\n const [opener] = React.useState(createModalOpener);\n const enabledRef = React.useRef(false);\n React.useInsertionEffect(() => {\n const wasEnabled = enabledRef.current;\n enabledRef.current = enabled;\n if (enabled === wasEnabled) return;\n if (!enabled) {\n opener.set(null);\n return;\n }\n const fromTrigger = trigger.focusRef.current;\n if (fromTrigger) {\n opener.set(fromTrigger);\n return;\n }\n const focused = getFocusedElement();\n opener.set(focused && !surface?.contains(focused) ? focused : null);\n });\n return opener.ref;\n}\n\n/**\n * Scopes a trigger's activation to one open session (overlays#9): when the modal opens, the\n * activated trigger joins the session; when it closes, the trigger is forgotten, so a later open\n * that no trigger started (a controlled modal opened by the parent) does not return focus to it.\n *\n * It updates the session in a layout effect, after the modal's focus restore has used the\n * activation: call it in the root component (whose effects run after its children's) and, when\n * that component also calls `useModalLayer`, after that call (a component's effects run in order).\n */\nexport function useModalTriggerSession(trigger: ModalTrigger, open: boolean): void {\n React.useLayoutEffect(() => {\n if (open) trigger.startSession();\n else trigger.endSession();\n }, [trigger, open]);\n}\n\n/**\n * Moves a kept-mounted surface to the top of its stack when it opens (D104). A portal's z-index is\n * its layer plus its nesting depth, so at equal depth the wrapper later in the document paints\n * above: a surface kept mounted since before another overlay opened (a confirm Dialog rendered\n * next to a Drawer) would open under it. In the commit in which `open` becomes `true`, a layout\n * effect moves the portal wrapper to the end of its container when it is not the container's last\n * element child (`container.appendChild(wrapper)`). The closed content is hidden, so the move loses\n * no visible state, and React removes the wrapper from the same parent later. An unmounting surface\n * is appended when it opens already, so pass `keptMounted: false` for it: it is never moved.\n *\n * Call it before `useModalLayer` (a component's layout effects run in order), so the move happens\n * before the layer registers, before other modals re-plan their isolation and before the focus\n * trap moves focus in.\n *\n * @param open Whether the surface is open.\n * @param keptMounted `true` with `unmountOnClose={false}`.\n * @param wrapperRef The `Portal`'s `ref` (its wrapper element).\n */\nexport function useRaiseOnOpen(\n open: boolean,\n keptMounted: boolean,\n wrapperRef: React.RefObject<HTMLElement | null>,\n): void {\n // The open state of the previous commit: the move happens only in the opening commit, never\n // while the surface is open (a move would blur the element inside that has focus).\n const wasOpenRef = React.useRef(false);\n React.useLayoutEffect(() => {\n const wasOpen = wasOpenRef.current;\n wasOpenRef.current = open;\n if (!open || wasOpen || !keptMounted) return;\n const wrapper = wrapperRef.current;\n const container = wrapper?.parentElement;\n if (wrapper && container && container.lastElementChild !== wrapper) {\n container.appendChild(wrapper);\n }\n });\n}\n\n/**\n * Development check of a kept-mounted surface (D106): a popup opened inside it (a Popover, a Menu,\n * a nested Dialog) that is still open when the surface closes stays open over the page, because\n * the content that would unmount it stays mounted. After each close of a kept-mounted surface it\n * schedules one check in a new task (`setTimeout(0)`, so a popup that the closing press itself\n * dismisses does not count) and warns once (`<componentName>:open-inside`) when an open layer\n * other than a tooltip descends from the surface's layer (`isDescendantLayer` follows the popup's\n * `parentId`, also after the surface's own layer unregistered) or has its anchor inside\n * `surfaceRef`'s element (an inline drawer, which registers no layer of its own, so a popup\n * opened inside it descends from no layer of the surface). Nothing runs with the default\n * `unmountOnClose`, where the popups unmount with the content, or in production.\n *\n * @param open Whether the surface is open.\n * @param keptMounted `true` with `unmountOnClose={false}`.\n * @param layerId The surface's dismiss layer (`useModalLayer`'s `layerId`).\n * @param componentName The public name for the warning key and text: `'Dialog'`, `'Drawer'`.\n * @param surfaceRef The surface element, for the anchor check (optional).\n */\nexport function useOpenInsideWarning(\n open: boolean,\n keptMounted: boolean,\n layerId: string,\n componentName: string,\n surfaceRef?: React.RefObject<HTMLElement | null>,\n): void {\n const wasOpenRef = React.useRef(open);\n React.useEffect(() => {\n const wasOpen = wasOpenRef.current;\n wasOpenRef.current = open;\n if (!isDev || open || !wasOpen || !keptMounted) return undefined;\n const timer = setTimeout(() => {\n const surface = surfaceRef?.current ?? null;\n const leftOpen = getOpenLayers().some((layer) => {\n if (layer.kind === 'tooltip') return false;\n if (isDescendantLayer(layer.id, layerId)) return true;\n const anchor = layer.getAnchor();\n return !!surface && !!anchor && surface.contains(anchor);\n });\n if (!leftOpen) return;\n warnOnce(\n `${componentName}:open-inside`,\n `${componentName} closed while a popup opened inside it is still open. With \\`unmountOnClose={false}\\` the popup stays open over the page: close it first, or keep the default \\`unmountOnClose\\`.`,\n );\n }, 0);\n return () => clearTimeout(timer);\n }, [open, keptMounted, layerId, componentName, surfaceRef]);\n}\n\n/**\n * C-CONTEXT: reads a compound component's context. Outside its root it throws\n * `[WaveUI] <componentName> must be used within <parentName>` in development, and in production\n * logs the same message once per page (`reportMissingContext`) and returns the inert value from\n * `getInert`.\n */\nexport function useRequiredContext<T>(\n context: React.Context<T | null>,\n componentName: string,\n parentName: string,\n getInert: () => T,\n): T {\n const value = React.useContext(context);\n if (value !== null) return value;\n reportMissingContext(componentName, parentName);\n return getInert();\n}\n\n/** What a modal surface (`Dialog.Content`, the Drawer panel) provides to its descendants. */\nexport interface ModalSurfaceContextValue {\n /**\n * Registers the id of a title element (`Dialog.Title`, `Drawer.Title`) for the surface's\n * `aria-labelledby`. Returns the unregister function.\n */\n registerTitle: (id: string) => () => void;\n /**\n * Receives the measured border-box height of the surface's sticky footer (`Dialog.Footer`) in\n * px, or `null` once it unmounts; the surface reserves it as the scroll padding of its body.\n * Absent on a surface without a footer part (the Drawer panel).\n */\n setFooterHeight?: (px: number | null) => void;\n /**\n * The element `Dialog.Title` actions portal into: the outlet in `Dialog.Content`'s title-actions\n * area, `null` until it is attached. Absent outside `Dialog.Content` (the Drawer panel), where a\n * title renders its action right after its heading.\n */\n titleActionsOutlet?: HTMLElement | null;\n}\n\n/**\n * Provided by every modal surface; `null` outside one. Titles register with it, and\n * `Dialog.Footer` reads it to report its height and to warn when it is rendered outside\n * `Dialog.Content`.\n */\nexport const ModalSurfaceContext = React.createContext<ModalSurfaceContextValue | null>(null);\nModalSurfaceContext.displayName = 'ModalSurfaceContext';\n\nconst inertSurface: ModalSurfaceContextValue = { registerTitle: () => () => {} };\n\n/** Returned by {@link useTitleRegistry}. */\nexport interface TitleRegistry {\n /** The id of the first registered title, for `aria-labelledby`. */\n titleId: string | undefined;\n /** Whether a title is registered right now. Read it in effects and handlers, not during render. */\n hasTitle: () => boolean;\n /** The memoised value for `ModalSurfaceContext.Provider`. */\n context: ModalSurfaceContextValue;\n}\n\n/**\n * The title registry of a modal surface. A title registers its id from its ref callback (when its\n * element attaches), so the surface's `aria-labelledby` follows the title elements that are\n * actually rendered.\n */\nexport function useTitleRegistry(): TitleRegistry {\n const [ids, setIds] = React.useState<readonly string[]>([]);\n const countRef = React.useRef(0);\n\n const registerTitle = React.useCallback((id: string) => {\n countRef.current += 1;\n setIds((current) => [...current, id]);\n let registered = true;\n return () => {\n if (!registered) return;\n registered = false;\n countRef.current -= 1;\n setIds((current) => {\n const index = current.indexOf(id);\n return index === -1 ? current : [...current.slice(0, index), ...current.slice(index + 1)];\n });\n };\n }, []);\n\n const hasTitle = React.useCallback(() => countRef.current > 0, []);\n const context = React.useMemo(() => ({ registerTitle }), [registerTitle]);\n return { titleId: ids[0], hasTitle, context };\n}\n\n/**\n * The `id` and `ref` of a title sub-component (`Dialog.Title`, `Drawer.Title`): the consumer's\n * `id` (or a generated one), registered with the enclosing surface while the element is mounted.\n */\nexport function useModalTitle(\n componentName: string,\n parentName: string,\n idProp: string | undefined,\n ref: React.Ref<HTMLHeadingElement> | undefined,\n): { id: string; ref: React.RefCallback<HTMLHeadingElement> } {\n const { registerTitle } = useRequiredContext(\n ModalSurfaceContext,\n componentName,\n parentName,\n () => inertSurface,\n );\n const generatedId = useId('wave-modal-title');\n const id = idProp ?? generatedId;\n const register = React.useCallback(\n (node: HTMLHeadingElement | null) => (node ? registerTitle(id) : undefined),\n [registerTitle, id],\n );\n const mergedRef = useMergedRefs<HTMLHeadingElement>(ref, register);\n return { id, ref: mergedRef };\n}\n\n/**\n * Development warning (once per component) when an open modal surface has no accessible name:\n * no `title`, no registered title element, no `aria-label` and no `aria-labelledby`.\n *\n * @param surface The open surface element (`null` while closed).\n * @param hasTitle From {@link useTitleRegistry}.\n * @param componentName The public name, e.g. `'Dialog.Content'`.\n * @param titleName The title sub-component to recommend, e.g. `'Dialog.Title'`.\n */\nexport function useUnnamedModalWarning(\n surface: HTMLElement | null,\n hasTitle: () => boolean,\n componentName: string,\n titleName: string,\n): void {\n React.useEffect(() => {\n if (!surface) return;\n if (\n surface.hasAttribute('aria-label') ||\n surface.hasAttribute('aria-labelledby') ||\n hasTitle()\n ) {\n return;\n }\n warnOnce(\n `${componentName}:unnamed`,\n `${componentName} has no accessible name. Pass \\`title\\`, render a ${titleName} inside it, or give it \\`aria-label\\` or \\`aria-labelledby\\`.`,\n );\n }, [surface, hasTitle, componentName, titleName]);\n}\n"],"mappings":"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"}
|