@mortenbrudvik/waveui 0.11.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.
Files changed (116) hide show
  1. package/README.md +97 -2
  2. package/dist/components/button/Link.cjs +1 -1
  3. package/dist/components/button/Link.cjs.map +1 -1
  4. package/dist/components/button/Link.mjs +4 -4
  5. package/dist/components/data-display/AvatarGroup.cjs +1 -1
  6. package/dist/components/data-display/AvatarGroup.cjs.map +1 -1
  7. package/dist/components/data-display/AvatarGroup.mjs +10 -10
  8. package/dist/components/data-display/InfoButton.cjs +1 -1
  9. package/dist/components/data-display/InfoButton.cjs.map +1 -1
  10. package/dist/components/data-display/InfoButton.mjs +12 -12
  11. package/dist/components/feedback/Toaster.cjs +1 -1
  12. package/dist/components/feedback/Toaster.cjs.map +1 -1
  13. package/dist/components/feedback/Toaster.mjs +235 -235
  14. package/dist/components/feedback/Toaster.mjs.map +1 -1
  15. package/dist/components/input/Combobox.cjs +1 -1
  16. package/dist/components/input/Combobox.cjs.map +1 -1
  17. package/dist/components/input/Combobox.mjs +176 -175
  18. package/dist/components/input/Combobox.mjs.map +1 -1
  19. package/dist/components/input/DatePicker.cjs +1 -1
  20. package/dist/components/input/DatePicker.cjs.map +1 -1
  21. package/dist/components/input/DatePicker.mjs +188 -187
  22. package/dist/components/input/DatePicker.mjs.map +1 -1
  23. package/dist/components/input/Dropdown.cjs +1 -1
  24. package/dist/components/input/Dropdown.cjs.map +1 -1
  25. package/dist/components/input/Dropdown.mjs +41 -40
  26. package/dist/components/input/Dropdown.mjs.map +1 -1
  27. package/dist/components/input/Option.cjs +1 -1
  28. package/dist/components/input/Option.cjs.map +1 -1
  29. package/dist/components/input/Option.mjs +89 -87
  30. package/dist/components/input/Option.mjs.map +1 -1
  31. package/dist/components/input/TagPicker.root.cjs +1 -1
  32. package/dist/components/input/TagPicker.root.cjs.map +1 -1
  33. package/dist/components/input/TagPicker.root.mjs +136 -135
  34. package/dist/components/input/TagPicker.root.mjs.map +1 -1
  35. package/dist/components/input/TimePicker.cjs +1 -1
  36. package/dist/components/input/TimePicker.cjs.map +1 -1
  37. package/dist/components/input/TimePicker.mjs +156 -154
  38. package/dist/components/input/TimePicker.mjs.map +1 -1
  39. package/dist/components/navigation/Menu.popover.cjs +1 -1
  40. package/dist/components/navigation/Menu.popover.cjs.map +1 -1
  41. package/dist/components/navigation/Menu.popover.mjs +137 -127
  42. package/dist/components/navigation/Menu.popover.mjs.map +1 -1
  43. package/dist/components/navigation/Menu.root.cjs +1 -1
  44. package/dist/components/navigation/Menu.root.cjs.map +1 -1
  45. package/dist/components/navigation/Menu.root.mjs +4 -4
  46. package/dist/components/overlays/Dialog.cjs +1 -1
  47. package/dist/components/overlays/Dialog.cjs.map +1 -1
  48. package/dist/components/overlays/Dialog.mjs +123 -123
  49. package/dist/components/overlays/Dialog.mjs.map +1 -1
  50. package/dist/components/overlays/Drawer.panel.cjs +1 -1
  51. package/dist/components/overlays/Drawer.panel.cjs.map +1 -1
  52. package/dist/components/overlays/Drawer.panel.mjs +12 -12
  53. package/dist/components/overlays/Drawer.panel.mjs.map +1 -1
  54. package/dist/components/overlays/Popover.cjs +1 -1
  55. package/dist/components/overlays/Popover.cjs.map +1 -1
  56. package/dist/components/overlays/Popover.mjs +173 -162
  57. package/dist/components/overlays/Popover.mjs.map +1 -1
  58. package/dist/components/overlays/TeachingPopover.cjs +1 -1
  59. package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
  60. package/dist/components/overlays/TeachingPopover.mjs +96 -91
  61. package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
  62. package/dist/components/overlays/Tooltip.cjs +1 -1
  63. package/dist/components/overlays/Tooltip.cjs.map +1 -1
  64. package/dist/components/overlays/Tooltip.mjs +47 -47
  65. package/dist/components/overlays/Tooltip.mjs.map +1 -1
  66. package/dist/components/portal/Portal.cjs +1 -1
  67. package/dist/components/portal/Portal.cjs.map +1 -1
  68. package/dist/components/portal/Portal.mjs +5 -5
  69. package/dist/components/table/DataGrid.cjs +1 -1
  70. package/dist/components/table/DataGrid.cjs.map +1 -1
  71. package/dist/components/table/DataGrid.mjs +1 -1
  72. package/dist/hooks/useDismiss.cjs.map +1 -1
  73. package/dist/hooks/useDismiss.mjs.map +1 -1
  74. package/dist/hooks/useFocusTrap.cjs.map +1 -1
  75. package/dist/hooks/useFocusTrap.mjs.map +1 -1
  76. package/dist/hooks/useFocusVisible.cjs +2 -0
  77. package/dist/hooks/useFocusVisible.cjs.map +1 -0
  78. package/dist/hooks/useFocusVisible.mjs +49 -0
  79. package/dist/hooks/useFocusVisible.mjs.map +1 -0
  80. package/dist/hooks/useFocusableGroup.cjs +2 -0
  81. package/dist/hooks/useFocusableGroup.cjs.map +1 -0
  82. package/dist/hooks/useFocusableGroup.mjs +70 -0
  83. package/dist/hooks/useFocusableGroup.mjs.map +1 -0
  84. package/dist/hooks/useModalLayer.cjs +1 -1
  85. package/dist/hooks/useModalLayer.cjs.map +1 -1
  86. package/dist/hooks/useModalLayer.mjs +4 -4
  87. package/dist/hooks/useModalOpen.cjs +2 -0
  88. package/dist/hooks/useModalOpen.cjs.map +1 -0
  89. package/dist/hooks/useModalOpen.mjs +14 -0
  90. package/dist/hooks/useModalOpen.mjs.map +1 -0
  91. package/dist/hooks/usePopupPosition.cjs +1 -1
  92. package/dist/hooks/usePopupPosition.cjs.map +1 -1
  93. package/dist/hooks/usePopupPosition.mjs +82 -53
  94. package/dist/hooks/usePopupPosition.mjs.map +1 -1
  95. package/dist/hooks/useResolvedTarget.cjs +2 -0
  96. package/dist/hooks/useResolvedTarget.cjs.map +1 -0
  97. package/dist/hooks/useResolvedTarget.mjs +37 -0
  98. package/dist/hooks/useResolvedTarget.mjs.map +1 -0
  99. package/dist/hooks/useRovingGrid.cjs +1 -1
  100. package/dist/hooks/useRovingGrid.cjs.map +1 -1
  101. package/dist/hooks/useRovingGrid.mjs +8 -57
  102. package/dist/hooks/useRovingGrid.mjs.map +1 -1
  103. package/dist/hooks/useRovingTabIndex.cjs +1 -1
  104. package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
  105. package/dist/hooks/useRovingTabIndex.mjs +142 -107
  106. package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
  107. package/dist/index.cjs +1 -1
  108. package/dist/index.d.cts +814 -18
  109. package/dist/index.d.ts +814 -18
  110. package/dist/index.mjs +120 -108
  111. package/dist/lib/layers.cjs +1 -1
  112. package/dist/lib/layers.cjs.map +1 -1
  113. package/dist/lib/layers.mjs +112 -109
  114. package/dist/lib/layers.mjs.map +1 -1
  115. package/dist/styles.css +1 -1
  116. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.root.cjs","names":["flattenChildren","isElementOfType","MenuTrigger","MenuPopover","useMenuListContext","React","PortalDepthContext","useControllable","useIsClient","useId","useCheckedValues","useEventCallback","withCheckedValuesListener","getLayerTreeElements","useHoverIntent","useContextMenuAnchor","useRovingTabIndex","MENU_ITEM_SELECTOR","useMergedRefs","getFirstTabbable","useCheckableRegistry","useMenuListPointer","MenuContext","MenuListContext","composeEventHandlers","withTypeaheadText","cn","menuClassNames","menuSurfaceClasses","focusRing","require_runtime","require_cn","require_children","require_dev","require_composeEventHandlers","require_classNames","require_useEventCallback","require_useControllable","require_useId","require_focus","require_useRovingTabIndex","require_useMergedRefs","require_useIsClient","require_layers","require_Portal","require_styles","require_useCheckedValues","require_useHoverIntent","require_Menu_context","require_Menu_shared","require_Menu_popover","require_useContextMenuAnchor","require_Menu_trigger","react","react_jsx_runtime","noop","HOVER_DELAY_MS","hasPopupParts","children","node","listProps","quoted","names","name","MenuRoot","openProp","persistOnItemClickProp","openOnHoverProp","openDelayProp","closeDelayProp","openOnContextProp","rest","list","portalDepth","parentList","parent","isSubmenu","openState","setOpen","openControlled","defaultOpen","onOpenChange","isClient","parentOpen","open","popup","triggerId","menuId","labelledBy","setLabelledBy","triggerRef","triggerElement","setTriggerElementState","setTriggerElement","element","surfaceApiRef","surfaceElement","setSurfaceElement","surfaceLayerId","setSurfaceLayerId","registerSurface","api","ownChecked","checkedValues","defaultCheckedValues","onCheckedValuesChange","parentChecked","ownsCheckedState","listens","listener","sharedChecked","checked","persistOnItemClick","openDelay","closeDelay","contextMode","hoverMode","ignoredProps","className","onKeyDown","onKeyDownCapture","onFocus","onPointerMove","value","ref","ignoredMessage","staticPopupProps","hoverAndContext","verb","pronoun","staticMenuRef","openSubmenuRef","containsFocus","surfaceApi","active","el","listContainsFocus","hoverCloseRef","isHoverClose","closeMenu","byHover","requestClose","requestHoverClose","openReasonRef","hoverOpenPendingRef","initialFocusRef","isHoverOpen","hoverIntentTriggerHandlers","hoverSurfaceHandlers","cancelHover","startHoverClose","forgetHoverOpening","hoverTriggerHandlers","event","openWithFocus","target","takeInitialFocus","contextAnchor","contextOpener","contextTriggerHandlers","contextSurfaceHandlers","parentListHoverFocusing","parentHoverFocusing","isHoverFocusing","contextPressRef","doc","onPointerDown","onPointerEnd","dismiss","reason","registerOpenSubmenu","previous","submenu","submenuHandle","registerWithParent","parentCloseChain","closeChain","contextValue","fromContext","rovingRef","rovingKeyDown","rovingKeyDownCapture","rovingFocus","mergedRef","menuIsTabStop","setMenuIsTabStop","menu","noItemTabStop","focusFirst","getTabIndex","registerCheckable","isListHoverFocusing","listPointerMove","listContext","hoverGroup"],"sources":["../../../src/components/navigation/Menu.root.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { menuClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { flattenChildren, isElementOfType } from '../../lib/children';\nimport { getFirstTabbable } from '../../lib/focus';\nimport { getLayerTreeElements, type DismissReason } from '../../lib/layers';\nimport { focusRing } from '../../lib/styles';\nimport type { CheckedValues, CheckedValuesChangeHandler } from '../../lib/types';\nimport { useCheckedValues, withCheckedValuesListener } from '../../hooks/useCheckedValues';\nimport { useContextMenuAnchor } from '../../hooks/useContextMenuAnchor';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useHoverIntent, type HoverIntent } from '../../hooks/useHoverIntent';\nimport { useId } from '../../hooks/useId';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport { PortalDepthContext } from '../portal/Portal';\nimport {\n MenuContext,\n MenuListContext,\n useCheckableRegistry,\n useMenuListContext,\n} from './Menu.context';\nimport type {\n InitialFocus,\n MenuContextValue,\n MenuListContextValue,\n MenuSurfaceApi,\n OpenSubmenu,\n} from './Menu.context';\nimport { MENU_ITEM_SELECTOR, menuSurfaceClasses, withTypeaheadText } from './Menu.shared';\nimport { MenuPopover, useMenuListPointer } from './Menu.popover';\nimport { MenuTrigger } from './Menu.trigger';\n\n/** Properties for the Menu component. */\nexport interface MenuProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Menu items and dividers (static menu), or a `Menu.Trigger` and a `Menu.Popover` (popup menu).\n */\n children: React.ReactNode;\n /**\n * Controlled open state of a popup menu (`Menu.Trigger` + `Menu.Popover`). Passing it, even\n * `false` (like passing `defaultOpen` or `onOpenChange`), makes Menu a popup menu that renders no\n * element of its own: use it only with `Menu.Trigger`/`Menu.Popover`. Items outside\n * `Menu.Popover` then have no `role=\"menu\"` parent (development warning). Leave all three out\n * for a static menu. The popup renders only in the browser: an open menu is closed in the\n * server HTML and opens once it has hydrated.\n */\n open?: boolean;\n /**\n * Initial open state of an uncontrolled popup menu; a popup menu starts closed without it.\n * Passing it, even `false`, makes Menu a popup menu (see `open`), so for a Menu without\n * `Menu.Trigger`/`Menu.Popover` children, leaving it out is not the same as `false`. The popup\n * renders only in the browser: a menu open by default is closed in the server HTML and opens\n * once it has hydrated.\n */\n defaultOpen?: boolean;\n /**\n * Called with the next open state when the popup menu opens or closes (only on change). Passing\n * it makes Menu a popup menu (see `open`).\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * Checked items of the menu's checkbox, radio and switch items, per group `name` (controlled).\n * A submenu without its own `checkedValues` or `defaultCheckedValues` shares its parent menu's\n * state. Works for static and popup menus; unlike `open`, it does not make Menu a popup menu.\n */\n checkedValues?: CheckedValues;\n /** Initial checked items for uncontrolled usage (gives a submenu its own state). @default {} */\n defaultCheckedValues?: CheckedValues;\n /**\n * Called when an item changes the checked items (only on change): the new checked values of every\n * group first, then `details` with the group's `name`, its `checkedItems` and the `event` (Fluent's\n * `onCheckedValueChange(event, { name, checkedItems })`). WaveUI always passes `details`; it is\n * typed optional until 1.0. On a submenu that shares its parent's state it only listens: it is\n * called after the parent's callback, for changes made in this submenu.\n */\n onCheckedValuesChange?: CheckedValuesChangeHandler;\n /**\n * Keep a popup menu open after any of its items is activated; an item's own `persistOnClick`\n * wins. A submenu inherits it unless it sets it.\n * @default false\n */\n persistOnItemClick?: boolean;\n /**\n * Open the popup menu when a mouse pointer rests on its trigger, and close it once the pointer\n * has been off the trigger and the menu for `closeDelay` while focus is not inside the menu. A\n * menu opened by hover does not take focus; a click (or Enter, Space, ArrowDown) on its trigger\n * keeps it open and moves focus into it, as opening it that way does. After Escape or an\n * outside press it does not reopen until the pointer has left the trigger. Touch and pen never\n * open it by hover, and an `aria-disabled` trigger never opens. A triangle between the trigger\n * and the menu keeps it open while the pointer moves diagonally into it. Ignored with\n * `openOnContext` (development warning) and on a static menu (development warning).\n * @default false (true for a submenu)\n */\n openOnHover?: boolean;\n /**\n * Milliseconds a hovering mouse pointer rests on the trigger before the menu opens (mouse hover\n * only). A submenu inherits its parent's, also from a static menu. @default 250\n */\n openDelay?: number;\n /**\n * Milliseconds before a hover-opened menu closes once the mouse pointer has left it and its\n * trigger (mouse hover only). A submenu inherits its parent's, also from a static menu.\n * @default 250\n */\n closeDelay?: number;\n /**\n * Make `Menu.Trigger` a context-menu region: a right click (a Ctrl+click on macOS, a long press\n * where the browser reports one) opens the menu at the pointer, and Shift+F10 or the\n * ContextMenu key opens it at the focused element inside the region, instead of a click; a\n * second gesture while it is open moves it there. Focus returns to the element that had it.\n * The browser's context menu is suppressed there and inside the menu, except in text fields\n * inside the region, which keep it. A press elsewhere, a right click outside or a scroll that\n * moves the region or the row of the gesture (the one under the pointer, or the focused one)\n * closes it. The trigger gets no `aria-haspopup`/`aria-expanded` (it is not a menu button; with\n * a render-prop child, do not spread them): name the menu with `aria-label` on `Menu.Popover`,\n * and consider `aria-keyshortcuts=\"Shift+F10\"` on the region. iOS Safari reports no long press.\n * Ignored on a submenu; `openOnHover` is ignored with it.\n * @default false\n */\n openOnContext?: boolean;\n /**\n * Ref to the static menu element (`role=\"menu\"`). A popup menu renders no root element, so it\n * ignores `ref`, `className` and other DOM props (development warning): pass them to\n * `Menu.Popover`.\n */\n ref?: React.Ref<HTMLDivElement>;\n}\n\nconst noop = () => {};\n\n/** Default of `openDelay` and `closeDelay` (InfoLabel's hover delays). */\nconst HOVER_DELAY_MS = 250;\n\n/**\n * Whether the children contain a `Menu.Trigger` or `Menu.Popover`: direct children and the\n * children of Fragments only (other elements and components are not searched). Parts written in\n * a Server Component (lazy client references) are recognised too.\n */\nexport function hasPopupParts(children: React.ReactNode): boolean {\n return flattenChildren(children).some(({ node }) =>\n isElementOfType(node, MenuTrigger, MenuPopover),\n );\n}\n\n/** Joins prop names for a message: `a`, `` `a` and `b` ``. */\nfunction listProps(names: string[]): string {\n const quoted = names.map((name) => `\\`${name}\\``);\n return quoted.length > 1\n ? `${quoted.slice(0, -1).join(', ')} and ${quoted[quoted.length - 1]}`\n : quoted.join('');\n}\n\n// The root of the `Menu` compound. Its component JSDoc is on the `Menu` export (Menu.tsx) only\n// (C-DOCS): a docblock here would replace it as the Storybook description.\nexport const MenuRoot = ({\n children,\n open: openProp,\n defaultOpen,\n onOpenChange,\n checkedValues,\n defaultCheckedValues,\n onCheckedValuesChange,\n persistOnItemClick: persistOnItemClickProp,\n openOnHover: openOnHoverProp,\n openDelay: openDelayProp,\n closeDelay: closeDelayProp,\n openOnContext: openOnContextProp,\n className,\n onKeyDown,\n onKeyDownCapture,\n onFocus,\n onPointerMove,\n ref,\n ...rest\n}: MenuProps) => {\n // A Menu rendered in a menu list with no portal between them is a submenu of that list's menu.\n // A Menu inside a Popover or Dialog opened from an item sits one portal deeper: a root menu.\n const list = useMenuListContext();\n const portalDepth = React.useContext(PortalDepthContext);\n const parentList = list !== null && list.portalDepth === portalDepth ? list : null;\n const parent = parentList?.menu ?? null;\n const isSubmenu = parent !== null;\n\n const [openState, setOpen, openControlled] = useControllable(\n openProp,\n defaultOpen ?? false,\n onOpenChange,\n );\n // The popup menu lives in a portal, which renders only in the browser: until then (the server\n // HTML, hydration) the menu reports itself closed, so the trigger's aria-expanded and\n // aria-controls never describe a menu that is not there. A submenu of a popup menu is open only\n // while that menu is: a parent that closes (through its controlled prop, or while it runs an\n // exit motion) takes the submenu's surface, layer and focus restore along in the same commit.\n const isClient = useIsClient();\n const parentOpen = parent === null || !parent.popup || parent.open;\n const open = openState && isClient && parentOpen;\n // A parent that closed without closing this submenu (its controlled `open` prop): an\n // uncontrolled submenu closes too, so it does not reopen with the parent. A controlled\n // submenu's state is the app's.\n React.useLayoutEffect(() => {\n if (parentOpen || !openState || openControlled) return;\n setOpen(false);\n }, [parentOpen, openState, openControlled, setOpen]);\n\n const popup =\n openProp !== undefined ||\n defaultOpen !== undefined ||\n onOpenChange !== undefined ||\n hasPopupParts(children);\n\n const triggerId = useId('wave-menu-trigger');\n const menuId = useId('wave-menu');\n const [labelledBy, setLabelledBy] = React.useState(triggerId);\n const triggerRef = React.useRef<HTMLElement | null>(null);\n const [triggerElement, setTriggerElementState] = React.useState<HTMLElement | null>(null);\n const setTriggerElement = React.useCallback((element: HTMLElement | null) => {\n triggerRef.current = element;\n setTriggerElementState(element);\n }, []);\n\n // The open surface: its API in a ref (read in events), its element and layer in state (the\n // hover and context-menu hooks observe them).\n const surfaceApiRef = React.useRef<MenuSurfaceApi | null>(null);\n const [surfaceElement, setSurfaceElement] = React.useState<HTMLElement | null>(null);\n const [surfaceLayerId, setSurfaceLayerId] = React.useState('');\n const registerSurface = React.useCallback((api: MenuSurfaceApi | null) => {\n surfaceApiRef.current = api;\n setSurfaceElement(api?.surface ?? null);\n // Kept after the surface closes: a context gesture records its opener against the last layer.\n if (api) setSurfaceLayerId(api.layerId);\n }, []);\n\n // Checked values: one state per menu tree. A Menu owns its state when it sets `checkedValues` or\n // `defaultCheckedValues`, or has no parent; otherwise it uses its parent's, and its own\n // `onCheckedValuesChange` only listens to the changes its items make (called after the owner's).\n const ownChecked = useCheckedValues(checkedValues, defaultCheckedValues, onCheckedValuesChange);\n const parentChecked = parent?.checked ?? null;\n const ownsCheckedState =\n parentChecked === null || checkedValues !== undefined || defaultCheckedValues !== undefined;\n const listens = onCheckedValuesChange !== undefined;\n const listener = useEventCallback(onCheckedValuesChange);\n const sharedChecked = React.useMemo(\n () =>\n parentChecked && listens ? withCheckedValuesListener(parentChecked, listener) : parentChecked,\n [parentChecked, listens, listener],\n );\n const checked = ownsCheckedState || sharedChecked === null ? ownChecked : sharedChecked;\n const persistOnItemClick = persistOnItemClickProp ?? parent?.persistOnItemClick ?? false;\n const openDelay = openDelayProp ?? parent?.openDelay ?? HOVER_DELAY_MS;\n const closeDelay = closeDelayProp ?? parent?.closeDelay ?? HOVER_DELAY_MS;\n\n // Context mode applies to a root popup menu; hover to a popup menu outside context mode.\n const contextMode = popup && !isSubmenu && openOnContextProp === true;\n const hoverMode = popup && !contextMode && (openOnHoverProp ?? isSubmenu);\n\n // C-DEV: a popup menu renders no root element, so root DOM props and the ref go nowhere.\n const ignoredProps: string[] = [];\n if (popup) {\n if (className !== undefined) ignoredProps.push('className');\n if (onKeyDown !== undefined) ignoredProps.push('onKeyDown');\n if (onKeyDownCapture !== undefined) ignoredProps.push('onKeyDownCapture');\n if (onFocus !== undefined) ignoredProps.push('onFocus');\n if (onPointerMove !== undefined) ignoredProps.push('onPointerMove');\n for (const [name, value] of Object.entries(rest)) {\n if (value !== undefined) ignoredProps.push(name);\n }\n if (ref != null) ignoredProps.push('ref');\n }\n const ignoredMessage =\n ignoredProps.length === 0\n ? ''\n : `Menu: a popup menu (Menu.Trigger + Menu.Popover) renders no element of its own, so ${ignoredProps\n .map((name) => `\\`${name}\\``)\n .join(', ')} on Menu ${ignoredProps.length === 1 ? 'is' : 'are'} ignored. Pass ${\n ignoredProps.length === 1 ? 'it' : 'them'\n } to Menu.Popover (the menu surface) or to the trigger's child instead.`;\n React.useEffect(() => {\n if (ignoredMessage) warnOnce('Menu:popup-ignored-props', ignoredMessage);\n }, [ignoredMessage]);\n\n // C-DEV: the popup openings do nothing on a static menu; hover gives way to context gestures.\n const staticPopupProps = popup\n ? ''\n : listProps(\n [openOnHoverProp ? 'openOnHover' : null, openOnContextProp ? 'openOnContext' : null].filter(\n (name): name is string => name !== null,\n ),\n );\n const hoverAndContext = contextMode && openOnHoverProp === true;\n React.useEffect(() => {\n if (!staticPopupProps) return;\n const [verb, pronoun] = staticPopupProps.includes(' and ') ? ['are', 'they'] : ['is', 'it'];\n warnOnce(\n 'Menu:static-popup-props',\n `Menu: ${staticPopupProps} ${verb} ignored on a static menu: ${pronoun} apply to a popup menu (Menu.Trigger + Menu.Popover). A static menu passes openDelay and closeDelay on to its submenus.`,\n );\n }, [staticPopupProps]);\n React.useEffect(() => {\n if (!hoverAndContext) return;\n warnOnce(\n 'Menu:hover-and-context',\n 'Menu: openOnHover is ignored with openOnContext: a context menu opens only from a context gesture (a right click, Shift+F10 or the ContextMenu key).',\n );\n }, [hoverAndContext]);\n\n const staticMenuRef = React.useRef<HTMLDivElement | null>(null);\n\n // The open submenu of this menu's list (one at a time) and what focus inside means for the chain.\n const openSubmenuRef = React.useRef<OpenSubmenu | null>(null);\n const containsFocus = useEventCallback((): boolean => {\n const surfaceApi = surfaceApiRef.current;\n const element = surfaceApi?.surface ?? staticMenuRef.current;\n const active = element?.ownerDocument.activeElement;\n if (!element || !active) return false;\n if (element.contains(active)) return true;\n // A popup menu's layer tree holds its submenus and the portals opened from its items; its own\n // elements (the trigger) do not count.\n if (surfaceApi) {\n return getLayerTreeElements(surfaceApi.layerId, { includeOwnElements: false }).some((el) =>\n el.contains(active),\n );\n }\n return openSubmenuRef.current?.containsFocus() ?? false;\n });\n // Focus in a list of the chain: this menu's list, else (recursively) its open submenu's. A\n // portal opened from an item does not count, so hover never takes focus from it.\n const listContainsFocus = useEventCallback((): boolean => {\n const element = surfaceApiRef.current?.surface ?? staticMenuRef.current;\n const active = element?.ownerDocument.activeElement;\n if (element && active && element.contains(active)) return true;\n return openSubmenuRef.current?.listContainsFocus() ?? false;\n });\n\n // Every close of this menu closes its open submenu first, innermost first, through the\n // submenu's own state: each controlled submenu hears onOpenChange(false) once. A close asked for\n // by the hover intent is marked (before the request, in case the app applies it synchronously),\n // so the surface's focus restore moves no focus; every other close request, and the next\n // opening, clears the mark. A submenu closed along with it is taken along by the restore itself.\n const hoverCloseRef = React.useRef(false);\n const isHoverClose = React.useCallback(() => hoverCloseRef.current, []);\n const closeMenu = (byHover: boolean) => {\n hoverCloseRef.current = byHover;\n openSubmenuRef.current?.close();\n setOpen(false);\n };\n const requestClose = useEventCallback(() => closeMenu(false));\n const requestHoverClose = useEventCallback(() => closeMenu(true));\n\n // Why the open menu is open: a hover opening stays unpinned (the hover close applies) until the\n // trigger is activated; every other opening (click, keys, context, a controlled `open`) pins it.\n const openReasonRef = React.useRef<'hover' | 'other'>('other');\n const hoverOpenPendingRef = React.useRef(false);\n const initialFocusRef = React.useRef<InitialFocus>('first');\n React.useLayoutEffect(() => {\n if (open) {\n openReasonRef.current = hoverOpenPendingRef.current ? 'hover' : 'other';\n hoverCloseRef.current = false;\n }\n hoverOpenPendingRef.current = false;\n }, [open]);\n const isHoverOpen = React.useCallback(() => openReasonRef.current === 'hover', []);\n\n const {\n triggerHandlers: hoverIntentTriggerHandlers,\n surfaceHandlers: hoverSurfaceHandlers,\n cancel: cancelHover,\n startClose: startHoverClose,\n } = useHoverIntent({\n enabled: hoverMode,\n open,\n openDelay,\n closeDelay,\n trigger: triggerElement,\n surface: surfaceElement,\n group: parentList?.hoverGroup,\n onOpen: () => {\n hoverOpenPendingRef.current = true;\n initialFocusRef.current = 'none';\n setOpen(true);\n },\n onClose: requestHoverClose,\n // Pinned, or focus inside the menu (not on its trigger): the hover close waits.\n canClose: () => openReasonRef.current === 'hover' && !containsFocus(),\n });\n\n // A hover opening stays pending until the menu opens, in a later render too (an app that\n // applies it in a transition). One the app has not applied when the pointer leaves the trigger\n // (a controlled menu whose app kept `open` false) is forgotten then, so a later opening by the\n // app is an ordinary one: it focuses the first item and is pinned.\n const forgetHoverOpening = useEventCallback(() => {\n if (open) return;\n hoverOpenPendingRef.current = false;\n if (initialFocusRef.current === 'none') initialFocusRef.current = 'first';\n });\n const hoverTriggerHandlers = React.useMemo<HoverIntent['triggerHandlers']>(\n () => ({\n ...hoverIntentTriggerHandlers,\n onPointerLeave: (event) => {\n hoverIntentTriggerHandlers.onPointerLeave(event);\n forgetHoverOpening();\n },\n }),\n [hoverIntentTriggerHandlers, forgetHoverOpening],\n );\n\n const openWithFocus = React.useCallback(\n (target: InitialFocus) => {\n // Any opening but hover pins the menu; an open, hover-opened menu is pinned and focused.\n openReasonRef.current = 'other';\n hoverOpenPendingRef.current = false;\n cancelHover();\n const surfaceApi = surfaceApiRef.current;\n if (surfaceApi) {\n if (target === 'last') surfaceApi.focusLast();\n else if (target === 'first') surfaceApi.focusFirst();\n return;\n }\n initialFocusRef.current = target;\n setOpen(true);\n },\n [setOpen, cancelHover],\n );\n const takeInitialFocus = React.useCallback((): InitialFocus => {\n const target = initialFocusRef.current;\n initialFocusRef.current = 'first';\n return target;\n }, []);\n\n // Context gestures on the trigger region: a context gesture opens the menu (focus on its first\n // item) at the pointer or the focused row; a right click outside or an anchor-moving scroll\n // closes it.\n const {\n anchor: contextAnchor,\n fromContext,\n opener: contextOpener,\n triggerHandlers: contextTriggerHandlers,\n surfaceHandlers: contextSurfaceHandlers,\n } = useContextMenuAnchor({\n enabled: contextMode,\n open,\n trigger: triggerElement,\n layerId: surfaceLayerId,\n onOpen: () => openWithFocus('first'),\n onClose: requestClose,\n });\n\n // Focus follows the mouse: a submenu that loses focus to an item the pointer is focusing in an\n // enclosing list becomes a hover-opened submenu and closes through the hover close. A submenu\n // with `openOnHover={false}` has no hover close, so it closes at once, as for a keyboard move.\n const parentListHoverFocusing = parentList?.isHoverFocusing;\n const parentHoverFocusing = parent?.isHoverFocusing;\n const isHoverFocusing = useEventCallback(\n (): boolean => (parentListHoverFocusing?.() ?? false) || (parentHoverFocusing?.() ?? false),\n );\n // A press in progress that can be a context gesture: the right button, a Ctrl+press (the macOS\n // context click) or a touch or pen press (a long press). Recorded at its pointerdown and\n // forgotten at its pointerup, while a context menu is open.\n const contextPressRef = React.useRef(false);\n React.useEffect(() => {\n if (!contextMode || !open || !triggerElement) return undefined;\n const doc = triggerElement.ownerDocument;\n const onPointerDown = (event: PointerEvent) => {\n contextPressRef.current =\n event.button === 2 ||\n (event.button === 0 &&\n (event.ctrlKey || event.pointerType === 'touch' || event.pointerType === 'pen'));\n };\n const onPointerEnd = () => {\n contextPressRef.current = false;\n };\n doc.addEventListener('pointerdown', onPointerDown, true);\n doc.addEventListener('pointerup', onPointerEnd, true);\n doc.addEventListener('pointercancel', onPointerEnd, true);\n return () => {\n doc.removeEventListener('pointerdown', onPointerDown, true);\n doc.removeEventListener('pointerup', onPointerEnd, true);\n doc.removeEventListener('pointercancel', onPointerEnd, true);\n contextPressRef.current = false;\n };\n }, [contextMode, open, triggerElement]);\n\n const dismiss = useEventCallback((reason: DismissReason, event: Event) => {\n // Focus that such a press moves into a context menu's region does not close the menu: a\n // right-button (or macOS Ctrl+) press focuses the row under the pointer before the contextmenu\n // event that moves the menu there (Chromium, Firefox). Any other focus move into the region (a\n // primary press, the app) closes it, as does an outside press and Tab (the surface's handler).\n if (\n reason === 'focus-outside' &&\n contextMode &&\n contextPressRef.current &&\n event.target instanceof Node &&\n triggerRef.current?.contains(event.target)\n ) {\n return;\n }\n if (reason === 'focus-outside' && isSubmenu && hoverMode && isHoverFocusing()) {\n openReasonRef.current = 'hover';\n startHoverClose(event);\n return;\n }\n requestClose();\n });\n\n const registerOpenSubmenu = React.useCallback((submenu: OpenSubmenu) => {\n const previous = openSubmenuRef.current;\n openSubmenuRef.current = submenu;\n // One open submenu per list: the one open before closes.\n if (previous && previous !== submenu) previous.close();\n return () => {\n if (openSubmenuRef.current === submenu) openSubmenuRef.current = null;\n };\n }, []);\n\n // A submenu registers with its parent while it is open.\n const submenuHandle = React.useMemo<OpenSubmenu>(\n () => ({ close: requestClose, containsFocus, listContainsFocus }),\n [requestClose, containsFocus, listContainsFocus],\n );\n const registerWithParent = parent?.registerOpenSubmenu;\n React.useLayoutEffect(() => {\n if (!open || !registerWithParent) return undefined;\n return registerWithParent(submenuHandle);\n }, [open, registerWithParent, submenuHandle]);\n\n // Item activation and Tab close the whole chain: a submenu of a popup menu hands the close up,\n // and the top menu (the root, or a submenu of a static menu) puts focus on its return target\n // first (focus before close: a Dialog an item opens returns focus there), then closes.\n const parentCloseChain = parent?.popup ? parent.closeChain : null;\n const closeChain = useEventCallback(() => {\n if (parentCloseChain) {\n parentCloseChain();\n return;\n }\n if (!popup) return;\n const target = surfaceApiRef.current?.getReturnFocus() ?? null;\n if (target) {\n const doc = target.ownerDocument;\n const active = doc.activeElement;\n const lost = !active || active === doc.body || active === doc.documentElement;\n if (lost || containsFocus()) target.focus({ preventScroll: true });\n }\n requestClose();\n });\n\n const contextValue = React.useMemo<MenuContextValue>(\n () => ({\n popup,\n open,\n setOpen,\n openWithFocus,\n takeInitialFocus,\n registerSurface,\n triggerId,\n labelledBy,\n onTriggerId: setLabelledBy,\n menuId,\n triggerRef,\n triggerElement,\n setTriggerElement,\n parent,\n checked,\n persistOnItemClick,\n isSubmenu,\n requestClose,\n closeChain,\n registerOpenSubmenu,\n listContainsFocus,\n openDelay,\n closeDelay,\n dismiss,\n isHoverFocusing,\n isHoverOpen,\n isHoverClose,\n hoverTriggerHandlers,\n hoverSurfaceHandlers,\n openOnContext: contextMode,\n contextTriggerHandlers,\n contextSurfaceHandlers,\n contextAnchor,\n fromContext,\n contextOpener,\n }),\n [\n popup,\n open,\n setOpen,\n openWithFocus,\n takeInitialFocus,\n registerSurface,\n triggerId,\n labelledBy,\n menuId,\n triggerElement,\n setTriggerElement,\n parent,\n checked,\n persistOnItemClick,\n isSubmenu,\n requestClose,\n closeChain,\n registerOpenSubmenu,\n listContainsFocus,\n openDelay,\n closeDelay,\n dismiss,\n isHoverFocusing,\n isHoverOpen,\n isHoverClose,\n hoverTriggerHandlers,\n hoverSurfaceHandlers,\n contextMode,\n contextTriggerHandlers,\n contextSurfaceHandlers,\n contextAnchor,\n fromContext,\n contextOpener,\n ],\n );\n\n // Static menu: roving tab stop over the items (the last focused one keeps it).\n const {\n containerProps: { ref: rovingRef },\n handleKeyDown: rovingKeyDown,\n handleKeyDownCapture: rovingKeyDownCapture,\n handleFocus: rovingFocus,\n focusFirst,\n getTabIndex,\n } = useRovingTabIndex({\n orientation: 'vertical',\n loop: true,\n typeahead: true,\n tabStop: 'last-focused',\n manageTabIndex: true,\n itemSelector: MENU_ITEM_SELECTOR,\n });\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, rovingRef, staticMenuRef);\n\n // Disabled items never hold the tab stop, so with no enabled item the static menu itself does:\n // Tab still reaches it and a screen reader announces it. Checked whenever the roving hook's tab\n // stop changes (`getTabIndex` changes with it: an item enabled, disabled, added or removed), and\n // after it is stamped (this effect runs after the hook's).\n const [menuIsTabStop, setMenuIsTabStop] = React.useState(false);\n React.useLayoutEffect(() => {\n const menu = staticMenuRef.current;\n if (popup || !menu) return;\n const noItemTabStop = getFirstTabbable(menu) === null;\n if (noItemTabStop === menuIsTabStop) return;\n setMenuIsTabStop(noItemTabStop);\n // An item became enabled while the menu itself had focus: focus moves on to it, rather than\n // staying on an element that is no longer focusable.\n if (!noItemTabStop && menu.ownerDocument.activeElement === menu) focusFirst();\n }, [popup, menuIsTabStop, focusFirst, getTabIndex]);\n\n // The static menu is a menu list: its items close nothing when activated, and the item under\n // the mouse takes focus while focus is inside the menu tree.\n const registerCheckable = useCheckableRegistry();\n const {\n hoverGroup,\n isHoverFocusing: isListHoverFocusing,\n onPointerMove: listPointerMove,\n } = useMenuListPointer(contextValue);\n const listContext = React.useMemo<MenuListContextValue>(\n () => ({\n menu: contextValue,\n isStatic: true,\n portalDepth,\n closeFromItem: noop,\n registerCheckable,\n hoverGroup,\n isHoverFocusing: isListHoverFocusing,\n }),\n [contextValue, portalDepth, registerCheckable, hoverGroup, isListHoverFocusing],\n );\n\n if (popup) {\n return <MenuContext.Provider value={contextValue}>{children}</MenuContext.Provider>;\n }\n\n return (\n <MenuContext.Provider value={contextValue}>\n <MenuListContext.Provider value={listContext}>\n <div\n role=\"menu\"\n {...rest}\n ref={mergedRef}\n tabIndex={rest.tabIndex ?? (menuIsTabStop ? 0 : undefined)}\n data-roving-container=\"\"\n onKeyDown={composeEventHandlers(onKeyDown, rovingKeyDown)}\n onKeyDownCapture={withTypeaheadText(\n composeEventHandlers(onKeyDownCapture, rovingKeyDownCapture),\n )}\n onFocus={composeEventHandlers(onFocus, rovingFocus, { checkDefaultPrevented: false })}\n onPointerMove={composeEventHandlers(onPointerMove, listPointerMove)}\n className={cn(menuClassNames.root, menuSurfaceClasses, focusRing, className)}\n >\n {children}\n </div>\n </MenuListContext.Provider>\n </MenuContext.Provider>\n );\n};\nMenuRoot.displayName = 'Menu';\n"],"mappings":"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"}
