@mortenbrudvik/waveui 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +97 -2
  2. package/dist/components/button/Link.cjs +1 -1
  3. package/dist/components/button/Link.cjs.map +1 -1
  4. package/dist/components/button/Link.mjs +4 -4
  5. package/dist/components/data-display/AvatarGroup.cjs +1 -1
  6. package/dist/components/data-display/AvatarGroup.cjs.map +1 -1
  7. package/dist/components/data-display/AvatarGroup.mjs +10 -10
  8. package/dist/components/data-display/InfoButton.cjs +1 -1
  9. package/dist/components/data-display/InfoButton.cjs.map +1 -1
  10. package/dist/components/data-display/InfoButton.mjs +12 -12
  11. package/dist/components/feedback/Toaster.cjs +1 -1
  12. package/dist/components/feedback/Toaster.cjs.map +1 -1
  13. package/dist/components/feedback/Toaster.mjs +235 -235
  14. package/dist/components/feedback/Toaster.mjs.map +1 -1
  15. package/dist/components/input/Combobox.cjs +1 -1
  16. package/dist/components/input/Combobox.cjs.map +1 -1
  17. package/dist/components/input/Combobox.mjs +176 -175
  18. package/dist/components/input/Combobox.mjs.map +1 -1
  19. package/dist/components/input/DatePicker.cjs +1 -1
  20. package/dist/components/input/DatePicker.cjs.map +1 -1
  21. package/dist/components/input/DatePicker.mjs +188 -187
  22. package/dist/components/input/DatePicker.mjs.map +1 -1
  23. package/dist/components/input/Dropdown.cjs +1 -1
  24. package/dist/components/input/Dropdown.cjs.map +1 -1
  25. package/dist/components/input/Dropdown.mjs +41 -40
  26. package/dist/components/input/Dropdown.mjs.map +1 -1
  27. package/dist/components/input/Option.cjs +1 -1
  28. package/dist/components/input/Option.cjs.map +1 -1
  29. package/dist/components/input/Option.mjs +89 -87
  30. package/dist/components/input/Option.mjs.map +1 -1
  31. package/dist/components/input/TagPicker.root.cjs +1 -1
  32. package/dist/components/input/TagPicker.root.cjs.map +1 -1
  33. package/dist/components/input/TagPicker.root.mjs +136 -135
  34. package/dist/components/input/TagPicker.root.mjs.map +1 -1
  35. package/dist/components/input/TimePicker.cjs +1 -1
  36. package/dist/components/input/TimePicker.cjs.map +1 -1
  37. package/dist/components/input/TimePicker.mjs +156 -154
  38. package/dist/components/input/TimePicker.mjs.map +1 -1
  39. package/dist/components/navigation/Menu.popover.cjs +1 -1
  40. package/dist/components/navigation/Menu.popover.cjs.map +1 -1
  41. package/dist/components/navigation/Menu.popover.mjs +137 -127
  42. package/dist/components/navigation/Menu.popover.mjs.map +1 -1
  43. package/dist/components/navigation/Menu.root.cjs +1 -1
  44. package/dist/components/navigation/Menu.root.cjs.map +1 -1
  45. package/dist/components/navigation/Menu.root.mjs +4 -4
  46. package/dist/components/overlays/Dialog.cjs +1 -1
  47. package/dist/components/overlays/Dialog.cjs.map +1 -1
  48. package/dist/components/overlays/Dialog.mjs +123 -123
  49. package/dist/components/overlays/Dialog.mjs.map +1 -1
  50. package/dist/components/overlays/Drawer.panel.cjs +1 -1
  51. package/dist/components/overlays/Drawer.panel.cjs.map +1 -1
  52. package/dist/components/overlays/Drawer.panel.mjs +12 -12
  53. package/dist/components/overlays/Drawer.panel.mjs.map +1 -1
  54. package/dist/components/overlays/Popover.cjs +1 -1
  55. package/dist/components/overlays/Popover.cjs.map +1 -1
  56. package/dist/components/overlays/Popover.mjs +173 -162
  57. package/dist/components/overlays/Popover.mjs.map +1 -1
  58. package/dist/components/overlays/TeachingPopover.cjs +1 -1
  59. package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
  60. package/dist/components/overlays/TeachingPopover.mjs +96 -91
  61. package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
  62. package/dist/components/overlays/Tooltip.cjs +1 -1
  63. package/dist/components/overlays/Tooltip.cjs.map +1 -1
  64. package/dist/components/overlays/Tooltip.mjs +47 -47
  65. package/dist/components/overlays/Tooltip.mjs.map +1 -1
  66. package/dist/components/portal/Portal.cjs +1 -1
  67. package/dist/components/portal/Portal.cjs.map +1 -1
  68. package/dist/components/portal/Portal.mjs +5 -5
  69. package/dist/components/table/DataGrid.cjs +1 -1
  70. package/dist/components/table/DataGrid.cjs.map +1 -1
  71. package/dist/components/table/DataGrid.mjs +1 -1
  72. package/dist/hooks/useDismiss.cjs.map +1 -1
  73. package/dist/hooks/useDismiss.mjs.map +1 -1
  74. package/dist/hooks/useFocusTrap.cjs.map +1 -1
  75. package/dist/hooks/useFocusTrap.mjs.map +1 -1
  76. package/dist/hooks/useFocusVisible.cjs +2 -0
  77. package/dist/hooks/useFocusVisible.cjs.map +1 -0
  78. package/dist/hooks/useFocusVisible.mjs +49 -0
  79. package/dist/hooks/useFocusVisible.mjs.map +1 -0
  80. package/dist/hooks/useFocusableGroup.cjs +2 -0
  81. package/dist/hooks/useFocusableGroup.cjs.map +1 -0
  82. package/dist/hooks/useFocusableGroup.mjs +70 -0
  83. package/dist/hooks/useFocusableGroup.mjs.map +1 -0
  84. package/dist/hooks/useModalLayer.cjs +1 -1
  85. package/dist/hooks/useModalLayer.cjs.map +1 -1
  86. package/dist/hooks/useModalLayer.mjs +4 -4
  87. package/dist/hooks/useModalOpen.cjs +2 -0
  88. package/dist/hooks/useModalOpen.cjs.map +1 -0
  89. package/dist/hooks/useModalOpen.mjs +14 -0
  90. package/dist/hooks/useModalOpen.mjs.map +1 -0
  91. package/dist/hooks/usePopupPosition.cjs +1 -1
  92. package/dist/hooks/usePopupPosition.cjs.map +1 -1
  93. package/dist/hooks/usePopupPosition.mjs +82 -53
  94. package/dist/hooks/usePopupPosition.mjs.map +1 -1
  95. package/dist/hooks/useResolvedTarget.cjs +2 -0
  96. package/dist/hooks/useResolvedTarget.cjs.map +1 -0
  97. package/dist/hooks/useResolvedTarget.mjs +37 -0
  98. package/dist/hooks/useResolvedTarget.mjs.map +1 -0
  99. package/dist/hooks/useRovingGrid.cjs +1 -1
  100. package/dist/hooks/useRovingGrid.cjs.map +1 -1
  101. package/dist/hooks/useRovingGrid.mjs +8 -57
  102. package/dist/hooks/useRovingGrid.mjs.map +1 -1
  103. package/dist/hooks/useRovingTabIndex.cjs +1 -1
  104. package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
  105. package/dist/hooks/useRovingTabIndex.mjs +142 -107
  106. package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
  107. package/dist/index.cjs +1 -1
  108. package/dist/index.d.cts +814 -18
  109. package/dist/index.d.ts +814 -18
  110. package/dist/index.mjs +120 -108
  111. package/dist/lib/layers.cjs +1 -1
  112. package/dist/lib/layers.cjs.map +1 -1
  113. package/dist/lib/layers.mjs +112 -109
  114. package/dist/lib/layers.mjs.map +1 -1
  115. package/dist/styles.css +1 -1
  116. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/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;
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"),ee=require("../../hooks/usePresence.cjs"),o=require("../../hooks/useRestoreFocus.cjs"),s=require("../../hooks/useModalLayer.cjs"),c=require("../../lib/styles.cjs"),l=require("../portal/Portal.cjs"),u=require("./Popover.shared.cjs"),d=require("./Dialog.shared.cjs"),f=require("./Dialog.slots.cjs");let p=require("react");p=e.__toESM(p,1);let m=require("react/jsx-runtime");function h(e,t){let n=a.useIsClient();return e===`inline`?t:t&&n}function g(e){return e===`bottom`?`height`:`width`}var _={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`}},v={start:`border-e`,end:`border-s`,left:`border-r`,right:`border-l`,bottom:`border-t`},y={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 b(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 te(e,t){return[y[e],v[e],_[g(e)][t],b(e,t)].join(` `)}var ne=[`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 x(e,t){let n=g(e);return[v[e],n===`height`?`w-full max-h-full`:``,_[n][t]].filter(Boolean).join(` `)}var re=`fixed flex flex-col border-border bg-background text-foreground shadow-64`,S=({componentName:e,type:a,open:c,requestOpen:h,position:g,size:_,separator:v,modalType:y,unmountOnClose:b,inlineAs:S,trigger:C,finalFocusRef:w,rootClassName:T,backdropClassName:ie,backdrop:E,id:D,className:O,onKeyDown:k,ref:A,children:j,...M})=>{let N=a===`inline`,P=!N,F=y===`non-modal`,I=P&&F,L=!b,{isMounted:R,ref:z,presenceProps:B}=ee.usePresence(c,{unmountOnExit:b}),[V,H]=p.useState(null),[U,W]=p.useState(null),G=p.useRef(null),K=p.useCallback(e=>{if(e)return G.current=e,H(e),()=>{G.current===e&&(G.current=null),H(null)}},[]),q=p.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);o.useRestoreFocus({enabled:c&&N,container:U,triggerRef:C.focusRef,finalFocusRef:w,requireFocusInside:!0});let Y=p.useRef(null);d.useRaiseOnOpen(c&&P,L,Y);let X=d.useBackdropPress(G,y!==`alert`),oe=d.useModalDismiss(h,e,X.afterOutsidePress),Z=s.useModalLayer({open:c&&P,modalType:y,onDismiss:oe,refs:[G],container:V,triggerRef:C.focusRef,finalFocusRef:w}),se=d.useModalOpener(c&&P,C,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`;p.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&&_===`full`;return p.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,m.jsx)(S,{ref:ae,id:D,"data-type":`inline`,"data-position":g,"data-size":_,"data-separator":v?``:void 0,...M,...B,onKeyDown:k,className:t.cn(T,ne,x(g,_),O),children:j}):(0,m.jsxs)(l.Portal,{ref:Y,layerId:Z.layerId,children:[!F&&(0,m.jsx)(f.ModalBackdrop,{backdrop:E,className:ie,layerId:Z.layerId,open:c,onMouseDown:X.onMouseDown,presenceProps:B}),(0,m.jsx)(`div`,{ref:J,role:y===`alert`?`alertdialog`:`dialog`,id:D,tabIndex:-1,"data-type":`overlay`,"data-position":g,"data-size":_,"data-modal-type":y,...M,...B,onKeyDown:r.composeEventHandlers(k,ce),className:t.cn(T,re,te(g,_),O),children:j})]}):null};S.displayName=`DrawerPanel`,exports.DrawerPanel=S,exports.useDrawerOpen=h;
2
2
  //# sourceMappingURL=Drawer.panel.cjs.map
