@mortenbrudvik/waveui 0.9.0 → 0.11.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 (264) hide show
  1. package/README.md +758 -152
  2. package/dist/components/button/Toolbar.cjs +1 -1
  3. package/dist/components/button/Toolbar.cjs.map +1 -1
  4. package/dist/components/button/Toolbar.mjs +25 -30
  5. package/dist/components/button/Toolbar.mjs.map +1 -1
  6. package/dist/components/button/Toolbar.navigation.cjs +2 -0
  7. package/dist/components/button/Toolbar.navigation.cjs.map +1 -0
  8. package/dist/components/button/Toolbar.navigation.mjs +17 -0
  9. package/dist/components/button/Toolbar.navigation.mjs.map +1 -0
  10. package/dist/components/data-display/Avatar.cjs +1 -1
  11. package/dist/components/data-display/Avatar.cjs.map +1 -1
  12. package/dist/components/data-display/Avatar.context.cjs +2 -0
  13. package/dist/components/data-display/Avatar.context.cjs.map +1 -0
  14. package/dist/components/data-display/Avatar.context.mjs +9 -0
  15. package/dist/components/data-display/Avatar.context.mjs.map +1 -0
  16. package/dist/components/data-display/Avatar.mjs +66 -61
  17. package/dist/components/data-display/Avatar.mjs.map +1 -1
  18. package/dist/components/data-display/InteractionTag.cjs +2 -0
  19. package/dist/components/data-display/InteractionTag.cjs.map +1 -0
  20. package/dist/components/data-display/InteractionTag.mjs +234 -0
  21. package/dist/components/data-display/InteractionTag.mjs.map +1 -0
  22. package/dist/components/data-display/Tag.cjs +1 -1
  23. package/dist/components/data-display/Tag.cjs.map +1 -1
  24. package/dist/components/data-display/Tag.mjs +222 -90
  25. package/dist/components/data-display/Tag.mjs.map +1 -1
  26. package/dist/components/data-display/TagGroup.cjs +2 -0
  27. package/dist/components/data-display/TagGroup.cjs.map +1 -0
  28. package/dist/components/data-display/TagGroup.context.cjs +2 -0
  29. package/dist/components/data-display/TagGroup.context.cjs.map +1 -0
  30. package/dist/components/data-display/TagGroup.context.mjs +113 -0
  31. package/dist/components/data-display/TagGroup.context.mjs.map +1 -0
  32. package/dist/components/data-display/TagGroup.mjs +149 -0
  33. package/dist/components/data-display/TagGroup.mjs.map +1 -0
  34. package/dist/components/data-display/tagStyles.cjs +2 -0
  35. package/dist/components/data-display/tagStyles.cjs.map +1 -0
  36. package/dist/components/data-display/tagStyles.mjs +108 -0
  37. package/dist/components/data-display/tagStyles.mjs.map +1 -0
  38. package/dist/components/feedback/Toaster.cjs +1 -1
  39. package/dist/components/feedback/Toaster.cjs.map +1 -1
  40. package/dist/components/feedback/Toaster.mjs +213 -181
  41. package/dist/components/feedback/Toaster.mjs.map +1 -1
  42. package/dist/components/input/Calendar.cjs +2 -0
  43. package/dist/components/input/Calendar.cjs.map +1 -0
  44. package/dist/components/input/Calendar.mjs +352 -0
  45. package/dist/components/input/Calendar.mjs.map +1 -0
  46. package/dist/components/input/Calendar.views.cjs +2 -0
  47. package/dist/components/input/Calendar.views.cjs.map +1 -0
  48. package/dist/components/input/Calendar.views.mjs +194 -0
  49. package/dist/components/input/Calendar.views.mjs.map +1 -0
  50. package/dist/components/input/ColorArea.cjs +1 -1
  51. package/dist/components/input/ColorArea.cjs.map +1 -1
  52. package/dist/components/input/ColorArea.mjs +18 -18
  53. package/dist/components/input/ColorArea.mjs.map +1 -1
  54. package/dist/components/input/Combobox.cjs +1 -1
  55. package/dist/components/input/Combobox.cjs.map +1 -1
  56. package/dist/components/input/Combobox.expand.cjs +1 -1
  57. package/dist/components/input/Combobox.expand.cjs.map +1 -1
  58. package/dist/components/input/Combobox.expand.mjs +7 -7
  59. package/dist/components/input/Combobox.expand.mjs.map +1 -1
  60. package/dist/components/input/Combobox.mjs +232 -156
  61. package/dist/components/input/Combobox.mjs.map +1 -1
  62. package/dist/components/input/Combobox.text.cjs +2 -0
  63. package/dist/components/input/Combobox.text.cjs.map +1 -0
  64. package/dist/components/input/Combobox.text.mjs +24 -0
  65. package/dist/components/input/Combobox.text.mjs.map +1 -0
  66. package/dist/components/input/DatePicker.cjs +1 -1
  67. package/dist/components/input/DatePicker.cjs.map +1 -1
  68. package/dist/components/input/DatePicker.mjs +203 -288
  69. package/dist/components/input/DatePicker.mjs.map +1 -1
  70. package/dist/components/input/Dropdown.cjs +1 -1
  71. package/dist/components/input/Dropdown.cjs.map +1 -1
  72. package/dist/components/input/Dropdown.mjs +135 -109
  73. package/dist/components/input/Dropdown.mjs.map +1 -1
  74. package/dist/components/input/Listbox.cjs +2 -0
  75. package/dist/components/input/Listbox.cjs.map +1 -0
  76. package/dist/components/input/Listbox.mjs +134 -0
  77. package/dist/components/input/Listbox.mjs.map +1 -0
  78. package/dist/components/input/Option.cjs +1 -1
  79. package/dist/components/input/Option.cjs.map +1 -1
  80. package/dist/components/input/Option.mjs +163 -97
  81. package/dist/components/input/Option.mjs.map +1 -1
  82. package/dist/components/input/SwatchPicker.cjs +1 -1
  83. package/dist/components/input/SwatchPicker.cjs.map +1 -1
  84. package/dist/components/input/SwatchPicker.context.cjs +2 -0
  85. package/dist/components/input/SwatchPicker.context.cjs.map +1 -0
  86. package/dist/components/input/SwatchPicker.context.mjs +35 -0
  87. package/dist/components/input/SwatchPicker.context.mjs.map +1 -0
  88. package/dist/components/input/SwatchPicker.mjs +131 -103
  89. package/dist/components/input/SwatchPicker.mjs.map +1 -1
  90. package/dist/components/input/SwatchPicker.swatches.cjs +2 -0
  91. package/dist/components/input/SwatchPicker.swatches.cjs.map +1 -0
  92. package/dist/components/input/SwatchPicker.swatches.mjs +207 -0
  93. package/dist/components/input/SwatchPicker.swatches.mjs.map +1 -0
  94. package/dist/components/input/TagPicker.cjs +1 -1
  95. package/dist/components/input/TagPicker.cjs.map +1 -1
  96. package/dist/components/input/TagPicker.context.cjs +2 -0
  97. package/dist/components/input/TagPicker.context.cjs.map +1 -0
  98. package/dist/components/input/TagPicker.context.mjs +20 -0
  99. package/dist/components/input/TagPicker.context.mjs.map +1 -0
  100. package/dist/components/input/TagPicker.create.cjs +2 -0
  101. package/dist/components/input/TagPicker.create.cjs.map +1 -0
  102. package/dist/components/input/TagPicker.create.mjs +24 -0
  103. package/dist/components/input/TagPicker.create.mjs.map +1 -0
  104. package/dist/components/input/TagPicker.mjs +13 -274
  105. package/dist/components/input/TagPicker.mjs.map +1 -1
  106. package/dist/components/input/TagPicker.option.cjs +2 -0
  107. package/dist/components/input/TagPicker.option.cjs.map +1 -0
  108. package/dist/components/input/TagPicker.option.mjs +45 -0
  109. package/dist/components/input/TagPicker.option.mjs.map +1 -0
  110. package/dist/components/input/TagPicker.overflow.cjs +2 -0
  111. package/dist/components/input/TagPicker.overflow.cjs.map +1 -0
  112. package/dist/components/input/TagPicker.overflow.mjs +153 -0
  113. package/dist/components/input/TagPicker.overflow.mjs.map +1 -0
  114. package/dist/components/input/TagPicker.parts.cjs +2 -0
  115. package/dist/components/input/TagPicker.parts.cjs.map +1 -0
  116. package/dist/components/input/TagPicker.parts.mjs +425 -0
  117. package/dist/components/input/TagPicker.parts.mjs.map +1 -0
  118. package/dist/components/input/TagPicker.root.cjs +2 -0
  119. package/dist/components/input/TagPicker.root.cjs.map +1 -0
  120. package/dist/components/input/TagPicker.root.mjs +416 -0
  121. package/dist/components/input/TagPicker.root.mjs.map +1 -0
  122. package/dist/components/input/TimePicker.cjs +1 -1
  123. package/dist/components/input/TimePicker.cjs.map +1 -1
  124. package/dist/components/input/TimePicker.mjs +77 -77
  125. package/dist/components/input/TimePicker.mjs.map +1 -1
  126. package/dist/components/input/dateUtils.cjs +1 -1
  127. package/dist/components/input/dateUtils.cjs.map +1 -1
  128. package/dist/components/input/dateUtils.mjs +114 -96
  129. package/dist/components/input/dateUtils.mjs.map +1 -1
  130. package/dist/components/input/pickerLabels.cjs +2 -0
  131. package/dist/components/input/pickerLabels.cjs.map +1 -0
  132. package/dist/components/input/pickerLabels.mjs +16 -0
  133. package/dist/components/input/pickerLabels.mjs.map +1 -0
  134. package/dist/components/input/pickerValues.cjs +2 -0
  135. package/dist/components/input/pickerValues.cjs.map +1 -0
  136. package/dist/components/input/pickerValues.mjs +24 -0
  137. package/dist/components/input/pickerValues.mjs.map +1 -0
  138. package/dist/components/layout/Accordion.cjs.map +1 -1
  139. package/dist/components/layout/Accordion.mjs.map +1 -1
  140. package/dist/components/navigation/Hamburger.cjs +2 -0
  141. package/dist/components/navigation/Hamburger.cjs.map +1 -0
  142. package/dist/components/navigation/Hamburger.mjs +54 -0
  143. package/dist/components/navigation/Hamburger.mjs.map +1 -0
  144. package/dist/components/navigation/Nav.cjs +1 -1
  145. package/dist/components/navigation/Nav.cjs.map +1 -1
  146. package/dist/components/navigation/Nav.context.cjs +2 -0
  147. package/dist/components/navigation/Nav.context.cjs.map +1 -0
  148. package/dist/components/navigation/Nav.context.mjs +137 -0
  149. package/dist/components/navigation/Nav.context.mjs.map +1 -0
  150. package/dist/components/navigation/Nav.mjs +151 -258
  151. package/dist/components/navigation/Nav.mjs.map +1 -1
  152. package/dist/components/navigation/Nav.parts.cjs +2 -0
  153. package/dist/components/navigation/Nav.parts.cjs.map +1 -0
  154. package/dist/components/navigation/Nav.parts.mjs +77 -0
  155. package/dist/components/navigation/Nav.parts.mjs.map +1 -0
  156. package/dist/components/navigation/Nav.root.cjs +2 -0
  157. package/dist/components/navigation/Nav.root.cjs.map +1 -0
  158. package/dist/components/navigation/Nav.root.mjs +78 -0
  159. package/dist/components/navigation/Nav.root.mjs.map +1 -0
  160. package/dist/components/navigation/NavDrawer.cjs +2 -0
  161. package/dist/components/navigation/NavDrawer.cjs.map +1 -0
  162. package/dist/components/navigation/NavDrawer.context.cjs +2 -0
  163. package/dist/components/navigation/NavDrawer.context.cjs.map +1 -0
  164. package/dist/components/navigation/NavDrawer.context.mjs +11 -0
  165. package/dist/components/navigation/NavDrawer.context.mjs.map +1 -0
  166. package/dist/components/navigation/NavDrawer.mjs +179 -0
  167. package/dist/components/navigation/NavDrawer.mjs.map +1 -0
  168. package/dist/components/overlays/Dialog.cjs +1 -1
  169. package/dist/components/overlays/Dialog.cjs.map +1 -1
  170. package/dist/components/overlays/Dialog.mjs +190 -125
  171. package/dist/components/overlays/Dialog.mjs.map +1 -1
  172. package/dist/components/overlays/Dialog.shared.cjs +1 -1
  173. package/dist/components/overlays/Dialog.shared.cjs.map +1 -1
  174. package/dist/components/overlays/Dialog.shared.mjs +157 -81
  175. package/dist/components/overlays/Dialog.shared.mjs.map +1 -1
  176. package/dist/components/overlays/Dialog.slots.cjs +2 -0
  177. package/dist/components/overlays/Dialog.slots.cjs.map +1 -0
  178. package/dist/components/overlays/Dialog.slots.mjs +129 -0
  179. package/dist/components/overlays/Dialog.slots.mjs.map +1 -0
  180. package/dist/components/overlays/Drawer.cjs +1 -1
  181. package/dist/components/overlays/Drawer.cjs.map +1 -1
  182. package/dist/components/overlays/Drawer.context.cjs +2 -0
  183. package/dist/components/overlays/Drawer.context.cjs.map +1 -0
  184. package/dist/components/overlays/Drawer.context.mjs +29 -0
  185. package/dist/components/overlays/Drawer.context.mjs.map +1 -0
  186. package/dist/components/overlays/Drawer.mjs +12 -187
  187. package/dist/components/overlays/Drawer.mjs.map +1 -1
  188. package/dist/components/overlays/Drawer.panel.cjs +2 -0
  189. package/dist/components/overlays/Drawer.panel.cjs.map +1 -0
  190. package/dist/components/overlays/Drawer.panel.mjs +159 -0
  191. package/dist/components/overlays/Drawer.panel.mjs.map +1 -0
  192. package/dist/components/overlays/Drawer.parts.cjs +2 -0
  193. package/dist/components/overlays/Drawer.parts.cjs.map +1 -0
  194. package/dist/components/overlays/Drawer.parts.mjs +152 -0
  195. package/dist/components/overlays/Drawer.parts.mjs.map +1 -0
  196. package/dist/components/overlays/Drawer.root.cjs +2 -0
  197. package/dist/components/overlays/Drawer.root.cjs.map +1 -0
  198. package/dist/components/overlays/Drawer.root.mjs +207 -0
  199. package/dist/components/overlays/Drawer.root.mjs.map +1 -0
  200. package/dist/components/overlays/Drawer.scroll.cjs +2 -0
  201. package/dist/components/overlays/Drawer.scroll.cjs.map +1 -0
  202. package/dist/components/overlays/Drawer.scroll.mjs +42 -0
  203. package/dist/components/overlays/Drawer.scroll.mjs.map +1 -0
  204. package/dist/components/table/useGridNavigation.cjs +1 -1
  205. package/dist/components/table/useGridNavigation.cjs.map +1 -1
  206. package/dist/components/table/useGridNavigation.mjs +67 -70
  207. package/dist/components/table/useGridNavigation.mjs.map +1 -1
  208. package/dist/hooks/useActiveDescendant.cjs +2 -0
  209. package/dist/hooks/useActiveDescendant.cjs.map +1 -0
  210. package/dist/hooks/useActiveDescendant.mjs +56 -0
  211. package/dist/hooks/useActiveDescendant.mjs.map +1 -0
  212. package/dist/hooks/useDismiss.cjs.map +1 -1
  213. package/dist/hooks/useDismiss.mjs.map +1 -1
  214. package/dist/hooks/useFocusTrap.cjs +1 -1
  215. package/dist/hooks/useFocusTrap.cjs.map +1 -1
  216. package/dist/hooks/useFocusTrap.mjs +115 -98
  217. package/dist/hooks/useFocusTrap.mjs.map +1 -1
  218. package/dist/hooks/useListbox.cjs +1 -1
  219. package/dist/hooks/useListbox.cjs.map +1 -1
  220. package/dist/hooks/useListbox.mjs +250 -210
  221. package/dist/hooks/useListbox.mjs.map +1 -1
  222. package/dist/hooks/useModalLayer.cjs +1 -1
  223. package/dist/hooks/useModalLayer.cjs.map +1 -1
  224. package/dist/hooks/useModalLayer.mjs +35 -22
  225. package/dist/hooks/useModalLayer.mjs.map +1 -1
  226. package/dist/hooks/useRestoreFocus.cjs +1 -1
  227. package/dist/hooks/useRestoreFocus.cjs.map +1 -1
  228. package/dist/hooks/useRestoreFocus.mjs +91 -78
  229. package/dist/hooks/useRestoreFocus.mjs.map +1 -1
  230. package/dist/hooks/useRovingGrid.cjs +2 -0
  231. package/dist/hooks/useRovingGrid.cjs.map +1 -0
  232. package/dist/hooks/useRovingGrid.mjs +69 -0
  233. package/dist/hooks/useRovingGrid.mjs.map +1 -0
  234. package/dist/hooks/useRovingTabIndex.cjs +1 -1
  235. package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
  236. package/dist/hooks/useRovingTabIndex.mjs +102 -78
  237. package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
  238. package/dist/index.cjs +1 -1
  239. package/dist/index.d.cts +4391 -394
  240. package/dist/index.d.ts +4391 -394
  241. package/dist/index.mjs +115 -101
  242. package/dist/lib/classNames.cjs +1 -1
  243. package/dist/lib/classNames.cjs.map +1 -1
  244. package/dist/lib/classNames.mjs +170 -74
  245. package/dist/lib/classNames.mjs.map +1 -1
  246. package/dist/lib/date.cjs +2 -0
  247. package/dist/lib/date.cjs.map +1 -0
  248. package/dist/lib/date.mjs +44 -0
  249. package/dist/lib/date.mjs.map +1 -0
  250. package/dist/lib/focus.cjs +1 -1
  251. package/dist/lib/focus.cjs.map +1 -1
  252. package/dist/lib/focus.mjs +5 -2
  253. package/dist/lib/focus.mjs.map +1 -1
  254. package/dist/lib/icons.cjs +1 -1
  255. package/dist/lib/icons.cjs.map +1 -1
  256. package/dist/lib/icons.mjs +13 -6
  257. package/dist/lib/icons.mjs.map +1 -1
  258. package/dist/lib/layers.cjs +1 -1
  259. package/dist/lib/layers.cjs.map +1 -1
  260. package/dist/lib/layers.mjs +53 -47
  261. package/dist/lib/layers.mjs.map +1 -1
  262. package/dist/styles.css +1 -1
  263. package/package.json +1 -1
  264. package/src/styles/tokens.css +25 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.mjs","names":["useId","useId$1","React","DrawerContext","inertDrawerContext","inertModalTrigger","useDrawerContext","useRequiredContext","componentName","positionClasses","NESTED_TRIGGER_WARNING_KEY","NESTED_TRIGGER_WARNING","UNREACHABLE_WARNING_KEY","UNREACHABLE_WARNING","REACHABILITY_CHECK_DELAY","DrawerTrigger","inPanel","warnOnce","useModalTriggerPart","panelId","props","DrawerClose","useModalClosePart","requestOpen","DrawerTitle","rest","titleId","titleRef","useModalTitle","id","ref","cn","drawerTitleClassNames","className","NESTED_TRIGGER_MAX_DEPTH","hasNestedTrigger","visit","level","node","item","depth","type","getElementType","isFragment","nested","children","splitChildren","triggers","content","flattenChildren","keyed","isElementOfType","DrawerRoot","openProp","openState","useModalOpenState","defaultOpen","onOpenChange","isClient","useIsClient","open","trigger","useModalTrigger","generatedId","propTitleId","titles","useTitleRegistry","panel","setPanel","panelRef","attachPanel","mergedRef","useMergedRefs","backdropPress","useBackdropPress","onDismiss","useModalDismiss","layer","useModalLayer","useModalTriggerSession","useUnnamedModalWarning","nestedWarnedRef","isDev","unreachable","latestRef","timer","latest","context","panelContext","hasTitle","slotRendersContent","title","Portal","drawerClassNames","position","ModalSurfaceContext","Button","DismissIcon","closeLabel","event","Drawer"],"sources":["../../../src/components/overlays/Drawer.tsx"],"sourcesContent":["import * as React from 'react';\nimport { flattenChildren, getElementType, isElementOfType } from '../../lib/children';\nimport { cn } from '../../lib/cn';\nimport { drawerClassNames, drawerTitleClassNames } from '../../lib/classNames';\nimport { isDev, warnOnce } from '../../lib/dev';\nimport { DismissIcon } from '../../lib/icons';\nimport { slotRendersContent } from '../../lib/slot';\nimport type { ModalOpenChangeReason, OpenChangeDetails } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useModalLayer } from '../../hooks/useModalLayer';\nimport { Button } from '../button/Button';\nimport { Portal } from '../portal/Portal';\nimport {\n inertModalTrigger,\n ModalSurfaceContext,\n useBackdropPress,\n useModalClosePart,\n useModalDismiss,\n useModalOpenState,\n useModalTitle,\n useModalTrigger,\n useModalTriggerPart,\n useModalTriggerSession,\n useRequiredContext,\n useTitleRegistry,\n useUnnamedModalWarning,\n type ModalRequestOpen,\n type ModalTrigger,\n} from './Dialog.shared';\n\n/**\n * Side of the screen the drawer is attached to. `start`/`end` follow the text direction (in a\n * right-to-left layout `end` is the left edge); `left`/`right` are physical sides.\n */\nexport type DrawerPosition = 'start' | 'end' | 'left' | 'right';\n\n/**\n * Why a {@link Drawer} asks to open or close: `trigger` (`Drawer.Trigger`), `close`\n * (`Drawer.Close`), `close-button` (the built-in Close button), `escape`, `outside-press` (the\n * backdrop). The shared `ModalOpenChangeReason`, as for Dialog.\n */\nexport type DrawerOpenChangeReason = ModalOpenChangeReason;\n\n/** The second argument of a {@link Drawer}'s `onOpenChange`: the reason and the DOM event. */\nexport type DrawerOpenChangeDetails = OpenChangeDetails<DrawerOpenChangeReason>;\n\n/** Properties for the Drawer component. */\nexport interface DrawerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n /**\n * Controlled open state of the drawer. The panel renders only in the browser: an open drawer\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 panel renders only in the browser: a drawer\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 drawer 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 drawer stays as it is until the parent updates\n * `open`.\n */\n onOpenChange?: (open: boolean, details?: DrawerOpenChangeDetails) => void;\n /**\n * Side of the screen the drawer is attached to. `start`/`end` follow the text direction;\n * `left`/`right` are physical sides.\n * @default 'end'\n */\n position?: DrawerPosition;\n /**\n * Title displayed in the drawer header; it names the drawer (`aria-labelledby`). Without it,\n * render a `Drawer.Title` or pass `aria-label`/`aria-labelledby`. A title that renders nothing\n * (`''`, `[]`, `true`) counts as none.\n */\n title?: React.ReactNode;\n /**\n * Accessible name of the built-in Close button (an icon-only button). Localize it with the\n * page's language.\n * @default 'Close'\n */\n closeLabel?: string;\n /**\n * Where focus goes when the drawer closes, if it can take focus. Otherwise focus returns to the\n * element that had focus when the drawer opened, then to the trigger, then to an element next to\n * where that opener was.\n */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * The drawer body. `Drawer.Trigger` children placed directly inside the Drawer, or in a Fragment\n * there (`{isMobile && <>…</>}`), render in place (outside the panel); everything else renders in\n * the panel's scrolling body. A `Drawer.Trigger` nested in another element, or rendered by a\n * component, is panel content, so it only exists while the drawer is open (development warnings\n * say so, also when an uncontrolled drawer still has no direct trigger a second after it mounts\n * and therefore cannot open; a controlled drawer whose trigger a component such as a Tooltip\n * wraps warns only once it opens).\n * Put wrappers inside the trigger instead: see `Drawer.Trigger`.\n */\n children: React.ReactNode;\n /** Ref to the drawer panel (`role=\"dialog\"`). */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Props a `Drawer.Trigger` puts on its element (and passes to a render-prop child). */\nexport interface DrawerTriggerRenderProps extends React.HTMLAttributes<HTMLElement> {\n 'aria-haspopup': 'dialog';\n 'aria-expanded': boolean;\n /** The panel's id, while the drawer 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 DrawerTrigger sub-component. */\nexport interface DrawerTriggerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that opens the drawer. A single element receives the trigger props (merged with its\n * own); a function receives them.\n */\n children: React.ReactNode | ((props: DrawerTriggerRenderProps) => React.ReactNode);\n /**\n * `false` renders a wrapper `<span>` around the children instead of merging the trigger props\n * onto the child. The span carries the click handler; `aria-haspopup`, `aria-expanded` and\n * `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 `Drawer.Close` puts on its element (and passes to a render-prop child). */\nexport interface DrawerCloseRenderProps 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 DrawerClose sub-component. */\nexport interface DrawerCloseProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that closes the drawer. A single element receives an `onClick` composed with its own\n * (its handler runs first; `preventDefault()` keeps the drawer open); a function receives the\n * props.\n */\n children: React.ReactNode | ((props: DrawerCloseRenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` that closes the drawer 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\n/** Properties for the DrawerTitle sub-component. */\nexport interface DrawerTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n /** The title; any content. */\n children: React.ReactNode;\n /** Ref to the heading element. */\n ref?: React.Ref<HTMLHeadingElement>;\n}\n\ninterface DrawerContextValue {\n open: boolean;\n /** Asks the root to open or close, with the reason and event for `onOpenChange`. */\n requestOpen: ModalRequestOpen;\n /** The trigger element (`attach`) and the focus-restore target resolved from it (`focusRef`). */\n trigger: ModalTrigger;\n /** The panel's id (for the trigger's `aria-controls`). */\n panelId: string;\n /** `true` for sub-components rendered inside the panel (a `Drawer.Trigger` there is misplaced). */\n inPanel: boolean;\n}\n\nconst DrawerContext = React.createContext<DrawerContextValue | null>(null);\nDrawerContext.displayName = 'DrawerContext';\n\nconst inertDrawerContext: DrawerContextValue = {\n open: false,\n requestOpen: () => {},\n trigger: inertModalTrigger,\n panelId: '',\n inPanel: false,\n};\n\nfunction useDrawerContext(componentName: string): DrawerContextValue {\n return useRequiredContext(DrawerContext, componentName, 'Drawer', () => inertDrawerContext);\n}\n\n/**\n * The side the panel is pinned to, and a border on its inner edge (the one facing the page): it\n * marks the panel where the shadow cannot, in high contrast (page, backdrop and panel are black)\n * and in forced colors (which drop shadows).\n */\nconst positionClasses: Record<DrawerPosition, string> = {\n start: 'start-0 border-e',\n end: 'end-0 border-s',\n left: 'left-0 border-r', // wave-allow-physical: the consumer asked for the physical left edge\n right: 'right-0 border-l', // wave-allow-physical: the consumer asked for the physical right edge\n};\n\nconst NESTED_TRIGGER_WARNING_KEY = 'Drawer.Trigger:nested';\nconst NESTED_TRIGGER_WARNING =\n 'Drawer.Trigger must be a direct child of Drawer (a Fragment is fine). Inside another element or a component it is rendered as panel content, which exists only while the drawer is open, so it cannot open the drawer. Make it a direct child, put wrappers such as a Tooltip inside the trigger, or control the Drawer with `open`/`onOpenChange` and open it from your own button.';\n\nconst UNREACHABLE_WARNING_KEY = 'Drawer:unreachable';\nconst UNREACHABLE_WARNING =\n 'Drawer has no way to open: a second after mounting it is still uncontrolled (no `open` prop), closed, and has no Drawer.Trigger as a direct child (or in a Fragment there). A Drawer.Trigger rendered by a component or nested in an element is panel content, which exists only while the drawer is open. Make the trigger a direct child of Drawer, or control the Drawer with `open`/`onOpenChange`.';\n\n/**\n * How long after mount (ms) the development check for a drawer without a trigger waits: long\n * enough for a trigger that a conditional Fragment renders once the page knows its layout.\n */\nconst REACHABILITY_CHECK_DELAY = 1000;\n\n/**\n * Opens the drawer. Place it directly inside `Drawer`, or in a Fragment there (not inside a wrapper\n * element or a component of your own): it renders in place, not in the panel; a misplaced one warns\n * in development. A Drawer may have several triggers: focus returns to the one that opened it. Puts\n * `aria-haspopup=\"dialog\"`, `aria-expanded`, `aria-controls` (while open), a click handler and a\n * ref on its single child, or passes them to a render-prop child. A custom child component must\n * forward `ref` and spread its props; one that does not is wrapped in a `<span>` automatically\n * (with a development warning), the span that `asChild={false}` renders. Focus returns to the\n * trigger when the drawer closes. On the span, the state ARIA goes to the first element in the tab\n * order inside it, and focus returns to that element (to the span when you made it the trigger\n * with a `role` such as `button` and `tabIndex={0}`, or when nothing inside it can take focus).\n *\n * A Tooltip (or any other wrapper) goes inside the trigger, not around it. Use a render-prop child\n * so the trigger props land on the button and the Tooltip describes that same button:\n *\n * @example\n * <Drawer title=\"Filters\">\n * <Drawer.Trigger>\n * {(triggerProps) => (\n * <Tooltip content=\"Narrow the list\">\n * <Button {...triggerProps}>Filters</Button>\n * </Tooltip>\n * )}\n * </Drawer.Trigger>\n * <FilterForm />\n * </Drawer>\n */\nexport const DrawerTrigger = (props: DrawerTriggerProps) => {\n const { open, requestOpen, trigger, panelId, inPanel } = useDrawerContext('Drawer.Trigger');\n\n // Rendered inside its own drawer's panel (e.g. by a component): it only exists while open.\n React.useEffect(() => {\n if (inPanel) warnOnce(NESTED_TRIGGER_WARNING_KEY, NESTED_TRIGGER_WARNING);\n }, [inPanel]);\n\n return useModalTriggerPart<DrawerTriggerRenderProps>(\n { open, requestOpen, trigger, controlsId: panelId },\n props,\n 'Drawer.Trigger',\n );\n};\nDrawerTrigger.displayName = 'DrawerTrigger';\n\n/**\n * Closes the drawer: composes a click handler onto its single child (its own `onClick` runs first;\n * calling `preventDefault()` there keeps the drawer open), or passes it to a render-prop child.\n */\nexport const DrawerClose = (props: DrawerCloseProps) => {\n const { requestOpen } = useDrawerContext('Drawer.Close');\n return useModalClosePart<DrawerCloseRenderProps>(requestOpen, props, 'Drawer.Close');\n};\nDrawerClose.displayName = 'DrawerClose';\n\n/**\n * A heading that names the drawer (`aria-labelledby`), for rich titles or custom layouts. Render it\n * inside the Drawer's content (instead of the `title` prop).\n */\nexport const DrawerTitle = ({ id, className, children, ref, ...rest }: DrawerTitleProps) => {\n const { id: titleId, ref: titleRef } = useModalTitle('Drawer.Title', 'Drawer', id, ref);\n return (\n <h2\n {...rest}\n id={titleId}\n ref={titleRef}\n className={cn(\n drawerTitleClassNames.root,\n 'text-subtitle-1 font-semibold text-foreground',\n className,\n )}\n >\n {children}\n </h2>\n );\n};\nDrawerTitle.displayName = 'DrawerTitle';\n\n/** Deepest element level the development check for nested triggers looks at. */\nconst NESTED_TRIGGER_MAX_DEPTH = 32;\n\n/**\n * Development check: whether the Drawer's children hold a `Drawer.Trigger` inside a host element\n * (at any depth, also through Fragments), which would become panel content; a trigger inside\n * Fragments only is direct (see `splitChildren`). Walks the element tree the consumer wrote, not\n * rendered output, so it descends only into host elements (`<div>`, `<span>`, …) and Fragments,\n * which render their `children` as written. A component's\n * output is unknown here — a wrapper that renders its own Drawer around its children, for one —\n * so components are not walked; a trigger rendered by a component is caught when it renders in the\n * open panel, or, while the drawer cannot open, by the unreachable-drawer check.\n */\nfunction hasNestedTrigger(children: React.ReactNode): boolean {\n // `depth` counts host elements only: a Fragment adds no level, as `splitChildren` flattens it.\n const visit = (node: unknown, depth: number, level: number): boolean => {\n if (level > NESTED_TRIGGER_MAX_DEPTH || typeof node !== 'object' || node === null) return false;\n if (Array.isArray(node)) return node.some((item) => visit(item, depth, level));\n if (!React.isValidElement(node)) return false;\n // A part written in a Server Component has a lazy type. The walk runs in effects, outside\n // render: a lazy part that is still loading must not throw its thenable there, so it counts\n // as no trigger (`suspend: false` returns the lazy itself, which matches nothing).\n const type = getElementType(node, { suspend: false });\n if (type === DrawerTrigger) return depth > 0;\n const isFragment = type === React.Fragment;\n if (typeof type !== 'string' && !isFragment) return false;\n const { children: nested } = node.props as { children?: unknown };\n return visit(nested, isFragment ? depth : depth + 1, level + 1);\n };\n return visit(children, 0, 0);\n}\n\n/**\n * Splits the Drawer's children into its direct `Drawer.Trigger` elements and the panel content.\n * Fragments are flattened (recursively), so a `Drawer.Trigger` in a Fragment —\n * `{isMobile && <><Drawer.Trigger>…</Drawer.Trigger><Filters /></>}` — counts as a direct child.\n * Every element keeps the key `flattenChildren` gives it: unique across Fragments and stable when a\n * sibling Fragment toggles, so panel content keeps its state. A trigger is recognised also when it\n * was written in a Server Component (a lazy type).\n */\nfunction splitChildren(children: React.ReactNode): {\n triggers: React.ReactNode[];\n content: React.ReactNode[];\n} {\n const triggers: React.ReactNode[] = [];\n const content: React.ReactNode[] = [];\n for (const { key, node } of flattenChildren(children)) {\n const keyed = React.isValidElement(node) ? React.cloneElement(node, { key }) : node;\n if (isElementOfType(node, DrawerTrigger)) triggers.push(keyed);\n else content.push(keyed);\n }\n return { triggers, content };\n}\n\n// The root of `Drawer` (documented on the export below).\nconst DrawerRoot = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n position = 'end',\n title,\n closeLabel = 'Close',\n finalFocusRef,\n children,\n className,\n id,\n ref,\n ...rest\n}: DrawerProps) => {\n const [openState, requestOpen] = useModalOpenState(openProp, defaultOpen, onOpenChange);\n // The panel lives in a portal, which renders only in the browser: until then (the server HTML,\n // hydration) the drawer reports itself closed, so the trigger's aria-expanded and aria-controls\n // never describe a panel that is not there.\n const isClient = useIsClient();\n const open = openState && isClient;\n const trigger = useModalTrigger();\n const generatedId = useId('wave-drawer');\n const panelId = id ?? generatedId;\n const propTitleId = useId('wave-drawer-title');\n const titles = useTitleRegistry();\n\n const [panel, setPanel] = React.useState<HTMLDivElement | null>(null);\n const panelRef = React.useRef<HTMLDivElement | null>(null);\n const attachPanel = React.useCallback((node: HTMLDivElement | null) => {\n panelRef.current = node;\n setPanel(node);\n }, []);\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, attachPanel);\n\n // Every backdrop press asks the drawer to close.\n const backdropPress = useBackdropPress(panelRef, true);\n const onDismiss = useModalDismiss(requestOpen, 'Drawer', backdropPress.afterOutsidePress);\n const layer = useModalLayer({\n open,\n onDismiss,\n refs: [panelRef],\n container: panel,\n triggerRef: trigger.focusRef,\n finalFocusRef,\n });\n // After useModalLayer's focus restore (effects run in order), start the trigger session, or end\n // it and forget the trigger that opened it.\n useModalTriggerSession(trigger, open);\n useUnnamedModalWarning(open ? panel : null, titles.hasTitle, 'Drawer', 'Drawer.Title');\n\n const { triggers, content } = splitChildren(children);\n\n // A trigger nested in the children is panel content: never rendered while the drawer is closed.\n // The children change on every parent render; once this drawer has warned, it stops walking.\n const nestedWarnedRef = React.useRef(false);\n React.useEffect(() => {\n if (!isDev || nestedWarnedRef.current || !hasNestedTrigger(children)) return;\n nestedWarnedRef.current = true;\n warnOnce(NESTED_TRIGGER_WARNING_KEY, NESTED_TRIGGER_WARNING);\n }, [children]);\n\n // An uncontrolled closed drawer without a direct trigger cannot open (e.g.\n // `<Drawer><FilterTrigger /></Drawer>`, whose trigger is panel content). Checked once, a moment\n // after mount, against the latest render: a trigger that a conditional Fragment adds right after\n // mount (`{isMobile && <>…</>}` with an SSR-safe media query) counts. A trigger nested in an\n // element already has the more specific warning above.\n const unreachable = openProp === undefined && !defaultOpen && triggers.length === 0;\n const latestRef = React.useRef({ unreachable, children });\n React.useLayoutEffect(() => {\n latestRef.current = { unreachable, children };\n });\n React.useEffect(() => {\n if (!isDev || !latestRef.current.unreachable) return;\n const timer = setTimeout(() => {\n const latest = latestRef.current;\n if (latest.unreachable && !hasNestedTrigger(latest.children)) {\n warnOnce(UNREACHABLE_WARNING_KEY, UNREACHABLE_WARNING);\n }\n }, REACHABILITY_CHECK_DELAY);\n return () => clearTimeout(timer);\n }, []);\n\n const context = React.useMemo<DrawerContextValue>(\n () => ({ open, requestOpen, trigger, panelId, inPanel: false }),\n [open, requestOpen, trigger, panelId],\n );\n const panelContext = React.useMemo<DrawerContextValue>(\n () => ({ ...context, inPanel: true }),\n [context],\n );\n\n const hasTitle = slotRendersContent(title);\n\n return (\n <DrawerContext.Provider value={context}>\n {triggers}\n {open && (\n <Portal layerId={layer.layerId}>\n <div\n className={cn(drawerClassNames.backdrop, 'fixed inset-0 bg-backdrop')}\n onMouseDown={backdropPress.onMouseDown}\n >\n <div\n ref={mergedRef}\n role=\"dialog\"\n id={panelId}\n aria-labelledby={hasTitle ? propTitleId : titles.titleId}\n tabIndex={-1}\n {...rest}\n className={cn(\n drawerClassNames.root,\n 'fixed top-0 flex h-full w-80 max-w-full flex-col border-border bg-background text-foreground shadow-64',\n positionClasses[position],\n className,\n )}\n >\n <DrawerContext.Provider value={panelContext}>\n <ModalSurfaceContext.Provider value={titles.context}>\n <div\n className={cn(\n drawerClassNames.header,\n 'flex items-center justify-between gap-2 border-b border-border p-4',\n )}\n >\n {hasTitle && (\n <h2\n id={propTitleId}\n className={cn(drawerTitleClassNames.root, 'text-subtitle-1 font-semibold')}\n >\n {title}\n </h2>\n )}\n <Button\n appearance=\"subtle\"\n size=\"small\"\n icon={<DismissIcon />}\n aria-label={closeLabel}\n onClick={(event) =>\n requestOpen(false, { reason: 'close-button', event: event.nativeEvent })\n }\n className={cn(drawerClassNames.closeButton, 'ms-auto text-muted-foreground')}\n />\n </div>\n <div className={cn(drawerClassNames.body, 'min-h-0 flex-1 overflow-y-auto p-4')}>\n {content}\n </div>\n </ModalSurfaceContext.Provider>\n </DrawerContext.Provider>\n </div>\n </div>\n </Portal>\n )}\n </DrawerContext.Provider>\n );\n};\nDrawerRoot.displayName = 'Drawer';\n\n/**\n * A modal panel attached to a side of the screen (Fluent UI v2 style), rendered in a portal\n * (inheriting the WaveProvider theme) while open.\n *\n * - **Opening**: controlled (`open`), or uncontrolled with a `Drawer.Trigger` placed directly inside\n * the Drawer or in a Fragment there (it renders in place, outside the panel).\n * - **Modal**: focus moves into the panel and Tab stays inside it (toasts included), the rest of the\n * page is `inert` (instead of `aria-modal`), and the page does not scroll.\n * - **Closing**: Escape (only the topmost layer: a popup opened inside closes first), a click on the\n * backdrop (a drag that starts inside does not close it), the Close button and `Drawer.Close`.\n * `onOpenChange` gets the reason as its second argument (`details.reason`), so a controlled\n * drawer can refuse some of them. A backdrop press blurs the focused field before the drawer\n * closes, so a typed value is committed as with the Close button; when a controlled drawer\n * refuses the press, the field gets focus back. Focus returns to the first of these that can\n * take focus: `finalFocusRef`, the element that had focus when the drawer opened, the trigger,\n * an element next to where that opener was.\n * - **Position**: `end` (default) and `start` follow the text direction.\n *\n * The sub-components are also exported under flat names (`DrawerTrigger`, `DrawerClose`,\n * `DrawerTitle`) for React Server Components, which cannot use the dotted form; dotted access\n * (`Drawer.Trigger`) needs a client file.\n *\n * @example\n * <Drawer title=\"Filters\">\n * <Drawer.Trigger><Button>Filters</Button></Drawer.Trigger>\n * <FilterForm />\n * <Drawer.Close><Button appearance=\"primary\">Apply</Button></Drawer.Close>\n * </Drawer>\n */\nexport const Drawer = /* @__PURE__ */ Object.assign(DrawerRoot, {\n Trigger: DrawerTrigger,\n Close: DrawerClose,\n Title: DrawerTitle,\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"Drawer.mjs","names":["Drawer","DrawerRoot","DrawerTrigger","DrawerClose","DrawerTitle","DrawerHeader","DrawerHeaderTitle","DrawerHeaderNavigation","DrawerBody","DrawerFooter"],"sources":["../../../src/components/overlays/Drawer.tsx"],"sourcesContent":["import {\n DrawerBody,\n DrawerClose,\n DrawerFooter,\n DrawerHeader,\n DrawerHeaderNavigation,\n DrawerHeaderTitle,\n DrawerTitle,\n DrawerTrigger,\n} from './Drawer.parts';\nimport { DrawerRoot } from './Drawer.root';\n\nexport type {\n DrawerPosition,\n DrawerSize,\n DrawerType,\n DrawerModalType,\n DrawerOpenChangeReason,\n DrawerOpenChangeDetails,\n} from './Drawer.context';\nexport type { DrawerProps } from './Drawer.root';\nexport type {\n DrawerTriggerProps,\n DrawerTriggerRenderProps,\n DrawerCloseProps,\n DrawerCloseRenderProps,\n DrawerTitleProps,\n DrawerHeaderProps,\n DrawerHeaderTitleProps,\n DrawerHeaderNavigationProps,\n DrawerBodyProps,\n DrawerFooterProps,\n} from './Drawer.parts';\n\n/**\n * A side or bottom panel (Fluent UI v2 style): by default an overlay, modal unless it is\n * non-modal, rendered in a portal (inheriting the WaveProvider theme) while open; with\n * `type=\"inline\"` a panel in the page layout, rendered in place. With `unmountOnClose={false}`\n * either kind stays mounted while closed, `hidden` and `inert`.\n *\n * - **Opening**: controlled (`open`), or uncontrolled with a `Drawer.Trigger` placed directly inside\n * the Drawer or in a Fragment there (it renders in place, outside the panel); the trigger opens\n * and closes it.\n * - **Modal**: focus moves into the panel and Tab stays inside it (toasts included), the rest of the\n * page is `inert` (instead of `aria-modal`), and the page does not scroll. `modalType=\"alert\"`\n * renders `role=\"alertdialog\"`, and a backdrop press does not close it.\n * - **Non-modal**: `modalType=\"non-modal\"` leaves the page usable (no backdrop, no focus trap,\n * nothing inert, the page scrolls). Focus moves in on open; Tab and Shift+Tab leave the panel in\n * the page's order right after the element that opened it; Escape closes it only while focus is\n * inside it; presses on the page never close it; focus returns to the opener only from inside.\n * Reserve the panel's room in the page layout while it is open, so it hides no page control.\n * - **Inline**: `type=\"inline\"` renders the panel where the Drawer is, after its direct triggers,\n * as an `<aside>` (a complementary landmark named by its title), also in the server HTML. It is\n * page content: no portal, backdrop, focus trap, inert page or scroll lock, and toasts keep\n * their corner next to it. Its trigger toggles it (with `aria-expanded` and `aria-controls`, no\n * `aria-haspopup`); opening it moves no focus; Escape and presses outside never close it;\n * closing it returns focus only when focus was inside. `position` picks its inner edge and\n * `size` its width (its height at the bottom); `separator` draws the inner edge. Place it in\n * your layout, for example a flex row of the panel and the page content. Changing `type`\n * remounts the panel and its content.\n * - **Closing**: Escape (only the topmost layer: a popup opened inside closes first), a click on the\n * backdrop (a drag that starts inside does not close it), the Close button and `Drawer.Close`\n * (an inline drawer: the trigger, the Close button and `Drawer.Close`).\n * `onOpenChange` gets the reason as its second argument (`details.reason`), so a controlled\n * drawer can refuse some of them. A backdrop press blurs the focused field before the drawer\n * closes, so a typed value is committed as with the Close button; when a controlled drawer\n * refuses the press, the field gets focus back. Focus returns to the first of these that can\n * take focus: `finalFocusRef`, the element that had focus when the drawer opened, the trigger,\n * an element next to where that opener was.\n * - **Size and position**: `position` is `end` (default) or `start`, which follow the text\n * direction, `left` or `right`, or `bottom` (along the bottom edge, the window wide). `size` sets\n * the width at a side and the height at the bottom: `small` (default, 320px), `medium` (592px),\n * `large` (940px) or `full`; the panel never grows past the window (an inline one past its\n * container). A width class in `className` (a height class for `bottom`) replaces the size. An\n * overlay panel pads the safe-area insets of the screen edges it touches (the iOS home\n * indicator, once the page sets `viewport-fit=cover`). Both render as `data-position` and\n * `data-size`, next to `data-type`.\n * - **Layout**: the `title` prop and the built-in Close button make the header row; a\n * `Drawer.Header` replaces it, with a `Drawer.HeaderNavigation` row (a Back button, commands)\n * and a `Drawer.HeaderTitle` (the heading, an `action` area and the Close button). The rest of\n * the content scrolls in the body (`Drawer.Body` gives it your props); a `Drawer.Footer` is an\n * action row below the body that never scrolls. Make the parts direct children of the Drawer (a\n * Fragment there is fine). The header draws a line under itself once the body is scrolled, the\n * footer one above itself while content continues below: the body, the header and the footer\n * render the body's scroll state as `data-scroll-state` (`none`, `top`, `middle`, `bottom`).\n * - **Backdrop, Close button and title actions**: the backdrop is the panel's sibling and a slot\n * (`backdrop`: `null` removes it, `appearance` picks `dimmed` or `transparent`); a modal opened\n * over another modal dims the page once. `closeButton` sets the content of every built-in Close\n * button, or hides them (`null`); a button passed there is merged into it. `titleAction` places\n * header buttons between the `title` heading and the Close button.\n * - **Kept mounted**: `unmountOnClose={false}` keeps the panel and its content mounted while the\n * drawer is closed, so a form keeps what was typed and the components inside keep their state;\n * each open of an overlay focuses the first focusable element again (an `autoFocus` inside never\n * applies), and a kept overlay opened while another overlay is open stacks above it. A kept\n * inline drawer is in the server HTML, hidden.\n * - **Presence**: the panel and the backdrop mount through the presence core and render\n * `data-presence` (`entered` while open, `exited` while kept closed); the backdrop and the\n * panel (an inline drawer's `<aside>`) are `inert` while exiting and `hidden` and `inert` while\n * kept closed. No motion ships:\n * `data-[presence=…]:` classes in `className` animate the panel, whose motion a closed drawer\n * waits for before it unmounts or hides (focus, the trap and the isolation follow the open\n * state at once).\n *\n * The sub-components are also exported under flat names (`DrawerTrigger`, `DrawerClose`,\n * `DrawerTitle`, `DrawerHeader`, `DrawerHeaderTitle`, `DrawerHeaderNavigation`, `DrawerBody`,\n * `DrawerFooter`) for React Server Components, which cannot use the dotted form; dotted access\n * (`Drawer.Trigger`) needs a client file.\n *\n * @example\n * <Drawer>\n * <Drawer.Trigger><Button>Filters</Button></Drawer.Trigger>\n * <Drawer.Header>\n * <Drawer.HeaderTitle>Filters</Drawer.HeaderTitle>\n * </Drawer.Header>\n * <FilterForm id=\"filters\" />\n * <Drawer.Footer>\n * <Button appearance=\"primary\" type=\"submit\" form=\"filters\">Apply</Button>\n * <Drawer.Close><Button>Cancel</Button></Drawer.Close>\n * </Drawer.Footer>\n * </Drawer>\n */\nexport const Drawer = /* @__PURE__ */ Object.assign(DrawerRoot, {\n Trigger: DrawerTrigger,\n Close: DrawerClose,\n Title: DrawerTitle,\n Header: DrawerHeader,\n HeaderTitle: DrawerHeaderTitle,\n HeaderNavigation: DrawerHeaderNavigation,\n Body: DrawerBody,\n Footer: DrawerFooter,\n});\n\nexport {\n DrawerTrigger,\n DrawerClose,\n DrawerTitle,\n DrawerHeader,\n DrawerHeaderTitle,\n DrawerHeaderNavigation,\n DrawerBody,\n DrawerFooter,\n};\n"],"mappings":";;;;AAyHA,IAAaA,IAAyB,uBAAO,OAAOC,GAAY;CAC9D,SAASC;CACT,OAAOC;CACP,OAAOC;CACP,QAAQC;CACR,aAAaC;CACb,kBAAkBC;CAClB,MAAMC;CACN,QAAQC;AACV,CAAC"}
@@ -0,0 +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/composeEventHandlers.cjs"),i=require("../../hooks/useMergedRefs.cjs"),a=require("../../hooks/useIsClient.cjs"),o=require("../../hooks/usePresence.cjs"),s=require("../portal/Portal.cjs"),c=require("../../lib/styles.cjs"),l=require("../../hooks/useRestoreFocus.cjs"),u=require("./Popover.shared.cjs"),d=require("./Dialog.shared.cjs"),ee=require("../../hooks/useModalLayer.cjs"),te=require("./Dialog.slots.cjs");let f=require("react");f=e.__toESM(f,1);let p=require("react/jsx-runtime");function m(e,t){let n=a.useIsClient();return e===`inline`?t:t&&n}function h(e){return e===`bottom`?`height`:`width`}var g={width:{small:`w-80`,medium:`w-148`,large:`w-235`,full:`w-full`},height:{small:`h-80`,medium:`h-148`,large:`h-235`,full:`h-full`}},_={start:`border-e`,end:`border-s`,left:`border-r`,right:`border-l`,bottom:`border-t`},v={start:`start-0 top-0 h-full max-w-full`,end:`end-0 top-0 h-full max-w-full`,left:`left-0 top-0 h-full max-w-full`,right:`right-0 top-0 h-full max-w-full`,bottom:`inset-x-0 bottom-0 w-full max-h-full`};function y(e,t){return e===`bottom`&&t!==`full`?`pb-[env(safe-area-inset-bottom)]`:`pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)]`}function ne(e,t){return[v[e],_[e],g[h(e)][t],y(e,t)].join(` `)}var re=[`relative flex min-h-0 shrink-0 flex-col max-w-full bg-background text-foreground`,`border-transparent data-[separator]:border-border`,c.forcedColors.border].join(` `);function b(e,t){let n=h(e);return[_[e],n===`height`?`w-full max-h-full`:``,g[n][t]].filter(Boolean).join(` `)}var ie=`fixed flex flex-col border-border bg-background text-foreground shadow-64`,x=({componentName:e,type:a,open:c,requestOpen:m,position:h,size:g,separator:_,modalType:v,unmountOnClose:y,inlineAs:x,trigger:S,finalFocusRef:C,rootClassName:w,backdropClassName:T,backdrop:E,id:D,className:O,onKeyDown:k,ref:A,children:j,...M})=>{let N=a===`inline`,P=!N,F=v===`non-modal`,I=P&&F,L=!y,{isMounted:R,ref:z,presenceProps:B}=o.usePresence(c,{unmountOnExit:y}),[V,H]=f.useState(null),[U,W]=f.useState(null),G=f.useRef(null),K=f.useCallback(e=>{if(e)return G.current=e,H(e),()=>{G.current===e&&(G.current=null),H(null)}},[]),q=f.useCallback(e=>{if(e)return G.current=e,W(e),()=>{G.current===e&&(G.current=null),W(null)}},[]),J=i.useMergedRefs(A,K,z),ae=i.useMergedRefs(A,q,z);l.useRestoreFocus({enabled:c&&N,container:U,triggerRef:S.focusRef,finalFocusRef:C,requireFocusInside:!0});let Y=f.useRef(null);d.useRaiseOnOpen(c&&P,L,Y);let X=d.useBackdropPress(G,v!==`alert`),oe=d.useModalDismiss(m,e,X.afterOutsidePress),Z=ee.useModalLayer({open:c&&P,modalType:v,onDismiss:oe,refs:[G],container:V,triggerRef:S.focusRef,finalFocusRef:C}),se=d.useModalOpener(c&&P,S,V),ce=u.usePopoverTabOrder({enabled:c&&I,surface:V,anchorRef:se,getPreviousStop:u.getTabbableThrough});d.useOpenInsideWarning(c,L,Z.layerId,e,G);let Q=(F||N)&&E!=null&&typeof E!=`boolean`;f.useEffect(()=>{Q&&n.warnOnce(`${e}:backdrop-ignored`,`${e}: \`backdrop\` is ignored: a non-modal or inline drawer has no backdrop, so the page around it stays usable.`)},[Q,e]);let $=c&&I&&g===`full`;return f.useEffect(()=>{$&&n.warnOnce(`${e}:non-modal-full`,`${e}: \`size="full"\` with \`modalType="non-modal"\` covers the whole page while leaving it usable, so Tab reaches controls hidden behind the drawer. Use \`modalType="modal"\`, \`type="inline"\`, or a smaller size with its room reserved in the page layout.`)},[$,e]),R?N?(0,p.jsx)(x,{ref:ae,id:D,"data-type":`inline`,"data-position":h,"data-size":g,"data-separator":_?``:void 0,...M,...B,onKeyDown:k,className:t.cn(w,re,b(h,g),O),children:j}):(0,p.jsxs)(s.Portal,{ref:Y,layerId:Z.layerId,children:[!F&&(0,p.jsx)(te.ModalBackdrop,{backdrop:E,className:T,layerId:Z.layerId,open:c,onMouseDown:X.onMouseDown,presenceProps:B}),(0,p.jsx)(`div`,{ref:J,role:v===`alert`?`alertdialog`:`dialog`,id:D,tabIndex:-1,"data-type":`overlay`,"data-position":h,"data-size":g,"data-modal-type":v,...M,...B,onKeyDown:r.composeEventHandlers(k,ce),className:t.cn(w,ie,ne(h,g),O),children:j})]}):null};x.displayName=`DrawerPanel`,exports.DrawerPanel=x,exports.useDrawerOpen=m;
2
+ //# sourceMappingURL=Drawer.panel.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Drawer.panel.cjs","names":["useIsClient","forcedColors","usePresence","React","useMergedRefs","useBackdropPress","useModalDismiss","useModalLayer","useModalOpener","usePopoverTabOrder","getTabbableThrough","InlinePanel","cn","Portal","ModalBackdrop","composeEventHandlers","require_runtime","require_cn","require_dev","require_composeEventHandlers","require_useMergedRefs","require_useIsClient","require_usePresence","require_Portal","require_styles","require_useRestoreFocus","require_Popover_shared","require_Dialog_shared","require_useModalLayer","require_Dialog_slots","react","react_jsx_runtime","useDrawerOpen","isClient","type","openState","getDrawerSizeAxis","position","drawerSizeClasses","drawerEdgeClasses","overlayPlacementClasses","getOverlayInsetClasses","size","getOverlayPanelClasses","inlinePanelClasses","getInlinePanelClasses","axis","OVERLAY_PANEL_CLASSES","DrawerPanel","rest","inline","overlay","nonModal","modalType","nonModalOverlay","keptMounted","unmountOnClose","presenceRef","open","overlayPanel","setOverlayPanel","inlinePanel","setInlinePanel","panelRef","attachOverlayPanel","node","attachInlinePanel","overlayRef","ref","inlineRef","trigger","portalRef","backdropPress","onDismiss","requestOpen","componentName","layer","opener","onTabOrderKeyDown","backdropIgnored","backdrop","coversUsablePage","isMounted","inlineAs","separator","presenceProps","rootClassName","className","backdropClassName","onKeyDown"],"sources":["../../../src/components/overlays/Drawer.panel.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport type { Slot, SlotObject } from '../../lib/slot';\nimport { forcedColors } from '../../lib/styles';\nimport type { BackdropAppearance, ModalType } from '../../lib/types';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useModalLayer } from '../../hooks/useModalLayer';\nimport { usePresence } from '../../hooks/usePresence';\nimport { useRestoreFocus } from '../../hooks/useRestoreFocus';\nimport { Portal } from '../portal/Portal';\nimport {\n useBackdropPress,\n useModalDismiss,\n useModalOpener,\n useOpenInsideWarning,\n useRaiseOnOpen,\n type ModalRequestOpen,\n type ModalTrigger,\n} from './Dialog.shared';\nimport { ModalBackdrop } from './Dialog.slots';\nimport type { DrawerPosition, DrawerSize, DrawerType } from './Drawer.context';\nimport { getTabbableThrough, usePopoverTabOrder } from './Popover.shared';\n\n/*\n * The drawer panel shell (D108): the panel element of both drawer types with its machinery, its\n * open state, and its placement, size and safe-area classes. Drawer's root and NavDrawer render it.\n * Imports the context module only among the Drawer modules (never the root, the parts or\n * `Drawer.tsx`), and no Nav module.\n */\n\n/**\n * The open state a drawer reports (its triggers' `aria-expanded`, its contexts): an inline\n * drawer's state as it is; an overlay's `false` until the page has hydrated (the portal renders\n * only in the browser), so the server HTML never points `aria-controls` at a panel that is not\n * there.\n */\nexport function useDrawerOpen(type: DrawerType, openState: boolean): boolean {\n const isClient = useIsClient();\n return type === 'inline' ? openState : openState && isClient;\n}\n\n/** The axis a drawer's `size` applies to: the width at a side, the height at the bottom. */\ntype DrawerSizeAxis = 'width' | 'height';\n\n/** The axis `size` sets for a drawer at `position`. */\nfunction getDrawerSizeAxis(position: DrawerPosition): DrawerSizeAxis {\n return position === 'bottom' ? 'height' : 'width';\n}\n\n/**\n * The size classes, keyed by axis: 320px, 592px and 940px on the spacing scale (rem, so they\n * follow the user's font size), and `full` the whole axis. A width (height) class in the\n * consumer's `className` replaces the size, as the consumer's class comes last in `cn()`.\n */\nconst drawerSizeClasses: Readonly<Record<DrawerSizeAxis, Readonly<Record<DrawerSize, string>>>> = {\n width: { small: 'w-80', medium: 'w-148', large: 'w-235', full: 'w-full' },\n height: { small: 'h-80', medium: 'h-148', large: 'h-235', full: 'h-full' },\n};\n\n/**\n * A border on the panel's inner edge (the one facing the page): it marks the panel where the\n * shadow cannot, in high contrast (page, backdrop and panel are black) and in forced colors\n * (which drop shadows).\n */\nconst drawerEdgeClasses: Readonly<Record<DrawerPosition, string>> = {\n start: 'border-e',\n end: 'border-s',\n left: 'border-r', // wave-allow-physical: the consumer asked for the physical left edge\n right: 'border-l', // wave-allow-physical: the consumer asked for the physical right edge\n bottom: 'border-t',\n};\n\n/**\n * Where an overlay panel is pinned: a side panel spans the window's height, a bottom one its\n * width; neither grows past the window (a size larger than the screen acts as `full`).\n */\nconst overlayPlacementClasses: Readonly<Record<DrawerPosition, string>> = {\n start: 'start-0 top-0 h-full max-w-full',\n end: 'end-0 top-0 h-full max-w-full',\n left: 'left-0 top-0 h-full max-w-full', // wave-allow-physical: the consumer asked for the physical left edge\n right: 'right-0 top-0 h-full max-w-full', // wave-allow-physical: the consumer asked for the physical right edge\n bottom: 'inset-x-0 bottom-0 w-full max-h-full',\n};\n\n/**\n * The safe-area insets of the screen edges an overlay panel touches (the iOS home indicator, a\n * notch; `0` unless the page sets `viewport-fit=cover`). The panel has no padding of its own, so\n * the inset is the whole padding. A side panel touches the top and bottom edges; a bottom panel\n * the bottom edge, and the top one too at `full`. The side insets (a landscape notch) are not\n * padded.\n */\nfunction getOverlayInsetClasses(position: DrawerPosition, size: DrawerSize): string {\n if (position === 'bottom' && size !== 'full') return 'pb-[env(safe-area-inset-bottom)]';\n return 'pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)]';\n}\n\n/**\n * The classes that place and size an overlay panel at `position`: the placement, the inner-edge\n * border, the size on the position's axis and the safe-area insets. They go after the panel's\n * base classes and before the consumer's `className`.\n */\nfunction getOverlayPanelClasses(position: DrawerPosition, size: DrawerSize): string {\n return [\n overlayPlacementClasses[position],\n drawerEdgeClasses[position],\n drawerSizeClasses[getDrawerSizeAxis(position)][size],\n getOverlayInsetClasses(position, size),\n ].join(' ');\n}\n\n/**\n * The base classes of an inline panel: an element of the page layout that keeps its width in a\n * flex row and lets its body scroll once the layout bounds its height. Its inner edge is\n * transparent unless the Drawer has `separator` (`data-separator`), and always drawn in forced\n * colors.\n */\nconst inlinePanelClasses = [\n 'relative flex min-h-0 shrink-0 flex-col max-w-full bg-background text-foreground',\n 'border-transparent data-[separator]:border-border',\n forcedColors.border,\n].join(' ');\n\n/**\n * The classes that place and size an inline panel at `position`: the inner-edge border and the\n * size on the position's axis (a bottom panel is as wide as its container and never taller than\n * it). `full` is the container's width (height). No placement, insets or shadow: where the panel\n * sits is up to the page layout. They go after {@link inlinePanelClasses} and before the\n * consumer's `className`.\n */\nfunction getInlinePanelClasses(position: DrawerPosition, size: DrawerSize): string {\n const axis = getDrawerSizeAxis(position);\n return [\n drawerEdgeClasses[position],\n axis === 'height' ? 'w-full max-h-full' : '',\n drawerSizeClasses[axis][size],\n ]\n .filter(Boolean)\n .join(' ');\n}\n\n/** What the drawer panel shell renders and wires (the frozen contract of D108). */\nexport interface DrawerPanelProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The public component, for the warning keys and texts: `'Drawer'`, `'NavDrawer'`\n * (`<componentName>:open-inside`, `:backdrop-ignored`, `:focus-outside`, `:non-modal-full`).\n */\n componentName: string;\n /**\n * `'overlay'`: a portal, the backdrop, `role=\"dialog\"` and the modal or non-modal machinery;\n * `'inline'`: the panel in place, with the inline focus restore only.\n */\n type: DrawerType;\n /** The reported open state, from {@link useDrawerOpen}. */\n open: boolean;\n /** The root's request function (`useModalOpenState`): Escape and the backdrop ask through it. */\n requestOpen: ModalRequestOpen;\n /** Rendered as `data-position`; picks the overlay's edge or the inline panel's inner edge. */\n position: DrawerPosition;\n /** Rendered as `data-size` (always: the component resolves its own default). */\n size: DrawerSize;\n /** Inline only: draws the inner edge (`data-separator`). Ignored by an overlay. */\n separator: boolean;\n /**\n * Overlay only: `modal`, `alert` or `non-modal` (`data-modal-type`, the role and the layer kind).\n * Ignored inline.\n */\n modalType: ModalType;\n /** `false` keeps the panel mounted while closed, `hidden` and `inert`. */\n unmountOnClose: boolean;\n /**\n * The element of an inline panel: `'aside'` (Drawer, a complementary landmark) or `'div'`\n * (NavDrawer, whose `<nav>` is the landmark).\n */\n inlineAs: 'aside' | 'div';\n /**\n * The root's triggers (`useModalTrigger()`), or `inertModalTrigger` for a component without\n * trigger parts (the layer and the inline restore then capture the element that had focus).\n */\n trigger: ModalTrigger;\n /** Where focus goes when the panel closes, if it can take focus (the root's `finalFocusRef`). */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * The panel's stable class(es), first in its `cn()`: `drawerClassNames.root`, followed by a\n * variant's root (`cn(drawerClassNames.root, navDrawerClassNames.root)`).\n */\n rootClassName: string;\n /**\n * The backdrop's stable class(es), first in its `cn()`: `drawerClassNames.backdrop`, followed by\n * a variant's (`cn(drawerClassNames.backdrop, navDrawerClassNames.backdrop)`).\n */\n backdropClassName: string;\n /**\n * The `backdrop` slot (overlay `modal` and `alert` only; a slot on a non-modal or inline panel\n * renders nothing and warns). `null` renders no backdrop.\n */\n backdrop?: Slot<'div'> | (SlotObject<'div'> & { appearance?: BackdropAppearance });\n /** The panel's id (always set: triggers point `aria-controls` at it). */\n id: string;\n /** Merged with the shell's own ref and the presence ref. */\n ref?: React.Ref<HTMLElement>;\n /** The panel's content, rendered as is: the shell adds no header, Close button or padding. */\n children?: React.ReactNode;\n}\n\n/**\n * The classes every overlay panel carries after its stable class: a fixed flex column on the\n * page's background with the overlay shadow, its inner edge in the border colour.\n */\nconst OVERLAY_PANEL_CLASSES =\n 'fixed flex flex-col border-border bg-background text-foreground shadow-64';\n\n/**\n * The drawer panel shell: the panel element of an overlay (in a portal, with its backdrop and the\n * modal or non-modal machinery) or of an inline drawer (in place, with the inline focus restore),\n * on the presence core, with the placement, size, separator and safe-area classes and the\n * `data-type`, `data-position`, `data-size`, `data-modal-type`, `data-separator` and\n * `data-presence` attributes. Returns `null` while unmounted. Its hooks key on `open`.\n *\n * It renders its `children` raw and provides no context: no header, title registry, Close button\n * or padding. The component that renders it holds the open state (`useModalOpenState`, then\n * {@link useDrawerOpen}), renders its triggers itself, names the panel, and calls\n * `useModalTriggerSession(trigger, open)` after rendering it (the shell's effects run first). A\n * change of `type` remounts the panel and its content.\n */\nexport const DrawerPanel = ({\n componentName,\n type,\n open,\n requestOpen,\n position,\n size,\n separator,\n modalType,\n unmountOnClose,\n inlineAs,\n trigger,\n finalFocusRef,\n rootClassName,\n backdropClassName,\n backdrop,\n id,\n className,\n onKeyDown,\n ref,\n children,\n ...rest\n}: DrawerPanelProps): React.ReactNode => {\n const inline = type === 'inline';\n const overlay = !inline;\n const nonModal = modalType === 'non-modal';\n const nonModalOverlay = overlay && nonModal;\n const keptMounted = !unmountOnClose;\n // The panel mounts through the presence core (D5, D103), with no motion of its own: kept mounted\n // 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\n // The panel element of each type, held in state through its own callback ref. A change of `type`\n // remounts the panel (D105): the overlay's hooks see only the portaled element and the inline\n // restore only the inline one, also in the commit that swaps them (the inline restore then still\n // knows the panel that focus was lost from).\n const [overlayPanel, setOverlayPanel] = React.useState<HTMLElement | null>(null);\n const [inlinePanel, setInlinePanel] = React.useState<HTMLElement | null>(null);\n // The mounted panel of either type; each element clears it only while it is still the one held.\n const panelRef = React.useRef<HTMLElement | null>(null);\n const attachOverlayPanel = React.useCallback((node: HTMLElement | null) => {\n if (!node) return undefined;\n panelRef.current = node;\n setOverlayPanel(node);\n return () => {\n if (panelRef.current === node) panelRef.current = null;\n setOverlayPanel(null);\n };\n }, []);\n const attachInlinePanel = React.useCallback((node: HTMLElement | null) => {\n if (!node) return undefined;\n panelRef.current = node;\n setInlinePanel(node);\n return () => {\n if (panelRef.current === node) panelRef.current = null;\n setInlinePanel(null);\n };\n }, []);\n const overlayRef = useMergedRefs<HTMLElement>(ref, attachOverlayPanel, presenceRef);\n const inlineRef = useMergedRefs<HTMLElement>(ref, attachInlinePanel, presenceRef);\n\n // An inline panel takes no focus on open and returns it on close only from inside (D101). Called\n // before useModalLayer: on a switch from inline to overlay it restores before the overlay's trap\n // moves focus in.\n useRestoreFocus({\n enabled: open && inline,\n container: inlinePanel,\n triggerRef: trigger.focusRef,\n finalFocusRef,\n requireFocusInside: true,\n });\n // The portal wrapper: a kept-mounted overlay moves to the top of its stack when it opens (D104),\n // before the layer registers and the trap moves focus in.\n const portalRef = React.useRef<HTMLDivElement | null>(null);\n useRaiseOnOpen(open && overlay, keptMounted, portalRef);\n\n // A backdrop press asks to close, except an alert's (Escape still does; useModalLayer registers\n // its layer without outside presses).\n const backdropPress = useBackdropPress(panelRef, modalType !== 'alert');\n const onDismiss = useModalDismiss(requestOpen, componentName, backdropPress.afterOutsidePress);\n // Only an overlay is a layer: an inline panel is page content (no trap, isolation, scroll lock,\n // Escape or outside press; toasts keep their corner). The overlay's layer is the one the Toaster\n // measures (`modal`, or `dialog` for a non-modal one).\n const layer = useModalLayer({\n open: open && overlay,\n modalType,\n onDismiss,\n refs: [panelRef],\n container: overlayPanel,\n triggerRef: trigger.focusRef,\n finalFocusRef,\n });\n // A non-modal overlay keeps its place in the page's keyboard order right after its opener\n // (D87.5). Both hooks are always called (C-HOOKS, D91). The opener is captured whenever the\n // overlay opens, so a modal panel that turns non-modal while open (focus inside it by then)\n // still knows it.\n const opener = useModalOpener(open && overlay, trigger, overlayPanel);\n const onTabOrderKeyDown = usePopoverTabOrder({\n enabled: open && nonModalOverlay,\n surface: overlayPanel,\n anchorRef: opener,\n getPreviousStop: getTabbableThrough,\n });\n // A popup opened inside a kept-mounted panel that is still open when the panel closes (D106).\n useOpenInsideWarning(open, keptMounted, layer.layerId, componentName, panelRef);\n // A non-modal or inline panel has no backdrop: a given slot (not undefined, null or a boolean)\n // is ignored.\n const backdropIgnored =\n (nonModal || inline) &&\n backdrop !== undefined &&\n backdrop !== null &&\n typeof backdrop !== 'boolean';\n React.useEffect(() => {\n if (!backdropIgnored) return;\n warnOnce(\n `${componentName}:backdrop-ignored`,\n `${componentName}: \\`backdrop\\` is ignored: a non-modal or inline drawer has no backdrop, so the page around it stays usable.`,\n );\n }, [backdropIgnored, componentName]);\n // A full non-modal overlay covers the page it leaves usable (D87.8).\n const coversUsablePage = open && nonModalOverlay && size === 'full';\n React.useEffect(() => {\n if (!coversUsablePage) return;\n warnOnce(\n `${componentName}:non-modal-full`,\n `${componentName}: \\`size=\"full\"\\` with \\`modalType=\"non-modal\"\\` covers the whole page while leaving it usable, so Tab reaches controls hidden behind the drawer. Use \\`modalType=\"modal\"\\`, \\`type=\"inline\"\\`, or a smaller size with its room reserved in the page layout.`,\n );\n }, [coversUsablePage, componentName]);\n\n if (!isMounted) return null;\n\n if (inline) {\n const InlinePanel = inlineAs;\n // In place: no role, tabIndex or modal attributes (D100). The presence attributes come after\n // the consumer's props: hidden and inert while kept closed.\n return (\n <InlinePanel\n ref={inlineRef}\n id={id}\n data-type=\"inline\"\n data-position={position}\n data-size={size}\n data-separator={separator ? '' : undefined}\n {...rest}\n {...presenceProps}\n onKeyDown={onKeyDown}\n className={cn(\n rootClassName,\n inlinePanelClasses,\n getInlinePanelClasses(position, size),\n className,\n )}\n >\n {children}\n </InlinePanel>\n );\n }\n\n return (\n <Portal ref={portalRef} layerId={layer.layerId}>\n {/* The backdrop of a modal or alert panel, the panel's sibling; a non-modal one has none.\n Both carry the presence attributes (D7, D103): hidden and inert while kept closed, so a\n closed panel leaves no backdrop over the page. */}\n {!nonModal && (\n <ModalBackdrop\n backdrop={backdrop}\n className={backdropClassName}\n layerId={layer.layerId}\n open={open}\n onMouseDown={backdropPress.onMouseDown}\n presenceProps={presenceProps}\n />\n )}\n <div\n ref={overlayRef}\n role={modalType === 'alert' ? 'alertdialog' : 'dialog'}\n id={id}\n tabIndex={-1}\n data-type=\"overlay\"\n data-position={position}\n data-size={size}\n data-modal-type={modalType}\n {...rest}\n {...presenceProps}\n onKeyDown={composeEventHandlers(onKeyDown, onTabOrderKeyDown)}\n className={cn(\n rootClassName,\n OVERLAY_PANEL_CLASSES,\n getOverlayPanelClasses(position, size),\n className,\n )}\n >\n {children}\n </div>\n </Portal>\n );\n};\nDrawerPanel.displayName = 'DrawerPanel';\n"],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ "use client";
2
+ import { cn as e } from "../../lib/cn.mjs";
3
+ import { warnOnce as t } from "../../lib/dev.mjs";
4
+ import { composeEventHandlers as n } from "../../lib/composeEventHandlers.mjs";
5
+ import { useMergedRefs as r } from "../../hooks/useMergedRefs.mjs";
6
+ import { useIsClient as i } from "../../hooks/useIsClient.mjs";
7
+ import { usePresence as ee } from "../../hooks/usePresence.mjs";
8
+ import { Portal as te } from "../portal/Portal.mjs";
9
+ import { forcedColors as a } from "../../lib/styles.mjs";
10
+ import { useRestoreFocus as ne } from "../../hooks/useRestoreFocus.mjs";
11
+ import { getTabbableThrough as re, usePopoverTabOrder as o } from "./Popover.shared.mjs";
12
+ import { useBackdropPress as s, useModalDismiss as c, useModalOpener as l, useOpenInsideWarning as u, useRaiseOnOpen as d } from "./Dialog.shared.mjs";
13
+ import { useModalLayer as ie } from "../../hooks/useModalLayer.mjs";
14
+ import { ModalBackdrop as ae } from "./Dialog.slots.mjs";
15
+ import * as f from "react";
16
+ import { jsx as p, jsxs as oe } from "react/jsx-runtime";
17
+ //#region src/components/overlays/Drawer.panel.tsx
18
+ function m(e, t) {
19
+ let n = i();
20
+ return e === "inline" ? t : t && n;
21
+ }
22
+ function h(e) {
23
+ return e === "bottom" ? "height" : "width";
24
+ }
25
+ var g = {
26
+ width: {
27
+ small: "w-80",
28
+ medium: "w-148",
29
+ large: "w-235",
30
+ full: "w-full"
31
+ },
32
+ height: {
33
+ small: "h-80",
34
+ medium: "h-148",
35
+ large: "h-235",
36
+ full: "h-full"
37
+ }
38
+ }, _ = {
39
+ start: "border-e",
40
+ end: "border-s",
41
+ left: "border-r",
42
+ right: "border-l",
43
+ bottom: "border-t"
44
+ }, v = {
45
+ start: "start-0 top-0 h-full max-w-full",
46
+ end: "end-0 top-0 h-full max-w-full",
47
+ left: "left-0 top-0 h-full max-w-full",
48
+ right: "right-0 top-0 h-full max-w-full",
49
+ bottom: "inset-x-0 bottom-0 w-full max-h-full"
50
+ };
51
+ function y(e, t) {
52
+ return e === "bottom" && t !== "full" ? "pb-[env(safe-area-inset-bottom)]" : "pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)]";
53
+ }
54
+ function b(e, t) {
55
+ return [
56
+ v[e],
57
+ _[e],
58
+ g[h(e)][t],
59
+ y(e, t)
60
+ ].join(" ");
61
+ }
62
+ var x = [
63
+ "relative flex min-h-0 shrink-0 flex-col max-w-full bg-background text-foreground",
64
+ "border-transparent data-[separator]:border-border",
65
+ a.border
66
+ ].join(" ");
67
+ function S(e, t) {
68
+ let n = h(e);
69
+ return [
70
+ _[e],
71
+ n === "height" ? "w-full max-h-full" : "",
72
+ g[n][t]
73
+ ].filter(Boolean).join(" ");
74
+ }
75
+ var C = "fixed flex flex-col border-border bg-background text-foreground shadow-64", w = ({ componentName: i, type: a, open: m, requestOpen: h, position: g, size: _, separator: v, modalType: y, unmountOnClose: w, inlineAs: T, trigger: E, finalFocusRef: D, rootClassName: O, backdropClassName: se, backdrop: k, id: A, className: j, onKeyDown: M, ref: N, children: P, ...F }) => {
76
+ let I = a === "inline", L = !I, R = y === "non-modal", z = L && R, B = !w, { isMounted: V, ref: H, presenceProps: U } = ee(m, { unmountOnExit: w }), [W, G] = f.useState(null), [ce, K] = f.useState(null), q = f.useRef(null), le = f.useCallback((e) => {
77
+ if (e) return q.current = e, G(e), () => {
78
+ q.current === e && (q.current = null), G(null);
79
+ };
80
+ }, []), ue = f.useCallback((e) => {
81
+ if (e) return q.current = e, K(e), () => {
82
+ q.current === e && (q.current = null), K(null);
83
+ };
84
+ }, []), de = r(N, le, H), fe = r(N, ue, H);
85
+ ne({
86
+ enabled: m && I,
87
+ container: ce,
88
+ triggerRef: E.focusRef,
89
+ finalFocusRef: D,
90
+ requireFocusInside: !0
91
+ });
92
+ let J = f.useRef(null);
93
+ d(m && L, B, J);
94
+ let Y = s(q, y !== "alert"), X = c(h, i, Y.afterOutsidePress), Z = ie({
95
+ open: m && L,
96
+ modalType: y,
97
+ onDismiss: X,
98
+ refs: [q],
99
+ container: W,
100
+ triggerRef: E.focusRef,
101
+ finalFocusRef: D
102
+ }), pe = l(m && L, E, W), me = o({
103
+ enabled: m && z,
104
+ surface: W,
105
+ anchorRef: pe,
106
+ getPreviousStop: re
107
+ });
108
+ u(m, B, Z.layerId, i, q);
109
+ let Q = (R || I) && k != null && typeof k != "boolean";
110
+ f.useEffect(() => {
111
+ Q && t(`${i}:backdrop-ignored`, `${i}: \`backdrop\` is ignored: a non-modal or inline drawer has no backdrop, so the page around it stays usable.`);
112
+ }, [Q, i]);
113
+ let $ = m && z && _ === "full";
114
+ return f.useEffect(() => {
115
+ $ && t(`${i}:non-modal-full`, `${i}: \`size="full"\` with \`modalType="non-modal"\` covers the whole page while leaving it usable, so Tab reaches controls hidden behind the drawer. Use \`modalType="modal"\`, \`type="inline"\`, or a smaller size with its room reserved in the page layout.`);
116
+ }, [$, i]), V ? I ? /* @__PURE__ */ p(T, {
117
+ ref: fe,
118
+ id: A,
119
+ "data-type": "inline",
120
+ "data-position": g,
121
+ "data-size": _,
122
+ "data-separator": v ? "" : void 0,
123
+ ...F,
124
+ ...U,
125
+ onKeyDown: M,
126
+ className: e(O, x, S(g, _), j),
127
+ children: P
128
+ }) : /* @__PURE__ */ oe(te, {
129
+ ref: J,
130
+ layerId: Z.layerId,
131
+ children: [!R && /* @__PURE__ */ p(ae, {
132
+ backdrop: k,
133
+ className: se,
134
+ layerId: Z.layerId,
135
+ open: m,
136
+ onMouseDown: Y.onMouseDown,
137
+ presenceProps: U
138
+ }), /* @__PURE__ */ p("div", {
139
+ ref: de,
140
+ role: y === "alert" ? "alertdialog" : "dialog",
141
+ id: A,
142
+ tabIndex: -1,
143
+ "data-type": "overlay",
144
+ "data-position": g,
145
+ "data-size": _,
146
+ "data-modal-type": y,
147
+ ...F,
148
+ ...U,
149
+ onKeyDown: n(M, me),
150
+ className: e(O, C, b(g, _), j),
151
+ children: P
152
+ })]
153
+ }) : null;
154
+ };
155
+ w.displayName = "DrawerPanel";
156
+ //#endregion
157
+ export { w as DrawerPanel, m as useDrawerOpen };
158
+
159
+ //# sourceMappingURL=Drawer.panel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Drawer.panel.mjs","names":["InlinePanel","React","useDrawerOpen","isClient","useIsClient","type","openState","getDrawerSizeAxis","position","drawerSizeClasses","drawerEdgeClasses","overlayPlacementClasses","getOverlayInsetClasses","size","getOverlayPanelClasses","inlinePanelClasses","forcedColors","getInlinePanelClasses","axis","OVERLAY_PANEL_CLASSES","DrawerPanel","rest","inline","overlay","nonModal","modalType","nonModalOverlay","keptMounted","unmountOnClose","presenceRef","usePresence","open","overlayPanel","setOverlayPanel","inlinePanel","setInlinePanel","panelRef","attachOverlayPanel","node","attachInlinePanel","overlayRef","useMergedRefs","ref","inlineRef","trigger","portalRef","backdropPress","useBackdropPress","onDismiss","useModalDismiss","requestOpen","componentName","layer","useModalLayer","opener","useModalOpener","onTabOrderKeyDown","usePopoverTabOrder","getTabbableThrough","backdropIgnored","backdrop","warnOnce","coversUsablePage","isMounted","inlineAs","separator","presenceProps","cn","rootClassName","className","Portal","ModalBackdrop","backdropClassName","composeEventHandlers","onKeyDown"],"sources":["../../../src/components/overlays/Drawer.panel.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport type { Slot, SlotObject } from '../../lib/slot';\nimport { forcedColors } from '../../lib/styles';\nimport type { BackdropAppearance, ModalType } from '../../lib/types';\nimport { useIsClient } from '../../hooks/useIsClient';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useModalLayer } from '../../hooks/useModalLayer';\nimport { usePresence } from '../../hooks/usePresence';\nimport { useRestoreFocus } from '../../hooks/useRestoreFocus';\nimport { Portal } from '../portal/Portal';\nimport {\n useBackdropPress,\n useModalDismiss,\n useModalOpener,\n useOpenInsideWarning,\n useRaiseOnOpen,\n type ModalRequestOpen,\n type ModalTrigger,\n} from './Dialog.shared';\nimport { ModalBackdrop } from './Dialog.slots';\nimport type { DrawerPosition, DrawerSize, DrawerType } from './Drawer.context';\nimport { getTabbableThrough, usePopoverTabOrder } from './Popover.shared';\n\n/*\n * The drawer panel shell (D108): the panel element of both drawer types with its machinery, its\n * open state, and its placement, size and safe-area classes. Drawer's root and NavDrawer render it.\n * Imports the context module only among the Drawer modules (never the root, the parts or\n * `Drawer.tsx`), and no Nav module.\n */\n\n/**\n * The open state a drawer reports (its triggers' `aria-expanded`, its contexts): an inline\n * drawer's state as it is; an overlay's `false` until the page has hydrated (the portal renders\n * only in the browser), so the server HTML never points `aria-controls` at a panel that is not\n * there.\n */\nexport function useDrawerOpen(type: DrawerType, openState: boolean): boolean {\n const isClient = useIsClient();\n return type === 'inline' ? openState : openState && isClient;\n}\n\n/** The axis a drawer's `size` applies to: the width at a side, the height at the bottom. */\ntype DrawerSizeAxis = 'width' | 'height';\n\n/** The axis `size` sets for a drawer at `position`. */\nfunction getDrawerSizeAxis(position: DrawerPosition): DrawerSizeAxis {\n return position === 'bottom' ? 'height' : 'width';\n}\n\n/**\n * The size classes, keyed by axis: 320px, 592px and 940px on the spacing scale (rem, so they\n * follow the user's font size), and `full` the whole axis. A width (height) class in the\n * consumer's `className` replaces the size, as the consumer's class comes last in `cn()`.\n */\nconst drawerSizeClasses: Readonly<Record<DrawerSizeAxis, Readonly<Record<DrawerSize, string>>>> = {\n width: { small: 'w-80', medium: 'w-148', large: 'w-235', full: 'w-full' },\n height: { small: 'h-80', medium: 'h-148', large: 'h-235', full: 'h-full' },\n};\n\n/**\n * A border on the panel's inner edge (the one facing the page): it marks the panel where the\n * shadow cannot, in high contrast (page, backdrop and panel are black) and in forced colors\n * (which drop shadows).\n */\nconst drawerEdgeClasses: Readonly<Record<DrawerPosition, string>> = {\n start: 'border-e',\n end: 'border-s',\n left: 'border-r', // wave-allow-physical: the consumer asked for the physical left edge\n right: 'border-l', // wave-allow-physical: the consumer asked for the physical right edge\n bottom: 'border-t',\n};\n\n/**\n * Where an overlay panel is pinned: a side panel spans the window's height, a bottom one its\n * width; neither grows past the window (a size larger than the screen acts as `full`).\n */\nconst overlayPlacementClasses: Readonly<Record<DrawerPosition, string>> = {\n start: 'start-0 top-0 h-full max-w-full',\n end: 'end-0 top-0 h-full max-w-full',\n left: 'left-0 top-0 h-full max-w-full', // wave-allow-physical: the consumer asked for the physical left edge\n right: 'right-0 top-0 h-full max-w-full', // wave-allow-physical: the consumer asked for the physical right edge\n bottom: 'inset-x-0 bottom-0 w-full max-h-full',\n};\n\n/**\n * The safe-area insets of the screen edges an overlay panel touches (the iOS home indicator, a\n * notch; `0` unless the page sets `viewport-fit=cover`). The panel has no padding of its own, so\n * the inset is the whole padding. A side panel touches the top and bottom edges; a bottom panel\n * the bottom edge, and the top one too at `full`. The side insets (a landscape notch) are not\n * padded.\n */\nfunction getOverlayInsetClasses(position: DrawerPosition, size: DrawerSize): string {\n if (position === 'bottom' && size !== 'full') return 'pb-[env(safe-area-inset-bottom)]';\n return 'pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)]';\n}\n\n/**\n * The classes that place and size an overlay panel at `position`: the placement, the inner-edge\n * border, the size on the position's axis and the safe-area insets. They go after the panel's\n * base classes and before the consumer's `className`.\n */\nfunction getOverlayPanelClasses(position: DrawerPosition, size: DrawerSize): string {\n return [\n overlayPlacementClasses[position],\n drawerEdgeClasses[position],\n drawerSizeClasses[getDrawerSizeAxis(position)][size],\n getOverlayInsetClasses(position, size),\n ].join(' ');\n}\n\n/**\n * The base classes of an inline panel: an element of the page layout that keeps its width in a\n * flex row and lets its body scroll once the layout bounds its height. Its inner edge is\n * transparent unless the Drawer has `separator` (`data-separator`), and always drawn in forced\n * colors.\n */\nconst inlinePanelClasses = [\n 'relative flex min-h-0 shrink-0 flex-col max-w-full bg-background text-foreground',\n 'border-transparent data-[separator]:border-border',\n forcedColors.border,\n].join(' ');\n\n/**\n * The classes that place and size an inline panel at `position`: the inner-edge border and the\n * size on the position's axis (a bottom panel is as wide as its container and never taller than\n * it). `full` is the container's width (height). No placement, insets or shadow: where the panel\n * sits is up to the page layout. They go after {@link inlinePanelClasses} and before the\n * consumer's `className`.\n */\nfunction getInlinePanelClasses(position: DrawerPosition, size: DrawerSize): string {\n const axis = getDrawerSizeAxis(position);\n return [\n drawerEdgeClasses[position],\n axis === 'height' ? 'w-full max-h-full' : '',\n drawerSizeClasses[axis][size],\n ]\n .filter(Boolean)\n .join(' ');\n}\n\n/** What the drawer panel shell renders and wires (the frozen contract of D108). */\nexport interface DrawerPanelProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The public component, for the warning keys and texts: `'Drawer'`, `'NavDrawer'`\n * (`<componentName>:open-inside`, `:backdrop-ignored`, `:focus-outside`, `:non-modal-full`).\n */\n componentName: string;\n /**\n * `'overlay'`: a portal, the backdrop, `role=\"dialog\"` and the modal or non-modal machinery;\n * `'inline'`: the panel in place, with the inline focus restore only.\n */\n type: DrawerType;\n /** The reported open state, from {@link useDrawerOpen}. */\n open: boolean;\n /** The root's request function (`useModalOpenState`): Escape and the backdrop ask through it. */\n requestOpen: ModalRequestOpen;\n /** Rendered as `data-position`; picks the overlay's edge or the inline panel's inner edge. */\n position: DrawerPosition;\n /** Rendered as `data-size` (always: the component resolves its own default). */\n size: DrawerSize;\n /** Inline only: draws the inner edge (`data-separator`). Ignored by an overlay. */\n separator: boolean;\n /**\n * Overlay only: `modal`, `alert` or `non-modal` (`data-modal-type`, the role and the layer kind).\n * Ignored inline.\n */\n modalType: ModalType;\n /** `false` keeps the panel mounted while closed, `hidden` and `inert`. */\n unmountOnClose: boolean;\n /**\n * The element of an inline panel: `'aside'` (Drawer, a complementary landmark) or `'div'`\n * (NavDrawer, whose `<nav>` is the landmark).\n */\n inlineAs: 'aside' | 'div';\n /**\n * The root's triggers (`useModalTrigger()`), or `inertModalTrigger` for a component without\n * trigger parts (the layer and the inline restore then capture the element that had focus).\n */\n trigger: ModalTrigger;\n /** Where focus goes when the panel closes, if it can take focus (the root's `finalFocusRef`). */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * The panel's stable class(es), first in its `cn()`: `drawerClassNames.root`, followed by a\n * variant's root (`cn(drawerClassNames.root, navDrawerClassNames.root)`).\n */\n rootClassName: string;\n /**\n * The backdrop's stable class(es), first in its `cn()`: `drawerClassNames.backdrop`, followed by\n * a variant's (`cn(drawerClassNames.backdrop, navDrawerClassNames.backdrop)`).\n */\n backdropClassName: string;\n /**\n * The `backdrop` slot (overlay `modal` and `alert` only; a slot on a non-modal or inline panel\n * renders nothing and warns). `null` renders no backdrop.\n */\n backdrop?: Slot<'div'> | (SlotObject<'div'> & { appearance?: BackdropAppearance });\n /** The panel's id (always set: triggers point `aria-controls` at it). */\n id: string;\n /** Merged with the shell's own ref and the presence ref. */\n ref?: React.Ref<HTMLElement>;\n /** The panel's content, rendered as is: the shell adds no header, Close button or padding. */\n children?: React.ReactNode;\n}\n\n/**\n * The classes every overlay panel carries after its stable class: a fixed flex column on the\n * page's background with the overlay shadow, its inner edge in the border colour.\n */\nconst OVERLAY_PANEL_CLASSES =\n 'fixed flex flex-col border-border bg-background text-foreground shadow-64';\n\n/**\n * The drawer panel shell: the panel element of an overlay (in a portal, with its backdrop and the\n * modal or non-modal machinery) or of an inline drawer (in place, with the inline focus restore),\n * on the presence core, with the placement, size, separator and safe-area classes and the\n * `data-type`, `data-position`, `data-size`, `data-modal-type`, `data-separator` and\n * `data-presence` attributes. Returns `null` while unmounted. Its hooks key on `open`.\n *\n * It renders its `children` raw and provides no context: no header, title registry, Close button\n * or padding. The component that renders it holds the open state (`useModalOpenState`, then\n * {@link useDrawerOpen}), renders its triggers itself, names the panel, and calls\n * `useModalTriggerSession(trigger, open)` after rendering it (the shell's effects run first). A\n * change of `type` remounts the panel and its content.\n */\nexport const DrawerPanel = ({\n componentName,\n type,\n open,\n requestOpen,\n position,\n size,\n separator,\n modalType,\n unmountOnClose,\n inlineAs,\n trigger,\n finalFocusRef,\n rootClassName,\n backdropClassName,\n backdrop,\n id,\n className,\n onKeyDown,\n ref,\n children,\n ...rest\n}: DrawerPanelProps): React.ReactNode => {\n const inline = type === 'inline';\n const overlay = !inline;\n const nonModal = modalType === 'non-modal';\n const nonModalOverlay = overlay && nonModal;\n const keptMounted = !unmountOnClose;\n // The panel mounts through the presence core (D5, D103), with no motion of its own: kept mounted\n // 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\n // The panel element of each type, held in state through its own callback ref. A change of `type`\n // remounts the panel (D105): the overlay's hooks see only the portaled element and the inline\n // restore only the inline one, also in the commit that swaps them (the inline restore then still\n // knows the panel that focus was lost from).\n const [overlayPanel, setOverlayPanel] = React.useState<HTMLElement | null>(null);\n const [inlinePanel, setInlinePanel] = React.useState<HTMLElement | null>(null);\n // The mounted panel of either type; each element clears it only while it is still the one held.\n const panelRef = React.useRef<HTMLElement | null>(null);\n const attachOverlayPanel = React.useCallback((node: HTMLElement | null) => {\n if (!node) return undefined;\n panelRef.current = node;\n setOverlayPanel(node);\n return () => {\n if (panelRef.current === node) panelRef.current = null;\n setOverlayPanel(null);\n };\n }, []);\n const attachInlinePanel = React.useCallback((node: HTMLElement | null) => {\n if (!node) return undefined;\n panelRef.current = node;\n setInlinePanel(node);\n return () => {\n if (panelRef.current === node) panelRef.current = null;\n setInlinePanel(null);\n };\n }, []);\n const overlayRef = useMergedRefs<HTMLElement>(ref, attachOverlayPanel, presenceRef);\n const inlineRef = useMergedRefs<HTMLElement>(ref, attachInlinePanel, presenceRef);\n\n // An inline panel takes no focus on open and returns it on close only from inside (D101). Called\n // before useModalLayer: on a switch from inline to overlay it restores before the overlay's trap\n // moves focus in.\n useRestoreFocus({\n enabled: open && inline,\n container: inlinePanel,\n triggerRef: trigger.focusRef,\n finalFocusRef,\n requireFocusInside: true,\n });\n // The portal wrapper: a kept-mounted overlay moves to the top of its stack when it opens (D104),\n // before the layer registers and the trap moves focus in.\n const portalRef = React.useRef<HTMLDivElement | null>(null);\n useRaiseOnOpen(open && overlay, keptMounted, portalRef);\n\n // A backdrop press asks to close, except an alert's (Escape still does; useModalLayer registers\n // its layer without outside presses).\n const backdropPress = useBackdropPress(panelRef, modalType !== 'alert');\n const onDismiss = useModalDismiss(requestOpen, componentName, backdropPress.afterOutsidePress);\n // Only an overlay is a layer: an inline panel is page content (no trap, isolation, scroll lock,\n // Escape or outside press; toasts keep their corner). The overlay's layer is the one the Toaster\n // measures (`modal`, or `dialog` for a non-modal one).\n const layer = useModalLayer({\n open: open && overlay,\n modalType,\n onDismiss,\n refs: [panelRef],\n container: overlayPanel,\n triggerRef: trigger.focusRef,\n finalFocusRef,\n });\n // A non-modal overlay keeps its place in the page's keyboard order right after its opener\n // (D87.5). Both hooks are always called (C-HOOKS, D91). The opener is captured whenever the\n // overlay opens, so a modal panel that turns non-modal while open (focus inside it by then)\n // still knows it.\n const opener = useModalOpener(open && overlay, trigger, overlayPanel);\n const onTabOrderKeyDown = usePopoverTabOrder({\n enabled: open && nonModalOverlay,\n surface: overlayPanel,\n anchorRef: opener,\n getPreviousStop: getTabbableThrough,\n });\n // A popup opened inside a kept-mounted panel that is still open when the panel closes (D106).\n useOpenInsideWarning(open, keptMounted, layer.layerId, componentName, panelRef);\n // A non-modal or inline panel has no backdrop: a given slot (not undefined, null or a boolean)\n // is ignored.\n const backdropIgnored =\n (nonModal || inline) &&\n backdrop !== undefined &&\n backdrop !== null &&\n typeof backdrop !== 'boolean';\n React.useEffect(() => {\n if (!backdropIgnored) return;\n warnOnce(\n `${componentName}:backdrop-ignored`,\n `${componentName}: \\`backdrop\\` is ignored: a non-modal or inline drawer has no backdrop, so the page around it stays usable.`,\n );\n }, [backdropIgnored, componentName]);\n // A full non-modal overlay covers the page it leaves usable (D87.8).\n const coversUsablePage = open && nonModalOverlay && size === 'full';\n React.useEffect(() => {\n if (!coversUsablePage) return;\n warnOnce(\n `${componentName}:non-modal-full`,\n `${componentName}: \\`size=\"full\"\\` with \\`modalType=\"non-modal\"\\` covers the whole page while leaving it usable, so Tab reaches controls hidden behind the drawer. Use \\`modalType=\"modal\"\\`, \\`type=\"inline\"\\`, or a smaller size with its room reserved in the page layout.`,\n );\n }, [coversUsablePage, componentName]);\n\n if (!isMounted) return null;\n\n if (inline) {\n const InlinePanel = inlineAs;\n // In place: no role, tabIndex or modal attributes (D100). The presence attributes come after\n // the consumer's props: hidden and inert while kept closed.\n return (\n <InlinePanel\n ref={inlineRef}\n id={id}\n data-type=\"inline\"\n data-position={position}\n data-size={size}\n data-separator={separator ? '' : undefined}\n {...rest}\n {...presenceProps}\n onKeyDown={onKeyDown}\n className={cn(\n rootClassName,\n inlinePanelClasses,\n getInlinePanelClasses(position, size),\n className,\n )}\n >\n {children}\n </InlinePanel>\n );\n }\n\n return (\n <Portal ref={portalRef} layerId={layer.layerId}>\n {/* The backdrop of a modal or alert panel, the panel's sibling; a non-modal one has none.\n Both carry the presence attributes (D7, D103): hidden and inert while kept closed, so a\n closed panel leaves no backdrop over the page. */}\n {!nonModal && (\n <ModalBackdrop\n backdrop={backdrop}\n className={backdropClassName}\n layerId={layer.layerId}\n open={open}\n onMouseDown={backdropPress.onMouseDown}\n presenceProps={presenceProps}\n />\n )}\n <div\n ref={overlayRef}\n role={modalType === 'alert' ? 'alertdialog' : 'dialog'}\n id={id}\n tabIndex={-1}\n data-type=\"overlay\"\n data-position={position}\n data-size={size}\n data-modal-type={modalType}\n {...rest}\n {...presenceProps}\n onKeyDown={composeEventHandlers(onKeyDown, onTabOrderKeyDown)}\n className={cn(\n rootClassName,\n OVERLAY_PANEL_CLASSES,\n getOverlayPanelClasses(position, size),\n className,\n )}\n >\n {children}\n </div>\n </Portal>\n );\n};\nDrawerPanel.displayName = 'DrawerPanel';\n"],"mappings":"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"}
@@ -0,0 +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/classNames.cjs"),a=require("../../lib/styles.cjs"),o=require("./Dialog.shared.cjs"),s=require("./Dialog.slots.cjs"),c=require("./Drawer.scroll.cjs"),l=require("./Drawer.context.cjs");let u=require("react");u=e.__toESM(u,1);let d=require("react/jsx-runtime");var f=`Drawer.Trigger:nested`,p="Drawer.Trigger must be a direct child of Drawer (a Fragment is fine). Inside another element or a component it is rendered as panel content, which is not rendered (or, with `unmountOnClose={false}`, is hidden) while the drawer is closed, so it cannot open the drawer. Make it a direct child, put wrappers such as a Tooltip inside the trigger, or control the Drawer with `open`/`onOpenChange` and open it from your own button.",m=e=>{let{open:t,requestOpen:r,trigger:i,panelId:a,type:s,inPanel:c}=l.useDrawerContext(`Drawer.Trigger`);return u.useEffect(()=>{c&&n.warnOnce(f,p)},[c]),o.useModalTriggerPart({open:t,requestOpen:r,trigger:i,controlsId:a,popup:s!==`inline`&&`dialog`},e,`Drawer.Trigger`)};m.displayName=`DrawerTrigger`;var h=e=>{let{requestOpen:t}=l.useDrawerContext(`Drawer.Close`);return o.useModalClosePart(t,e,`Drawer.Close`)};h.displayName=`DrawerClose`;var g=({id:e,headingLevel:n=2,className:r,children:a,ref:s,...c})=>{let{id:l,ref:u}=o.useModalTitle(`Drawer.Title`,`Drawer`,e,s),f=`h${n}`;return(0,d.jsx)(f,{...c,id:l,ref:u,className:t.cn(i.drawerTitleClassNames.root,`text-subtitle-1 font-semibold text-foreground`,r),children:a})};g.displayName=`DrawerTitle`;var _=({requestOpen:e,label:n,closeButton:r,className:a})=>(0,d.jsx)(s.ModalCloseButton,{componentName:`Drawer`,closeButton:r,closeLabel:n,onClose:t=>e(!1,{reason:`close-button`,event:t}),className:t.cn(i.drawerClassNames.closeButton,a)});_.displayName=`DrawerCloseButton`;var v=`Drawer.Header:unscanned`,y=`Drawer.Header is not a direct child of Drawer, so it renders inside the body instead of replacing the header. Make it a direct child (a Fragment there is fine).`,b=`Drawer.Body:unscanned`,x=`Drawer.Body is not a direct child of Drawer, so its props do not reach the scrolling body and it renders as an element inside it. Make it a direct child (a Fragment there is fine).`,S=`Drawer.Footer:unscanned`,C="Drawer.Footer is not a direct child of Drawer, so it renders inside the scrolling body instead of below it. Make it a direct child (a Fragment there is fine); a submit button in it can name a form in the body with the `form` attribute.",w=`Drawer.HeaderTitle:outside-header`,T=`Drawer.HeaderTitle is not inside a Drawer.Header, so it renders in the body without the Close button. Put it in a Drawer.Header, or use Drawer.Title for a heading in the body.`;function E(){return u.useContext(l.DrawerPartContext)===`placed`}function D(e,t,r){u.useEffect(()=>{e&&n.warnOnce(t,r)},[e,t,r])}var O=({className:e,children:n,ref:a,...o})=>{l.useDrawerContext(`Drawer.Header`);let s=E(),f=u.useContext(l.DrawerScrollStateContext)??`none`;return D(!s,v,y),r.slotRendersContent(n)?(0,d.jsx)(`div`,{"data-scroll-state":f,...o,ref:a,className:t.cn(i.drawerHeaderClassNames.root,`flex shrink-0 flex-col gap-2 p-4`,c.scrollSeparatorClasses.header,e),children:(0,d.jsx)(l.DrawerHeaderContext.Provider,{value:!0,children:(0,d.jsx)(l.DrawerPartContext.Provider,{value:`content`,children:r.materialiseSlotContent(n)})})}):null};O.displayName=`DrawerHeader`;var k=({id:e,headingLevel:n=2,action:a,className:s,children:c,ref:f,...p})=>{let{requestOpen:m,closeLabel:h,closeButton:g}=l.useDrawerContext(`Drawer.HeaderTitle`),v=u.useContext(l.DrawerHeaderContext),{id:y,ref:b}=o.useModalTitle(`Drawer.HeaderTitle`,`Drawer`,e,void 0);D(!v,w,T);let x=`h${n}`;return(0,d.jsx)(`div`,{...p,ref:f,className:t.cn(i.drawerHeaderTitleClassNames.root,`flex items-start gap-2`,s),children:(0,d.jsxs)(l.DrawerPartContext.Provider,{value:`content`,children:[(0,d.jsx)(x,{id:y,ref:b,className:t.cn(i.drawerHeaderTitleClassNames.heading,`min-w-0 flex-1 text-subtitle-1 font-semibold text-foreground`),children:c}),r.slotRendersContent(a)?r.renderSlot(a,`span`,t.cn(i.drawerHeaderTitleClassNames.action,`flex min-h-7 shrink-0 items-center gap-1`)):null,v&&(0,d.jsx)(_,{requestOpen:m,label:h,closeButton:g,className:`mt-0.5 shrink-0 text-muted-foreground`})]})})};k.displayName=`DrawerHeaderTitle`;var A=({className:e,children:n,ref:r,...a})=>(l.useDrawerContext(`Drawer.HeaderNavigation`),(0,d.jsx)(`nav`,{...a,ref:r,className:t.cn(i.drawerHeaderNavigationClassNames.root,`flex items-center gap-1`,e),children:(0,d.jsx)(l.DrawerPartContext.Provider,{value:`content`,children:n})}));A.displayName=`DrawerHeaderNavigation`;var j=({className:e,children:n,ref:r,...o})=>(l.useDrawerContext(`Drawer.Body`),D(!0,b,x),(0,d.jsx)(`div`,{...o,ref:r,className:t.cn(i.drawerBodyClassNames.root,a.focusRingInset,e),children:(0,d.jsx)(l.DrawerPartContext.Provider,{value:`content`,children:n})}));j.displayName=`DrawerBody`;var M=({className:e,children:n,ref:a,...o})=>{l.useDrawerContext(`Drawer.Footer`);let s=E(),f=u.useContext(l.DrawerScrollStateContext)??`none`;return D(!s,S,C),r.slotRendersContent(n)?(0,d.jsx)(`div`,{"data-scroll-state":f,...o,ref:a,className:t.cn(i.drawerFooterClassNames.root,`flex shrink-0 flex-wrap items-center gap-2 p-4`,c.scrollSeparatorClasses.footer,e),children:(0,d.jsx)(l.DrawerPartContext.Provider,{value:`content`,children:r.materialiseSlotContent(n)})}):null};M.displayName=`DrawerFooter`,exports.DrawerBody=j,exports.DrawerClose=h,exports.DrawerCloseButton=_,exports.DrawerFooter=M,exports.DrawerHeader=O,exports.DrawerHeaderNavigation=A,exports.DrawerHeaderTitle=k,exports.DrawerTitle=g,exports.DrawerTrigger=m,exports.NESTED_TRIGGER_WARNING=p,exports.NESTED_TRIGGER_WARNING_KEY=f;
2
+ //# sourceMappingURL=Drawer.parts.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Drawer.parts.cjs","names":["useDrawerContext","useModalTriggerPart","useModalClosePart","useModalTitle","cn","drawerTitleClassNames","ModalCloseButton","drawerClassNames","React","DrawerPartContext","DrawerScrollStateContext","slotRendersContent","drawerHeaderClassNames","scrollSeparatorClasses","DrawerHeaderContext","materialiseSlotContent","drawerHeaderTitleClassNames","renderSlot","drawerHeaderNavigationClassNames","drawerBodyClassNames","focusRingInset","drawerFooterClassNames","require_runtime","require_cn","require_dev","require_slot","require_classNames","require_styles","require_Dialog_shared","require_Dialog_slots","require_Drawer_scroll","require_Drawer_context","react","react_jsx_runtime","NESTED_TRIGGER_WARNING_KEY","NESTED_TRIGGER_WARNING","DrawerTrigger","inPanel","panelId","type","props","DrawerClose","requestOpen","DrawerTitle","rest","titleId","titleRef","id","ref","Heading","headingLevel","className","DrawerCloseButton","label","HEADER_UNSCANNED_WARNING_KEY","HEADER_UNSCANNED_WARNING","BODY_UNSCANNED_WARNING_KEY","BODY_UNSCANNED_WARNING","FOOTER_UNSCANNED_WARNING_KEY","FOOTER_UNSCANNED_WARNING","HEADER_TITLE_OUTSIDE_WARNING_KEY","HEADER_TITLE_OUTSIDE_WARNING","usePlaced","useWarnWhen","condition","key","message","DrawerHeader","placed","scrollState","children","DrawerHeaderTitle","inHeader","headingId","headingRef","action","closeLabel","DrawerHeaderNavigation","DrawerBody","DrawerFooter"],"sources":["../../../src/components/overlays/Drawer.parts.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport {\n drawerBodyClassNames,\n drawerClassNames,\n drawerFooterClassNames,\n drawerHeaderClassNames,\n drawerHeaderNavigationClassNames,\n drawerHeaderTitleClassNames,\n drawerTitleClassNames,\n} from '../../lib/classNames';\nimport { warnOnce } from '../../lib/dev';\nimport { materialiseSlotContent, renderSlot, slotRendersContent, type Slot } from '../../lib/slot';\nimport { focusRingInset } from '../../lib/styles';\nimport type { HeadingLevel } from '../../lib/types';\nimport {\n useModalClosePart,\n useModalTitle,\n useModalTriggerPart,\n type ModalRequestOpen,\n} from './Dialog.shared';\nimport { ModalCloseButton } from './Dialog.slots';\nimport {\n DrawerHeaderContext,\n DrawerPartContext,\n DrawerScrollStateContext,\n useDrawerContext,\n} from './Drawer.context';\nimport { scrollSeparatorClasses } from './Drawer.scroll';\n\n/*\n * The Drawer's parts. Imports the context and scroll modules only (never the root or\n * `Drawer.tsx`).\n */\n\n/** Props a `Drawer.Trigger` puts on its element (and passes to a render-prop child). */\nexport interface DrawerTriggerRenderProps extends React.HTMLAttributes<HTMLElement> {\n /**\n * `'dialog'` for an overlay drawer; absent (no key) for an inline drawer, which is not a popup.\n */\n 'aria-haspopup'?: 'dialog';\n 'aria-expanded': boolean;\n /** The panel's id, while the drawer 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 DrawerTrigger sub-component. */\nexport interface DrawerTriggerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that opens and closes the drawer. A single element receives the trigger props\n * (merged with its own); a function receives them.\n */\n children: React.ReactNode | ((props: DrawerTriggerRenderProps) => React.ReactNode);\n /**\n * `false` renders a wrapper `<span>` around the children instead of merging the trigger props\n * onto the child. The span carries the click handler; `aria-haspopup`, `aria-expanded` and\n * `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 `Drawer.Close` puts on its element (and passes to a render-prop child). */\nexport interface DrawerCloseRenderProps 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 DrawerClose sub-component. */\nexport interface DrawerCloseProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that closes the drawer. A single element receives an `onClick` composed with its own\n * (its handler runs first; `preventDefault()` keeps the drawer open); a function receives the\n * props.\n */\n children: React.ReactNode | ((props: DrawerCloseRenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` that closes the drawer 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\n/** Properties for the DrawerTitle sub-component. */\nexport interface DrawerTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n /** The title; any content. */\n children: React.ReactNode;\n /**\n * Level of the heading element (`h1` … `h6`). Fluent's `heading` slot, which also takes another\n * element.\n * @default 2\n */\n headingLevel?: HeadingLevel;\n /** Ref to the heading element. */\n ref?: React.Ref<HTMLHeadingElement>;\n}\n\n/** Properties for the DrawerHeader sub-component. */\nexport interface DrawerHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** `Drawer.HeaderNavigation`, `Drawer.HeaderTitle`, or any content, in the order written. */\n children?: React.ReactNode;\n /** Ref to the header element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DrawerHeaderTitle sub-component. */\nexport interface DrawerHeaderTitleProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The title; any content. The heading names the drawer (`aria-labelledby`). */\n children: React.ReactNode;\n /**\n * Content between the heading and the built-in Close button, such as icon buttons for the\n * drawer's own commands (Fluent's `action`). It comes before the Close button in DOM and Tab\n * order and is interactive (not `aria-hidden`): name icon-only buttons. Renders nothing when it\n * renders no content.\n */\n action?: Slot<'span'>;\n /** Id of the heading element, the element that names the drawer. @default a generated id */\n id?: string;\n /**\n * Level of the heading element (`h1` … `h6`). Fluent's `heading` slot, which also takes another\n * element.\n * @default 2\n */\n headingLevel?: HeadingLevel;\n /** Ref to the title row (the heading's parent). */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DrawerHeaderNavigation sub-component. */\nexport interface DrawerHeaderNavigationProps extends React.HTMLAttributes<HTMLElement> {\n /** The navigation controls: a Back button, a Toolbar of commands. */\n children?: React.ReactNode;\n /** Ref to the `<nav>` element. */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** Properties for the DrawerBody sub-component. */\nexport interface DrawerBodyProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Content of the scrolling body, rendered in the Body's place among the other content. */\n children?: React.ReactNode;\n /** Ref to the scrolling body element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DrawerFooter sub-component. */\nexport interface DrawerFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The drawer's actions, typically buttons (wrap closing ones in `Drawer.Close`). */\n children?: React.ReactNode;\n /** Ref to the footer element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** The warning key of a `Drawer.Trigger` that renders as panel content (the root checks it too). */\nexport const NESTED_TRIGGER_WARNING_KEY = 'Drawer.Trigger:nested';\n\n/** The text of the {@link NESTED_TRIGGER_WARNING_KEY} warning. */\nexport const NESTED_TRIGGER_WARNING =\n 'Drawer.Trigger must be a direct child of Drawer (a Fragment is fine). Inside another element or a component it is rendered as panel content, which is not rendered (or, with `unmountOnClose={false}`, is hidden) while the drawer is closed, so it cannot open the drawer. Make it a direct child, put wrappers such as a Tooltip inside the trigger, or control the Drawer with `open`/`onOpenChange` and open it from your own button.';\n\n/**\n * Opens and closes the drawer: a click while it is open asks it to close (reason `trigger`), which\n * the trigger of a non-modal or inline drawer can receive (a modal one makes the page inert).\n * Fluent's `DialogTrigger` never toggles (outside the surface it only opens, inside it only\n * closes); this trigger always does.\n * Place it directly inside `Drawer`, or in a Fragment there (not inside a wrapper element or a\n * component of your own): it renders in place, not in the panel (an inline drawer's triggers\n * render right before its panel, so the panel follows its button in the reading order); a\n * misplaced one warns in development. A Drawer may have several triggers: focus returns to the one\n * that opened it. Puts `aria-haspopup=\"dialog\"` (none on an inline drawer's trigger: an inline\n * panel is page content, not a popup), `aria-expanded`, `aria-controls` (while open), a click\n * handler and a ref on its single child, or passes them to a render-prop child. A custom child\n * component must forward `ref` and spread its props; one that does not is wrapped in a `<span>`\n * automatically (with a development warning), the span that `asChild={false}` renders. Focus\n * returns to the trigger when the drawer closes (for a non-modal or inline drawer, only when focus\n * was inside it). On the span, the state ARIA goes to the first element in the tab order inside\n * it, and focus returns to that element (to the span when you made it the trigger with a `role`\n * such as `button` and `tabIndex={0}`, or when nothing inside it can take focus).\n *\n * A Tooltip (or any other wrapper) goes inside the trigger, not around it. Use a render-prop child\n * so the trigger props land on the button and the Tooltip describes that same button:\n *\n * @example\n * <Drawer title=\"Filters\">\n * <Drawer.Trigger>\n * {(triggerProps) => (\n * <Tooltip content=\"Narrow the list\">\n * <Button {...triggerProps}>Filters</Button>\n * </Tooltip>\n * )}\n * </Drawer.Trigger>\n * <FilterForm />\n * </Drawer>\n */\nexport const DrawerTrigger = (props: DrawerTriggerProps) => {\n const { open, requestOpen, trigger, panelId, type, inPanel } = useDrawerContext('Drawer.Trigger');\n\n // Rendered inside its own drawer's panel (e.g. by a component): not rendered (or, kept mounted,\n // hidden) while the drawer is closed.\n React.useEffect(() => {\n if (inPanel) warnOnce(NESTED_TRIGGER_WARNING_KEY, NESTED_TRIGGER_WARNING);\n }, [inPanel]);\n\n return useModalTriggerPart<DrawerTriggerRenderProps>(\n {\n open,\n requestOpen,\n trigger,\n controlsId: panelId,\n popup: type === 'inline' ? false : 'dialog',\n },\n props,\n 'Drawer.Trigger',\n );\n};\nDrawerTrigger.displayName = 'DrawerTrigger';\n\n/**\n * Closes the drawer: composes a click handler onto its single child (its own `onClick` runs first;\n * calling `preventDefault()` there keeps the drawer open), or passes it to a render-prop child.\n */\nexport const DrawerClose = (props: DrawerCloseProps) => {\n const { requestOpen } = useDrawerContext('Drawer.Close');\n return useModalClosePart<DrawerCloseRenderProps>(requestOpen, props, 'Drawer.Close');\n};\nDrawerClose.displayName = 'DrawerClose';\n\n/**\n * A heading that names the drawer (`aria-labelledby`), for rich titles or custom layouts. Render it\n * inside the Drawer's content (instead of the `title` prop); for the title of a composed header,\n * use `Drawer.HeaderTitle` in a `Drawer.Header`. `headingLevel` picks the heading element (`h2`\n * by default).\n */\nexport const DrawerTitle = ({\n id,\n headingLevel = 2,\n className,\n children,\n ref,\n ...rest\n}: DrawerTitleProps) => {\n const { id: titleId, ref: titleRef } = useModalTitle('Drawer.Title', 'Drawer', id, ref);\n const Heading: `h${HeadingLevel}` = `h${headingLevel}`;\n return (\n <Heading\n {...rest}\n id={titleId}\n ref={titleRef}\n className={cn(\n drawerTitleClassNames.root,\n 'text-subtitle-1 font-semibold text-foreground',\n className,\n )}\n >\n {children}\n </Heading>\n );\n};\nDrawerTitle.displayName = 'DrawerTitle';\n\n/** Properties of the internal {@link DrawerCloseButton}. */\nexport interface DrawerCloseButtonProps {\n /** The Drawer's request function: the button asks it to close, reason `close-button`. */\n requestOpen: ModalRequestOpen;\n /** The button's accessible name (the Drawer's `closeLabel`). */\n label: string;\n /** The Drawer's `closeButton` slot: the button's content, or `null` to render none. */\n closeButton: Slot<'span'> | undefined;\n /** Placement classes, after the button's own (`drawerClassNames.closeButton`). */\n className?: string;\n}\n\n/**\n * The Drawer's built-in Close button (internal): the Wave `Button`, subtle and small, with the\n * dismiss glyph or the Drawer's `closeButton` content (the slot rules of `Dialog.Content`'s\n * `closeButton`), named by the Drawer's `closeLabel`. The built-in header and every\n * `Drawer.HeaderTitle` in a `Drawer.Header` render it; it carries `drawerClassNames.closeButton`.\n * Renders nothing for `closeButton={null}`.\n */\nexport const DrawerCloseButton = ({\n requestOpen,\n label,\n closeButton,\n className,\n}: DrawerCloseButtonProps) => (\n <ModalCloseButton\n componentName=\"Drawer\"\n closeButton={closeButton}\n closeLabel={label}\n onClose={(event) => requestOpen(false, { reason: 'close-button', event })}\n className={cn(drawerClassNames.closeButton, className)}\n />\n);\nDrawerCloseButton.displayName = 'DrawerCloseButton';\n\n/** The warning key of a `Drawer.Header` that the Drawer's scan did not place. */\nconst HEADER_UNSCANNED_WARNING_KEY = 'Drawer.Header:unscanned';\nconst HEADER_UNSCANNED_WARNING =\n 'Drawer.Header is not a direct child of Drawer, so it renders inside the body instead of replacing the header. Make it a direct child (a Fragment there is fine).';\n\n/** The warning key of a `Drawer.Body` that the Drawer's scan did not place. */\nconst BODY_UNSCANNED_WARNING_KEY = 'Drawer.Body:unscanned';\nconst BODY_UNSCANNED_WARNING =\n 'Drawer.Body is not a direct child of Drawer, so its props do not reach the scrolling body and it renders as an element inside it. Make it a direct child (a Fragment there is fine).';\n\n/** The warning key of a `Drawer.Footer` that the Drawer's scan did not place. */\nconst FOOTER_UNSCANNED_WARNING_KEY = 'Drawer.Footer:unscanned';\nconst FOOTER_UNSCANNED_WARNING =\n 'Drawer.Footer is not a direct child of Drawer, so it renders inside the scrolling body instead of below it. Make it a direct child (a Fragment there is fine); a submit button in it can name a form in the body with the `form` attribute.';\n\n/** The warning key of a `Drawer.HeaderTitle` outside a `Drawer.Header`. */\nconst HEADER_TITLE_OUTSIDE_WARNING_KEY = 'Drawer.HeaderTitle:outside-header';\nconst HEADER_TITLE_OUTSIDE_WARNING =\n 'Drawer.HeaderTitle is not inside a Drawer.Header, so it renders in the body without the Close button. Put it in a Drawer.Header, or use Drawer.Title for a heading in the body.';\n\n/** Whether the Drawer's scan placed the part that reads this (a direct child of the Drawer). */\nfunction usePlaced(): boolean {\n return React.useContext(DrawerPartContext) === 'placed';\n}\n\n/** Warns once, from an effect, while `condition` holds. */\nfunction useWarnWhen(condition: boolean, key: string, message: string): void {\n React.useEffect(() => {\n if (condition) warnOnce(key, message);\n }, [condition, key, message]);\n}\n\n/**\n * The drawer's header, replacing the built-in one (the `title` and Close button row): a\n * `Drawer.HeaderNavigation` row and a `Drawer.HeaderTitle`, or your own content. The built-in\n * Close button ends each `Drawer.HeaderTitle`; a header without one has no Close button (wrap your\n * own in `Drawer.Close`). Make it a direct child of `Drawer` (a Fragment there is fine); nested in\n * an element or rendered by a component of yours it renders in the body, with a development\n * warning. It draws a line under itself while the body is scrolled away from its top\n * (`data-scroll-state`). When an overlay drawer opens, focus goes to the header's first focusable\n * element (a Back button, a title action): give the control that should start `autoFocus`. A\n * header whose children render nothing renders no element (the drawer then has no header; Escape\n * and the backdrop of an overlay, and `Drawer.Close`, still close it). Fluent's `DrawerHeader`.\n */\nexport const DrawerHeader = ({ className, children, ref, ...rest }: DrawerHeaderProps) => {\n useDrawerContext('Drawer.Header');\n const placed = usePlaced();\n const scrollState = React.useContext(DrawerScrollStateContext) ?? 'none';\n useWarnWhen(!placed, HEADER_UNSCANNED_WARNING_KEY, HEADER_UNSCANNED_WARNING);\n if (!slotRendersContent(children)) return null;\n return (\n <div\n data-scroll-state={scrollState}\n {...rest}\n ref={ref}\n className={cn(\n drawerHeaderClassNames.root,\n 'flex shrink-0 flex-col gap-2 p-4',\n scrollSeparatorClasses.header,\n className,\n )}\n >\n <DrawerHeaderContext.Provider value={true}>\n <DrawerPartContext.Provider value=\"content\">\n {materialiseSlotContent(children)}\n </DrawerPartContext.Provider>\n </DrawerHeaderContext.Provider>\n </div>\n );\n};\nDrawerHeader.displayName = 'DrawerHeader';\n\n/**\n * A title row for `Drawer.Header`: the heading that names the drawer, your `action` content and\n * the built-in Close button (named by the Drawer's `closeLabel`; the Drawer's `closeButton` sets\n * its content, or hides it with `null`), in that DOM and Tab order.\n * Render one per header; `headingLevel` picks the heading element (`h2` by default). Outside a\n * `Drawer.Header` it renders without the Close button and warns: use `Drawer.Title` for a heading\n * in the body. Unlike Fluent's `DrawerHeaderTitle`, whose `action` is where you put a close\n * button, it renders the Close button itself.\n */\nexport const DrawerHeaderTitle = ({\n id,\n headingLevel = 2,\n action,\n className,\n children,\n ref,\n ...rest\n}: DrawerHeaderTitleProps) => {\n const { requestOpen, closeLabel, closeButton } = useDrawerContext('Drawer.HeaderTitle');\n const inHeader = React.useContext(DrawerHeaderContext);\n const { id: headingId, ref: headingRef } = useModalTitle(\n 'Drawer.HeaderTitle',\n 'Drawer',\n id,\n undefined,\n );\n useWarnWhen(!inHeader, HEADER_TITLE_OUTSIDE_WARNING_KEY, HEADER_TITLE_OUTSIDE_WARNING);\n const Heading: `h${HeadingLevel}` = `h${headingLevel}`;\n return (\n <div\n {...rest}\n ref={ref}\n className={cn(drawerHeaderTitleClassNames.root, 'flex items-start gap-2', className)}\n >\n <DrawerPartContext.Provider value=\"content\">\n <Heading\n id={headingId}\n ref={headingRef}\n className={cn(\n drawerHeaderTitleClassNames.heading,\n 'min-w-0 flex-1 text-subtitle-1 font-semibold text-foreground',\n )}\n >\n {children}\n </Heading>\n {slotRendersContent(action)\n ? renderSlot(\n action,\n 'span',\n cn(drawerHeaderTitleClassNames.action, 'flex min-h-7 shrink-0 items-center gap-1'),\n )\n : null}\n {inHeader && (\n <DrawerCloseButton\n requestOpen={requestOpen}\n label={closeLabel}\n closeButton={closeButton}\n className=\"mt-0.5 shrink-0 text-muted-foreground\"\n />\n )}\n </DrawerPartContext.Provider>\n </div>\n );\n};\nDrawerHeaderTitle.displayName = 'DrawerHeaderTitle';\n\n/**\n * A `<nav>` row at the top of `Drawer.Header`, for a multi-level drawer's Back button and the\n * drawer's commands. Give it an `aria-label` when the page has other navigation landmarks.\n * Fluent's `DrawerHeaderNavigation`.\n */\nexport const DrawerHeaderNavigation = ({\n className,\n children,\n ref,\n ...rest\n}: DrawerHeaderNavigationProps) => {\n useDrawerContext('Drawer.HeaderNavigation');\n return (\n <nav\n {...rest}\n ref={ref}\n className={cn(drawerHeaderNavigationClassNames.root, 'flex items-center gap-1', className)}\n >\n <DrawerPartContext.Provider value=\"content\">{children}</DrawerPartContext.Provider>\n </nav>\n );\n};\nDrawerHeaderNavigation.displayName = 'DrawerHeaderNavigation';\n\n/**\n * Optional: gives the drawer's scrolling body your props (`className`, `style`, `ref`, `id`,\n * `role`, `tabIndex`, `aria-*`, `data-*`, handlers), for example `tabIndex={0} role=\"region\"\n * aria-label=\"…\"` to let the keyboard scroll a body without focusable content (the body then\n * shows the focus ring inside its edge). Its children render in its place among the drawer's\n * other content. Make it a direct child of `Drawer` (a Fragment there is fine) and render one;\n * nested in an element or rendered by a component of yours it renders as an element inside the\n * body, with a development warning. Fluent's `DrawerBody`.\n */\nexport const DrawerBody = ({ className, children, ref, ...rest }: DrawerBodyProps) => {\n useDrawerContext('Drawer.Body');\n // The Drawer renders a placed Body's props on its scrolling body and its children in place, so\n // this element renders only for a Body its scan did not place.\n useWarnWhen(true, BODY_UNSCANNED_WARNING_KEY, BODY_UNSCANNED_WARNING);\n return (\n <div {...rest} ref={ref} className={cn(drawerBodyClassNames.root, focusRingInset, className)}>\n <DrawerPartContext.Provider value=\"content\">{children}</DrawerPartContext.Provider>\n </div>\n );\n};\nDrawerBody.displayName = 'DrawerBody';\n\n/**\n * The drawer's action row, below the scrolling body: it never scrolls and never covers a focused\n * field. Its actions start at the inline start and wrap. Make it a direct child of `Drawer` (a\n * Fragment there is fine): it renders after the body wherever it is written; nested in an element\n * (a `<form>`) or rendered by a component of yours it renders where it is, in the body, with a\n * development warning. For a form in the body, give the footer's submit button `form={formId}`.\n * It draws a line above itself while content continues below (`data-scroll-state`). A footer\n * whose children render nothing renders no element. Fluent's `DrawerFooter`.\n */\nexport const DrawerFooter = ({ className, children, ref, ...rest }: DrawerFooterProps) => {\n useDrawerContext('Drawer.Footer');\n const placed = usePlaced();\n const scrollState = React.useContext(DrawerScrollStateContext) ?? 'none';\n useWarnWhen(!placed, FOOTER_UNSCANNED_WARNING_KEY, FOOTER_UNSCANNED_WARNING);\n if (!slotRendersContent(children)) return null;\n return (\n <div\n data-scroll-state={scrollState}\n {...rest}\n ref={ref}\n className={cn(\n drawerFooterClassNames.root,\n 'flex shrink-0 flex-wrap items-center gap-2 p-4',\n scrollSeparatorClasses.footer,\n className,\n )}\n >\n <DrawerPartContext.Provider value=\"content\">\n {materialiseSlotContent(children)}\n </DrawerPartContext.Provider>\n </div>\n );\n};\nDrawerFooter.displayName = 'DrawerFooter';\n"],"mappings":"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"}