1
+ {"version":3,"file":"Menu.root.cjs","names":["flattenChildren","isElementOfType","MenuTrigger","MenuPopover","useMenuListContext","React","PortalDepthContext","useControllable","useIsClient","useId","useCheckedValues","useEventCallback","withCheckedValuesListener","getLayerTreeElements","useHoverIntent","useContextMenuAnchor","useRovingTabIndex","MENU_ITEM_SELECTOR","useMergedRefs","getFirstTabbable","useCheckableRegistry","useMenuListPointer","MenuContext","MenuListContext","composeEventHandlers","withTypeaheadText","cn","menuClassNames","menuSurfaceClasses","focusRing","require_runtime","require_cn","require_children","require_dev","require_composeEventHandlers","require_classNames","require_useEventCallback","require_useControllable","require_useId","require_focus","require_useRovingTabIndex","require_useMergedRefs","require_useIsClient","require_layers","require_styles","require_Portal","require_useCheckedValues","require_useHoverIntent","require_Menu_context","require_Menu_shared","require_Menu_popover","require_useContextMenuAnchor","require_Menu_trigger","react","react_jsx_runtime","noop","HOVER_DELAY_MS","hasPopupParts","children","node","listProps","quoted","names","name","MenuRoot","openProp","persistOnItemClickProp","openOnHoverProp","openDelayProp","closeDelayProp","openOnContextProp","rest","list","portalDepth","parentList","parent","isSubmenu","openState","setOpen","openControlled","defaultOpen","onOpenChange","isClient","parentOpen","open","popup","triggerId","menuId","labelledBy","setLabelledBy","triggerRef","triggerElement","setTriggerElementState","setTriggerElement","element","surfaceApiRef","surfaceElement","setSurfaceElement","surfaceLayerId","setSurfaceLayerId","registerSurface","api","ownChecked","checkedValues","defaultCheckedValues","onCheckedValuesChange","parentChecked","ownsCheckedState","listens","listener","sharedChecked","checked","persistOnItemClick","openDelay","closeDelay","contextMode","hoverMode","ignoredProps","className","onKeyDown","onKeyDownCapture","onFocus","onPointerMove","value","ref","ignoredMessage","staticPopupProps","hoverAndContext","verb","pronoun","staticMenuRef","openSubmenuRef","containsFocus","surfaceApi","active","el","listContainsFocus","hoverCloseRef","isHoverClose","closeMenu","byHover","requestClose","requestHoverClose","openReasonRef","hoverOpenPendingRef","initialFocusRef","isHoverOpen","hoverIntentTriggerHandlers","hoverSurfaceHandlers","cancelHover","startHoverClose","forgetHoverOpening","hoverTriggerHandlers","event","openWithFocus","target","takeInitialFocus","contextAnchor","contextOpener","contextTriggerHandlers","contextSurfaceHandlers","parentListHoverFocusing","parentHoverFocusing","isHoverFocusing","contextPressRef","doc","onPointerDown","onPointerEnd","dismiss","reason","registerOpenSubmenu","previous","submenu","submenuHandle","registerWithParent","parentCloseChain","closeChain","contextValue","fromContext","rovingRef","rovingKeyDown","rovingKeyDownCapture","rovingFocus","mergedRef","menuIsTabStop","setMenuIsTabStop","menu","noItemTabStop","focusFirst","getTabIndex","registerCheckable","isListHoverFocusing","listPointerMove","listContext","hoverGroup"],"sources":["../../../src/components/navigation/Menu.root.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { menuClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { flattenChildren, isElementOfType } from '../../lib/children';\nimport { getFirstTabbable } from '../../lib/focus';\nimport { getLayerTreeElements, type DismissReason } from '../../lib/layers';\nimport { focusRing } from '../../lib/styles';\nimport type { CheckedValues, CheckedValuesChangeHandler } from '../../lib/types';\nimport { useCheckedValues, withCheckedValuesListener } from '../../hooks/useCheckedValues';\nimport { useContextMenuAnchor } from '../../hooks/useContextMenuAnchor';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useHoverIntent, type HoverIntent } from '../../hooks/useHoverIntent';\nimport { useId } from '../../hooks/useId';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport { PortalDepthContext } from '../portal/Portal';\nimport {\n MenuContext,\n MenuListContext,\n useCheckableRegistry,\n useMenuListContext,\n} from './Menu.context';\nimport type {\n InitialFocus,\n MenuContextValue,\n MenuListContextValue,\n MenuSurfaceApi,\n OpenSubmenu,\n} from './Menu.context';\nimport { MENU_ITEM_SELECTOR, menuSurfaceClasses, withTypeaheadText } from './Menu.shared';\nimport { MenuPopover, useMenuListPointer } from './Menu.popover';\nimport { MenuTrigger } from './Menu.trigger';\n\n/** Properties for the Menu component. */\nexport interface MenuProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Menu items and dividers (static menu), or a `Menu.Trigger` and a `Menu.Popover` (popup menu).\n */\n children: React.ReactNode;\n /**\n * Controlled open state of a popup menu (`Menu.Trigger` + `Menu.Popover`). Passing it, even\n * `false` (like passing `defaultOpen` or `onOpenChange`), makes Menu a popup menu that renders no\n * element of its own: use it only with `Menu.Trigger`/`Menu.Popover`. Items outside\n * `Menu.Popover` then have no `role=\"menu\"` parent (development warning). Leave all three out\n * for a static menu. The popup renders only in the browser: an open menu is closed in the\n * server HTML and opens once it has hydrated.\n */\n open?: boolean;\n /**\n * Initial open state of an uncontrolled popup menu; a popup menu starts closed without it.\n * Passing it, even `false`, makes Menu a popup menu (see `open`), so for a Menu without\n * `Menu.Trigger`/`Menu.Popover` children, leaving it out is not the same as `false`. The popup\n * renders only in the browser: a menu open by default is closed in the server HTML and opens\n * once it has hydrated.\n */\n defaultOpen?: boolean;\n /**\n * Called with the next open state when the popup menu opens or closes (only on change). Passing\n * it makes Menu a popup menu (see `open`).\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * Checked items of the menu's checkbox, radio and switch items, per group `name` (controlled).\n * A submenu without its own `checkedValues` or `defaultCheckedValues` shares its parent menu's\n * state. Works for static and popup menus; unlike `open`, it does not make Menu a popup menu.\n */\n checkedValues?: CheckedValues;\n /** Initial checked items for uncontrolled usage (gives a submenu its own state). @default {} */\n defaultCheckedValues?: CheckedValues;\n /**\n * Called when an item changes the checked items (only on change): the new checked values of every\n * group first, then `details` with the group's `name`, its `checkedItems` and the `event` (Fluent's\n * `onCheckedValueChange(event, { name, checkedItems })`). WaveUI always passes `details`; it is\n * typed optional until 1.0. On a submenu that shares its parent's state it only listens: it is\n * called after the parent's callback, for changes made in this submenu.\n */\n onCheckedValuesChange?: CheckedValuesChangeHandler;\n /**\n * Keep a popup menu open after any of its items is activated; an item's own `persistOnClick`\n * wins. A submenu inherits it unless it sets it.\n * @default false\n */\n persistOnItemClick?: boolean;\n /**\n * Open the popup menu when a mouse pointer rests on its trigger, and close it once the pointer\n * has been off the trigger and the menu for `closeDelay` while focus is not inside the menu. A\n * menu opened by hover does not take focus; a click (or Enter, Space, ArrowDown) on its trigger\n * keeps it open and moves focus into it, as opening it that way does. After Escape or an\n * outside press it does not reopen until the pointer has left the trigger. Touch and pen never\n * open it by hover, and an `aria-disabled` trigger never opens. A triangle between the trigger\n * and the menu keeps it open while the pointer moves diagonally into it. Ignored with\n * `openOnContext` (development warning) and on a static menu (development warning).\n * @default false (true for a submenu)\n */\n openOnHover?: boolean;\n /**\n * Milliseconds a hovering mouse pointer rests on the trigger before the menu opens (mouse hover\n * only). A submenu inherits its parent's, also from a static menu. @default 250\n */\n openDelay?: number;\n /**\n * Milliseconds before a hover-opened menu closes once the mouse pointer has left it and its\n * trigger (mouse hover only). A submenu inherits its parent's, also from a static menu.\n * @default 250\n */\n closeDelay?: number;\n /**\n * Make `Menu.Trigger` a context-menu region: a right click (a Ctrl+click on macOS, a long press\n * where the browser reports one) opens the menu at the pointer, and Shift+F10 or the\n * ContextMenu key opens it at the focused element inside the region, instead of a click; a\n * second gesture while it is open moves it there. Focus returns to the element that had it.\n * The browser's context menu is suppressed there and inside the menu, except in text fields\n * inside the region, which keep it. A press elsewhere, a right click outside or a scroll that\n * moves the region or the row of the gesture (the one under the pointer, or the focused one)\n * closes it. The trigger gets no `aria-haspopup`/`aria-expanded` (it is not a menu button; with\n * a render-prop child, do not spread them): name the menu with `aria-label` on `Menu.Popover`,\n * and consider `aria-keyshortcuts=\"Shift+F10\"` on the region. iOS Safari reports no long press.\n * Ignored on a submenu; `openOnHover` is ignored with it.\n * @default false\n */\n openOnContext?: boolean;\n /**\n * Ref to the static menu element (`role=\"menu\"`). A popup menu renders no root element, so it\n * ignores `ref`, `className` and other DOM props (development warning): pass them to\n * `Menu.Popover`.\n */\n ref?: React.Ref<HTMLDivElement>;\n}\n\nconst noop = () => {};\n\n/** Default of `openDelay` and `closeDelay` (InfoLabel's hover delays). */\nconst HOVER_DELAY_MS = 250;\n\n/**\n * Whether the children contain a `Menu.Trigger` or `Menu.Popover`: direct children and the\n * children of Fragments only (other elements and components are not searched). Parts written in\n * a Server Component (lazy client references) are recognised too.\n */\nexport function hasPopupParts(children: React.ReactNode): boolean {\n return flattenChildren(children).some(({ node }) =>\n isElementOfType(node, MenuTrigger, MenuPopover),\n );\n}\n\n/** Joins prop names for a message: `a`, `` `a` and `b` ``. */\nfunction listProps(names: string[]): string {\n const quoted = names.map((name) => `\\`${name}\\``);\n return quoted.length > 1\n ? `${quoted.slice(0, -1).join(', ')} and ${quoted[quoted.length - 1]}`\n : quoted.join('');\n}\n\n// The root of the `Menu` compound. Its component JSDoc is on the `Menu` export (Menu.tsx) only\n// (C-DOCS): a docblock here would replace it as the Storybook description.\nexport const MenuRoot = ({\n children,\n open: openProp,\n defaultOpen,\n onOpenChange,\n checkedValues,\n defaultCheckedValues,\n onCheckedValuesChange,\n persistOnItemClick: persistOnItemClickProp,\n openOnHover: openOnHoverProp,\n openDelay: openDelayProp,\n closeDelay: closeDelayProp,\n openOnContext: openOnContextProp,\n className,\n onKeyDown,\n onKeyDownCapture,\n onFocus,\n onPointerMove,\n ref,\n ...rest\n}: MenuProps) => {\n // A Menu rendered in a menu list with no portal between them is a submenu of that list's menu.\n // A Menu inside a Popover or Dialog opened from an item sits one portal deeper: a root menu.\n const list = useMenuListContext();\n const portalDepth = React.useContext(PortalDepthContext);\n const parentList = list !== null && list.portalDepth === portalDepth ? list : null;\n const parent = parentList?.menu ?? null;\n const isSubmenu = parent !== null;\n\n const [openState, setOpen, openControlled] = useControllable(\n openProp,\n defaultOpen ?? false,\n onOpenChange,\n );\n // The popup menu lives in a portal, which renders only in the browser: until then (the server\n // HTML, hydration) the menu reports itself closed, so the trigger's aria-expanded and\n // aria-controls never describe a menu that is not there. A submenu of a popup menu is open only\n // while that menu is: a parent that closes (through its controlled prop, or while it runs an\n // exit motion) takes the submenu's surface, layer and focus restore along in the same commit.\n const isClient = useIsClient();\n const parentOpen = parent === null || !parent.popup || parent.open;\n const open = openState && isClient && parentOpen;\n // A parent that closed without closing this submenu (its controlled `open` prop): an\n // uncontrolled submenu closes too, so it does not reopen with the parent. A controlled\n // submenu's state is the app's.\n React.useLayoutEffect(() => {\n if (parentOpen || !openState || openControlled) return;\n setOpen(false);\n }, [parentOpen, openState, openControlled, setOpen]);\n\n const popup =\n openProp !== undefined ||\n defaultOpen !== undefined ||\n onOpenChange !== undefined ||\n hasPopupParts(children);\n\n const triggerId = useId('wave-menu-trigger');\n const menuId = useId('wave-menu');\n const [labelledBy, setLabelledBy] = React.useState(triggerId);\n const triggerRef = React.useRef<HTMLElement | null>(null);\n const [triggerElement, setTriggerElementState] = React.useState<HTMLElement | null>(null);\n const setTriggerElement = React.useCallback((element: HTMLElement | null) => {\n triggerRef.current = element;\n setTriggerElementState(element);\n }, []);\n\n // The open surface: its API in a ref (read in events), its element and layer in state (the\n // hover and context-menu hooks observe them).\n const surfaceApiRef = React.useRef<MenuSurfaceApi | null>(null);\n const [surfaceElement, setSurfaceElement] = React.useState<HTMLElement | null>(null);\n const [surfaceLayerId, setSurfaceLayerId] = React.useState('');\n const registerSurface = React.useCallback((api: MenuSurfaceApi | null) => {\n surfaceApiRef.current = api;\n setSurfaceElement(api?.surface ?? null);\n // Kept after the surface closes: a context gesture records its opener against the last layer.\n if (api) setSurfaceLayerId(api.layerId);\n }, []);\n\n // Checked values: one state per menu tree. A Menu owns its state when it sets `checkedValues` or\n // `defaultCheckedValues`, or has no parent; otherwise it uses its parent's, and its own\n // `onCheckedValuesChange` only listens to the changes its items make (called after the owner's).\n const ownChecked = useCheckedValues(checkedValues, defaultCheckedValues, onCheckedValuesChange);\n const parentChecked = parent?.checked ?? null;\n const ownsCheckedState =\n parentChecked === null || checkedValues !== undefined || defaultCheckedValues !== undefined;\n const listens = onCheckedValuesChange !== undefined;\n const listener = useEventCallback(onCheckedValuesChange);\n const sharedChecked = React.useMemo(\n () =>\n parentChecked && listens ? withCheckedValuesListener(parentChecked, listener) : parentChecked,\n [parentChecked, listens, listener],\n );\n const checked = ownsCheckedState || sharedChecked === null ? ownChecked : sharedChecked;\n const persistOnItemClick = persistOnItemClickProp ?? parent?.persistOnItemClick ?? false;\n const openDelay = openDelayProp ?? parent?.openDelay ?? HOVER_DELAY_MS;\n const closeDelay = closeDelayProp ?? parent?.closeDelay ?? HOVER_DELAY_MS;\n\n // Context mode applies to a root popup menu; hover to a popup menu outside context mode.\n const contextMode = popup && !isSubmenu && openOnContextProp === true;\n const hoverMode = popup && !contextMode && (openOnHoverProp ?? isSubmenu);\n\n // C-DEV: a popup menu renders no root element, so root DOM props and the ref go nowhere.\n const ignoredProps: string[] = [];\n if (popup) {\n if (className !== undefined) ignoredProps.push('className');\n if (onKeyDown !== undefined) ignoredProps.push('onKeyDown');\n if (onKeyDownCapture !== undefined) ignoredProps.push('onKeyDownCapture');\n if (onFocus !== undefined) ignoredProps.push('onFocus');\n if (onPointerMove !== undefined) ignoredProps.push('onPointerMove');\n for (const [name, value] of Object.entries(rest)) {\n if (value !== undefined) ignoredProps.push(name);\n }\n if (ref != null) ignoredProps.push('ref');\n }\n const ignoredMessage =\n ignoredProps.length === 0\n ? ''\n : `Menu: a popup menu (Menu.Trigger + Menu.Popover) renders no element of its own, so ${ignoredProps\n .map((name) => `\\`${name}\\``)\n .join(', ')} on Menu ${ignoredProps.length === 1 ? 'is' : 'are'} ignored. Pass ${\n ignoredProps.length === 1 ? 'it' : 'them'\n } to Menu.Popover (the menu surface) or to the trigger's child instead.`;\n React.useEffect(() => {\n if (ignoredMessage) warnOnce('Menu:popup-ignored-props', ignoredMessage);\n }, [ignoredMessage]);\n\n // C-DEV: the popup openings do nothing on a static menu; hover gives way to context gestures.\n const staticPopupProps = popup\n ? ''\n : listProps(\n [openOnHoverProp ? 'openOnHover' : null, openOnContextProp ? 'openOnContext' : null].filter(\n (name): name is string => name !== null,\n ),\n );\n const hoverAndContext = contextMode && openOnHoverProp === true;\n React.useEffect(() => {\n if (!staticPopupProps) return;\n const [verb, pronoun] = staticPopupProps.includes(' and ') ? ['are', 'they'] : ['is', 'it'];\n warnOnce(\n 'Menu:static-popup-props',\n `Menu: ${staticPopupProps} ${verb} ignored on a static menu: ${pronoun} apply to a popup menu (Menu.Trigger + Menu.Popover). A static menu passes openDelay and closeDelay on to its submenus.`,\n );\n }, [staticPopupProps]);\n React.useEffect(() => {\n if (!hoverAndContext) return;\n warnOnce(\n 'Menu:hover-and-context',\n 'Menu: openOnHover is ignored with openOnContext: a context menu opens only from a context gesture (a right click, Shift+F10 or the ContextMenu key).',\n );\n }, [hoverAndContext]);\n\n const staticMenuRef = React.useRef<HTMLDivElement | null>(null);\n\n // The open submenu of this menu's list (one at a time) and what focus inside means for the chain.\n const openSubmenuRef = React.useRef<OpenSubmenu | null>(null);\n const containsFocus = useEventCallback((): boolean => {\n const surfaceApi = surfaceApiRef.current;\n const element = surfaceApi?.surface ?? staticMenuRef.current;\n const active = element?.ownerDocument.activeElement;\n if (!element || !active) return false;\n if (element.contains(active)) return true;\n // A popup menu's layer tree holds its submenus and the portals opened from its items; its own\n // elements (the trigger) do not count.\n if (surfaceApi) {\n return getLayerTreeElements(surfaceApi.layerId, { includeOwnElements: false }).some((el) =>\n el.contains(active),\n );\n }\n return openSubmenuRef.current?.containsFocus() ?? false;\n });\n // Focus in a list of the chain: this menu's list, else (recursively) its open submenu's. A\n // portal opened from an item does not count, so hover never takes focus from it.\n const listContainsFocus = useEventCallback((): boolean => {\n const element = surfaceApiRef.current?.surface ?? staticMenuRef.current;\n const active = element?.ownerDocument.activeElement;\n if (element && active && element.contains(active)) return true;\n return openSubmenuRef.current?.listContainsFocus() ?? false;\n });\n\n // Every close of this menu closes its open submenu first, innermost first, through the\n // submenu's own state: each controlled submenu hears onOpenChange(false) once. A close asked for\n // by the hover intent is marked (before the request, in case the app applies it synchronously),\n // so the surface's focus restore moves no focus; every other close request, and the next\n // opening, clears the mark. A submenu closed along with it is taken along by the restore itself.\n const hoverCloseRef = React.useRef(false);\n const isHoverClose = React.useCallback(() => hoverCloseRef.current, []);\n const closeMenu = (byHover: boolean) => {\n hoverCloseRef.current = byHover;\n openSubmenuRef.current?.close();\n setOpen(false);\n };\n const requestClose = useEventCallback(() => closeMenu(false));\n const requestHoverClose = useEventCallback(() => closeMenu(true));\n\n // Why the open menu is open: a hover opening stays unpinned (the hover close applies) until the\n // trigger is activated; every other opening (click, keys, context, a controlled `open`) pins it.\n const openReasonRef = React.useRef<'hover' | 'other'>('other');\n const hoverOpenPendingRef = React.useRef(false);\n const initialFocusRef = React.useRef<InitialFocus>('first');\n React.useLayoutEffect(() => {\n if (open) {\n openReasonRef.current = hoverOpenPendingRef.current ? 'hover' : 'other';\n hoverCloseRef.current = false;\n }\n hoverOpenPendingRef.current = false;\n }, [open]);\n const isHoverOpen = React.useCallback(() => openReasonRef.current === 'hover', []);\n\n const {\n triggerHandlers: hoverIntentTriggerHandlers,\n surfaceHandlers: hoverSurfaceHandlers,\n cancel: cancelHover,\n startClose: startHoverClose,\n } = useHoverIntent({\n enabled: hoverMode,\n open,\n openDelay,\n closeDelay,\n trigger: triggerElement,\n surface: surfaceElement,\n group: parentList?.hoverGroup,\n onOpen: () => {\n hoverOpenPendingRef.current = true;\n initialFocusRef.current = 'none';\n setOpen(true);\n },\n onClose: requestHoverClose,\n // Pinned, or focus inside the menu (not on its trigger): the hover close waits.\n canClose: () => openReasonRef.current === 'hover' && !containsFocus(),\n });\n\n // A hover opening stays pending until the menu opens, in a later render too (an app that\n // applies it in a transition). One the app has not applied when the pointer leaves the trigger\n // (a controlled menu whose app kept `open` false) is forgotten then, so a later opening by the\n // app is an ordinary one: it focuses the first item and is pinned.\n const forgetHoverOpening = useEventCallback(() => {\n if (open) return;\n hoverOpenPendingRef.current = false;\n if (initialFocusRef.current === 'none') initialFocusRef.current = 'first';\n });\n const hoverTriggerHandlers = React.useMemo<HoverIntent['triggerHandlers']>(\n () => ({\n ...hoverIntentTriggerHandlers,\n onPointerLeave: (event) => {\n hoverIntentTriggerHandlers.onPointerLeave(event);\n forgetHoverOpening();\n },\n }),\n [hoverIntentTriggerHandlers, forgetHoverOpening],\n );\n\n const openWithFocus = React.useCallback(\n (target: InitialFocus) => {\n // Any opening but hover pins the menu; an open, hover-opened menu is pinned and focused.\n openReasonRef.current = 'other';\n hoverOpenPendingRef.current = false;\n cancelHover();\n const surfaceApi = surfaceApiRef.current;\n if (surfaceApi) {\n if (target === 'last') surfaceApi.focusLast();\n else if (target === 'first') surfaceApi.focusFirst();\n return;\n }\n initialFocusRef.current = target;\n setOpen(true);\n },\n [setOpen, cancelHover],\n );\n const takeInitialFocus = React.useCallback((): InitialFocus => {\n const target = initialFocusRef.current;\n initialFocusRef.current = 'first';\n return target;\n }, []);\n\n // Context gestures on the trigger region: a context gesture opens the menu (focus on its first\n // item) at the pointer or the focused row; a right click outside or an anchor-moving scroll\n // closes it.\n const {\n anchor: contextAnchor,\n fromContext,\n opener: contextOpener,\n triggerHandlers: contextTriggerHandlers,\n surfaceHandlers: contextSurfaceHandlers,\n } = useContextMenuAnchor({\n enabled: contextMode,\n open,\n trigger: triggerElement,\n layerId: surfaceLayerId,\n onOpen: () => openWithFocus('first'),\n onClose: requestClose,\n });\n\n // Focus follows the mouse: a submenu that loses focus to an item the pointer is focusing in an\n // enclosing list becomes a hover-opened submenu and closes through the hover close. A submenu\n // with `openOnHover={false}` has no hover close, so it closes at once, as for a keyboard move.\n const parentListHoverFocusing = parentList?.isHoverFocusing;\n const parentHoverFocusing = parent?.isHoverFocusing;\n const isHoverFocusing = useEventCallback(\n (): boolean => (parentListHoverFocusing?.() ?? false) || (parentHoverFocusing?.() ?? false),\n );\n // A press in progress that can be a context gesture: the right button, a Ctrl+press (the macOS\n // context click) or a touch or pen press (a long press). Recorded at its pointerdown and\n // forgotten at its pointerup, while a context menu is open.\n const contextPressRef = React.useRef(false);\n React.useEffect(() => {\n if (!contextMode || !open || !triggerElement) return undefined;\n const doc = triggerElement.ownerDocument;\n const onPointerDown = (event: PointerEvent) => {\n contextPressRef.current =\n event.button === 2 ||\n (event.button === 0 &&\n (event.ctrlKey || event.pointerType === 'touch' || event.pointerType === 'pen'));\n };\n const onPointerEnd = () => {\n contextPressRef.current = false;\n };\n doc.addEventListener('pointerdown', onPointerDown, true);\n doc.addEventListener('pointerup', onPointerEnd, true);\n doc.addEventListener('pointercancel', onPointerEnd, true);\n return () => {\n doc.removeEventListener('pointerdown', onPointerDown, true);\n doc.removeEventListener('pointerup', onPointerEnd, true);\n doc.removeEventListener('pointercancel', onPointerEnd, true);\n contextPressRef.current = false;\n };\n }, [contextMode, open, triggerElement]);\n\n const dismiss = useEventCallback((reason: DismissReason, event: Event) => {\n // Focus that such a press moves into a context menu's region does not close the menu: a\n // right-button (or macOS Ctrl+) press focuses the row under the pointer before the contextmenu\n // event that moves the menu there (Chromium, Firefox). Any other focus move into the region (a\n // primary press, the app) closes it, as does an outside press and Tab (the surface's handler).\n if (\n reason === 'focus-outside' &&\n contextMode &&\n contextPressRef.current &&\n event.target instanceof Node &&\n triggerRef.current?.contains(event.target)\n ) {\n return;\n }\n if (reason === 'focus-outside' && isSubmenu && hoverMode && isHoverFocusing()) {\n openReasonRef.current = 'hover';\n startHoverClose(event);\n return;\n }\n requestClose();\n });\n\n const registerOpenSubmenu = React.useCallback((submenu: OpenSubmenu) => {\n const previous = openSubmenuRef.current;\n openSubmenuRef.current = submenu;\n // One open submenu per list: the one open before closes.\n if (previous && previous !== submenu) previous.close();\n return () => {\n if (openSubmenuRef.current === submenu) openSubmenuRef.current = null;\n };\n }, []);\n\n // A submenu registers with its parent while it is open.\n const submenuHandle = React.useMemo<OpenSubmenu>(\n () => ({ close: requestClose, containsFocus, listContainsFocus }),\n [requestClose, containsFocus, listContainsFocus],\n );\n const registerWithParent = parent?.registerOpenSubmenu;\n React.useLayoutEffect(() => {\n if (!open || !registerWithParent) return undefined;\n return registerWithParent(submenuHandle);\n }, [open, registerWithParent, submenuHandle]);\n\n // Item activation and Tab close the whole chain: a submenu of a popup menu hands the close up,\n // and the top menu (the root, or a submenu of a static menu) puts focus on its return target\n // first (focus before close: a Dialog an item opens returns focus there), then closes.\n const parentCloseChain = parent?.popup ? parent.closeChain : null;\n const closeChain = useEventCallback(() => {\n if (parentCloseChain) {\n parentCloseChain();\n return;\n }\n if (!popup) return;\n const target = surfaceApiRef.current?.getReturnFocus() ?? null;\n if (target) {\n const doc = target.ownerDocument;\n const active = doc.activeElement;\n const lost = !active || active === doc.body || active === doc.documentElement;\n if (lost || containsFocus()) target.focus({ preventScroll: true });\n }\n requestClose();\n });\n\n const contextValue = React.useMemo<MenuContextValue>(\n () => ({\n popup,\n open,\n setOpen,\n openWithFocus,\n takeInitialFocus,\n registerSurface,\n triggerId,\n labelledBy,\n onTriggerId: setLabelledBy,\n menuId,\n triggerRef,\n triggerElement,\n setTriggerElement,\n parent,\n checked,\n persistOnItemClick,\n isSubmenu,\n requestClose,\n closeChain,\n registerOpenSubmenu,\n listContainsFocus,\n openDelay,\n closeDelay,\n dismiss,\n isHoverFocusing,\n isHoverOpen,\n isHoverClose,\n hoverTriggerHandlers,\n hoverSurfaceHandlers,\n openOnContext: contextMode,\n contextTriggerHandlers,\n contextSurfaceHandlers,\n contextAnchor,\n fromContext,\n contextOpener,\n }),\n [\n popup,\n open,\n setOpen,\n openWithFocus,\n takeInitialFocus,\n registerSurface,\n triggerId,\n labelledBy,\n menuId,\n triggerElement,\n setTriggerElement,\n parent,\n checked,\n persistOnItemClick,\n isSubmenu,\n requestClose,\n closeChain,\n registerOpenSubmenu,\n listContainsFocus,\n openDelay,\n closeDelay,\n dismiss,\n isHoverFocusing,\n isHoverOpen,\n isHoverClose,\n hoverTriggerHandlers,\n hoverSurfaceHandlers,\n contextMode,\n contextTriggerHandlers,\n contextSurfaceHandlers,\n contextAnchor,\n fromContext,\n contextOpener,\n ],\n );\n\n // Static menu: roving tab stop over the items (the last focused one keeps it).\n const {\n containerProps: { ref: rovingRef },\n handleKeyDown: rovingKeyDown,\n handleKeyDownCapture: rovingKeyDownCapture,\n handleFocus: rovingFocus,\n focusFirst,\n getTabIndex,\n } = useRovingTabIndex({\n orientation: 'vertical',\n loop: true,\n typeahead: true,\n tabStop: 'last-focused',\n manageTabIndex: true,\n itemSelector: MENU_ITEM_SELECTOR,\n });\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, rovingRef, staticMenuRef);\n\n // Disabled items never hold the tab stop, so with no enabled item the static menu itself does:\n // Tab still reaches it and a screen reader announces it. Checked whenever the roving hook's tab\n // stop changes (`getTabIndex` changes with it: an item enabled, disabled, added or removed), and\n // after it is stamped (this effect runs after the hook's).\n const [menuIsTabStop, setMenuIsTabStop] = React.useState(false);\n React.useLayoutEffect(() => {\n const menu = staticMenuRef.current;\n if (popup || !menu) return;\n const noItemTabStop = getFirstTabbable(menu) === null;\n if (noItemTabStop === menuIsTabStop) return;\n setMenuIsTabStop(noItemTabStop);\n // An item became enabled while the menu itself had focus: focus moves on to it, rather than\n // staying on an element that is no longer focusable.\n if (!noItemTabStop && menu.ownerDocument.activeElement === menu) focusFirst();\n }, [popup, menuIsTabStop, focusFirst, getTabIndex]);\n\n // The static menu is a menu list: its items close nothing when activated, and the item under\n // the mouse takes focus while focus is inside the menu tree.\n const registerCheckable = useCheckableRegistry();\n const {\n hoverGroup,\n isHoverFocusing: isListHoverFocusing,\n onPointerMove: listPointerMove,\n } = useMenuListPointer(contextValue);\n const listContext = React.useMemo<MenuListContextValue>(\n () => ({\n menu: contextValue,\n isStatic: true,\n portalDepth,\n closeFromItem: noop,\n registerCheckable,\n hoverGroup,\n isHoverFocusing: isListHoverFocusing,\n }),\n [contextValue, portalDepth, registerCheckable, hoverGroup, isListHoverFocusing],\n );\n\n if (popup) {\n return <MenuContext.Provider value={contextValue}>{children}</MenuContext.Provider>;\n }\n\n return (\n <MenuContext.Provider value={contextValue}>\n <MenuListContext.Provider value={listContext}>\n <div\n role=\"menu\"\n {...rest}\n ref={mergedRef}\n tabIndex={rest.tabIndex ?? (menuIsTabStop ? 0 : undefined)}\n data-roving-container=\"\"\n onKeyDown={composeEventHandlers(onKeyDown, rovingKeyDown)}\n onKeyDownCapture={withTypeaheadText(\n composeEventHandlers(onKeyDownCapture, rovingKeyDownCapture),\n )}\n onFocus={composeEventHandlers(onFocus, rovingFocus, { checkDefaultPrevented: false })}\n onPointerMove={composeEventHandlers(onPointerMove, listPointerMove)}\n className={cn(menuClassNames.root, menuSurfaceClasses, focusRing, className)}\n >\n {children}\n </div>\n </MenuListContext.Provider>\n </MenuContext.Provider>\n );\n};\nMenuRoot.displayName = 'Menu';\n"],"mappings":"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"}
@@ -12,8 +12,8 @@ import { useRovingTabIndex as ie } from "../../hooks/useRovingTabIndex.mjs";
12
12
  import { useMergedRefs as ae } from "../../hooks/useMergedRefs.mjs";