@@ -1 +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":"2nBAuCA,SAAgBgC,EAAc,EAAkB,EAA6B,CAC3E,IAAMC,EAAWjC,EAAAA,YAAY,EAC7B,OAAOkC,IAAS,SAAWC,EAAYA,GAAaF,CACtD,CAMA,SAASG,EAAkB,EAA0C,CACnE,OAAOC,IAAa,SAAW,SAAW,OAC5C,CAOA,IAAMC,EAA4F,CAChG,MAAO,CAAE,MAAO,OAAQ,OAAQ,QAAS,MAAO,QAAS,KAAM,QAAS,EACxE,OAAQ,CAAE,MAAO,OAAQ,OAAQ,QAAS,MAAO,QAAS,KAAM,QAAS,CAC3E,EAOMC,EAA8D,CAClE,MAAO,WACP,IAAK,WACL,KAAM,WACN,MAAO,WACP,OAAQ,UACV,EAMMC,EAAoE,CACxE,MAAO,kCACP,IAAK,gCACL,KAAM,iCACN,MAAO,kCACP,OAAQ,sCACV,EASA,SAASC,EAAuB,EAA0B,EAA0B,CAElF,OADIJ,IAAa,UAAYK,IAAS,OAAe,mCAC9C,gEACT,CAOA,SAASC,GAAuB,EAA0B,EAA0B,CAClF,MAAO,CACLH,EAAwBH,GACxBE,EAAkBF,GAClBC,EAAkBF,EAAkBC,CAAQ,EAAE,CAACK,GAC/CD,EAAuBJ,EAAUK,CAAI,CACvC,CAAC,CAAC,KAAK,GAAG,CACZ,CAQA,IAAME,GAAqB,CACzB,mFACA,oDACA3C,EAAAA,aAAa,MACf,CAAC,CAAC,KAAK,GAAG,EASV,SAAS4C,EAAsB,EAA0B,EAA0B,CACjF,IAAMC,EAAOV,EAAkBC,CAAQ,EACvC,MAAO,CACLE,EAAkBF,GAClBS,IAAS,SAAW,oBAAsB,GAC1CR,EAAkBQ,EAAK,CAACJ,EAC1B,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,CACb,CAsEA,IAAMK,GACJ,4EAeWC,GAAe,CAC1B,gBACA,OACA,OACA,cACA,WACA,OACA,YACA,YACA,iBACA,WACA,UACA,gBACA,gBACA,oBACA,WACA,KACA,YACA,YACA,MACA,WACA,GAAGC,KACoC,CACvC,IAAMC,EAAShB,IAAS,SAClBiB,EAAU,CAACD,EACXE,EAAWC,IAAc,YACzBC,EAAkBH,GAAWC,EAC7BG,EAAc,CAACC,EAGf,CACJ,YACA,IAAKC,EACL,iBACEvD,EAAAA,YAAYwD,EAAM,CAAE,cAAeF,CAAe,CAAC,EAMjD,CAACG,EAAcC,GAAmBzD,EAAM,SAA6B,IAAI,EACzE,CAAC0D,EAAaC,GAAkB3D,EAAM,SAA6B,IAAI,EAEvE4D,EAAW5D,EAAM,OAA2B,IAAI,EAChD6D,EAAqB7D,EAAM,YAAa,GAA6B,CACzE,GAAK8D,EAGL,MAFA,GAAS,QAAUA,EACnBL,EAAgBK,CAAI,MACP,CACPF,EAAS,UAAYE,IAAM,EAAS,QAAU,MAClDL,EAAgB,IAAI,CACtB,CACF,EAAG,CAAC,CAAC,EACCM,EAAoB/D,EAAM,YAAa,GAA6B,CACxE,GAAK8D,EAGL,MAFA,GAAS,QAAUA,EACnBH,EAAeG,CAAI,MACN,CACPF,EAAS,UAAYE,IAAM,EAAS,QAAU,MAClDH,EAAe,IAAI,CACrB,CACF,EAAG,CAAC,CAAC,EACCK,EAAa/D,EAAAA,cAA2BgE,EAAKJ,EAAoBP,CAAW,EAC5EY,GAAYjE,EAAAA,cAA2BgE,EAAKF,EAAmBT,CAAW,EAKhFhC,EAAA,gBAAgB,CACd,QAASiC,GAAQR,EACjB,UAAWW,EACX,WAAYS,EAAQ,SACpB,gBACA,mBAAoB,EACtB,CAAC,EAGD,IAAMC,EAAYpE,EAAM,OAA8B,IAAI,EAC1DwB,EAAA,eAAe+B,GAAQP,EAASI,EAAagB,CAAS,EAItD,IAAMC,EAAgBnE,EAAAA,iBAAiB0D,EAAUV,IAAc,OAAO,EAChEoB,GAAYnE,EAAAA,gBAAgBoE,EAAaC,EAAeH,EAAc,iBAAiB,EAIvFI,EAAQrE,GAAAA,cAAc,CAC1B,KAAMmD,GAAQP,EACd,YACA,aACA,KAAM,CAACY,CAAQ,EACf,UAAWJ,EACX,WAAYW,EAAQ,SACpB,eACF,CAAC,EAKKO,GAASrE,EAAAA,eAAekD,GAAQP,EAASmB,EAASX,CAAY,EAC9DmB,GAAoBrE,EAAAA,mBAAmB,CAC3C,QAASiD,GAAQJ,EACjB,QAASK,EACT,UAAWkB,GACX,gBAAiBnE,EAAAA,kBACnB,CAAC,EAEDiB,EAAA,qBAAqB+B,EAAMH,EAAaqB,EAAM,QAASD,EAAeZ,CAAQ,EAG9E,IAAMgB,GACH3B,GAAYF,IACb8B,GACa,MACb,OAAOA,GAAa,UACtBlD,EAAM,cAAgB,CACfiD,GACL7D,EAAA,SACE,GAAGyD,EAAc,mBACjB,GAAGA,EAAc,6GACnB,CACF,EAAG,CAACI,EAAiBJ,CAAa,CAAC,EAEnC,IAAMM,EAAmBvB,GAAQJ,GAAmBZ,IAAS,OAsC7D,OArCAZ,EAAM,cAAgB,CACfmD,GACL/D,EAAA,SACE,GAAGyD,EAAc,iBACjB,GAAGA,EAAc,6PACnB,CACF,EAAG,CAACM,EAAkBN,CAAa,CAAC,EAE/BO,EAEDhC,GAKA,EAAAnB,EAAA,IAAA,CAACpB,EAAD,CACE,IAAK0D,GACD,KACJ,YAAU,SACV,gBAAehC,EACf,YAAWK,EACX,iBAAgB0C,EAAY,GAAK,IAAA,GACjC,GAAInC,EACJ,GAAIoC,EACO,YACX,UAAWzE,EAAAA,GACT0E,EACA1C,GACAC,EAAsBR,EAAUK,CAAI,EACpC6C,CACF,EAEC,UACU,CAAA,GAKf,EAAAxD,EAAA,KAAA,CAAClB,EAAAA,OAAD,CAAQ,IAAK0D,EAAW,QAASK,EAAM,QAAvC,SAAA,CAIG,CAACxB,IACA,EAAArB,EAAA,IAAA,CAACjB,GAAAA,cAAD,CACY,WACV,UAAW0E,EACX,QAASZ,EAAM,QACT,OACN,YAAaJ,EAAc,YACZ,eAChB,CAAA,GAEH,EAAAzC,EAAA,IAAA,CAAC,MAAD,CACE,IAAKoC,EACL,KAAMd,IAAc,QAAU,cAAgB,SAC1C,KACJ,SAAU,GACV,YAAU,UACV,gBAAehB,EACf,YAAWK,EACX,kBAAiBW,EACjB,GAAIJ,EACJ,GAAIoC,EACJ,UAAWtE,EAAAA,qBAAqB0E,EAAWX,EAAiB,EAC5D,UAAWlE,EAAAA,GACT0E,EACAvC,GACAJ,GAAuBN,EAAUK,CAAI,EACrC6C,CACF,EAEC,UACE,CAAA,CACC,IAjEa,IAmEzB,EACA,EAAY,YAAc"}
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_useRestoreFocus","require_useModalLayer","require_styles","require_Portal","require_Popover_shared","require_Dialog_shared","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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"}
@@ -5,12 +5,12 @@ import { composeEventHandlers as n } from "../../lib/composeEventHandlers.mjs";
5
5
  import { useMergedRefs as r } from "../../hooks/useMergedRefs.mjs";