13
13
  import { useIsClient as oe } from "../../hooks/useIsClient.mjs";
14
14
  import { getLayerTreeElements as se } from "../../lib/layers.mjs";
15
- import { PortalDepthContext as ce } from "../portal/Portal.mjs";
16
- import { focusRing as le } from "../../lib/styles.mjs";
15
+ import { focusRing as ce } from "../../lib/styles.mjs";
16
+ import { PortalDepthContext as le } from "../portal/Portal.mjs";
17
17
  import { useCheckedValues as ue, withCheckedValuesListener as de } from "../../hooks/useCheckedValues.mjs";
18
18
  import { useHoverIntent as fe } from "../../hooks/useHoverIntent.mjs";
19
19
  import { MenuContext as o, MenuListContext as pe, useCheckableRegistry as me, useMenuListContext as he } from "./Menu.context.mjs";
@@ -33,7 +33,7 @@ function we(e) {
33
33
  return t.length > 1 ? `${t.slice(0, -1).join(", ")} and ${t[t.length - 1]}` : t.join("");
34
34
  }
35
35
  var d = ({ children: t, open: n, defaultOpen: s, onOpenChange: c, checkedValues: d, defaultCheckedValues: Te, onCheckedValuesChange: f, persistOnItemClick: Ee, openOnHover: p, openDelay: De, closeDelay: Oe, openOnContext: ke, className: Ae, onKeyDown: je, onKeyDownCapture: Me, onFocus: Ne, onPointerMove: Pe, ref: Fe, ...m }) => {
36
- let h = he(), g = l.useContext(ce), _ = h !== null && h.portalDepth === g ? h : null, v = _?.menu ?? null, y = v !== null, [b, x, S] = te(n, s ?? !1, c), Ie = oe(), C = v === null || !v.popup || v.open, w = b && Ie && C;
36
+ let h = he(), g = l.useContext(le), _ = h !== null && h.portalDepth === g ? h : null, v = _?.menu ?? null, y = v !== null, [b, x, S] = te(n, s ?? !1, c), Ie = oe(), C = v === null || !v.popup || v.open, w = b && Ie && C;
37
37
  l.useLayoutEffect(() => {
38
38
  C || !b || S || x(!1);
39
39
  }, [
@@ -296,7 +296,7 @@ var d = ({ children: t, open: n, defaultOpen: s, onOpenChange: c, checkedValues:
296
296
  onKeyDownCapture: ve(i(Me, Tt)),
297
297
  onFocus: i(Ne, Et, { checkDefaultPrevented: !1 }),
298
298
  onPointerMove: i(Pe, Pt),
299
- className: e(ee.root, _e, le, Ae),
299
+ className: e(ee.root, _e, ce, Ae),
300
300
  children: t
301
301
  })
302
302
  })
@@ -1,2 +1,2 @@
1
- "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/slot.cjs"),i=require("../../lib/composeEventHandlers.cjs"),a=require("../../lib/classNames.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../hooks/useMergedRefs.cjs"),c=require("../../hooks/useIsClient.cjs"),l=require("../../hooks/usePresence.cjs"),u=require("../portal/Portal.cjs"),d=require("./Popover.shared.cjs"),f=require("./Dialog.shared.cjs"),p=require("../../hooks/useModalLayer.cjs"),m=require("./Dialog.slots.cjs");let h=require("react");h=e.__toESM(h,1);let g=require("react/jsx-runtime"),_=require("react-dom");var v=h.createContext(null);v.displayName=`DialogContext`;var y={open:!1,requestOpen:()=>{},modalType:`modal`,trigger:f.inertModalTrigger,finalFocusRef:void 0,unmountOnClose:!0,contentId:void 0,registerContentId:()=>()=>{}};function b(e){return f.useRequiredContext(v,e,`Dialog`,()=>y)}var x=({open:e,defaultOpen:t,onOpenChange:n,modalType:r=`modal`,finalFocusRef:i,unmountOnClose:a=!0,children:o})=>{let[s,l]=f.useModalOpenState(e,t,n),u=c.useIsClient(),d=s&&u,p=f.useModalTrigger();f.useModalTriggerSession(p,d);let[m,_]=h.useState(void 0),y=h.useCallback(e=>(_(e),()=>_(t=>t===e?void 0:t)),[]),b=h.useMemo(()=>({open:d,requestOpen:l,modalType:r,trigger:p,finalFocusRef:i,unmountOnClose:a,contentId:m,registerContentId:y}),[d,l,r,p,i,a,m,y]);return(0,g.jsx)(v.Provider,{value:b,children:o})};x.displayName=`Dialog`;var S=e=>{let{open:t,requestOpen:n,trigger:r,contentId:i}=b(`Dialog.Trigger`);return f.useModalTriggerPart({open:t,requestOpen:n,trigger:r,controlsId:i},e,`Dialog.Trigger`)};S.displayName=`DialogTrigger`;var C=e=>{let{requestOpen:t}=b(`Dialog.Close`);return f.useModalClosePart(t,e,`Dialog.Close`)};C.displayName=`DialogClose`;var ee={small:`max-w-[400px]`,medium:`max-w-[600px]`,large:`max-w-[940px]`,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))]`},te=`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))]`,ne=8,re=`Dialog.Content:backdrop-ignored`,w='Dialog.Content: `backdrop` is ignored with `modalType="non-modal"`: a non-modal dialog has no backdrop, so the page behind it stays usable.',ie=`Dialog.Content:non-modal-full`,ae='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.';function oe(e){let[t,n]=h.useState(null);return h.useLayoutEffect(()=>{if(!e||typeof ResizeObserver>`u`)return;let t=new ResizeObserver(t=>{let r=t[t.length-1];r&&n(r.borderBoxSize?.[0]?.inlineSize??e.offsetWidth)});return t.observe(e,{box:`border-box`}),()=>{t.disconnect(),n(null)}},[e]),t}var T=({title:e,size:c=`medium`,backdrop:_,closeButton:v,titleAction:y,closeLabel:x=`Close`,children:S,className:C,style:T,id:E,onKeyDown:D,ref:O,...k})=>{let{open:A,requestOpen:j,modalType:M,trigger:N,finalFocusRef:se,unmountOnClose:P,registerContentId:F}=b(`Dialog.Content`),{isMounted:ce,ref:le,presenceProps:I}=l.usePresence(A,{unmountOnExit:P}),L=!P,ue=o.useId(`wave-dialog`),R=E??ue,z=o.useId(`wave-dialog-title`),B=f.useTitleRegistry(),[V,de]=h.useState(null),H=h.useRef(null),fe=h.useCallback(e=>{H.current=e,de(e)},[]),pe=h.useCallback(e=>e?F(R):void 0,[F,R]),me=s.useMergedRefs(O,fe,pe,le),U=h.useRef(null);f.useRaiseOnOpen(A,L,U);let W=f.useBackdropPress(H,M!==`alert`),he=f.useModalDismiss(j,`Dialog`,W.afterOutsidePress),G=p.useModalLayer({open:A,modalType:M,onDismiss:he,refs:[H],container:V,triggerRef:N.focusRef,finalFocusRef:se}),K=M===`non-modal`,ge=f.useModalOpener(A,N,V),_e=d.usePopoverTabOrder({enabled:A&&K,surface:V,anchorRef:ge,getPreviousStop:d.getTabbableThrough});f.useUnnamedModalWarning(A?V:null,B.hasTitle,`Dialog.Content`,`Dialog.Title`),f.useOpenInsideWarning(A,L,G.layerId,`Dialog`);let q=K&&_!=null&&typeof _!=`boolean`;h.useEffect(()=>{q&&n.warnOnce(re,w)},[q]);let J=A&&K&&c===`full`;h.useEffect(()=>{J&&n.warnOnce(ie,ae)},[J]);let[ve,ye]=h.useState(null),[Y,be]=h.useState(null),X=oe(A?ve:null),[Z,xe]=h.useState(null),Se=h.useMemo(()=>({...B.context,setFooterHeight:xe,titleActionsOutlet:Y}),[B.context,Y]);if(!ce)return null;let Q=r.slotRendersContent(e),$=X===null?void 0:X>0?`${X+ne}px`:`0px`,Ce=$===void 0?T:{"--wave-dialog-title-end-padding":$,...T};return(0,g.jsxs)(u.Portal,{ref:U,layerId:G.layerId,children:[!K&&(0,g.jsx)(m.ModalBackdrop,{backdrop:_,className:a.dialogContentClassNames.backdrop,layerId:G.layerId,open:A,onMouseDown:W.onMouseDown,presenceProps:I}),(0,g.jsx)(`div`,{...I,className:t.cn(a.dialogContentClassNames.positioner,`pointer-events-none fixed inset-0 flex items-center justify-center`),children:(0,g.jsx)(`div`,{ref:me,role:M===`alert`?`alertdialog`:`dialog`,id:R,"aria-labelledby":Q?z:B.titleId,tabIndex:-1,"data-modal-type":M,"data-size":c,...k,"data-presence":I[`data-presence`],style:Ce,onKeyDown:i.composeEventHandlers(D,_e),className:t.cn(a.dialogContentClassNames.root,`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`,ee[c],C),children:(0,g.jsxs)(f.ModalSurfaceContext.Provider,{value:Se,children:[Q&&(0,g.jsx)(`h2`,{id:z,className:t.cn(a.dialogTitleClassNames.root,`pe-[var(--wave-dialog-title-end-padding,2rem)] text-subtitle-1 font-semibold`),children:e}),(0,g.jsxs)(`div`,{ref:ye,className:t.cn(a.dialogContentClassNames.titleActions,`absolute end-4 top-4 flex items-start gap-1`,c===`full`&&te),children:[r.slotRendersContent(y)?r.renderSlot(y,`span`,t.cn(a.dialogContentClassNames.titleAction,`inline-flex items-center gap-1`)):null,(0,g.jsx)(`span`,{ref:be,className:`contents`}),(0,g.jsx)(m.ModalCloseButton,{componentName:`Dialog.Content`,closeButton:v,closeLabel:x,onClose:e=>j(!1,{reason:`close-button`,event:e}),className:t.cn(a.dialogContentClassNames.closeButton,`text-muted-foreground`)})]}),(0,g.jsx)(`div`,{className:t.cn(a.dialogContentClassNames.body,`-mx-1 mt-1 min-h-0 flex-1 overflow-y-auto scroll-pb-(--wave-dialog-footer-height) p-1 text-body-1`),style:Z===null?void 0:{"--wave-dialog-footer-height":`${Z}px`},children:S})]})})})]})};T.displayName=`DialogContent`;var E=({id:e,action:n,className:i,children:o,ref:s,...c})=>{let{id:l,ref:u}=f.useModalTitle(`Dialog.Title`,`Dialog.Content`,e,s),d=h.useContext(f.ModalSurfaceContext)?.titleActionsOutlet,p=(0,g.jsx)(`h2`,{...c,id:l,ref:u,className:t.cn(a.dialogTitleClassNames.root,`pe-[var(--wave-dialog-title-end-padding,2rem)] text-subtitle-1 font-semibold text-foreground`,i),children:o});if(!r.slotRendersContent(n))return p;let m=r.renderSlot(n,`span`,t.cn(a.dialogTitleClassNames.action,`inline-flex items-center gap-1`));return(0,g.jsxs)(g.Fragment,{children:[p,d===void 0?m:d&&(0,_.createPortal)(m,d)]})};E.displayName=`DialogTitle`;var D=`sticky -bottom-1 z-10 -mx-1 -mb-1 mt-6 flex justify-end gap-2 bg-background px-1 pb-2 pt-3`,O=`mt-6 flex justify-end gap-2`,k=({children:e,className:r,ref:i,...o})=>{let c=h.useContext(f.ModalSurfaceContext),l=c===null,u=c?.setFooterHeight,[d,p]=h.useState(null),m=s.useMergedRefs(i,p);return h.useEffect(()=>{l&&n.warnOnce(`Dialog.Footer:outside-content`,`Dialog.Footer must be rendered inside Dialog.Content. Outside it, the footer stays on the page while the dialog is closed.`)},[l]),h.useLayoutEffect(()=>{if(!d||!u||typeof ResizeObserver>`u`)return;let e=new ResizeObserver(e=>{let t=e[e.length-1];t&&u(t.borderBoxSize?.[0]?.blockSize??d.offsetHeight)});return e.observe(d,{box:`border-box`}),()=>{e.disconnect(),u(null)}},[d,u]),(0,g.jsx)(`div`,{ref:m,...o,className:t.cn(a.dialogFooterClassNames.root,u?D:O,r),children:e})};k.displayName=`DialogFooter`;var A=Object.assign(x,{Trigger:S,Content:T,Footer:k,Title:E,Close:C});exports.Dialog=A,exports.DialogClose=C,exports.DialogContent=T,exports.DialogFooter=k,exports.DialogTitle=E,exports.DialogTrigger=S;
1
+ "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/slot.cjs"),i=require("../../lib/composeEventHandlers.cjs"),a=require("../../lib/classNames.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../hooks/useMergedRefs.cjs"),c=require("../../hooks/useIsClient.cjs"),l=require("../../hooks/usePresence.cjs"),u=require("../../hooks/useModalLayer.cjs"),d=require("../portal/Portal.cjs"),f=require("./Popover.shared.cjs"),p=require("./Dialog.shared.cjs"),m=require("./Dialog.slots.cjs");let h=require("react");h=e.__toESM(h,1);let g=require("react/jsx-runtime"),_=require("react-dom");var v=h.createContext(null);v.displayName=`DialogContext`;var y={open:!1,requestOpen:()=>{},modalType:`modal`,trigger:p.inertModalTrigger,finalFocusRef:void 0,unmountOnClose:!0,contentId:void 0,registerContentId:()=>()=>{}};function b(e){return p.useRequiredContext(v,e,`Dialog`,()=>y)}var x=({open:e,defaultOpen:t,onOpenChange:n,modalType:r=`modal`,finalFocusRef:i,unmountOnClose:a=!0,children:o})=>{let[s,l]=p.useModalOpenState(e,t,n),u=c.useIsClient(),d=s&&u,f=p.useModalTrigger();p.useModalTriggerSession(f,d);let[m,_]=h.useState(void 0),y=h.useCallback(e=>(_(e),()=>_(t=>t===e?void 0:t)),[]),b=h.useMemo(()=>({open:d,requestOpen:l,modalType:r,trigger:f,finalFocusRef:i,unmountOnClose:a,contentId:m,registerContentId:y}),[d,l,r,f,i,a,m,y]);return(0,g.jsx)(v.Provider,{value:b,children:o})};x.displayName=`Dialog`;var S=e=>{let{open:t,requestOpen:n,trigger:r,contentId:i}=b(`Dialog.Trigger`);return p.useModalTriggerPart({open:t,requestOpen:n,trigger:r,controlsId:i},e,`Dialog.Trigger`)};S.displayName=`DialogTrigger`;var C=e=>{let{requestOpen:t}=b(`Dialog.Close`);return p.useModalClosePart(t,e,`Dialog.Close`)};C.displayName=`DialogClose`;var ee={small:`max-w-[400px]`,medium:`max-w-[600px]`,large:`max-w-[940px]`,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))]`},te=`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))]`,ne=8,re=`Dialog.Content:backdrop-ignored`,w='Dialog.Content: `backdrop` is ignored with `modalType="non-modal"`: a non-modal dialog has no backdrop, so the page behind it stays usable.',ie=`Dialog.Content:non-modal-full`,ae='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.';function oe(e){let[t,n]=h.useState(null);return h.useLayoutEffect(()=>{if(!e||typeof ResizeObserver>`u`)return;let t=new ResizeObserver(t=>{let r=t[t.length-1];r&&n(r.borderBoxSize?.[0]?.inlineSize??e.offsetWidth)});return t.observe(e,{box:`border-box`}),()=>{t.disconnect(),n(null)}},[e]),t}var T=({title:e,size:c=`medium`,backdrop:_,closeButton:v,titleAction:y,closeLabel:x=`Close`,children:S,className:C,style:T,id:E,onKeyDown:D,ref:O,...k})=>{let{open:A,requestOpen:j,modalType:M,trigger:N,finalFocusRef:se,unmountOnClose:P,registerContentId:F}=b(`Dialog.Content`),{isMounted:ce,ref:le,presenceProps:I}=l.usePresence(A,{unmountOnExit:P}),L=!P,ue=o.useId(`wave-dialog`),R=E??ue,z=o.useId(`wave-dialog-title`),B=p.useTitleRegistry(),[V,de]=h.useState(null),H=h.useRef(null),fe=h.useCallback(e=>{H.current=e,de(e)},[]),pe=h.useCallback(e=>e?F(R):void 0,[F,R]),me=s.useMergedRefs(O,fe,pe,le),U=h.useRef(null);p.useRaiseOnOpen(A,L,U);let W=p.useBackdropPress(H,M!==`alert`),he=p.useModalDismiss(j,`Dialog`,W.afterOutsidePress),G=u.useModalLayer({open:A,modalType:M,onDismiss:he,refs:[H],container:V,triggerRef:N.focusRef,finalFocusRef:se}),K=M===`non-modal`,ge=p.useModalOpener(A,N,V),_e=f.usePopoverTabOrder({enabled:A&&K,surface:V,anchorRef:ge,getPreviousStop:f.getTabbableThrough});p.useUnnamedModalWarning(A?V:null,B.hasTitle,`Dialog.Content`,`Dialog.Title`),p.useOpenInsideWarning(A,L,G.layerId,`Dialog`);let q=K&&_!=null&&typeof _!=`boolean`;h.useEffect(()=>{q&&n.warnOnce(re,w)},[q]);let J=A&&K&&c===`full`;h.useEffect(()=>{J&&n.warnOnce(ie,ae)},[J]);let[ve,ye]=h.useState(null),[Y,be]=h.useState(null),X=oe(A?ve:null),[Z,xe]=h.useState(null),Se=h.useMemo(()=>({...B.context,setFooterHeight:xe,titleActionsOutlet:Y}),[B.context,Y]);if(!ce)return null;let Q=r.slotRendersContent(e),$=X===null?void 0:X>0?`${X+ne}px`:`0px`,Ce=$===void 0?T:{"--wave-dialog-title-end-padding":$,...T};return(0,g.jsxs)(d.Portal,{ref:U,layerId:G.layerId,children:[!K&&(0,g.jsx)(m.ModalBackdrop,{backdrop:_,className:a.dialogContentClassNames.backdrop,layerId:G.layerId,open:A,onMouseDown:W.onMouseDown,presenceProps:I}),(0,g.jsx)(`div`,{...I,className:t.cn(a.dialogContentClassNames.positioner,`pointer-events-none fixed inset-0 flex items-center justify-center`),children:(0,g.jsx)(`div`,{ref:me,role:M===`alert`?`alertdialog`:`dialog`,id:R,"aria-labelledby":Q?z:B.titleId,tabIndex:-1,"data-modal-type":M,"data-size":c,...k,"data-presence":I[`data-presence`],style:Ce,onKeyDown:i.composeEventHandlers(D,_e),className:t.cn(a.dialogContentClassNames.root,`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`,ee[c],C),children:(0,g.jsxs)(p.ModalSurfaceContext.Provider,{value:Se,children:[Q&&(0,g.jsx)(`h2`,{id:z,className:t.cn(a.dialogTitleClassNames.root,`pe-[var(--wave-dialog-title-end-padding,2rem)] text-subtitle-1 font-semibold`),children:e}),(0,g.jsxs)(`div`,{ref:ye,className:t.cn(a.dialogContentClassNames.titleActions,`absolute end-4 top-4 flex items-start gap-1`,c===`full`&&te),children:[r.slotRendersContent(y)?r.renderSlot(y,`span`,t.cn(a.dialogContentClassNames.titleAction,`inline-flex items-center gap-1`)):null,(0,g.jsx)(`span`,{ref:be,className:`contents`}),(0,g.jsx)(m.ModalCloseButton,{componentName:`Dialog.Content`,closeButton:v,closeLabel:x,onClose:e=>j(!1,{reason:`close-button`,event:e}),className:t.cn(a.dialogContentClassNames.closeButton,`text-muted-foreground`)})]}),(0,g.jsx)(`div`,{className:t.cn(a.dialogContentClassNames.body,`-mx-1 mt-1 min-h-0 flex-1 overflow-y-auto scroll-pb-(--wave-dialog-footer-height) p-1 text-body-1`),style:Z===null?void 0:{"--wave-dialog-footer-height":`${Z}px`},children:S})]})})})]})};T.displayName=`DialogContent`;var E=({id:e,action:n,className:i,children:o,ref:s,...c})=>{let{id:l,ref:u}=p.useModalTitle(`Dialog.Title`,`Dialog.Content`,e,s),d=h.useContext(p.ModalSurfaceContext)?.titleActionsOutlet,f=(0,g.jsx)(`h2`,{...c,id:l,ref:u,className:t.cn(a.dialogTitleClassNames.root,`pe-[var(--wave-dialog-title-end-padding,2rem)] text-subtitle-1 font-semibold text-foreground`,i),children:o});if(!r.slotRendersContent(n))return f;let m=r.renderSlot(n,`span`,t.cn(a.dialogTitleClassNames.action,`inline-flex items-center gap-1`));return(0,g.jsxs)(g.Fragment,{children:[f,d===void 0?m:d&&(0,_.createPortal)(m,d)]})};E.displayName=`DialogTitle`;var D=`sticky -bottom-1 z-10 -mx-1 -mb-1 mt-6 flex justify-end gap-2 bg-background px-1 pb-2 pt-3`,O=`mt-6 flex justify-end gap-2`,k=({children:e,className:r,ref:i,...o})=>{let c=h.useContext(p.ModalSurfaceContext),l=c===null,u=c?.setFooterHeight,[d,f]=h.useState(null),m=s.useMergedRefs(i,f);return h.useEffect(()=>{l&&n.warnOnce(`Dialog.Footer:outside-content`,`Dialog.Footer must be rendered inside Dialog.Content. Outside it, the footer stays on the page while the dialog is closed.`)},[l]),h.useLayoutEffect(()=>{if(!d||!u||typeof ResizeObserver>`u`)return;let e=new ResizeObserver(e=>{let t=e[e.length-1];t&&u(t.borderBoxSize?.[0]?.blockSize??d.offsetHeight)});return e.observe(d,{box:`border-box`}),()=>{e.disconnect(),u(null)}},[d,u]),(0,g.jsx)(`div`,{ref:m,...o,className:t.cn(a.dialogFooterClassNames.root,u?D:O,r),children:e})};k.displayName=`DialogFooter`;var A=Object.assign(x,{Trigger:S,Content:T,Footer:k,Title:E,Close:C});exports.Dialog=A,exports.DialogClose=C,exports.DialogContent=T,exports.DialogFooter=k,exports.DialogTitle=E,exports.DialogTrigger=S;
2
2
  //# sourceMappingURL=Dialog.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.cjs","names":["React","inertModalTrigger","useRequiredContext","useModalOpenState","useIsClient","useModalTrigger","useModalTriggerPart","useModalClosePart","usePresence","useId","useTitleRegistry","useMergedRefs","useBackdropPress","useModalDismiss","useModalLayer","useModalOpener","usePopoverTabOrder","getTabbableThrough","slotRendersContent","Portal","ModalBackdrop","dialogContentClassNames","cn","composeEventHandlers","ModalSurfaceContext","dialogTitleClassNames","renderSlot","ModalCloseButton","useModalTitle","_Fragment","createPortal","dialogFooterClassNames","require_runtime","require_cn","require_dev","require_slot","require_composeEventHandlers","require_classNames","require_useId","require_useMergedRefs","require_useIsClient","require_usePresence","require_Portal","require_Popover_shared","require_Dialog_shared","require_useModalLayer","require_Dialog_slots","react","react_jsx_runtime","react_dom","DialogContext","inertDialogContext","useDialogContext","componentName","DialogRoot","openState","requestOpen","open","defaultOpen","onOpenChange","isClient","isOpen","trigger","contentId","setContentId","registerContentId","id","current","context","modalType","finalFocusRef","unmountOnClose","DialogTrigger","props","DialogClose","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","keptMounted","generatedId","propTitleId","titles","surface","setSurface","surfaceRef","attachSurface","node","registerId","mergedRef","ref","portalRef","backdropPress","onDismiss","layer","nonModal","opener","onTabOrderKeyDown","backdropIgnored","backdrop","coversUsablePage","size","titleActionsArea","setTitleActionsArea","titleActionsOutlet","setTitleActionsOutlet","titleActionsWidth","footerHeight","setFooterHeight","surfaceContext","isMounted","hasTitle","title","titleEndPadding","surfaceStyle","style","presenceProps","onKeyDown","className","titleAction","DialogTitle","titleId","titleRef","outlet","heading","action","actionElement","stickyFooterClasses","footerRowClasses","DialogFooter","outsideContent","footer","setFooter","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":"0qBA+RA,IAAMkD,EAAgBlD,EAAM,cAAyC,IAAI,EACzE,EAAc,YAAc,gBAE5B,IAAMmD,EAAyC,CAC7C,KAAM,GACN,gBAAmB,CAAC,EACpB,UAAW,QACX,QAASlD,EAAAA,kBACT,cAAe,IAAA,GACf,eAAgB,GAChB,UAAW,IAAA,GACX,0BAA+B,CAAC,CAClC,EAEA,SAASmD,EAAiB,EAA2C,CACnE,OAAOlD,EAAAA,mBAAmBgD,EAAeG,EAAe,aAAgBF,CAAkB,CAC5F,CAKA,IAAMG,GAAc,CAClB,OACA,cACA,eACA,YAAY,QACZ,gBACA,iBAAiB,GACjB,cACiB,CACjB,GAAM,CAACC,EAAWC,GAAerD,EAAAA,kBAAkBsD,EAAMC,EAAaC,CAAY,EAI5EC,EAAWxD,EAAAA,YAAY,EACvByD,EAASN,GAAaK,EACtBE,EAAUzD,EAAAA,gBAAgB,EAGhCuC,EAAA,uBAAuBkB,EAASD,CAAM,EACtC,GAAM,CAACE,EAAWC,GAAgBhE,EAAM,SAA6B,IAAA,EAAS,EACxEiE,EAAoBjE,EAAM,YAAa,IAC3CgE,EAAaE,CAAE,MACFF,EAAc,GAAaG,IAAYD,EAAK,IAAA,GAAYC,CAAQ,GAC5E,CAAC,CAAC,EAECC,EAAUpE,EAAM,aACb,CACL,KAAM6D,EACN,cACA,YACA,UACA,gBACA,iBACA,YACA,mBACF,GACA,CACEA,EACAL,EACAa,EACAP,EACAQ,EACAC,EACAR,EACAE,CACF,CACF,EAEA,OAAO,EAAAjB,EAAA,IAAA,CAACE,EAAc,SAAf,CAAwB,MAAOkB,EAAU,UAAiC,CAAA,CACnF,EACA,EAAW,YAAc,SAgBzB,IAAaI,EAAiB,GAA8B,CAC1D,GAAM,CAAE,OAAM,cAAa,UAAS,aAAcpB,EAAiB,gBAAgB,EACnF,OAAO9C,EAAAA,oBACL,CAAE,OAAM,cAAa,UAAS,WAAYyD,CAAU,EACpDU,EACA,gBACF,CACF,EACA,EAAc,YAAc,gBAS5B,IAAaC,EAAe,GAA4B,CACtD,GAAM,CAAE,eAAgBtB,EAAiB,cAAc,EACvD,OAAO7C,EAAAA,kBAA0CiD,EAAaiB,EAAO,cAAc,CACrF,EACA,EAAY,YAAc,cAS1B,IAAME,GAA0C,CAC9C,MAAO,gBACP,OAAQ,gBACR,MAAO,gBACP,KAAM,qOACR,EAGMC,GACJ,yIAGIC,GAAoB,EAEpBC,GAA+B,kCAC/BC,EACJ,8IAEIC,GAA6B,gCAC7BC,GACJ,qPAOF,SAASC,GAAqB,EAAyC,CACrE,GAAM,CAACC,EAAOC,GAAYpF,EAAM,SAAwB,IAAI,EAc5D,OAbA+C,EAAM,oBAAsB,CAC1B,GAAI,CAACsC,GAAQ,OAAO,eAAmB,IAAa,OACpD,IAAMC,EAAW,IAAI,eAAgB,GAAY,CAC/C,IAAMC,EAAQC,EAAQA,EAAQ,OAAS,GAClCD,GACLH,EAASG,EAAM,gBAAgB,EAAE,EAAE,YAAcF,EAAK,WAAW,CACnE,CAAC,EAED,OADAC,EAAS,QAAQD,EAAM,CAAE,IAAK,YAAa,CAAC,MAC/B,CACXC,EAAS,WAAW,EACpBF,EAAS,IAAI,CACf,CACF,EAAG,CAACC,CAAI,CAAC,EACFF,CACT,CA0BA,IAAaM,GAAiB,CAC5B,QACA,OAAO,SACP,WACA,cACA,cACA,aAAa,QACb,WACA,YACA,QACA,KACA,YACA,MACA,GAAGC,KACqB,CACxB,GAAM,CACJ,OACA,cACA,YACA,UACA,iBACA,iBACA,qBACEtC,EAAiB,gBAAgB,EAG/B,CACJ,aACA,IAAKuC,GACL,iBACEnF,EAAAA,YAAYiD,EAAM,CAAE,cAAec,CAAe,CAAC,EACjDqB,EAAc,CAACrB,EACfsB,GAAcpF,EAAAA,MAAM,aAAa,EACjCsD,EAAYG,GAAM2B,GAClBC,EAAcrF,EAAAA,MAAM,mBAAmB,EACvCsF,EAASrF,EAAAA,iBAAiB,EAE1B,CAACsF,EAASC,IAAcjG,EAAM,SAAgC,IAAI,EAClEkG,EAAalG,EAAM,OAA8B,IAAI,EACrDmG,GAAgBnG,EAAM,YAAa,GAAgC,CACvE,EAAW,QAAUoG,EACrBH,GAAWG,CAAI,CACjB,EAAG,CAAC,CAAC,EAGCC,GAAarG,EAAM,YACtB,GAAiCoG,EAAOnC,EAAkBF,CAAS,EAAI,IAAA,GACxE,CAACE,EAAmBF,CAAS,CAC/B,EACMuC,GAAY3F,EAAAA,cAA8B4F,EAAKJ,GAAeE,GAAYV,EAAW,EAGrFa,EAAYxG,EAAM,OAA8B,IAAI,EAC1D4C,EAAA,eAAea,EAAMmC,EAAaY,CAAS,EAI3C,IAAMC,EAAgB7F,EAAAA,iBAAiBsF,EAAY7B,IAAc,OAAO,EAClEqC,GAAY7F,EAAAA,gBAAgB2C,EAAa,SAAUiD,EAAc,iBAAiB,EAClFE,EAAQ7F,EAAAA,cAAc,CAC1B,OACA,YACA,aACA,KAAM,CAACoF,CAAU,EACjB,UAAWF,EACX,WAAYlC,EAAQ,SACpB,gBACF,CAAC,EAIK8C,EAAWvC,IAAc,YACzBwC,GAAS9F,EAAAA,eAAe0C,EAAMK,EAASkC,CAAO,EAC9Cc,GAAoB9F,EAAAA,mBAAmB,CAC3C,QAASyC,GAAQmD,EACjB,UACA,UAAWC,GACX,gBAAiB5F,EAAAA,kBACnB,CAAC,EACD2B,EAAA,uBAAuBa,EAAOuC,EAAU,KAAMD,EAAO,SAAU,iBAAkB,cAAc,EAC/FnD,EAAA,qBAAqBa,EAAMmC,EAAae,EAAM,QAAS,QAAQ,EAG/D,IAAMI,EACJH,GAAYI,GAAuC,MAAQ,OAAOA,GAAa,UACjFjE,EAAM,cAAgB,CAChBgE,GAAiB7E,EAAA,SAAS4C,GAA8BC,CAAwB,CACtF,EAAG,CAACgC,CAAe,CAAC,EAEpB,IAAME,EAAmBxD,GAAQmD,GAAYM,IAAS,OACtDnE,EAAM,cAAgB,CAChBkE,GAAkB/E,EAAA,SAAS8C,GAA4BC,EAAsB,CACnF,EAAG,CAACgC,CAAgB,CAAC,EAMrB,GAAM,CAACE,GAAkBC,IAAuBpH,EAAM,SAAgC,IAAI,EACpF,CAACqH,EAAoBC,IAAyBtH,EAAM,SAAiC,IAAI,EACzFuH,EAAoBrC,GAAqBzB,EAAO0D,GAAmB,IAAI,EAGvE,CAACK,EAAcC,IAAmBzH,EAAM,SAAwB,IAAI,EACpE0H,GAAiB1H,EAAM,aACpB,CAAE,GAAG+F,EAAO,QAAS,mBAAiB,oBAAmB,GAChE,CAACA,EAAO,QAASsB,CAAkB,CACrC,EAEA,GAAI,CAACM,GAAW,OAAO,KAEvB,IAAMC,EAAW1G,EAAAA,mBAAmB2G,CAAK,EAGnCC,EACJP,IAAsB,KAClB,IAAA,GACAA,EAAoB,EAClB,GAAGA,EAAoB1C,GAAkB,IACzC,MACFkD,GACJD,IAAoB,IAAA,GAChBE,EACC,CAAE,kCAAmCF,EAAiB,GAAGE,CAAM,EAEtE,OACE,EAAAhF,EAAA,KAAA,CAAC7B,EAAAA,OAAD,CAAQ,IAAKqF,EAAW,QAASG,EAAM,QAAvC,SAAA,CAGG,CAACC,IACA,EAAA5D,EAAA,IAAA,CAAC5B,EAAAA,cAAD,CACY,WACV,UAAWC,EAAAA,wBAAwB,SACnC,QAASsF,EAAM,QACT,OACN,YAAaF,EAAc,YACZ,eAChB,CAAA,GAEH,EAAAzD,EAAA,IAAA,CAAC,MAAD,CACE,GAAIiF,EAGJ,UAAW3G,EAAAA,GACTD,EAAAA,wBAAwB,WACxB,oEACF,EAEA,UAAA,EAAA2B,EAAA,IAAA,CAAC,MAAD,CACE,IAAKsD,GACL,KAAMjC,IAAc,QAAU,cAAgB,SAC9C,GAAIN,EACJ,kBAAiB6D,EAAW9B,EAAcC,EAAO,QACjD,SAAU,GACV,kBAAiB1B,EACjB,YAAW6C,EACX,GAAIxB,EACJ,gBAAeuC,EAAc,iBAC7B,MAAOF,GACP,UAAWxG,EAAAA,qBAAqB2G,EAAWpB,EAAiB,EAC5D,UAAWxF,EAAAA,GACTD,EAAAA,wBAAwB,KAOxB,sKACAsD,GAAYuC,GACZiB,CACF,EAEA,UAAA,EAAAnF,EAAA,KAAA,CAACxB,EAAAA,oBAAoB,SAArB,CAA8B,MAAOkG,GAArC,SAAA,CACGE,IACC,EAAA5E,EAAA,IAAA,CAAC,KAAD,CACE,GAAI8C,EACJ,UAAWxE,EAAAA,GACTG,EAAAA,sBAAsB,KACtB,8EACF,EAEC,SAAAoG,CACC,CAAA,GAEN,EAAA7E,EAAA,KAAA,CAAC,MAAD,CACE,IAAKoE,GACL,UAAW9F,EAAAA,GACTD,EAAAA,wBAAwB,aACxB,8CACA6F,IAAS,QAAUtC,EACrB,EANF,SAAA,CAQG1D,EAAAA,mBAAmBkH,CAAW,EAC3B1G,EAAAA,WACE0G,EACA,OACA9G,EAAAA,GAAGD,EAAAA,wBAAwB,YAAa,gCAAgC,CAC1E,EACA,MAEJ,EAAA2B,EAAA,IAAA,CAAC,OAAD,CAAM,IAAKsE,GAAuB,UAAU,UAAY,CAAA,GACxD,EAAAtE,EAAA,IAAA,CAACrB,EAAAA,iBAAD,CACE,cAAc,iBACD,cACD,aACZ,QAAU,GAAU6B,EAAY,GAAO,CAAE,OAAQ,eAAgB,OAAM,CAAC,EACxE,UAAWlC,EAAAA,GAAGD,EAAAA,wBAAwB,YAAa,uBAAuB,CAC3E,CAAA,CACE,KACL,EAAA2B,EAAA,IAAA,CAAC,MAAD,CAEE,UAAW1B,EAAAA,GACTD,EAAAA,wBAAwB,KACxB,mGACF,EACA,MACEmG,IAAiB,KACb,IAAA,GACC,CAAE,8BAA+B,GAAGA,EAAa,GAAI,EAG3D,UACE,CAAA,CACuB,GAC3B,CAAA,CACF,CAAA,CACC,GAEZ,EACA,EAAc,YAAc,gBAS5B,IAAaa,GAAe,CAC1B,KACA,SACA,YACA,WACA,MACA,GAAG3C,KACmB,CACtB,GAAM,CAAE,GAAI4C,EAAS,IAAKC,GAAa3G,EAAAA,cAAc,eAAgB,iBAAkBsC,EAAIqC,CAAG,EAExFiC,EAASxI,EAAM,WAAWwB,EAAAA,mBAAmB,CAAC,EAAE,mBAChDiH,GACJ,EAAAzF,EAAA,IAAA,CAAC,KAAD,CACE,GAAI0C,EACJ,GAAI4C,EACJ,IAAKC,EACL,UAAWjH,EAAAA,GACTG,EAAAA,sBAAsB,KACtB,+FACA0G,CACF,EAEC,UACC,CAAA,EAEN,GAAI,CAACjH,EAAAA,mBAAmBwH,CAAM,EAAG,OAAOD,EACxC,IAAME,EAAgBjH,EAAAA,WACpBgH,EACA,OACApH,EAAAA,GAAGG,EAAAA,sBAAsB,OAAQ,gCAAgC,CACnE,EACA,OACE,EAAAuB,EAAA,KAAA,CAAAnB,EAAAA,SAAA,CAAA,SAAA,CACG4G,EACAD,IAAW,IAAA,GAAYG,EAAgBH,IAAA,EAAU1G,EAAAA,aAAAA,CAAa6G,EAAeH,CAAM,CACpF,CAAA,CAAA,CAEN,EACA,EAAY,YAAc,cAO1B,IAAMI,EACJ,6FAMIC,EAAmB,8BAaZC,GAAgB,CAAE,WAAU,YAAW,MAAK,GAAGpD,KAA8B,CACxF,IAAMgC,EAAiB1H,EAAM,WAAWwB,EAAAA,mBAAmB,EACrDuH,EAAiBrB,IAAmB,KACpCD,EAAkBC,GAAgB,gBAClC,CAACsB,EAAQC,GAAajJ,EAAM,SAAgC,IAAI,EAChEsG,EAAY3F,EAAAA,cAA8B4F,EAAK0C,CAAS,EA2B9D,OAzBAlG,EAAM,cAAgB,CACfgG,GACL7G,EAAA,SACE,gCACA,4HACF,CACF,EAAG,CAAC6G,CAAc,CAAC,EAKnBhG,EAAM,oBAAsB,CAC1B,GAAI,CAACiG,GAAU,CAACvB,GAAmB,OAAO,eAAmB,IAAa,OAC1E,IAAMnC,EAAW,IAAI,eAAgB,GAAY,CAC/C,IAAMC,EAAQC,EAAQA,EAAQ,OAAS,GAClCD,GACLkC,EAAgBlC,EAAM,gBAAgB,EAAE,EAAE,WAAayD,EAAO,YAAY,CAC5E,CAAC,EAED,OADA1D,EAAS,QAAQ0D,EAAQ,CAAE,IAAK,YAAa,CAAC,MACjC,CACX1D,EAAS,WAAW,EACpBmC,EAAgB,IAAI,CACtB,CACF,EAAG,CAACuB,EAAQvB,CAAe,CAAC,GAG1B,EAAAzE,EAAA,IAAA,CAAC,MAAD,CACE,IAAKsD,EACL,GAAIZ,EAEJ,UAAWpE,EAAAA,GACTS,EAAAA,uBAAuB,KACvB0F,EAAkBmB,EAAsBC,EACxCV,CACF,EAEC,UACE,CAAA,CAET,EACA,EAAa,YAAc,eA6D3B,IAAae,EAAyB,OAAO,OAAO5F,EAAY,CAC9D,QAASkB,EACT,QAASiB,EACT,OAAQqD,EACR,MAAOT,EACP,MAAO3D,CACT,CAAC"}
1
+ {"version":3,"file":"Dialog.cjs","names":["React","inertModalTrigger","useRequiredContext","useModalOpenState","useIsClient","useModalTrigger","useModalTriggerPart","useModalClosePart","usePresence","useId","useTitleRegistry","useMergedRefs","useBackdropPress","useModalDismiss","useModalLayer","useModalOpener","usePopoverTabOrder","getTabbableThrough","slotRendersContent","Portal","ModalBackdrop","dialogContentClassNames","cn","composeEventHandlers","ModalSurfaceContext","dialogTitleClassNames","renderSlot","ModalCloseButton","useModalTitle","_Fragment","createPortal","dialogFooterClassNames","require_runtime","require_cn","require_dev","require_slot","require_composeEventHandlers","require_classNames","require_useId","require_useMergedRefs","require_useIsClient","require_usePresence","require_useModalLayer","require_Portal","require_Popover_shared","require_Dialog_shared","require_Dialog_slots","react","react_jsx_runtime","react_dom","DialogContext","inertDialogContext","useDialogContext","componentName","DialogRoot","openState","requestOpen","open","defaultOpen","onOpenChange","isClient","isOpen","trigger","contentId","setContentId","registerContentId","id","current","context","modalType","finalFocusRef","unmountOnClose","DialogTrigger","props","DialogClose","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","keptMounted","generatedId","propTitleId","titles","surface","setSurface","surfaceRef","attachSurface","node","registerId","mergedRef","ref","portalRef","backdropPress","onDismiss","layer","nonModal","opener","onTabOrderKeyDown","backdropIgnored","backdrop","coversUsablePage","size","titleActionsArea","setTitleActionsArea","titleActionsOutlet","setTitleActionsOutlet","titleActionsWidth","footerHeight","setFooterHeight","surfaceContext","isMounted","hasTitle","title","titleEndPadding","surfaceStyle","style","presenceProps","onKeyDown","className","titleAction","DialogTitle","titleId","titleRef","outlet","heading","action","actionElement","stickyFooterClasses","footerRowClasses","DialogFooter","outsideContent","footer","setFooter","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":"0qBA+RA,IAAMkD,EAAgBlD,EAAM,cAAyC,IAAI,EACzE,EAAc,YAAc,gBAE5B,IAAMmD,EAAyC,CAC7C,KAAM,GACN,gBAAmB,CAAC,EACpB,UAAW,QACX,QAASlD,EAAAA,kBACT,cAAe,IAAA,GACf,eAAgB,GAChB,UAAW,IAAA,GACX,0BAA+B,CAAC,CAClC,EAEA,SAASmD,EAAiB,EAA2C,CACnE,OAAOlD,EAAAA,mBAAmBgD,EAAeG,EAAe,aAAgBF,CAAkB,CAC5F,CAKA,IAAMG,GAAc,CAClB,OACA,cACA,eACA,YAAY,QACZ,gBACA,iBAAiB,GACjB,cACiB,CACjB,GAAM,CAACC,EAAWC,GAAerD,EAAAA,kBAAkBsD,EAAMC,EAAaC,CAAY,EAI5EC,EAAWxD,EAAAA,YAAY,EACvByD,EAASN,GAAaK,EACtBE,EAAUzD,EAAAA,gBAAgB,EAGhCwC,EAAA,uBAAuBiB,EAASD,CAAM,EACtC,GAAM,CAACE,EAAWC,GAAgBhE,EAAM,SAA6B,IAAA,EAAS,EACxEiE,EAAoBjE,EAAM,YAAa,IAC3CgE,EAAaE,CAAE,MACFF,EAAc,GAAaG,IAAYD,EAAK,IAAA,GAAYC,CAAQ,GAC5E,CAAC,CAAC,EAECC,EAAUpE,EAAM,aACb,CACL,KAAM6D,EACN,cACA,YACA,UACA,gBACA,iBACA,YACA,mBACF,GACA,CACEA,EACAL,EACAa,EACAP,EACAQ,EACAC,EACAR,EACAE,CACF,CACF,EAEA,OAAO,EAAAjB,EAAA,IAAA,CAACE,EAAc,SAAf,CAAwB,MAAOkB,EAAU,UAAiC,CAAA,CACnF,EACA,EAAW,YAAc,SAgBzB,IAAaI,EAAiB,GAA8B,CAC1D,GAAM,CAAE,OAAM,cAAa,UAAS,aAAcpB,EAAiB,gBAAgB,EACnF,OAAO9C,EAAAA,oBACL,CAAE,OAAM,cAAa,UAAS,WAAYyD,CAAU,EACpDU,EACA,gBACF,CACF,EACA,EAAc,YAAc,gBAS5B,IAAaC,EAAe,GAA4B,CACtD,GAAM,CAAE,eAAgBtB,EAAiB,cAAc,EACvD,OAAO7C,EAAAA,kBAA0CiD,EAAaiB,EAAO,cAAc,CACrF,EACA,EAAY,YAAc,cAS1B,IAAME,GAA0C,CAC9C,MAAO,gBACP,OAAQ,gBACR,MAAO,gBACP,KAAM,qOACR,EAGMC,GACJ,yIAGIC,GAAoB,EAEpBC,GAA+B,kCAC/BC,EACJ,8IAEIC,GAA6B,gCAC7BC,GACJ,qPAOF,SAASC,GAAqB,EAAyC,CACrE,GAAM,CAACC,EAAOC,GAAYpF,EAAM,SAAwB,IAAI,EAc5D,OAbA+C,EAAM,oBAAsB,CAC1B,GAAI,CAACsC,GAAQ,OAAO,eAAmB,IAAa,OACpD,IAAMC,EAAW,IAAI,eAAgB,GAAY,CAC/C,IAAMC,EAAQC,EAAQA,EAAQ,OAAS,GAClCD,GACLH,EAASG,EAAM,gBAAgB,EAAE,EAAE,YAAcF,EAAK,WAAW,CACnE,CAAC,EAED,OADAC,EAAS,QAAQD,EAAM,CAAE,IAAK,YAAa,CAAC,MAC/B,CACXC,EAAS,WAAW,EACpBF,EAAS,IAAI,CACf,CACF,EAAG,CAACC,CAAI,CAAC,EACFF,CACT,CA0BA,IAAaM,GAAiB,CAC5B,QACA,OAAO,SACP,WACA,cACA,cACA,aAAa,QACb,WACA,YACA,QACA,KACA,YACA,MACA,GAAGC,KACqB,CACxB,GAAM,CACJ,OACA,cACA,YACA,UACA,iBACA,iBACA,qBACEtC,EAAiB,gBAAgB,EAG/B,CACJ,aACA,IAAKuC,GACL,iBACEnF,EAAAA,YAAYiD,EAAM,CAAE,cAAec,CAAe,CAAC,EACjDqB,EAAc,CAACrB,EACfsB,GAAcpF,EAAAA,MAAM,aAAa,EACjCsD,EAAYG,GAAM2B,GAClBC,EAAcrF,EAAAA,MAAM,mBAAmB,EACvCsF,EAASrF,EAAAA,iBAAiB,EAE1B,CAACsF,EAASC,IAAcjG,EAAM,SAAgC,IAAI,EAClEkG,EAAalG,EAAM,OAA8B,IAAI,EACrDmG,GAAgBnG,EAAM,YAAa,GAAgC,CACvE,EAAW,QAAUoG,EACrBH,GAAWG,CAAI,CACjB,EAAG,CAAC,CAAC,EAGCC,GAAarG,EAAM,YACtB,GAAiCoG,EAAOnC,EAAkBF,CAAS,EAAI,IAAA,GACxE,CAACE,EAAmBF,CAAS,CAC/B,EACMuC,GAAY3F,EAAAA,cAA8B4F,EAAKJ,GAAeE,GAAYV,EAAW,EAGrFa,EAAYxG,EAAM,OAA8B,IAAI,EAC1D6C,EAAA,eAAeY,EAAMmC,EAAaY,CAAS,EAI3C,IAAMC,EAAgB7F,EAAAA,iBAAiBsF,EAAY7B,IAAc,OAAO,EAClEqC,GAAY7F,EAAAA,gBAAgB2C,EAAa,SAAUiD,EAAc,iBAAiB,EAClFE,EAAQ7F,EAAAA,cAAc,CAC1B,OACA,YACA,aACA,KAAM,CAACoF,CAAU,EACjB,UAAWF,EACX,WAAYlC,EAAQ,SACpB,gBACF,CAAC,EAIK8C,EAAWvC,IAAc,YACzBwC,GAAS9F,EAAAA,eAAe0C,EAAMK,EAASkC,CAAO,EAC9Cc,GAAoB9F,EAAAA,mBAAmB,CAC3C,QAASyC,GAAQmD,EACjB,UACA,UAAWC,GACX,gBAAiB5F,EAAAA,kBACnB,CAAC,EACD4B,EAAA,uBAAuBY,EAAOuC,EAAU,KAAMD,EAAO,SAAU,iBAAkB,cAAc,EAC/FlD,EAAA,qBAAqBY,EAAMmC,EAAae,EAAM,QAAS,QAAQ,EAG/D,IAAMI,EACJH,GAAYI,GAAuC,MAAQ,OAAOA,GAAa,UACjFjE,EAAM,cAAgB,CAChBgE,GAAiB7E,EAAA,SAAS4C,GAA8BC,CAAwB,CACtF,EAAG,CAACgC,CAAe,CAAC,EAEpB,IAAME,EAAmBxD,GAAQmD,GAAYM,IAAS,OACtDnE,EAAM,cAAgB,CAChBkE,GAAkB/E,EAAA,SAAS8C,GAA4BC,EAAsB,CACnF,EAAG,CAACgC,CAAgB,CAAC,EAMrB,GAAM,CAACE,GAAkBC,IAAuBpH,EAAM,SAAgC,IAAI,EACpF,CAACqH,EAAoBC,IAAyBtH,EAAM,SAAiC,IAAI,EACzFuH,EAAoBrC,GAAqBzB,EAAO0D,GAAmB,IAAI,EAGvE,CAACK,EAAcC,IAAmBzH,EAAM,SAAwB,IAAI,EACpE0H,GAAiB1H,EAAM,aACpB,CAAE,GAAG+F,EAAO,QAAS,mBAAiB,oBAAmB,GAChE,CAACA,EAAO,QAASsB,CAAkB,CACrC,EAEA,GAAI,CAACM,GAAW,OAAO,KAEvB,IAAMC,EAAW1G,EAAAA,mBAAmB2G,CAAK,EAGnCC,EACJP,IAAsB,KAClB,IAAA,GACAA,EAAoB,EAClB,GAAGA,EAAoB1C,GAAkB,IACzC,MACFkD,GACJD,IAAoB,IAAA,GAChBE,EACC,CAAE,kCAAmCF,EAAiB,GAAGE,CAAM,EAEtE,OACE,EAAAhF,EAAA,KAAA,CAAC7B,EAAAA,OAAD,CAAQ,IAAKqF,EAAW,QAASG,EAAM,QAAvC,SAAA,CAGG,CAACC,IACA,EAAA5D,EAAA,IAAA,CAAC5B,EAAAA,cAAD,CACY,WACV,UAAWC,EAAAA,wBAAwB,SACnC,QAASsF,EAAM,QACT,OACN,YAAaF,EAAc,YACZ,eAChB,CAAA,GAEH,EAAAzD,EAAA,IAAA,CAAC,MAAD,CACE,GAAIiF,EAGJ,UAAW3G,EAAAA,GACTD,EAAAA,wBAAwB,WACxB,oEACF,EAEA,UAAA,EAAA2B,EAAA,IAAA,CAAC,MAAD,CACE,IAAKsD,GACL,KAAMjC,IAAc,QAAU,cAAgB,SAC9C,GAAIN,EACJ,kBAAiB6D,EAAW9B,EAAcC,EAAO,QACjD,SAAU,GACV,kBAAiB1B,EACjB,YAAW6C,EACX,GAAIxB,EACJ,gBAAeuC,EAAc,iBAC7B,MAAOF,GACP,UAAWxG,EAAAA,qBAAqB2G,EAAWpB,EAAiB,EAC5D,UAAWxF,EAAAA,GACTD,EAAAA,wBAAwB,KAOxB,sKACAsD,GAAYuC,GACZiB,CACF,EAEA,UAAA,EAAAnF,EAAA,KAAA,CAACxB,EAAAA,oBAAoB,SAArB,CAA8B,MAAOkG,GAArC,SAAA,CACGE,IACC,EAAA5E,EAAA,IAAA,CAAC,KAAD,CACE,GAAI8C,EACJ,UAAWxE,EAAAA,GACTG,EAAAA,sBAAsB,KACtB,8EACF,EAEC,SAAAoG,CACC,CAAA,GAEN,EAAA7E,EAAA,KAAA,CAAC,MAAD,CACE,IAAKoE,GACL,UAAW9F,EAAAA,GACTD,EAAAA,wBAAwB,aACxB,8CACA6F,IAAS,QAAUtC,EACrB,EANF,SAAA,CAQG1D,EAAAA,mBAAmBkH,CAAW,EAC3B1G,EAAAA,WACE0G,EACA,OACA9G,EAAAA,GAAGD,EAAAA,wBAAwB,YAAa,gCAAgC,CAC1E,EACA,MAEJ,EAAA2B,EAAA,IAAA,CAAC,OAAD,CAAM,IAAKsE,GAAuB,UAAU,UAAY,CAAA,GACxD,EAAAtE,EAAA,IAAA,CAACrB,EAAAA,iBAAD,CACE,cAAc,iBACD,cACD,aACZ,QAAU,GAAU6B,EAAY,GAAO,CAAE,OAAQ,eAAgB,OAAM,CAAC,EACxE,UAAWlC,EAAAA,GAAGD,EAAAA,wBAAwB,YAAa,uBAAuB,CAC3E,CAAA,CACE,KACL,EAAA2B,EAAA,IAAA,CAAC,MAAD,CAEE,UAAW1B,EAAAA,GACTD,EAAAA,wBAAwB,KACxB,mGACF,EACA,MACEmG,IAAiB,KACb,IAAA,GACC,CAAE,8BAA+B,GAAGA,EAAa,GAAI,EAG3D,UACE,CAAA,CACuB,GAC3B,CAAA,CACF,CAAA,CACC,GAEZ,EACA,EAAc,YAAc,gBAS5B,IAAaa,GAAe,CAC1B,KACA,SACA,YACA,WACA,MACA,GAAG3C,KACmB,CACtB,GAAM,CAAE,GAAI4C,EAAS,IAAKC,GAAa3G,EAAAA,cAAc,eAAgB,iBAAkBsC,EAAIqC,CAAG,EAExFiC,EAASxI,EAAM,WAAWwB,EAAAA,mBAAmB,CAAC,EAAE,mBAChDiH,GACJ,EAAAzF,EAAA,IAAA,CAAC,KAAD,CACE,GAAI0C,EACJ,GAAI4C,EACJ,IAAKC,EACL,UAAWjH,EAAAA,GACTG,EAAAA,sBAAsB,KACtB,+FACA0G,CACF,EAEC,UACC,CAAA,EAEN,GAAI,CAACjH,EAAAA,mBAAmBwH,CAAM,EAAG,OAAOD,EACxC,IAAME,EAAgBjH,EAAAA,WACpBgH,EACA,OACApH,EAAAA,GAAGG,EAAAA,sBAAsB,OAAQ,gCAAgC,CACnE,EACA,OACE,EAAAuB,EAAA,KAAA,CAAAnB,EAAAA,SAAA,CAAA,SAAA,CACG4G,EACAD,IAAW,IAAA,GAAYG,EAAgBH,IAAA,EAAU1G,EAAAA,aAAAA,CAAa6G,EAAeH,CAAM,CACpF,CAAA,CAAA,CAEN,EACA,EAAY,YAAc,cAO1B,IAAMI,EACJ,6FAMIC,EAAmB,8BAaZC,GAAgB,CAAE,WAAU,YAAW,MAAK,GAAGpD,KAA8B,CACxF,IAAMgC,EAAiB1H,EAAM,WAAWwB,EAAAA,mBAAmB,EACrDuH,EAAiBrB,IAAmB,KACpCD,EAAkBC,GAAgB,gBAClC,CAACsB,EAAQC,GAAajJ,EAAM,SAAgC,IAAI,EAChEsG,EAAY3F,EAAAA,cAA8B4F,EAAK0C,CAAS,EA2B9D,OAzBAlG,EAAM,cAAgB,CACfgG,GACL7G,EAAA,SACE,gCACA,4HACF,CACF,EAAG,CAAC6G,CAAc,CAAC,EAKnBhG,EAAM,oBAAsB,CAC1B,GAAI,CAACiG,GAAU,CAACvB,GAAmB,OAAO,eAAmB,IAAa,OAC1E,IAAMnC,EAAW,IAAI,eAAgB,GAAY,CAC/C,IAAMC,EAAQC,EAAQA,EAAQ,OAAS,GAClCD,GACLkC,EAAgBlC,EAAM,gBAAgB,EAAE,EAAE,WAAayD,EAAO,YAAY,CAC5E,CAAC,EAED,OADA1D,EAAS,QAAQ0D,EAAQ,CAAE,IAAK,YAAa,CAAC,MACjC,CACX1D,EAAS,WAAW,EACpBmC,EAAgB,IAAI,CACtB,CACF,EAAG,CAACuB,EAAQvB,CAAe,CAAC,GAG1B,EAAAzE,EAAA,IAAA,CAAC,MAAD,CACE,IAAKsD,EACL,GAAIZ,EAEJ,UAAWpE,EAAAA,GACTS,EAAAA,uBAAuB,KACvB0F,EAAkBmB,EAAsBC,EACxCV,CACF,EAEC,UACE,CAAA,CAET,EACA,EAAa,YAAc,eA6D3B,IAAae,EAAyB,OAAO,OAAO5F,EAAY,CAC9D,QAASkB,EACT,QAASiB,EACT,OAAQqD,EACR,MAAOT,EACP,MAAO3D,CACT,CAAC"}