6
6
  import { useIsClient as i } from "../../hooks/useIsClient.mjs";
7
7
  import { usePresence as ee } from "../../hooks/usePresence.mjs";
8
- import { Portal as te } from "../portal/Portal.mjs";
8
+ import { useRestoreFocus as te } from "../../hooks/useRestoreFocus.mjs";
9
+ import { useModalLayer as ne } from "../../hooks/useModalLayer.mjs";
9
10
  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";
11
+ import { Portal as re } from "../portal/Portal.mjs";
12
+ import { getTabbableThrough as o, usePopoverTabOrder as s } from "./Popover.shared.mjs";
13
+ import { useBackdropPress as c, useModalDismiss as l, useModalOpener as u, useOpenInsideWarning as d, useRaiseOnOpen as ie } from "./Dialog.shared.mjs";
14
14
  import { ModalBackdrop as ae } from "./Dialog.slots.mjs";
15
15
  import * as f from "react";
16
16
  import { jsx as p, jsxs as oe } from "react/jsx-runtime";
@@ -82,7 +82,7 @@ var C = "fixed flex flex-col border-border bg-background text-foreground shadow-
82
82
  q.current === e && (q.current = null), K(null);
83
83
  };
84
84
  }, []), de = r(N, le, H), fe = r(N, ue, H);
85
- ne({
85
+ te({
86
86
  enabled: m && I,
87
87
  container: ce,
88
88
  triggerRef: E.focusRef,
@@ -90,8 +90,8 @@ var C = "fixed flex flex-col border-border bg-background text-foreground shadow-
90
90
  requireFocusInside: !0
91
91
  });
92
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({
93
+ ie(m && L, B, J);
94
+ let Y = c(q, y !== "alert"), X = l(h, i, Y.afterOutsidePress), Z = ne({
95
95
  open: m && L,
96
96
  modalType: y,
97
97
  onDismiss: X,
@@ -99,13 +99,13 @@ var C = "fixed flex flex-col border-border bg-background text-foreground shadow-
99
99
  container: W,
100
100
  triggerRef: E.focusRef,
101
101
  finalFocusRef: D
102
- }), pe = l(m && L, E, W), me = o({
102
+ }), pe = u(m && L, E, W), me = s({
103
103
  enabled: m && z,
104
104
  surface: W,
105
105
  anchorRef: pe,
106
- getPreviousStop: re
106
+ getPreviousStop: o
107
107
  });
108
- u(m, B, Z.layerId, i, q);
108
+ d(m, B, Z.layerId, i, q);
109
109
  let Q = (R || I) && k != null && typeof k != "boolean";
110
110
  f.useEffect(() => {
111
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.`);
@@ -125,7 +125,7 @@ var C = "fixed flex flex-col border-border bg-background text-foreground shadow-
125
125
  onKeyDown: M,
126
126
  className: e(O, x, S(g, _), j),
127
127
  children: P
128
- }) : /* @__PURE__ */ oe(te, {
128
+ }) : /* @__PURE__ */ oe(re, {
129
129
  ref: J,
130
130
  layerId: Z.layerId,
131
131
  children: [!R && /* @__PURE__ */ p(ae, {
@@ -1 +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":";;;;;;;;;;;;;;;;;AAuCA,SAAgBE,EAAc,GAAkB,GAA6B;CAC3E,IAAMC,IAAWC,EAAY;CAC7B,OAAOC,MAAS,WAAWC,IAAYA,KAAaH;AACtD;AAMA,SAASI,EAAkB,GAA0C;CACnE,OAAOC,MAAa,WAAW,WAAW;AAC5C;AAOA,IAAMC,IAA4F;CAChG,OAAO;EAAE,OAAO;EAAQ,QAAQ;EAAS,OAAO;EAAS,MAAM;CAAS;CACxE,QAAQ;EAAE,OAAO;EAAQ,QAAQ;EAAS,OAAO;EAAS,MAAM;CAAS;AAC3E,GAOMC,IAA8D;CAClE,OAAO;CACP,KAAK;CACL,MAAM;CACN,OAAO;CACP,QAAQ;AACV,GAMMC,IAAoE;CACxE,OAAO;CACP,KAAK;CACL,MAAM;CACN,OAAO;CACP,QAAQ;AACV;AASA,SAASC,EAAuB,GAA0B,GAA0B;CAElF,OADIJ,MAAa,YAAYK,MAAS,SAAe,qCAC9C;AACT;AAOA,SAASC,EAAuB,GAA0B,GAA0B;CAClF,OAAO;EACLH,EAAwBH;EACxBE,EAAkBF;EAClBC,EAAkBF,EAAkBC,CAAQ,EAAE,CAACK;EAC/CD,EAAuBJ,GAAUK,CAAI;CACvC,CAAC,CAAC,KAAK,GAAG;AACZ;AAQA,IAAME,IAAqB;CACzB;CACA;CACAC,EAAa;AACf,CAAC,CAAC,KAAK,GAAG;AASV,SAASC,EAAsB,GAA0B,GAA0B;CACjF,IAAMC,IAAOX,EAAkBC,CAAQ;CACvC,OAAO;EACLE,EAAkBF;EAClBU,MAAS,WAAW,sBAAsB;EAC1CT,EAAkBS,EAAK,CAACL;CAC1B,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;AACb;AAsEA,IAAMM,IACJ,6EAeWC,KAAe,EAC1B,kBACA,SACA,SACA,gBACA,aACA,SACA,cACA,cACA,mBACA,aACA,YACA,kBACA,kBACA,uBACA,aACA,OACA,cACA,cACA,QACA,aACA,GAAGC,QACoC;CACvC,IAAMC,IAASjB,MAAS,UAClBkB,IAAU,CAACD,GACXE,IAAWC,MAAc,aACzBC,IAAkBH,KAAWC,GAC7BG,IAAc,CAACC,GAGf,EACJ,cACA,KAAKC,GACL,qBACEC,GAAYC,GAAM,EAAE,eAAeH,EAAe,CAAC,GAMjD,CAACI,GAAcC,KAAmBhC,EAAM,SAA6B,IAAI,GACzE,CAACiC,IAAaC,KAAkBlC,EAAM,SAA6B,IAAI,GAEvEmC,IAAWnC,EAAM,OAA2B,IAAI,GAChDoC,KAAqBpC,EAAM,aAAa,MAA6B;EACzE,IAAKqC,GAGL,OAFA,EAAS,UAAUA,GACnBL,EAAgBK,CAAI,SACP;GAEX,AADIF,EAAS,YAAYE,MAAM,EAAS,UAAU,OAClDL,EAAgB,IAAI;EACtB;CACF,GAAG,CAAC,CAAC,GACCM,KAAoBtC,EAAM,aAAa,MAA6B;EACxE,IAAKqC,GAGL,OAFA,EAAS,UAAUA,GACnBH,EAAeG,CAAI,SACN;GAEX,AADIF,EAAS,YAAYE,MAAM,EAAS,UAAU,OAClDH,EAAe,IAAI;EACrB;CACF,GAAG,CAAC,CAAC,GACCK,KAAaC,EAA2BC,GAAKL,IAAoBR,CAAW,GAC5Ec,KAAYF,EAA2BC,GAAKH,IAAmBV,CAAW;CAKhF,GAAgB;EACd,SAASE,KAAQT;EACjB,WAAWY;EACX,YAAYU,EAAQ;EACpB;EACA,oBAAoB;CACtB,CAAC;CAGD,IAAMC,IAAY5C,EAAM,OAA8B,IAAI;CAC1D,EAAe8B,KAAQR,GAASI,GAAakB,CAAS;CAItD,IAAMC,IAAgBC,EAAiBX,GAAUX,MAAc,OAAO,GAChEuB,IAAYC,EAAgBC,GAAaC,GAAeL,EAAc,iBAAiB,GAIvFM,IAAQC,GAAc;EAC1B,MAAMtB,KAAQR;EACd;EACA;EACA,MAAM,CAACa,CAAQ;EACf,WAAWJ;EACX,YAAYY,EAAQ;EACpB;CACF,CAAC,GAKKU,KAASC,EAAexB,KAAQR,GAASqB,GAASZ,CAAY,GAC9DwB,KAAoBC,EAAmB;EAC3C,SAAS1B,KAAQL;EACjB,SAASM;EACT,WAAWsB;EACX,iBAAiBI;CACnB,CAAC;CAED,EAAqB3B,GAAMJ,GAAayB,EAAM,SAASD,GAAef,CAAQ;CAG9E,IAAMuB,KACHnC,KAAYF,MACbsC,KACa,QACb,OAAOA,KAAa;CACtB,EAAM,gBAAgB;EACpB,AAAKD,KACLE,EACE,GAAGV,EAAc,oBACjB,GAAGA,EAAc,6GACnB;CACF,GAAG,CAACQ,GAAiBR,CAAa,CAAC;CAEnC,IAAMW,IAAmB/B,KAAQL,KAAmBb,MAAS;CAsC7D,OArCAZ,EAAM,gBAAgB;EACpB,AAAK6D,KACLD,EACE,GAAGV,EAAc,kBACjB,GAAGA,EAAc,6PACnB;CACF,GAAG,CAACW,GAAkBX,CAAa,CAAC,GAE/BY,IAEDzC,IAKA,kBAACtB,GAAD;EACE,KAAK2C;EACD;EACJ,aAAU;EACV,iBAAenC;EACf,aAAWK;EACX,kBAAgBoD,IAAY,KAAK,KAAA;EACjC,GAAI5C;EACJ,GAAI6C;EACO;EACX,WAAWC,EACTC,GACArD,GACAE,EAAsBT,GAAUK,CAAI,GACpCwD,CACF;EAEC;CACU,CAAA,IAKf,mBAACC,IAAD;EAAQ,KAAKzB;EAAW,SAASO,EAAM;EAAvC,UAAA,CAIG,CAAC5B,KACA,kBAAC+C,IAAD;GACY;GACV,WAAWC;GACX,SAASpB,EAAM;GACT;GACN,aAAaN,EAAc;GACZ;EAChB,CAAA,GAEH,kBAAC,OAAD;GACE,KAAKN;GACL,MAAMf,MAAc,UAAU,gBAAgB;GAC1C;GACJ,UAAU;GACV,aAAU;GACV,iBAAejB;GACf,aAAWK;GACX,mBAAiBY;GACjB,GAAIJ;GACJ,GAAI6C;GACJ,WAAWO,EAAqBC,GAAWlB,EAAiB;GAC5D,WAAWW,EACTC,GACAjD,GACAL,EAAuBN,GAAUK,CAAI,GACrCwD,CACF;GAEC;EACE,CAAA,CACC;MAjEa;AAmEzB;AACA,EAAY,cAAc"}
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":";;;;;;;;;;;;;;;;;AAuCA,SAAgBE,EAAc,GAAkB,GAA6B;CAC3E,IAAMC,IAAWC,EAAY;CAC7B,OAAOC,MAAS,WAAWC,IAAYA,KAAaH;AACtD;AAMA,SAASI,EAAkB,GAA0C;CACnE,OAAOC,MAAa,WAAW,WAAW;AAC5C;AAOA,IAAMC,IAA4F;CAChG,OAAO;EAAE,OAAO;EAAQ,QAAQ;EAAS,OAAO;EAAS,MAAM;CAAS;CACxE,QAAQ;EAAE,OAAO;EAAQ,QAAQ;EAAS,OAAO;EAAS,MAAM;CAAS;AAC3E,GAOMC,IAA8D;CAClE,OAAO;CACP,KAAK;CACL,MAAM;CACN,OAAO;CACP,QAAQ;AACV,GAMMC,IAAoE;CACxE,OAAO;CACP,KAAK;CACL,MAAM;CACN,OAAO;CACP,QAAQ;AACV;AASA,SAASC,EAAuB,GAA0B,GAA0B;CAElF,OADIJ,MAAa,YAAYK,MAAS,SAAe,qCAC9C;AACT;AAOA,SAASC,EAAuB,GAA0B,GAA0B;CAClF,OAAO;EACLH,EAAwBH;EACxBE,EAAkBF;EAClBC,EAAkBF,EAAkBC,CAAQ,EAAE,CAACK;EAC/CD,EAAuBJ,GAAUK,CAAI;CACvC,CAAC,CAAC,KAAK,GAAG;AACZ;AAQA,IAAME,IAAqB;CACzB;CACA;CACAC,EAAa;AACf,CAAC,CAAC,KAAK,GAAG;AASV,SAASC,EAAsB,GAA0B,GAA0B;CACjF,IAAMC,IAAOX,EAAkBC,CAAQ;CACvC,OAAO;EACLE,EAAkBF;EAClBU,MAAS,WAAW,sBAAsB;EAC1CT,EAAkBS,EAAK,CAACL;CAC1B,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;AACb;AAsEA,IAAMM,IACJ,6EAeWC,KAAe,EAC1B,kBACA,SACA,SACA,gBACA,aACA,SACA,cACA,cACA,mBACA,aACA,YACA,kBACA,kBACA,uBACA,aACA,OACA,cACA,cACA,QACA,aACA,GAAGC,QACoC;CACvC,IAAMC,IAASjB,MAAS,UAClBkB,IAAU,CAACD,GACXE,IAAWC,MAAc,aACzBC,IAAkBH,KAAWC,GAC7BG,IAAc,CAACC,GAGf,EACJ,cACA,KAAKC,GACL,qBACEC,GAAYC,GAAM,EAAE,eAAeH,EAAe,CAAC,GAMjD,CAACI,GAAcC,KAAmBhC,EAAM,SAA6B,IAAI,GACzE,CAACiC,IAAaC,KAAkBlC,EAAM,SAA6B,IAAI,GAEvEmC,IAAWnC,EAAM,OAA2B,IAAI,GAChDoC,KAAqBpC,EAAM,aAAa,MAA6B;EACzE,IAAKqC,GAGL,OAFA,EAAS,UAAUA,GACnBL,EAAgBK,CAAI,SACP;GAEX,AADIF,EAAS,YAAYE,MAAM,EAAS,UAAU,OAClDL,EAAgB,IAAI;EACtB;CACF,GAAG,CAAC,CAAC,GACCM,KAAoBtC,EAAM,aAAa,MAA6B;EACxE,IAAKqC,GAGL,OAFA,EAAS,UAAUA,GACnBH,EAAeG,CAAI,SACN;GAEX,AADIF,EAAS,YAAYE,MAAM,EAAS,UAAU,OAClDH,EAAe,IAAI;EACrB;CACF,GAAG,CAAC,CAAC,GACCK,KAAaC,EAA2BC,GAAKL,IAAoBR,CAAW,GAC5Ec,KAAYF,EAA2BC,GAAKH,IAAmBV,CAAW;CAKhF,GAAgB;EACd,SAASE,KAAQT;EACjB,WAAWY;EACX,YAAYU,EAAQ;EACpB;EACA,oBAAoB;CACtB,CAAC;CAGD,IAAMC,IAAY5C,EAAM,OAA8B,IAAI;CAC1D,GAAe8B,KAAQR,GAASI,GAAakB,CAAS;CAItD,IAAMC,IAAgBC,EAAiBX,GAAUX,MAAc,OAAO,GAChEuB,IAAYC,EAAgBC,GAAaC,GAAeL,EAAc,iBAAiB,GAIvFM,IAAQC,GAAc;EAC1B,MAAMtB,KAAQR;EACd;EACA;EACA,MAAM,CAACa,CAAQ;EACf,WAAWJ;EACX,YAAYY,EAAQ;EACpB;CACF,CAAC,GAKKU,KAASC,EAAexB,KAAQR,GAASqB,GAASZ,CAAY,GAC9DwB,KAAoBC,EAAmB;EAC3C,SAAS1B,KAAQL;EACjB,SAASM;EACT,WAAWsB;EACX,iBAAiBI;CACnB,CAAC;CAED,EAAqB3B,GAAMJ,GAAayB,EAAM,SAASD,GAAef,CAAQ;CAG9E,IAAMuB,KACHnC,KAAYF,MACbsC,KACa,QACb,OAAOA,KAAa;CACtB,EAAM,gBAAgB;EACpB,AAAKD,KACLE,EACE,GAAGV,EAAc,oBACjB,GAAGA,EAAc,6GACnB;CACF,GAAG,CAACQ,GAAiBR,CAAa,CAAC;CAEnC,IAAMW,IAAmB/B,KAAQL,KAAmBb,MAAS;CAsC7D,OArCAZ,EAAM,gBAAgB;EACpB,AAAK6D,KACLD,EACE,GAAGV,EAAc,kBACjB,GAAGA,EAAc,6PACnB;CACF,GAAG,CAACW,GAAkBX,CAAa,CAAC,GAE/BY,IAEDzC,IAKA,kBAACtB,GAAD;EACE,KAAK2C;EACD;EACJ,aAAU;EACV,iBAAenC;EACf,aAAWK;EACX,kBAAgBoD,IAAY,KAAK,KAAA;EACjC,GAAI5C;EACJ,GAAI6C;EACO;EACX,WAAWC,EACTC,GACArD,GACAE,EAAsBT,GAAUK,CAAI,GACpCwD,CACF;EAEC;CACU,CAAA,IAKf,mBAACC,IAAD;EAAQ,KAAKzB;EAAW,SAASO,EAAM;EAAvC,UAAA,CAIG,CAAC5B,KACA,kBAAC+C,IAAD;GACY;GACV,WAAWC;GACX,SAASpB,EAAM;GACT;GACN,aAAaN,EAAc;GACZ;EAChB,CAAA,GAEH,kBAAC,OAAD;GACE,KAAKN;GACL,MAAMf,MAAc,UAAU,gBAAgB;GAC1C;GACJ,UAAU;GACV,aAAU;GACV,iBAAejB;GACf,aAAWK;GACX,mBAAiBY;GACjB,GAAIJ;GACJ,GAAI6C;GACJ,WAAWO,EAAqBC,GAAWlB,EAAiB;GAC5D,WAAWW,EACTC,GACAjD,GACAL,EAAuBN,GAAUK,CAAI,GACrCwD,CACF;GAEC;EACE,CAAA,CACC;MAjEa;AAmEzB;AACA,EAAY,cAAc"}
@@ -1,2 +1,2 @@
1
- "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/slot.cjs"),i=require("../../lib/composeEventHandlers.cjs"),a=require("../../lib/classNames.cjs"),o=require("../../hooks/useEventCallback.cjs"),s=require("../../hooks/useControllable.cjs"),c=require("../../hooks/useId.cjs"),l=require("../../lib/focus.cjs"),u=require("../../hooks/useMergedRefs.cjs"),d=require("../../hooks/useIsClient.cjs"),f=require("../../hooks/useDismiss.cjs"),p=require("../portal/Portal.cjs"),m=require("../../hooks/usePopupPosition.cjs"),ee=require("../../hooks/useRestoreFocus.cjs"),te=require("../../hooks/useHoverIntent.cjs"),h=require("./Popover.shared.cjs"),g=require("../../hooks/useTriggerElement.cjs"),_=require("../../hooks/useContextMenuAnchor.cjs");let v=require("react");v=e.__toESM(v,1);let y=require("react/jsx-runtime");var b=v.createContext(null);b.displayName=`PopoverContext`;var x=null;function S(){return x??={open:!1,setOpen:()=>{},contentId:`wave-popover-inert-content`,setCustomContentId:()=>{},triggerId:`wave-popover-inert-trigger`,resolvedTriggerId:void 0,setResolvedTriggerId:()=>{},triggerRef:{current:null},triggerElement:null,triggerElementRef:()=>{},surfaceElementRef:()=>{},arrowRef:{current:null},onTriggerClick:()=>{},onTriggerKeyDown:()=>{},hoverTriggerHandlers:null,hoverSurfaceHandlers:null,contextMode:!1,contextTriggerHandlers:null,onContentContextMenu:()=>{},keyboardContext:!1,onContentKeyDown:()=>{},layerId:`wave-popover-inert-layer`,floatingProps:{"data-side":`bottom`,"data-align":`start`,style:{}},arrowStyles:{},placedSide:`bottom`},x}function C(e){return v.useContext(b)||(n.reportMissingContext(e,`Popover`),S())}function w(e,t){let n=(t??``).split(/\s+/).filter(t=>t&&e.getElementById(t));return n.length>0?n.join(` `):void 0}function T(e,t){if(!e)return t;let n=e.ownerDocument,r=(t?n.getElementById(t):null)??g.getTriggerFocusTarget(e)??e;return w(n,r.getAttribute(`aria-labelledby`))??(r.id||e.id||void 0)}function ne(e,t){return t.split(/\s+/).some(t=>{let n=t?e.getElementById(t):null;return n?n.getAttribute(`aria-label`)?.trim()||n.textContent?.trim()?!0:!!n.querySelector(`[aria-label]:not([aria-label=""]), [alt]:not([alt=""]), [title]:not([title=""])`):!1})}var re=()=>()=>{};function E(e){return!!e&&typeof e.nodeType==`number`}function D(e){return{get current(){return e()}}}function O(e,t,n){return g.getTriggerFocusTarget(e)??h.getTabbableThrough(e,t,n)}var k=({open:e,defaultOpen:t,onOpenChange:r,side:i=`bottom`,align:a=`start`,ignoreOutsideRefs:p,openOnHover:x=!1,openDelay:S=250,closeDelay:C=500,openOnContext:w=!1,target:T,children:ne})=>{let[re,k]=s.useControllable(e,t??!1,r),A=v.useRef(!1),j=o.useEventCallback(e=>{A.current=!1,k(e)}),M=v.useCallback(()=>A.current,[]),N=d.useIsClient(),P=re&&N,[F,I]=v.useState(`other`),[L,R]=v.useState(!1),[ie,ae]=v.useState(P),z=F;P!==ie&&(ae(P),P&&(z=L?`hover`:`other`)),z!==F&&I(z),L&&R(!1);let oe=c.useId(`popover-content`),[B,V]=v.useState(void 0),H=B??oe,U=c.useId(`popover-trigger`),[W,se]=v.useState(void 0),[G,ce]=v.useState(null),[K,le]=v.useState(null),q=v.useRef(null),J=v.useRef(null),ue=v.useRef(null),de=E(T)?T:null,Y=v.useRef(null);v.useInsertionEffect(()=>{Y.current=de},[de]);let{setReference:fe,setFloating:pe,floatingProps:me,arrowStyles:he,side:ge}=m.usePopupPosition({open:P,side:i,align:a,offset:8,arrowRef:ue}),_e=v.useRef(null),ve=o.useEventCallback(()=>{let e=w?_e.current?.current:null;if(e&&l.isConnectedAndFocusable(e))return e;let t=q.current,n=t?g.getTriggerFocusTarget(t):null;if(n)return n;let r=Y.current;return r&&l.isConnectedAndFocusable(r)?r:t}),ye=v.useMemo(()=>D(ve),[ve]),be=o.useEventCallback(e=>!(e.ctrlKey&&q.current?.contains(e.target))),{layerId:X}=f.useDismiss({open:P,onDismiss:()=>j(!1),refs:w?[J,Y,...p??[]]:[J,q,Y,...p??[]],anchorRef:ye,kind:`popover`,outsidePress:!w||be}),Z=v.useRef(!1),{anchor:xe,fromContext:Se,origin:Ce,opener:Q,triggerHandlers:we,surfaceHandlers:Te}=_.useContextMenuAnchor({enabled:w,open:P,trigger:K,layerId:X,onOpen:e=>{Z.current=e===`keyboard`,j(!0)},onClose:()=>j(!1)});v.useInsertionEffect(()=>{_e.current=Q},[Q]);let Ee=g.useTriggerFocusRef(q);ee.useRestoreFocus({enabled:P,container:G,triggerRef:w?void 0:Ee,finalFocusRef:w?Q:void 0,fallback:ve,onlyIfFocusInside:!0,isHoverClose:M}),v.useLayoutEffect(()=>{P&&(A.current=!1)},[P]);let De=u.useMergedRefs(q,le),Oe=u.useMergedRefs(J,ce,pe);v.useLayoutEffect(()=>{fe(Se?xe??(K&&(g.getTriggerFocusTarget(K)??K)):T??K)},[xe,Se,T,K,fe]),v.useLayoutEffect(()=>{if(Z.current){if(!P){Z.current=!1;return}G&&(Z.current=!1,l.focusElement(l.getFirstTabbable(G)??G,{preventScroll:!0}))}}),v.useEffect(()=>{x&&w&&n.warnOnce(`Popover:hover-and-context`,"Popover: `openOnHover` is ignored with `openOnContext`: a context popover opens on a right click, Shift+F10 or the ContextMenu key, not on hover.")},[x,w]);let $=x&&!w,ke=o.useEventCallback(()=>z===`hover`&&!h.isFocusInSurfaceTree(J.current,X)),{triggerHandlers:Ae,surfaceHandlers:je,cancel:Me}=te.useHoverIntent({enabled:$,open:P,openDelay:S,closeDelay:C,trigger:K,surface:G,onOpen:()=>{R(!0),j(!0)},onClose:()=>{A.current=!0,k(!1)},canClose:ke}),Ne=o.useEventCallback(()=>{Me(),P&&z===`hover`?I(`other`):j(e=>!e)}),Pe=o.useEventCallback(()=>{let e=q.current,t=w?Q.current:null;return t&&e?.contains(t)?t:e??Y.current}),Fe=v.useMemo(()=>D(Pe),[Pe]),Ie=o.useEventCallback(e=>{if(e.key!==`Tab`||e.shiftKey||!P)return;if(w){let t=Pe();if(!t||e.target!==(g.getTriggerFocusTarget(t)??t))return}let t=J.current,n=t?l.getFirstTabbable(t):null;n&&(e.preventDefault(),n.focus())}),Le=h.usePopoverTabOrder({enabled:P,surface:G,anchorRef:Fe,getPreviousStop:O}),Re=Se&&Ce===`keyboard`,ze=v.useMemo(()=>({open:P,setOpen:j,contentId:H,setCustomContentId:V,triggerId:U,resolvedTriggerId:W,setResolvedTriggerId:se,triggerRef:q,triggerElement:K,triggerElementRef:De,surfaceElementRef:Oe,arrowRef:ue,onTriggerClick:Ne,onTriggerKeyDown:Ie,hoverTriggerHandlers:$?Ae:null,hoverSurfaceHandlers:$?je:null,contextMode:w,contextTriggerHandlers:w?we:null,onContentContextMenu:Te.onContextMenu,keyboardContext:Re,onContentKeyDown:Le,layerId:X,floatingProps:me,arrowStyles:he,placedSide:ge}),[P,j,H,U,W,K,De,Oe,Ne,Ie,$,Ae,je,w,we,Te,Re,Le,X,me,he,ge]);return(0,y.jsx)(b.Provider,{value:ze,children:ne})};k.displayName=`Popover`;var A=({children:e,asChild:t,id:n,onClick:r,onKeyDown:a,onContextMenu:o,onPointerEnter:s,onPointerMove:c,onPointerLeave:l,ref:d,...f})=>{let{open:p,contentId:m,triggerId:ee,triggerElementRef:te,setResolvedTriggerId:h,onTriggerClick:_,onTriggerKeyDown:v,hoverTriggerHandlers:y,contextMode:b,contextTriggerHandlers:x}=C(`Popover.Trigger`),S=u.useMergedRefs(d,te),w={...f,id:n??ee,"aria-haspopup":`dialog`,"aria-expanded":!b&&p,"aria-controls":p&&!b?m:void 0,onClick:i.composeEventHandlers(r,b?void 0:_),onKeyDown:i.composeEventHandlers(a,x?i.composeEventHandlers(x.onKeyDown,v):v),onContextMenu:x?i.composeEventHandlers(o,x.onContextMenu):o,onPointerEnter:y?i.composeEventHandlers(s,y.onPointerEnter):s,onPointerMove:y?i.composeEventHandlers(c,y.onPointerMove):c,onPointerLeave:y?i.composeEventHandlers(l,y.onPointerLeave):l,ref:S};return g.useTriggerElement(e,w,{componentName:`Popover.Trigger`,asChild:t,onResolvedId:h,omitStateAria:b})};A.displayName=`PopoverTrigger`;var j=({children:e,title:o,id:s,className:l,style:d,"aria-label":f,"aria-labelledby":m,onKeyDown:ee,onContextMenu:te,onPointerEnter:g,onPointerLeave:_,ref:b,...x})=>{let{open:S,contentId:w,setCustomContentId:E,resolvedTriggerId:D,triggerRef:O,triggerElement:k,surfaceElementRef:A,arrowRef:j,layerId:M,floatingProps:N,arrowStyles:P,placedSide:F,onContentKeyDown:I,hoverSurfaceHandlers:L,contextMode:R,onContentContextMenu:ie,keyboardContext:ae}=C(`Popover.Content`),z=c.useId(`popover-title`),oe=u.useMergedRefs(b,A),B=r.slotRendersContent(o),V=m===void 0&&!f&&!B,H=S&&V&&!R,U=v.useCallback(e=>{if(!H||!k||typeof MutationObserver>`u`)return re();let t=new MutationObserver(e);return t.observe(k,{attributes:!0,attributeFilter:[`id`,`aria-labelledby`],childList:!0,subtree:!0}),()=>t.disconnect()},[H,k]),W=v.useSyncExternalStore(U,()=>H?T(k,D):void 0,()=>H?D:void 0),se=m??(f?void 0:B?z:W),G=s||void 0;return v.useEffect(()=>(E(G),()=>E(void 0)),[G,E]),v.useEffect(()=>{S&&V&&R&&n.isDev&&n.warnOnce(`Popover.Content:name`,"Popover.Content: the popover has no accessible name. A context popover (openOnContext) is not named by its region: pass `title`, `aria-label` or `aria-labelledby`.")},[S,V,R]),v.useEffect(()=>{if(!H||!n.isDev)return;let e=O.current;if(!e){n.warnOnce(`Popover.Content:name`,"Popover.Content: the popover has no accessible name. Pass `title`, `aria-label` or `aria-labelledby`, or open it from a Popover.Trigger.");return}let t=T(e,D);t?ne(e.ownerDocument,t)||n.warnOnce(`Popover.Content:trigger-name`,"Popover.Content: the popover is named by its trigger, but the trigger has no text to name it (an icon-only trigger needs `aria-label`, or `aria-labelledby` pointing at text), so the popover has no accessible name. Name the trigger, or pass `title`, `aria-label` or `aria-labelledby`."):n.warnOnce(`Popover.Content:trigger-id`,"Popover.Content: the popover is named by its trigger, but the trigger element has no `id` (a render-prop child of Popover.Trigger must spread the `id` it receives), so the popover has no accessible name. Spread every trigger prop onto the element, or pass `title`, `aria-label` or `aria-labelledby`.")},[H,D,O,W]),S?(0,y.jsx)(p.Portal,{layerId:M,children:(0,y.jsxs)(`div`,{role:`dialog`,"aria-label":f,"aria-labelledby":se,tabIndex:ae?-1:void 0,...x,ref:oe,id:G??w,"data-side":N[`data-side`],"data-align":N[`data-align`],style:{...d,...N.style},onKeyDown:i.composeEventHandlers(ee,I),onContextMenu:i.composeEventHandlers(te,ie),onPointerEnter:L?i.composeEventHandlers(g,L.onPointerEnter):g,onPointerLeave:L?i.composeEventHandlers(_,L.onPointerLeave):_,className:t.cn(a.popoverContentClassNames.root,`w-64 rounded-md border border-border bg-background p-4 text-body-1 font-normal text-foreground normal-case tracking-normal text-start shadow-4`,l),children:[(0,y.jsx)(h.PopoverBeak,{ref:j,side:F,style:P,"data-wave-popover-arrow":``,className:a.popoverContentClassNames.beak}),B&&(0,y.jsx)(`h2`,{id:z,className:t.cn(a.popoverContentClassNames.title,`mb-2 text-subtitle-2 font-semibold`),children:o}),e]})}):null};j.displayName=`PopoverContent`;var M=Object.assign(k,{Trigger:A,Content:j});exports.Popover=M,exports.PopoverContent=j,exports.PopoverTrigger=A;
1
+ "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/slot.cjs"),i=require("../../lib/composeEventHandlers.cjs"),a=require("../../lib/classNames.cjs"),o=require("../../hooks/useEventCallback.cjs"),s=require("../../hooks/useControllable.cjs"),c=require("../../hooks/useId.cjs"),l=require("../../lib/focus.cjs"),u=require("../../hooks/useMergedRefs.cjs"),ee=require("../../hooks/useIsClient.cjs"),d=require("../../hooks/usePopupPosition.cjs"),f=require("../../hooks/useDismiss.cjs"),te=require("../../hooks/useRestoreFocus.cjs"),p=require("../portal/Portal.cjs"),ne=require("../../hooks/useHoverIntent.cjs"),m=require("./Popover.shared.cjs"),h=require("../../hooks/useTriggerElement.cjs"),g=require("../../hooks/useResolvedTarget.cjs"),_=require("../../hooks/useContextMenuAnchor.cjs");let v=require("react");v=e.__toESM(v,1);let y=require("react/jsx-runtime");var b=v.createContext(null);b.displayName=`PopoverContext`;var x=null;function S(){return x??={open:!1,setOpen:()=>{},contentId:`wave-popover-inert-content`,setCustomContentId:()=>{},triggerId:`wave-popover-inert-trigger`,resolvedTriggerId:void 0,setResolvedTriggerId:()=>{},triggerRef:{current:null},triggerElement:null,triggerElementRef:()=>{},surfaceElementRef:()=>{},arrowRef:{current:null},onTriggerClick:()=>{},onTriggerKeyDown:()=>{},hoverTriggerHandlers:null,hoverSurfaceHandlers:null,contextMode:!1,contextTriggerHandlers:null,onContentContextMenu:()=>{},keyboardContext:!1,onContentKeyDown:()=>{},layerId:`wave-popover-inert-layer`,floatingProps:{"data-side":`bottom`,"data-align":`start`,style:{}},arrowStyles:{},placedSide:`bottom`,fitViewport:!1},x}function C(e){return v.useContext(b)||(n.reportMissingContext(e,`Popover`),S())}function w(e,t){let n=(t??``).split(/\s+/).filter(t=>t&&e.getElementById(t));return n.length>0?n.join(` `):void 0}function T(e,t){if(!e)return t;let n=e.ownerDocument,r=(t?n.getElementById(t):null)??h.getTriggerFocusTarget(e)??e;return w(n,r.getAttribute(`aria-labelledby`))??(r.id||e.id||void 0)}function E(e,t){return t.split(/\s+/).some(t=>{let n=t?e.getElementById(t):null;return n?n.getAttribute(`aria-label`)?.trim()||n.textContent?.trim()?!0:!!n.querySelector(`[aria-label]:not([aria-label=""]), [alt]:not([alt=""]), [title]:not([title=""])`):!1})}var re=()=>()=>{};function D(e){return!!e&&typeof e.nodeType==`number`}function O(e){return{get current(){return e()}}}function k(e,t,n){return h.getTriggerFocusTarget(e)??m.getTabbableThrough(e,t,n)}var A=({open:e,defaultOpen:t,onOpenChange:r,side:i=`bottom`,align:a=`start`,ignoreOutsideRefs:p,openOnHover:x=!1,openDelay:S=250,closeDelay:C=500,openOnContext:w=!1,target:T,positioning:E,children:re})=>{let{target:A,pending:j}=g.usePopupTarget(`Popover`,T,E),[M,N]=s.useControllable(e,t??!1,r),P=v.useRef(!1),F=o.useEventCallback(e=>{P.current=!1,N(e)}),ie=v.useCallback(()=>P.current,[]),ae=ee.useIsClient(),I=M&&ae,[L,oe]=v.useState(`other`),[se,R]=v.useState(!1),[ce,z]=v.useState(I),B=L;I!==ce&&(z(I),I&&(B=se?`hover`:`other`)),B!==L&&oe(B),se&&R(!1);let V=c.useId(`popover-content`),[le,ue]=v.useState(void 0),de=le??V,H=c.useId(`popover-trigger`),[U,fe]=v.useState(void 0),[W,pe]=v.useState(null),[G,me]=v.useState(null),K=v.useRef(null),q=v.useRef(null),he=v.useRef(null),ge=D(A)?A:null,J=v.useRef(null);v.useInsertionEffect(()=>{J.current=ge},[ge]);let{setReference:_e,setFloating:ve,floatingProps:Y,arrowStyles:ye,side:be}=d.usePopupPosition({open:I,side:i,align:a,arrowRef:he,...d.resolvePositioning(E,{offset:8})}),xe=v.useMemo(()=>j?{...Y,style:{...Y.style,visibility:`hidden`}}:Y,[j,Y]),Se=v.useRef(null),Ce=o.useEventCallback(()=>{let e=w?Se.current?.current:null;if(e&&l.isConnectedAndFocusable(e))return e;let t=K.current,n=t?h.getTriggerFocusTarget(t):null;if(n)return n;let r=J.current;return r&&l.isConnectedAndFocusable(r)?r:t}),we=v.useMemo(()=>O(Ce),[Ce]),Te=o.useEventCallback(e=>!(e.ctrlKey&&K.current?.contains(e.target))),{layerId:X}=f.useDismiss({open:I,onDismiss:()=>F(!1),refs:w?[q,J,...p??[]]:[q,K,J,...p??[]],anchorRef:we,kind:`popover`,outsidePress:!w||Te}),Z=v.useRef(!1),{anchor:Ee,fromContext:De,origin:Oe,opener:Q,triggerHandlers:ke,surfaceHandlers:Ae}=_.useContextMenuAnchor({enabled:w,open:I,trigger:G,layerId:X,onOpen:e=>{Z.current=e===`keyboard`,F(!0)},onClose:()=>F(!1)});v.useInsertionEffect(()=>{Se.current=Q},[Q]);let je=h.useTriggerFocusRef(K);te.useRestoreFocus({enabled:I,container:W,triggerRef:w?void 0:je,finalFocusRef:w?Q:void 0,fallback:Ce,onlyIfFocusInside:!0,isHoverClose:ie}),v.useLayoutEffect(()=>{I&&(P.current=!1)},[I]);let Me=u.useMergedRefs(K,me),Ne=u.useMergedRefs(q,pe,ve);v.useLayoutEffect(()=>{_e(De?Ee??(G&&(h.getTriggerFocusTarget(G)??G)):A??G)},[Ee,De,A,G,_e]),v.useLayoutEffect(()=>{if(Z.current){if(!I){Z.current=!1;return}W&&(Z.current=!1,l.focusElement(l.getFirstTabbable(W)??W,{preventScroll:!0}))}}),v.useEffect(()=>{x&&w&&n.warnOnce(`Popover:hover-and-context`,"Popover: `openOnHover` is ignored with `openOnContext`: a context popover opens on a right click, Shift+F10 or the ContextMenu key, not on hover.")},[x,w]);let $=x&&!w,Pe=o.useEventCallback(()=>B===`hover`&&!m.isFocusInSurfaceTree(q.current,X)),{triggerHandlers:Fe,surfaceHandlers:Ie,cancel:Le}=ne.useHoverIntent({enabled:$,open:I,openDelay:S,closeDelay:C,trigger:G,surface:W,onOpen:()=>{R(!0),F(!0)},onClose:()=>{P.current=!0,N(!1)},canClose:Pe}),Re=o.useEventCallback(()=>{Le(),I&&B===`hover`?oe(`other`):F(e=>!e)}),ze=o.useEventCallback(()=>{let e=K.current,t=w?Q.current:null;return t&&e?.contains(t)?t:e??J.current}),Be=v.useMemo(()=>O(ze),[ze]),Ve=o.useEventCallback(e=>{if(e.key!==`Tab`||e.shiftKey||!I)return;if(w){let t=ze();if(!t||e.target!==(h.getTriggerFocusTarget(t)??t))return}let t=q.current,n=t?l.getFirstTabbable(t):null;n&&(e.preventDefault(),n.focus())}),He=m.usePopoverTabOrder({enabled:I,surface:W,anchorRef:Be,getPreviousStop:k}),Ue=De&&Oe===`keyboard`,We=v.useMemo(()=>({open:I,setOpen:F,contentId:de,setCustomContentId:ue,triggerId:H,resolvedTriggerId:U,setResolvedTriggerId:fe,triggerRef:K,triggerElement:G,triggerElementRef:Me,surfaceElementRef:Ne,arrowRef:he,onTriggerClick:Re,onTriggerKeyDown:Ve,hoverTriggerHandlers:$?Fe:null,hoverSurfaceHandlers:$?Ie:null,contextMode:w,contextTriggerHandlers:w?ke:null,onContentContextMenu:Ae.onContextMenu,keyboardContext:Ue,onContentKeyDown:He,layerId:X,floatingProps:xe,arrowStyles:ye,placedSide:be,fitViewport:E?.fitViewport===!0}),[I,F,de,H,U,G,Me,Ne,Re,Ve,$,Fe,Ie,w,ke,Ae,Ue,He,X,xe,ye,be,E?.fitViewport]);return(0,y.jsx)(b.Provider,{value:We,children:re})};A.displayName=`Popover`;var j=({children:e,asChild:t,id:n,onClick:r,onKeyDown:a,onContextMenu:o,onPointerEnter:s,onPointerMove:c,onPointerLeave:l,ref:ee,...d})=>{let{open:f,contentId:te,triggerId:p,triggerElementRef:ne,setResolvedTriggerId:m,onTriggerClick:g,onTriggerKeyDown:_,hoverTriggerHandlers:v,contextMode:y,contextTriggerHandlers:b}=C(`Popover.Trigger`),x=u.useMergedRefs(ee,ne),S={...d,id:n??p,"aria-haspopup":`dialog`,"aria-expanded":!y&&f,"aria-controls":f&&!y?te:void 0,onClick:i.composeEventHandlers(r,y?void 0:g),onKeyDown:i.composeEventHandlers(a,b?i.composeEventHandlers(b.onKeyDown,_):_),onContextMenu:b?i.composeEventHandlers(o,b.onContextMenu):o,onPointerEnter:v?i.composeEventHandlers(s,v.onPointerEnter):s,onPointerMove:v?i.composeEventHandlers(c,v.onPointerMove):c,onPointerLeave:v?i.composeEventHandlers(l,v.onPointerLeave):l,ref:x};return h.useTriggerElement(e,S,{componentName:`Popover.Trigger`,asChild:t,onResolvedId:m,omitStateAria:y})};j.displayName=`PopoverTrigger`;var M=({children:e,title:o,id:s,className:l,style:ee,"aria-label":d,"aria-labelledby":f,onKeyDown:te,onContextMenu:ne,onPointerEnter:h,onPointerLeave:g,ref:_,...b})=>{let{open:x,contentId:S,setCustomContentId:w,resolvedTriggerId:D,triggerRef:O,triggerElement:k,surfaceElementRef:A,arrowRef:j,layerId:M,floatingProps:N,arrowStyles:P,placedSide:F,fitViewport:ie,onContentKeyDown:ae,hoverSurfaceHandlers:I,contextMode:L,onContentContextMenu:oe,keyboardContext:se}=C(`Popover.Content`),R=c.useId(`popover-title`),ce=u.useMergedRefs(_,A),z=r.slotRendersContent(o),B=f===void 0&&!d&&!z,V=x&&B&&!L,le=v.useCallback(e=>{if(!V||!k||typeof MutationObserver>`u`)return re();let t=new MutationObserver(e);return t.observe(k,{attributes:!0,attributeFilter:[`id`,`aria-labelledby`],childList:!0,subtree:!0}),()=>t.disconnect()},[V,k]),ue=v.useSyncExternalStore(le,()=>V?T(k,D):void 0,()=>V?D:void 0),de=f??(d?void 0:z?R:ue),H=s||void 0;if(v.useEffect(()=>(w(H),()=>w(void 0)),[H,w]),v.useEffect(()=>{x&&B&&L&&n.isDev&&n.warnOnce(`Popover.Content:name`,"Popover.Content: the popover has no accessible name. A context popover (openOnContext) is not named by its region: pass `title`, `aria-label` or `aria-labelledby`.")},[x,B,L]),v.useEffect(()=>{if(!V||!n.isDev)return;let e=O.current;if(!e){n.warnOnce(`Popover.Content:name`,"Popover.Content: the popover has no accessible name. Pass `title`, `aria-label` or `aria-labelledby`, or open it from a Popover.Trigger.");return}let t=T(e,D);t?E(e.ownerDocument,t)||n.warnOnce(`Popover.Content:trigger-name`,"Popover.Content: the popover is named by its trigger, but the trigger has no text to name it (an icon-only trigger needs `aria-label`, or `aria-labelledby` pointing at text), so the popover has no accessible name. Name the trigger, or pass `title`, `aria-label` or `aria-labelledby`."):n.warnOnce(`Popover.Content:trigger-id`,"Popover.Content: the popover is named by its trigger, but the trigger element has no `id` (a render-prop child of Popover.Trigger must spread the `id` it receives), so the popover has no accessible name. Spread every trigger prop onto the element, or pass `title`, `aria-label` or `aria-labelledby`.")},[V,D,O,ue]),!x)return null;let U=(0,y.jsxs)(y.Fragment,{children:[z&&(0,y.jsx)(`h2`,{id:R,className:t.cn(a.popoverContentClassNames.title,`mb-2 text-subtitle-2 font-semibold`),children:o}),e]});return(0,y.jsx)(p.Portal,{layerId:M,children:(0,y.jsxs)(`div`,{role:`dialog`,"aria-label":d,"aria-labelledby":de,tabIndex:se?-1:void 0,...b,ref:ce,id:H??S,"data-side":N[`data-side`],"data-align":N[`data-align`],style:{...ee,...N.style},onKeyDown:i.composeEventHandlers(te,ae),onContextMenu:i.composeEventHandlers(ne,oe),onPointerEnter:I?i.composeEventHandlers(h,I.onPointerEnter):h,onPointerLeave:I?i.composeEventHandlers(g,I.onPointerLeave):g,className:t.cn(a.popoverContentClassNames.root,`w-64 rounded-md border border-border bg-background p-4 text-body-1 font-normal text-foreground normal-case tracking-normal text-start shadow-4`,l),children:[(0,y.jsx)(m.PopoverBeak,{ref:j,side:F,style:P,"data-wave-popover-arrow":``,className:a.popoverContentClassNames.beak}),ie?(0,y.jsx)(`div`,{className:`overflow-y-auto max-h-[calc(var(--wave-popup-available-height)-2rem-2px)]`,children:U}):U]})})};M.displayName=`PopoverContent`;var N=Object.assign(A,{Trigger:j,Content:M});exports.Popover=N,exports.PopoverContent=M,exports.PopoverTrigger=j;
2
2
  //# sourceMappingURL=Popover.cjs.map