@mortenbrudvik/waveui 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +454 -74
- package/dist/components/button/Link.cjs +1 -1
- package/dist/components/button/Link.cjs.map +1 -1
- package/dist/components/button/Link.mjs +4 -4
- package/dist/components/button/Toolbar.cjs +1 -1
- package/dist/components/button/Toolbar.cjs.map +1 -1
- package/dist/components/button/Toolbar.mjs +25 -30
- package/dist/components/button/Toolbar.mjs.map +1 -1
- package/dist/components/button/Toolbar.navigation.cjs +2 -0
- package/dist/components/button/Toolbar.navigation.cjs.map +1 -0
- package/dist/components/button/Toolbar.navigation.mjs +17 -0
- package/dist/components/button/Toolbar.navigation.mjs.map +1 -0
- package/dist/components/data-display/Avatar.cjs +1 -1
- package/dist/components/data-display/Avatar.cjs.map +1 -1
- package/dist/components/data-display/Avatar.context.cjs +2 -0
- package/dist/components/data-display/Avatar.context.cjs.map +1 -0
- package/dist/components/data-display/Avatar.context.mjs +9 -0
- package/dist/components/data-display/Avatar.context.mjs.map +1 -0
- package/dist/components/data-display/Avatar.mjs +66 -61
- package/dist/components/data-display/Avatar.mjs.map +1 -1
- package/dist/components/data-display/AvatarGroup.cjs +1 -1
- package/dist/components/data-display/AvatarGroup.cjs.map +1 -1
- package/dist/components/data-display/AvatarGroup.mjs +10 -10
- package/dist/components/data-display/InfoButton.cjs +1 -1
- package/dist/components/data-display/InfoButton.cjs.map +1 -1
- package/dist/components/data-display/InfoButton.mjs +12 -12
- package/dist/components/data-display/InteractionTag.cjs +2 -0
- package/dist/components/data-display/InteractionTag.cjs.map +1 -0
- package/dist/components/data-display/InteractionTag.mjs +234 -0
- package/dist/components/data-display/InteractionTag.mjs.map +1 -0
- package/dist/components/data-display/Tag.cjs +1 -1
- package/dist/components/data-display/Tag.cjs.map +1 -1
- package/dist/components/data-display/Tag.mjs +222 -90
- package/dist/components/data-display/Tag.mjs.map +1 -1
- package/dist/components/data-display/TagGroup.cjs +2 -0
- package/dist/components/data-display/TagGroup.cjs.map +1 -0
- package/dist/components/data-display/TagGroup.context.cjs +2 -0
- package/dist/components/data-display/TagGroup.context.cjs.map +1 -0
- package/dist/components/data-display/TagGroup.context.mjs +113 -0
- package/dist/components/data-display/TagGroup.context.mjs.map +1 -0
- package/dist/components/data-display/TagGroup.mjs +149 -0
- package/dist/components/data-display/TagGroup.mjs.map +1 -0
- package/dist/components/data-display/tagStyles.cjs +2 -0
- package/dist/components/data-display/tagStyles.cjs.map +1 -0
- package/dist/components/data-display/tagStyles.mjs +108 -0
- package/dist/components/data-display/tagStyles.mjs.map +1 -0
- package/dist/components/feedback/Toaster.cjs +1 -1
- package/dist/components/feedback/Toaster.cjs.map +1 -1
- package/dist/components/feedback/Toaster.mjs +287 -255
- package/dist/components/feedback/Toaster.mjs.map +1 -1
- package/dist/components/input/Combobox.cjs +1 -1
- package/dist/components/input/Combobox.cjs.map +1 -1
- package/dist/components/input/Combobox.expand.cjs +1 -1
- package/dist/components/input/Combobox.expand.cjs.map +1 -1
- package/dist/components/input/Combobox.expand.mjs +7 -7
- package/dist/components/input/Combobox.expand.mjs.map +1 -1
- package/dist/components/input/Combobox.mjs +176 -175
- package/dist/components/input/Combobox.mjs.map +1 -1
- package/dist/components/input/DatePicker.cjs +1 -1
- package/dist/components/input/DatePicker.cjs.map +1 -1
- package/dist/components/input/DatePicker.mjs +188 -187
- package/dist/components/input/DatePicker.mjs.map +1 -1
- package/dist/components/input/Dropdown.cjs +1 -1
- package/dist/components/input/Dropdown.cjs.map +1 -1
- package/dist/components/input/Dropdown.mjs +41 -40
- package/dist/components/input/Dropdown.mjs.map +1 -1
- package/dist/components/input/Option.cjs +1 -1
- package/dist/components/input/Option.cjs.map +1 -1
- package/dist/components/input/Option.mjs +101 -94
- package/dist/components/input/Option.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.cjs.map +1 -1
- package/dist/components/input/SwatchPicker.context.cjs.map +1 -1
- package/dist/components/input/SwatchPicker.context.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.mjs.map +1 -1
- package/dist/components/input/TagPicker.cjs +1 -1
- package/dist/components/input/TagPicker.cjs.map +1 -1
- package/dist/components/input/TagPicker.context.cjs +2 -0
- package/dist/components/input/TagPicker.context.cjs.map +1 -0
- package/dist/components/input/TagPicker.context.mjs +20 -0
- package/dist/components/input/TagPicker.context.mjs.map +1 -0
- package/dist/components/input/TagPicker.create.cjs +2 -0
- package/dist/components/input/TagPicker.create.cjs.map +1 -0
- package/dist/components/input/TagPicker.create.mjs +24 -0
- package/dist/components/input/TagPicker.create.mjs.map +1 -0
- package/dist/components/input/TagPicker.mjs +13 -279
- package/dist/components/input/TagPicker.mjs.map +1 -1
- package/dist/components/input/TagPicker.option.cjs +2 -0
- package/dist/components/input/TagPicker.option.cjs.map +1 -0
- package/dist/components/input/TagPicker.option.mjs +45 -0
- package/dist/components/input/TagPicker.option.mjs.map +1 -0
- package/dist/components/input/TagPicker.overflow.cjs +2 -0
- package/dist/components/input/TagPicker.overflow.cjs.map +1 -0
- package/dist/components/input/TagPicker.overflow.mjs +153 -0
- package/dist/components/input/TagPicker.overflow.mjs.map +1 -0
- package/dist/components/input/TagPicker.parts.cjs +2 -0
- package/dist/components/input/TagPicker.parts.cjs.map +1 -0
- package/dist/components/input/TagPicker.parts.mjs +425 -0
- package/dist/components/input/TagPicker.parts.mjs.map +1 -0
- package/dist/components/input/TagPicker.root.cjs +2 -0
- package/dist/components/input/TagPicker.root.cjs.map +1 -0
- package/dist/components/input/TagPicker.root.mjs +417 -0
- package/dist/components/input/TagPicker.root.mjs.map +1 -0
- package/dist/components/input/TimePicker.cjs +1 -1
- package/dist/components/input/TimePicker.cjs.map +1 -1
- package/dist/components/input/TimePicker.mjs +156 -154
- package/dist/components/input/TimePicker.mjs.map +1 -1
- package/dist/components/layout/Accordion.cjs.map +1 -1
- package/dist/components/layout/Accordion.mjs.map +1 -1
- package/dist/components/navigation/Hamburger.cjs +2 -0
- package/dist/components/navigation/Hamburger.cjs.map +1 -0
- package/dist/components/navigation/Hamburger.mjs +54 -0
- package/dist/components/navigation/Hamburger.mjs.map +1 -0
- package/dist/components/navigation/Menu.popover.cjs +1 -1
- package/dist/components/navigation/Menu.popover.cjs.map +1 -1
- package/dist/components/navigation/Menu.popover.mjs +137 -127
- package/dist/components/navigation/Menu.popover.mjs.map +1 -1
- package/dist/components/navigation/Menu.root.cjs +1 -1
- package/dist/components/navigation/Menu.root.cjs.map +1 -1
- package/dist/components/navigation/Menu.root.mjs +4 -4
- package/dist/components/navigation/Nav.cjs +1 -1
- package/dist/components/navigation/Nav.cjs.map +1 -1
- package/dist/components/navigation/Nav.context.cjs +2 -0
- package/dist/components/navigation/Nav.context.cjs.map +1 -0
- package/dist/components/navigation/Nav.context.mjs +137 -0
- package/dist/components/navigation/Nav.context.mjs.map +1 -0
- package/dist/components/navigation/Nav.mjs +151 -258
- package/dist/components/navigation/Nav.mjs.map +1 -1
- package/dist/components/navigation/Nav.parts.cjs +2 -0
- package/dist/components/navigation/Nav.parts.cjs.map +1 -0
- package/dist/components/navigation/Nav.parts.mjs +77 -0
- package/dist/components/navigation/Nav.parts.mjs.map +1 -0
- package/dist/components/navigation/Nav.root.cjs +2 -0
- package/dist/components/navigation/Nav.root.cjs.map +1 -0
- package/dist/components/navigation/Nav.root.mjs +78 -0
- package/dist/components/navigation/Nav.root.mjs.map +1 -0
- package/dist/components/navigation/NavDrawer.cjs +2 -0
- package/dist/components/navigation/NavDrawer.cjs.map +1 -0
- package/dist/components/navigation/NavDrawer.context.cjs +2 -0
- package/dist/components/navigation/NavDrawer.context.cjs.map +1 -0
- package/dist/components/navigation/NavDrawer.context.mjs +11 -0
- package/dist/components/navigation/NavDrawer.context.mjs.map +1 -0
- package/dist/components/navigation/NavDrawer.mjs +179 -0
- package/dist/components/navigation/NavDrawer.mjs.map +1 -0
- package/dist/components/overlays/Dialog.cjs +1 -1
- package/dist/components/overlays/Dialog.cjs.map +1 -1
- package/dist/components/overlays/Dialog.mjs +188 -123
- package/dist/components/overlays/Dialog.mjs.map +1 -1
- package/dist/components/overlays/Dialog.shared.cjs +1 -1
- package/dist/components/overlays/Dialog.shared.cjs.map +1 -1
- package/dist/components/overlays/Dialog.shared.mjs +157 -81
- package/dist/components/overlays/Dialog.shared.mjs.map +1 -1
- package/dist/components/overlays/Dialog.slots.cjs +2 -0
- package/dist/components/overlays/Dialog.slots.cjs.map +1 -0
- package/dist/components/overlays/Dialog.slots.mjs +129 -0
- package/dist/components/overlays/Dialog.slots.mjs.map +1 -0
- package/dist/components/overlays/Drawer.cjs +1 -1
- package/dist/components/overlays/Drawer.cjs.map +1 -1
- package/dist/components/overlays/Drawer.context.cjs +2 -0
- package/dist/components/overlays/Drawer.context.cjs.map +1 -0
- package/dist/components/overlays/Drawer.context.mjs +29 -0
- package/dist/components/overlays/Drawer.context.mjs.map +1 -0
- package/dist/components/overlays/Drawer.mjs +12 -187
- package/dist/components/overlays/Drawer.mjs.map +1 -1
- package/dist/components/overlays/Drawer.panel.cjs +2 -0
- package/dist/components/overlays/Drawer.panel.cjs.map +1 -0
- package/dist/components/overlays/Drawer.panel.mjs +159 -0
- package/dist/components/overlays/Drawer.panel.mjs.map +1 -0
- package/dist/components/overlays/Drawer.parts.cjs +2 -0
- package/dist/components/overlays/Drawer.parts.cjs.map +1 -0
- package/dist/components/overlays/Drawer.parts.mjs +152 -0
- package/dist/components/overlays/Drawer.parts.mjs.map +1 -0
- package/dist/components/overlays/Drawer.root.cjs +2 -0
- package/dist/components/overlays/Drawer.root.cjs.map +1 -0
- package/dist/components/overlays/Drawer.root.mjs +207 -0
- package/dist/components/overlays/Drawer.root.mjs.map +1 -0
- package/dist/components/overlays/Drawer.scroll.cjs +2 -0
- package/dist/components/overlays/Drawer.scroll.cjs.map +1 -0
- package/dist/components/overlays/Drawer.scroll.mjs +42 -0
- package/dist/components/overlays/Drawer.scroll.mjs.map +1 -0
- package/dist/components/overlays/Popover.cjs +1 -1
- package/dist/components/overlays/Popover.cjs.map +1 -1
- package/dist/components/overlays/Popover.mjs +173 -162
- package/dist/components/overlays/Popover.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.cjs +1 -1
- package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.mjs +96 -91
- package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
- package/dist/components/overlays/Tooltip.cjs +1 -1
- package/dist/components/overlays/Tooltip.cjs.map +1 -1
- package/dist/components/overlays/Tooltip.mjs +47 -47
- package/dist/components/overlays/Tooltip.mjs.map +1 -1
- package/dist/components/portal/Portal.cjs +1 -1
- package/dist/components/portal/Portal.cjs.map +1 -1
- package/dist/components/portal/Portal.mjs +5 -5
- package/dist/components/table/DataGrid.cjs +1 -1
- package/dist/components/table/DataGrid.cjs.map +1 -1
- package/dist/components/table/DataGrid.mjs +1 -1
- package/dist/hooks/useDismiss.cjs.map +1 -1
- package/dist/hooks/useDismiss.mjs.map +1 -1
- package/dist/hooks/useFocusTrap.cjs +1 -1
- package/dist/hooks/useFocusTrap.cjs.map +1 -1
- package/dist/hooks/useFocusTrap.mjs +115 -98
- package/dist/hooks/useFocusTrap.mjs.map +1 -1
- package/dist/hooks/useFocusVisible.cjs +2 -0
- package/dist/hooks/useFocusVisible.cjs.map +1 -0
- package/dist/hooks/useFocusVisible.mjs +49 -0
- package/dist/hooks/useFocusVisible.mjs.map +1 -0
- package/dist/hooks/useFocusableGroup.cjs +2 -0
- package/dist/hooks/useFocusableGroup.cjs.map +1 -0
- package/dist/hooks/useFocusableGroup.mjs +70 -0
- package/dist/hooks/useFocusableGroup.mjs.map +1 -0
- package/dist/hooks/useModalLayer.cjs +1 -1
- package/dist/hooks/useModalLayer.cjs.map +1 -1
- package/dist/hooks/useModalLayer.mjs +34 -21
- package/dist/hooks/useModalLayer.mjs.map +1 -1
- package/dist/hooks/useModalOpen.cjs +2 -0
- package/dist/hooks/useModalOpen.cjs.map +1 -0
- package/dist/hooks/useModalOpen.mjs +14 -0
- package/dist/hooks/useModalOpen.mjs.map +1 -0
- package/dist/hooks/usePopupPosition.cjs +1 -1
- package/dist/hooks/usePopupPosition.cjs.map +1 -1
- package/dist/hooks/usePopupPosition.mjs +82 -53
- package/dist/hooks/usePopupPosition.mjs.map +1 -1
- package/dist/hooks/useResolvedTarget.cjs +2 -0
- package/dist/hooks/useResolvedTarget.cjs.map +1 -0
- package/dist/hooks/useResolvedTarget.mjs +37 -0
- package/dist/hooks/useResolvedTarget.mjs.map +1 -0
- package/dist/hooks/useRestoreFocus.cjs +1 -1
- package/dist/hooks/useRestoreFocus.cjs.map +1 -1
- package/dist/hooks/useRestoreFocus.mjs +91 -78
- package/dist/hooks/useRestoreFocus.mjs.map +1 -1
- package/dist/hooks/useRovingGrid.cjs +1 -1
- package/dist/hooks/useRovingGrid.cjs.map +1 -1
- package/dist/hooks/useRovingGrid.mjs +8 -57
- package/dist/hooks/useRovingGrid.mjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.cjs +1 -1
- package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.mjs +180 -121
- package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3070 -269
- package/dist/index.d.ts +3070 -269
- package/dist/index.mjs +127 -107
- package/dist/lib/classNames.cjs +1 -1
- package/dist/lib/classNames.cjs.map +1 -1
- package/dist/lib/classNames.mjs +137 -77
- package/dist/lib/classNames.mjs.map +1 -1
- package/dist/lib/icons.cjs +1 -1
- package/dist/lib/icons.cjs.map +1 -1
- package/dist/lib/icons.mjs +13 -6
- package/dist/lib/icons.mjs.map +1 -1
- package/dist/lib/layers.cjs +1 -1
- package/dist/lib/layers.cjs.map +1 -1
- package/dist/lib/layers.mjs +120 -111
- package/dist/lib/layers.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/styles/tokens.css +25 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../../lib/cn.mjs";
|
|
3
|
+
import { warnOnce as t } from "../../lib/dev.mjs";
|
|
4
|
+
import { materialiseSlotContent as n, renderSlot as r, slotRendersContent as i } from "../../lib/slot.mjs";
|
|
5
|
+
import { drawerBodyClassNames as a, drawerClassNames as o, drawerFooterClassNames as s, drawerHeaderClassNames as c, drawerHeaderNavigationClassNames as l, drawerHeaderTitleClassNames as u, drawerTitleClassNames as d } from "../../lib/classNames.mjs";
|
|
6
|
+
import { focusRingInset as f } from "../../lib/styles.mjs";
|
|
7
|
+
import { useModalClosePart as p, useModalTitle as m, useModalTriggerPart as h } from "./Dialog.shared.mjs";
|
|
8
|
+
import { ModalCloseButton as g } from "./Dialog.slots.mjs";
|
|
9
|
+
import { scrollSeparatorClasses as _ } from "./Drawer.scroll.mjs";
|
|
10
|
+
import { DrawerHeaderContext as v, DrawerPartContext as y, DrawerScrollStateContext as b, useDrawerContext as x } from "./Drawer.context.mjs";
|
|
11
|
+
import * as S from "react";
|
|
12
|
+
import { jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
13
|
+
//#region src/components/overlays/Drawer.parts.tsx
|
|
14
|
+
var T = "Drawer.Trigger:nested", E = "Drawer.Trigger must be a direct child of Drawer (a Fragment is fine). Inside another element or a component it is rendered as panel content, which is not rendered (or, with `unmountOnClose={false}`, is hidden) while the drawer is closed, so it cannot open the drawer. Make it a direct child, put wrappers such as a Tooltip inside the trigger, or control the Drawer with `open`/`onOpenChange` and open it from your own button.", D = (e) => {
|
|
15
|
+
let { open: n, requestOpen: r, trigger: i, panelId: a, type: o, inPanel: s } = x("Drawer.Trigger");
|
|
16
|
+
return S.useEffect(() => {
|
|
17
|
+
s && t(T, E);
|
|
18
|
+
}, [s]), h({
|
|
19
|
+
open: n,
|
|
20
|
+
requestOpen: r,
|
|
21
|
+
trigger: i,
|
|
22
|
+
controlsId: a,
|
|
23
|
+
popup: o !== "inline" && "dialog"
|
|
24
|
+
}, e, "Drawer.Trigger");
|
|
25
|
+
};
|
|
26
|
+
D.displayName = "DrawerTrigger";
|
|
27
|
+
var O = (e) => {
|
|
28
|
+
let { requestOpen: t } = x("Drawer.Close");
|
|
29
|
+
return p(t, e, "Drawer.Close");
|
|
30
|
+
};
|
|
31
|
+
O.displayName = "DrawerClose";
|
|
32
|
+
var k = ({ id: t, headingLevel: n = 2, className: r, children: i, ref: a, ...o }) => {
|
|
33
|
+
let { id: s, ref: c } = m("Drawer.Title", "Drawer", t, a), l = `h${n}`;
|
|
34
|
+
return /* @__PURE__ */ C(l, {
|
|
35
|
+
...o,
|
|
36
|
+
id: s,
|
|
37
|
+
ref: c,
|
|
38
|
+
className: e(d.root, "text-subtitle-1 font-semibold text-foreground", r),
|
|
39
|
+
children: i
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
k.displayName = "DrawerTitle";
|
|
43
|
+
var A = ({ requestOpen: t, label: n, closeButton: r, className: i }) => /* @__PURE__ */ C(g, {
|
|
44
|
+
componentName: "Drawer",
|
|
45
|
+
closeButton: r,
|
|
46
|
+
closeLabel: n,
|
|
47
|
+
onClose: (e) => t(!1, {
|
|
48
|
+
reason: "close-button",
|
|
49
|
+
event: e
|
|
50
|
+
}),
|
|
51
|
+
className: e(o.closeButton, i)
|
|
52
|
+
});
|
|
53
|
+
A.displayName = "DrawerCloseButton";
|
|
54
|
+
var j = "Drawer.Header:unscanned", M = "Drawer.Header is not a direct child of Drawer, so it renders inside the body instead of replacing the header. Make it a direct child (a Fragment there is fine).", N = "Drawer.Body:unscanned", P = "Drawer.Body is not a direct child of Drawer, so its props do not reach the scrolling body and it renders as an element inside it. Make it a direct child (a Fragment there is fine).", F = "Drawer.Footer:unscanned", I = "Drawer.Footer is not a direct child of Drawer, so it renders inside the scrolling body instead of below it. Make it a direct child (a Fragment there is fine); a submit button in it can name a form in the body with the `form` attribute.", L = "Drawer.HeaderTitle:outside-header", R = "Drawer.HeaderTitle is not inside a Drawer.Header, so it renders in the body without the Close button. Put it in a Drawer.Header, or use Drawer.Title for a heading in the body.";
|
|
55
|
+
function z() {
|
|
56
|
+
return S.useContext(y) === "placed";
|
|
57
|
+
}
|
|
58
|
+
function B(e, n, r) {
|
|
59
|
+
S.useEffect(() => {
|
|
60
|
+
e && t(n, r);
|
|
61
|
+
}, [
|
|
62
|
+
e,
|
|
63
|
+
n,
|
|
64
|
+
r
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
var V = ({ className: t, children: r, ref: a, ...o }) => {
|
|
68
|
+
x("Drawer.Header");
|
|
69
|
+
let s = z(), l = S.useContext(b) ?? "none";
|
|
70
|
+
return B(!s, j, M), i(r) ? /* @__PURE__ */ C("div", {
|
|
71
|
+
"data-scroll-state": l,
|
|
72
|
+
...o,
|
|
73
|
+
ref: a,
|
|
74
|
+
className: e(c.root, "flex shrink-0 flex-col gap-2 p-4", _.header, t),
|
|
75
|
+
children: /* @__PURE__ */ C(v.Provider, {
|
|
76
|
+
value: !0,
|
|
77
|
+
children: /* @__PURE__ */ C(y.Provider, {
|
|
78
|
+
value: "content",
|
|
79
|
+
children: n(r)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
}) : null;
|
|
83
|
+
};
|
|
84
|
+
V.displayName = "DrawerHeader";
|
|
85
|
+
var H = ({ id: t, headingLevel: n = 2, action: a, className: o, children: s, ref: c, ...l }) => {
|
|
86
|
+
let { requestOpen: d, closeLabel: f, closeButton: p } = x("Drawer.HeaderTitle"), h = S.useContext(v), { id: g, ref: _ } = m("Drawer.HeaderTitle", "Drawer", t, void 0);
|
|
87
|
+
B(!h, L, R);
|
|
88
|
+
let b = `h${n}`;
|
|
89
|
+
return /* @__PURE__ */ C("div", {
|
|
90
|
+
...l,
|
|
91
|
+
ref: c,
|
|
92
|
+
className: e(u.root, "flex items-start gap-2", o),
|
|
93
|
+
children: /* @__PURE__ */ w(y.Provider, {
|
|
94
|
+
value: "content",
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ C(b, {
|
|
97
|
+
id: g,
|
|
98
|
+
ref: _,
|
|
99
|
+
className: e(u.heading, "min-w-0 flex-1 text-subtitle-1 font-semibold text-foreground"),
|
|
100
|
+
children: s
|
|
101
|
+
}),
|
|
102
|
+
i(a) ? r(a, "span", e(u.action, "flex min-h-7 shrink-0 items-center gap-1")) : null,
|
|
103
|
+
h && /* @__PURE__ */ C(A, {
|
|
104
|
+
requestOpen: d,
|
|
105
|
+
label: f,
|
|
106
|
+
closeButton: p,
|
|
107
|
+
className: "mt-0.5 shrink-0 text-muted-foreground"
|
|
108
|
+
})
|
|
109
|
+
]
|
|
110
|
+
})
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
H.displayName = "DrawerHeaderTitle";
|
|
114
|
+
var U = ({ className: t, children: n, ref: r, ...i }) => (x("Drawer.HeaderNavigation"), /* @__PURE__ */ C("nav", {
|
|
115
|
+
...i,
|
|
116
|
+
ref: r,
|
|
117
|
+
className: e(l.root, "flex items-center gap-1", t),
|
|
118
|
+
children: /* @__PURE__ */ C(y.Provider, {
|
|
119
|
+
value: "content",
|
|
120
|
+
children: n
|
|
121
|
+
})
|
|
122
|
+
}));
|
|
123
|
+
U.displayName = "DrawerHeaderNavigation";
|
|
124
|
+
var W = ({ className: t, children: n, ref: r, ...i }) => (x("Drawer.Body"), B(!0, N, P), /* @__PURE__ */ C("div", {
|
|
125
|
+
...i,
|
|
126
|
+
ref: r,
|
|
127
|
+
className: e(a.root, f, t),
|
|
128
|
+
children: /* @__PURE__ */ C(y.Provider, {
|
|
129
|
+
value: "content",
|
|
130
|
+
children: n
|
|
131
|
+
})
|
|
132
|
+
}));
|
|
133
|
+
W.displayName = "DrawerBody";
|
|
134
|
+
var G = ({ className: t, children: r, ref: a, ...o }) => {
|
|
135
|
+
x("Drawer.Footer");
|
|
136
|
+
let c = z(), l = S.useContext(b) ?? "none";
|
|
137
|
+
return B(!c, F, I), i(r) ? /* @__PURE__ */ C("div", {
|
|
138
|
+
"data-scroll-state": l,
|
|
139
|
+
...o,
|
|
140
|
+
ref: a,
|
|
141
|
+
className: e(s.root, "flex shrink-0 flex-wrap items-center gap-2 p-4", _.footer, t),
|
|
142
|
+
children: /* @__PURE__ */ C(y.Provider, {
|
|
143
|
+
value: "content",
|
|
144
|
+
children: n(r)
|
|
145
|
+
})
|
|
146
|
+
}) : null;
|
|
147
|
+
};
|
|
148
|
+
G.displayName = "DrawerFooter";
|
|
149
|
+
//#endregion
|
|
150
|
+
export { W as DrawerBody, O as DrawerClose, A as DrawerCloseButton, G as DrawerFooter, V as DrawerHeader, U as DrawerHeaderNavigation, H as DrawerHeaderTitle, k as DrawerTitle, D as DrawerTrigger, E as NESTED_TRIGGER_WARNING, T as NESTED_TRIGGER_WARNING_KEY };
|
|
151
|
+
|
|
152
|
+
//# sourceMappingURL=Drawer.parts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Drawer.parts.mjs","names":["React","NESTED_TRIGGER_WARNING_KEY","NESTED_TRIGGER_WARNING","DrawerTrigger","useDrawerContext","inPanel","warnOnce","useModalTriggerPart","panelId","type","props","DrawerClose","useModalClosePart","requestOpen","DrawerTitle","rest","titleId","titleRef","useModalTitle","id","ref","Heading","headingLevel","cn","drawerTitleClassNames","className","DrawerCloseButton","ModalCloseButton","label","drawerClassNames","HEADER_UNSCANNED_WARNING_KEY","HEADER_UNSCANNED_WARNING","BODY_UNSCANNED_WARNING_KEY","BODY_UNSCANNED_WARNING","FOOTER_UNSCANNED_WARNING_KEY","FOOTER_UNSCANNED_WARNING","HEADER_TITLE_OUTSIDE_WARNING_KEY","HEADER_TITLE_OUTSIDE_WARNING","usePlaced","DrawerPartContext","useWarnWhen","condition","key","message","DrawerHeader","placed","scrollState","DrawerScrollStateContext","slotRendersContent","children","drawerHeaderClassNames","scrollSeparatorClasses","DrawerHeaderContext","materialiseSlotContent","DrawerHeaderTitle","inHeader","headingId","headingRef","drawerHeaderTitleClassNames","action","renderSlot","closeLabel","DrawerHeaderNavigation","drawerHeaderNavigationClassNames","DrawerBody","drawerBodyClassNames","focusRingInset","DrawerFooter","drawerFooterClassNames"],"sources":["../../../src/components/overlays/Drawer.parts.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport {\n drawerBodyClassNames,\n drawerClassNames,\n drawerFooterClassNames,\n drawerHeaderClassNames,\n drawerHeaderNavigationClassNames,\n drawerHeaderTitleClassNames,\n drawerTitleClassNames,\n} from '../../lib/classNames';\nimport { warnOnce } from '../../lib/dev';\nimport { materialiseSlotContent, renderSlot, slotRendersContent, type Slot } from '../../lib/slot';\nimport { focusRingInset } from '../../lib/styles';\nimport type { HeadingLevel } from '../../lib/types';\nimport {\n useModalClosePart,\n useModalTitle,\n useModalTriggerPart,\n type ModalRequestOpen,\n} from './Dialog.shared';\nimport { ModalCloseButton } from './Dialog.slots';\nimport {\n DrawerHeaderContext,\n DrawerPartContext,\n DrawerScrollStateContext,\n useDrawerContext,\n} from './Drawer.context';\nimport { scrollSeparatorClasses } from './Drawer.scroll';\n\n/*\n * The Drawer's parts. Imports the context and scroll modules only (never the root or\n * `Drawer.tsx`).\n */\n\n/** Props a `Drawer.Trigger` puts on its element (and passes to a render-prop child). */\nexport interface DrawerTriggerRenderProps extends React.HTMLAttributes<HTMLElement> {\n /**\n * `'dialog'` for an overlay drawer; absent (no key) for an inline drawer, which is not a popup.\n */\n 'aria-haspopup'?: 'dialog';\n 'aria-expanded': boolean;\n /** The panel's id, while the drawer is open. */\n 'aria-controls'?: string;\n onClick: React.MouseEventHandler<HTMLElement>;\n /** A callback ref, so the props spread onto any element type. */\n ref: React.RefCallback<HTMLElement>;\n}\n\n/** Properties for the DrawerTrigger sub-component. */\nexport interface DrawerTriggerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that opens and closes the drawer. A single element receives the trigger props\n * (merged with its own); a function receives them.\n */\n children: React.ReactNode | ((props: DrawerTriggerRenderProps) => React.ReactNode);\n /**\n * `false` renders a wrapper `<span>` around the children instead of merging the trigger props\n * onto the child. The span carries the click handler; `aria-haspopup`, `aria-expanded` and\n * `aria-controls` go to the first element in the tab order inside it.\n * @default true\n */\n asChild?: boolean;\n /** Ref to the trigger element (the child, or the wrapper span). */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** Props a `Drawer.Close` puts on its element (and passes to a render-prop child). */\nexport interface DrawerCloseRenderProps extends React.HTMLAttributes<HTMLElement> {\n onClick: React.MouseEventHandler<HTMLElement>;\n /** A callback ref, so the props spread onto any element type. */\n ref: React.RefCallback<HTMLElement>;\n}\n\n/** Properties for the DrawerClose sub-component. */\nexport interface DrawerCloseProps extends Omit<React.HTMLAttributes<HTMLElement>, 'children'> {\n /**\n * The element that closes the drawer. A single element receives an `onClick` composed with its own\n * (its handler runs first; `preventDefault()` keeps the drawer open); a function receives the\n * props.\n */\n children: React.ReactNode | ((props: DrawerCloseRenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` that closes the drawer on click. @default true */\n asChild?: boolean;\n /** Ref to the close element (the child, or the wrapper span). */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** Properties for the DrawerTitle sub-component. */\nexport interface DrawerTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n /** The title; any content. */\n children: React.ReactNode;\n /**\n * Level of the heading element (`h1` … `h6`). Fluent's `heading` slot, which also takes another\n * element.\n * @default 2\n */\n headingLevel?: HeadingLevel;\n /** Ref to the heading element. */\n ref?: React.Ref<HTMLHeadingElement>;\n}\n\n/** Properties for the DrawerHeader sub-component. */\nexport interface DrawerHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** `Drawer.HeaderNavigation`, `Drawer.HeaderTitle`, or any content, in the order written. */\n children?: React.ReactNode;\n /** Ref to the header element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DrawerHeaderTitle sub-component. */\nexport interface DrawerHeaderTitleProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The title; any content. The heading names the drawer (`aria-labelledby`). */\n children: React.ReactNode;\n /**\n * Content between the heading and the built-in Close button, such as icon buttons for the\n * drawer's own commands (Fluent's `action`). It comes before the Close button in DOM and Tab\n * order and is interactive (not `aria-hidden`): name icon-only buttons. Renders nothing when it\n * renders no content.\n */\n action?: Slot<'span'>;\n /** Id of the heading element, the element that names the drawer. @default a generated id */\n id?: string;\n /**\n * Level of the heading element (`h1` … `h6`). Fluent's `heading` slot, which also takes another\n * element.\n * @default 2\n */\n headingLevel?: HeadingLevel;\n /** Ref to the title row (the heading's parent). */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DrawerHeaderNavigation sub-component. */\nexport interface DrawerHeaderNavigationProps extends React.HTMLAttributes<HTMLElement> {\n /** The navigation controls: a Back button, a Toolbar of commands. */\n children?: React.ReactNode;\n /** Ref to the `<nav>` element. */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** Properties for the DrawerBody sub-component. */\nexport interface DrawerBodyProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Content of the scrolling body, rendered in the Body's place among the other content. */\n children?: React.ReactNode;\n /** Ref to the scrolling body element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the DrawerFooter sub-component. */\nexport interface DrawerFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The drawer's actions, typically buttons (wrap closing ones in `Drawer.Close`). */\n children?: React.ReactNode;\n /** Ref to the footer element. */\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** The warning key of a `Drawer.Trigger` that renders as panel content (the root checks it too). */\nexport const NESTED_TRIGGER_WARNING_KEY = 'Drawer.Trigger:nested';\n\n/** The text of the {@link NESTED_TRIGGER_WARNING_KEY} warning. */\nexport const NESTED_TRIGGER_WARNING =\n 'Drawer.Trigger must be a direct child of Drawer (a Fragment is fine). Inside another element or a component it is rendered as panel content, which is not rendered (or, with `unmountOnClose={false}`, is hidden) while the drawer is closed, so it cannot open the drawer. Make it a direct child, put wrappers such as a Tooltip inside the trigger, or control the Drawer with `open`/`onOpenChange` and open it from your own button.';\n\n/**\n * Opens and closes the drawer: a click while it is open asks it to close (reason `trigger`), which\n * the trigger of a non-modal or inline drawer can receive (a modal one makes the page inert).\n * Fluent's `DialogTrigger` never toggles (outside the surface it only opens, inside it only\n * closes); this trigger always does.\n * Place it directly inside `Drawer`, or in a Fragment there (not inside a wrapper element or a\n * component of your own): it renders in place, not in the panel (an inline drawer's triggers\n * render right before its panel, so the panel follows its button in the reading order); a\n * misplaced one warns in development. A Drawer may have several triggers: focus returns to the one\n * that opened it. Puts `aria-haspopup=\"dialog\"` (none on an inline drawer's trigger: an inline\n * panel is page content, not a popup), `aria-expanded`, `aria-controls` (while open), a click\n * handler and a ref on its single child, or passes them to a render-prop child. A custom child\n * component must forward `ref` and spread its props; one that does not is wrapped in a `<span>`\n * automatically (with a development warning), the span that `asChild={false}` renders. Focus\n * returns to the trigger when the drawer closes (for a non-modal or inline drawer, only when focus\n * was inside it). On the span, the state ARIA goes to the first element in the tab order inside\n * it, and focus returns to that element (to the span when you made it the trigger with a `role`\n * such as `button` and `tabIndex={0}`, or when nothing inside it can take focus).\n *\n * A Tooltip (or any other wrapper) goes inside the trigger, not around it. Use a render-prop child\n * so the trigger props land on the button and the Tooltip describes that same button:\n *\n * @example\n * <Drawer title=\"Filters\">\n * <Drawer.Trigger>\n * {(triggerProps) => (\n * <Tooltip content=\"Narrow the list\">\n * <Button {...triggerProps}>Filters</Button>\n * </Tooltip>\n * )}\n * </Drawer.Trigger>\n * <FilterForm />\n * </Drawer>\n */\nexport const DrawerTrigger = (props: DrawerTriggerProps) => {\n const { open, requestOpen, trigger, panelId, type, inPanel } = useDrawerContext('Drawer.Trigger');\n\n // Rendered inside its own drawer's panel (e.g. by a component): not rendered (or, kept mounted,\n // hidden) while the drawer is closed.\n React.useEffect(() => {\n if (inPanel) warnOnce(NESTED_TRIGGER_WARNING_KEY, NESTED_TRIGGER_WARNING);\n }, [inPanel]);\n\n return useModalTriggerPart<DrawerTriggerRenderProps>(\n {\n open,\n requestOpen,\n trigger,\n controlsId: panelId,\n popup: type === 'inline' ? false : 'dialog',\n },\n props,\n 'Drawer.Trigger',\n );\n};\nDrawerTrigger.displayName = 'DrawerTrigger';\n\n/**\n * Closes the drawer: composes a click handler onto its single child (its own `onClick` runs first;\n * calling `preventDefault()` there keeps the drawer open), or passes it to a render-prop child.\n */\nexport const DrawerClose = (props: DrawerCloseProps) => {\n const { requestOpen } = useDrawerContext('Drawer.Close');\n return useModalClosePart<DrawerCloseRenderProps>(requestOpen, props, 'Drawer.Close');\n};\nDrawerClose.displayName = 'DrawerClose';\n\n/**\n * A heading that names the drawer (`aria-labelledby`), for rich titles or custom layouts. Render it\n * inside the Drawer's content (instead of the `title` prop); for the title of a composed header,\n * use `Drawer.HeaderTitle` in a `Drawer.Header`. `headingLevel` picks the heading element (`h2`\n * by default).\n */\nexport const DrawerTitle = ({\n id,\n headingLevel = 2,\n className,\n children,\n ref,\n ...rest\n}: DrawerTitleProps) => {\n const { id: titleId, ref: titleRef } = useModalTitle('Drawer.Title', 'Drawer', id, ref);\n const Heading: `h${HeadingLevel}` = `h${headingLevel}`;\n return (\n <Heading\n {...rest}\n id={titleId}\n ref={titleRef}\n className={cn(\n drawerTitleClassNames.root,\n 'text-subtitle-1 font-semibold text-foreground',\n className,\n )}\n >\n {children}\n </Heading>\n );\n};\nDrawerTitle.displayName = 'DrawerTitle';\n\n/** Properties of the internal {@link DrawerCloseButton}. */\nexport interface DrawerCloseButtonProps {\n /** The Drawer's request function: the button asks it to close, reason `close-button`. */\n requestOpen: ModalRequestOpen;\n /** The button's accessible name (the Drawer's `closeLabel`). */\n label: string;\n /** The Drawer's `closeButton` slot: the button's content, or `null` to render none. */\n closeButton: Slot<'span'> | undefined;\n /** Placement classes, after the button's own (`drawerClassNames.closeButton`). */\n className?: string;\n}\n\n/**\n * The Drawer's built-in Close button (internal): the Wave `Button`, subtle and small, with the\n * dismiss glyph or the Drawer's `closeButton` content (the slot rules of `Dialog.Content`'s\n * `closeButton`), named by the Drawer's `closeLabel`. The built-in header and every\n * `Drawer.HeaderTitle` in a `Drawer.Header` render it; it carries `drawerClassNames.closeButton`.\n * Renders nothing for `closeButton={null}`.\n */\nexport const DrawerCloseButton = ({\n requestOpen,\n label,\n closeButton,\n className,\n}: DrawerCloseButtonProps) => (\n <ModalCloseButton\n componentName=\"Drawer\"\n closeButton={closeButton}\n closeLabel={label}\n onClose={(event) => requestOpen(false, { reason: 'close-button', event })}\n className={cn(drawerClassNames.closeButton, className)}\n />\n);\nDrawerCloseButton.displayName = 'DrawerCloseButton';\n\n/** The warning key of a `Drawer.Header` that the Drawer's scan did not place. */\nconst HEADER_UNSCANNED_WARNING_KEY = 'Drawer.Header:unscanned';\nconst HEADER_UNSCANNED_WARNING =\n 'Drawer.Header is not a direct child of Drawer, so it renders inside the body instead of replacing the header. Make it a direct child (a Fragment there is fine).';\n\n/** The warning key of a `Drawer.Body` that the Drawer's scan did not place. */\nconst BODY_UNSCANNED_WARNING_KEY = 'Drawer.Body:unscanned';\nconst BODY_UNSCANNED_WARNING =\n 'Drawer.Body is not a direct child of Drawer, so its props do not reach the scrolling body and it renders as an element inside it. Make it a direct child (a Fragment there is fine).';\n\n/** The warning key of a `Drawer.Footer` that the Drawer's scan did not place. */\nconst FOOTER_UNSCANNED_WARNING_KEY = 'Drawer.Footer:unscanned';\nconst FOOTER_UNSCANNED_WARNING =\n 'Drawer.Footer is not a direct child of Drawer, so it renders inside the scrolling body instead of below it. Make it a direct child (a Fragment there is fine); a submit button in it can name a form in the body with the `form` attribute.';\n\n/** The warning key of a `Drawer.HeaderTitle` outside a `Drawer.Header`. */\nconst HEADER_TITLE_OUTSIDE_WARNING_KEY = 'Drawer.HeaderTitle:outside-header';\nconst HEADER_TITLE_OUTSIDE_WARNING =\n 'Drawer.HeaderTitle is not inside a Drawer.Header, so it renders in the body without the Close button. Put it in a Drawer.Header, or use Drawer.Title for a heading in the body.';\n\n/** Whether the Drawer's scan placed the part that reads this (a direct child of the Drawer). */\nfunction usePlaced(): boolean {\n return React.useContext(DrawerPartContext) === 'placed';\n}\n\n/** Warns once, from an effect, while `condition` holds. */\nfunction useWarnWhen(condition: boolean, key: string, message: string): void {\n React.useEffect(() => {\n if (condition) warnOnce(key, message);\n }, [condition, key, message]);\n}\n\n/**\n * The drawer's header, replacing the built-in one (the `title` and Close button row): a\n * `Drawer.HeaderNavigation` row and a `Drawer.HeaderTitle`, or your own content. The built-in\n * Close button ends each `Drawer.HeaderTitle`; a header without one has no Close button (wrap your\n * own in `Drawer.Close`). Make it a direct child of `Drawer` (a Fragment there is fine); nested in\n * an element or rendered by a component of yours it renders in the body, with a development\n * warning. It draws a line under itself while the body is scrolled away from its top\n * (`data-scroll-state`). When an overlay drawer opens, focus goes to the header's first focusable\n * element (a Back button, a title action): give the control that should start `autoFocus`. A\n * header whose children render nothing renders no element (the drawer then has no header; Escape\n * and the backdrop of an overlay, and `Drawer.Close`, still close it). Fluent's `DrawerHeader`.\n */\nexport const DrawerHeader = ({ className, children, ref, ...rest }: DrawerHeaderProps) => {\n useDrawerContext('Drawer.Header');\n const placed = usePlaced();\n const scrollState = React.useContext(DrawerScrollStateContext) ?? 'none';\n useWarnWhen(!placed, HEADER_UNSCANNED_WARNING_KEY, HEADER_UNSCANNED_WARNING);\n if (!slotRendersContent(children)) return null;\n return (\n <div\n data-scroll-state={scrollState}\n {...rest}\n ref={ref}\n className={cn(\n drawerHeaderClassNames.root,\n 'flex shrink-0 flex-col gap-2 p-4',\n scrollSeparatorClasses.header,\n className,\n )}\n >\n <DrawerHeaderContext.Provider value={true}>\n <DrawerPartContext.Provider value=\"content\">\n {materialiseSlotContent(children)}\n </DrawerPartContext.Provider>\n </DrawerHeaderContext.Provider>\n </div>\n );\n};\nDrawerHeader.displayName = 'DrawerHeader';\n\n/**\n * A title row for `Drawer.Header`: the heading that names the drawer, your `action` content and\n * the built-in Close button (named by the Drawer's `closeLabel`; the Drawer's `closeButton` sets\n * its content, or hides it with `null`), in that DOM and Tab order.\n * Render one per header; `headingLevel` picks the heading element (`h2` by default). Outside a\n * `Drawer.Header` it renders without the Close button and warns: use `Drawer.Title` for a heading\n * in the body. Unlike Fluent's `DrawerHeaderTitle`, whose `action` is where you put a close\n * button, it renders the Close button itself.\n */\nexport const DrawerHeaderTitle = ({\n id,\n headingLevel = 2,\n action,\n className,\n children,\n ref,\n ...rest\n}: DrawerHeaderTitleProps) => {\n const { requestOpen, closeLabel, closeButton } = useDrawerContext('Drawer.HeaderTitle');\n const inHeader = React.useContext(DrawerHeaderContext);\n const { id: headingId, ref: headingRef } = useModalTitle(\n 'Drawer.HeaderTitle',\n 'Drawer',\n id,\n undefined,\n );\n useWarnWhen(!inHeader, HEADER_TITLE_OUTSIDE_WARNING_KEY, HEADER_TITLE_OUTSIDE_WARNING);\n const Heading: `h${HeadingLevel}` = `h${headingLevel}`;\n return (\n <div\n {...rest}\n ref={ref}\n className={cn(drawerHeaderTitleClassNames.root, 'flex items-start gap-2', className)}\n >\n <DrawerPartContext.Provider value=\"content\">\n <Heading\n id={headingId}\n ref={headingRef}\n className={cn(\n drawerHeaderTitleClassNames.heading,\n 'min-w-0 flex-1 text-subtitle-1 font-semibold text-foreground',\n )}\n >\n {children}\n </Heading>\n {slotRendersContent(action)\n ? renderSlot(\n action,\n 'span',\n cn(drawerHeaderTitleClassNames.action, 'flex min-h-7 shrink-0 items-center gap-1'),\n )\n : null}\n {inHeader && (\n <DrawerCloseButton\n requestOpen={requestOpen}\n label={closeLabel}\n closeButton={closeButton}\n className=\"mt-0.5 shrink-0 text-muted-foreground\"\n />\n )}\n </DrawerPartContext.Provider>\n </div>\n );\n};\nDrawerHeaderTitle.displayName = 'DrawerHeaderTitle';\n\n/**\n * A `<nav>` row at the top of `Drawer.Header`, for a multi-level drawer's Back button and the\n * drawer's commands. Give it an `aria-label` when the page has other navigation landmarks.\n * Fluent's `DrawerHeaderNavigation`.\n */\nexport const DrawerHeaderNavigation = ({\n className,\n children,\n ref,\n ...rest\n}: DrawerHeaderNavigationProps) => {\n useDrawerContext('Drawer.HeaderNavigation');\n return (\n <nav\n {...rest}\n ref={ref}\n className={cn(drawerHeaderNavigationClassNames.root, 'flex items-center gap-1', className)}\n >\n <DrawerPartContext.Provider value=\"content\">{children}</DrawerPartContext.Provider>\n </nav>\n );\n};\nDrawerHeaderNavigation.displayName = 'DrawerHeaderNavigation';\n\n/**\n * Optional: gives the drawer's scrolling body your props (`className`, `style`, `ref`, `id`,\n * `role`, `tabIndex`, `aria-*`, `data-*`, handlers), for example `tabIndex={0} role=\"region\"\n * aria-label=\"…\"` to let the keyboard scroll a body without focusable content (the body then\n * shows the focus ring inside its edge). Its children render in its place among the drawer's\n * other content. Make it a direct child of `Drawer` (a Fragment there is fine) and render one;\n * nested in an element or rendered by a component of yours it renders as an element inside the\n * body, with a development warning. Fluent's `DrawerBody`.\n */\nexport const DrawerBody = ({ className, children, ref, ...rest }: DrawerBodyProps) => {\n useDrawerContext('Drawer.Body');\n // The Drawer renders a placed Body's props on its scrolling body and its children in place, so\n // this element renders only for a Body its scan did not place.\n useWarnWhen(true, BODY_UNSCANNED_WARNING_KEY, BODY_UNSCANNED_WARNING);\n return (\n <div {...rest} ref={ref} className={cn(drawerBodyClassNames.root, focusRingInset, className)}>\n <DrawerPartContext.Provider value=\"content\">{children}</DrawerPartContext.Provider>\n </div>\n );\n};\nDrawerBody.displayName = 'DrawerBody';\n\n/**\n * The drawer's action row, below the scrolling body: it never scrolls and never covers a focused\n * field. Its actions start at the inline start and wrap. Make it a direct child of `Drawer` (a\n * Fragment there is fine): it renders after the body wherever it is written; nested in an element\n * (a `<form>`) or rendered by a component of yours it renders where it is, in the body, with a\n * development warning. For a form in the body, give the footer's submit button `form={formId}`.\n * It draws a line above itself while content continues below (`data-scroll-state`). A footer\n * whose children render nothing renders no element. Fluent's `DrawerFooter`.\n */\nexport const DrawerFooter = ({ className, children, ref, ...rest }: DrawerFooterProps) => {\n useDrawerContext('Drawer.Footer');\n const placed = usePlaced();\n const scrollState = React.useContext(DrawerScrollStateContext) ?? 'none';\n useWarnWhen(!placed, FOOTER_UNSCANNED_WARNING_KEY, FOOTER_UNSCANNED_WARNING);\n if (!slotRendersContent(children)) return null;\n return (\n <div\n data-scroll-state={scrollState}\n {...rest}\n ref={ref}\n className={cn(\n drawerFooterClassNames.root,\n 'flex shrink-0 flex-wrap items-center gap-2 p-4',\n scrollSeparatorClasses.footer,\n className,\n )}\n >\n <DrawerPartContext.Provider value=\"content\">\n {materialiseSlotContent(children)}\n </DrawerPartContext.Provider>\n </div>\n );\n};\nDrawerFooter.displayName = 'DrawerFooter';\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/children.cjs"),r=require("../../lib/dev.cjs"),i=require("../../lib/slot.cjs"),a=require("../../lib/classNames.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../hooks/useMergedRefs.cjs"),c=require("../../lib/styles.cjs"),l=require("./Dialog.shared.cjs"),u=require("./Drawer.panel.cjs"),d=require("./Drawer.scroll.cjs"),f=require("./Drawer.context.cjs"),p=require("./Drawer.parts.cjs");let m=require("react");m=e.__toESM(m,1);let h=require("react/jsx-runtime");var g=`Drawer:unreachable`,_="Drawer has no way to open: a second after mounting it is still uncontrolled (no `open` prop), closed, and has no Drawer.Trigger as a direct child (or in a Fragment there). A Drawer.Trigger rendered by a component or nested in an element is panel content, which is not rendered or is hidden while the drawer is closed. Make the trigger a direct child of Drawer, or control the Drawer with `open`/`onOpenChange`.",v=1e3,y=32;function b(e){let t=(e,r,i)=>{if(i>y||typeof e!=`object`||!e)return!1;if(Array.isArray(e))return e.some(e=>t(e,r,i));if(!m.isValidElement(e))return!1;let a=n.getElementType(e,{suspend:!1});if(a===p.DrawerTrigger)return r>0;let o=a===m.Fragment;if(typeof a!=`string`&&!o)return!1;let{children:s}=e.props;return t(s,o?r:r+1,i+1)};return t(e,0,0)}var x=`Drawer:title-ignored`,ee="Drawer: `title` and `titleAction` are ignored because a Drawer.Header is among the children. Put a Drawer.HeaderTitle (with its `action`) in the header instead.",te=`Drawer.Body:duplicate`,ne=`Drawer has more than one Drawer.Body: the props of the first one apply to the scrolling body, and the children of every one render in their place. Render one Drawer.Body.`;function re(e){let t={triggers:[],headers:[],bodyProps:void 0,bodyCount:0,content:[],footers:[]};for(let{key:r,node:i}of n.flattenChildren(e)){if(n.isElementOfType(i,p.DrawerBody)){t.bodyCount+=1,t.bodyCount===1&&(t.bodyProps=i.props),t.content.push((0,h.jsx)(m.Fragment,{children:i.props.children},r));continue}let e=m.isValidElement(i)?m.cloneElement(i,{key:r}):i;n.isElementOfType(i,p.DrawerTrigger)?t.triggers.push(e):n.isElementOfType(i,p.DrawerHeader)?t.headers.push(e):n.isElementOfType(i,p.DrawerFooter)?t.footers.push(e):t.content.push(e)}return t}function S({title:e,hasTitle:n,titleId:r,titleAction:o,requestOpen:s,closeLabel:c,closeButton:l}){let u=m.useContext(f.DrawerScrollStateContext)??`none`,g=i.slotRendersContent(o);return!n&&!g&&l===null?null:(0,h.jsxs)(`div`,{"data-scroll-state":u,className:t.cn(a.drawerClassNames.header,`flex shrink-0 items-center justify-between gap-2 p-4`,d.scrollSeparatorClasses.header),children:[n&&(0,h.jsx)(`h2`,{id:r,className:t.cn(a.drawerTitleClassNames.root,`text-subtitle-1 font-semibold`),children:e}),g?i.renderSlot(o,`span`,t.cn(a.drawerClassNames.titleAction,`ms-auto flex shrink-0 items-center gap-1`)):null,(0,h.jsx)(p.DrawerCloseButton,{requestOpen:s,label:c,closeButton:l,className:t.cn(!g&&`ms-auto`,`text-muted-foreground`)})]})}S.displayName=`DrawerBuiltInHeader`;function C({header:e,bodyProps:n,content:r,footers:i}){let[o,l]=m.useState(null),u=d.useScrollState(o),{children:p,className:g,ref:_,...v}=n??{},y=s.useMergedRefs(l,_);return(0,h.jsx)(f.DrawerScrollStateContext.Provider,{value:u,children:(0,h.jsxs)(f.DrawerHeaderContext.Provider,{value:!1,children:[(0,h.jsx)(f.DrawerPartContext.Provider,{value:`placed`,children:e}),(0,h.jsx)(`div`,{"data-scroll-state":u,...v,ref:y,className:t.cn(a.drawerClassNames.body,n&&a.drawerBodyClassNames.root,`min-h-0 flex-1 overflow-y-auto p-4`,c.focusRingInset,g),children:(0,h.jsx)(f.DrawerPartContext.Provider,{value:`content`,children:r})}),(0,h.jsx)(f.DrawerPartContext.Provider,{value:`placed`,children:i})]})})}C.displayName=`DrawerLayout`;var w=({open:e,defaultOpen:t,onOpenChange:n,type:c=`overlay`,separator:d=!1,position:y=`end`,size:w=`small`,modalType:ie=`modal`,backdrop:T,closeButton:E,titleAction:D,title:O,closeLabel:k=`Close`,finalFocusRef:A,unmountOnClose:j=!0,children:M,id:N,ref:ae,...oe})=>{let[se,P]=l.useModalOpenState(e,t,n),F=u.useDrawerOpen(c,se),I=l.useModalTrigger(),ce=o.useId(`wave-drawer`),L=N??ce,R=o.useId(`wave-drawer-title`),z=l.useTitleRegistry(),[B,V]=m.useState(null),H=s.useMergedRefs(ae,V);l.useUnnamedModalWarning(F?B:null,z.hasTitle,`Drawer`,`Drawer.HeaderTitle or a Drawer.Title`);let{triggers:U,headers:W,bodyProps:le,bodyCount:ue,content:de,footers:fe}=re(M),G=W.length>0,K=i.slotRendersContent(O),q=K&&!G,J=(K||i.slotRendersContent(D))&&G;m.useEffect(()=>{J&&r.warnOnce(x,ee)},[J]);let Y=ue>1;m.useEffect(()=>{Y&&r.warnOnce(te,ne)},[Y]);let X=m.useRef(!1);m.useEffect(()=>{r.isDev&&!X.current&&b(M)&&(X.current=!0,r.warnOnce(p.NESTED_TRIGGER_WARNING_KEY,p.NESTED_TRIGGER_WARNING))},[M]);let Z=e===void 0&&!t&&U.length===0,Q=m.useRef({unreachable:Z,children:M});m.useLayoutEffect(()=>{Q.current={unreachable:Z,children:M}}),m.useEffect(()=>{if(!r.isDev||!Q.current.unreachable)return;let e=setTimeout(()=>{let e=Q.current;e.unreachable&&!b(e.children)&&r.warnOnce(g,_)},v);return()=>clearTimeout(e)},[]);let $=m.useMemo(()=>({open:F,requestOpen:P,trigger:I,panelId:L,type:c,inPanel:!1,closeLabel:k,closeButton:E}),[F,P,I,L,c,k,E]),pe=m.useMemo(()=>({...$,inPanel:!0}),[$]),me=(0,h.jsx)(f.DrawerContext.Provider,{value:pe,children:(0,h.jsx)(l.ModalSurfaceContext.Provider,{value:z.context,children:(0,h.jsx)(C,{header:G?W:(0,h.jsx)(S,{title:O,hasTitle:q,titleId:R,titleAction:D,requestOpen:P,closeLabel:k,closeButton:E}),bodyProps:le,content:de,footers:fe})})}),he=q?R:z.titleId,ge=(0,h.jsx)(u.DrawerPanel,{componentName:`Drawer`,type:c,open:F,requestOpen:P,position:y,size:w,separator:d,modalType:ie,unmountOnClose:j,inlineAs:`aside`,trigger:I,finalFocusRef:A,rootClassName:a.drawerClassNames.root,backdropClassName:a.drawerClassNames.backdrop,backdrop:T,id:L,"aria-labelledby":he,...oe,ref:H,children:me});return l.useModalTriggerSession(I,F),(0,h.jsxs)(f.DrawerContext.Provider,{value:$,children:[U,ge]})};w.displayName=`Drawer`,exports.DrawerRoot=w;
|
|
2
|
+
//# sourceMappingURL=Drawer.root.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Drawer.root.cjs","names":["React","getElementType","DrawerTrigger","flattenChildren","isElementOfType","DrawerBody","DrawerHeader","DrawerFooter","DrawerScrollStateContext","slotRendersContent","cn","drawerClassNames","scrollSeparatorClasses","drawerTitleClassNames","renderSlot","DrawerCloseButton","useScrollState","useMergedRefs","DrawerHeaderContext","DrawerPartContext","drawerBodyClassNames","focusRingInset","useModalOpenState","useDrawerOpen","useModalTrigger","useId","useTitleRegistry","isDev","NESTED_TRIGGER_WARNING_KEY","NESTED_TRIGGER_WARNING","DrawerContext","ModalSurfaceContext","DrawerPanel","require_runtime","require_cn","require_children","require_dev","require_slot","require_classNames","require_useId","require_useMergedRefs","require_styles","require_Dialog_shared","require_Drawer_panel","require_Drawer_scroll","require_Drawer_context","require_Drawer_parts","react","react_jsx_runtime","UNREACHABLE_WARNING_KEY","UNREACHABLE_WARNING","REACHABILITY_CHECK_DELAY","NESTED_TRIGGER_MAX_DEPTH","hasNestedTrigger","visit","level","node","item","depth","type","isFragment","nested","children","TITLE_IGNORED_WARNING_KEY","TITLE_IGNORED_WARNING","BODY_DUPLICATE_WARNING_KEY","BODY_DUPLICATE_WARNING","splitChildren","partition","key","keyed","DrawerBuiltInHeader","scrollState","hasTitleAction","titleAction","hasTitle","closeButton","titleId","title","closeLabel","DrawerLayout","body","setBody","_children","bodyRest","bodyProps","bodyRef","ref","header","className","content","footers","DrawerRoot","openProp","rest","openState","requestOpen","defaultOpen","onOpenChange","open","trigger","generatedId","panelId","id","propTitleId","titles","panel","setPanel","panelRef","hasHeader","headers","titleRendersContent","titleIgnored","duplicateBody","bodyCount","nestedWarnedRef","unreachable","triggers","latestRef","timer","latest","context","panelContext","layout","labelledBy","panelElement"],"sources":["../../../src/components/overlays/Drawer.root.tsx"],"sourcesContent":["import * as React from 'react';\nimport { flattenChildren, getElementType, isElementOfType } from '../../lib/children';\nimport { cn } from '../../lib/cn';\nimport {\n drawerBodyClassNames,\n drawerClassNames,\n drawerTitleClassNames,\n} from '../../lib/classNames';\nimport { isDev, warnOnce } from '../../lib/dev';\nimport { renderSlot, slotRendersContent, type Slot, type SlotObject } from '../../lib/slot';\nimport { focusRingInset } from '../../lib/styles';\nimport type { BackdropAppearance } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport {\n ModalSurfaceContext,\n useModalOpenState,\n useModalTrigger,\n useModalTriggerSession,\n useTitleRegistry,\n useUnnamedModalWarning,\n type ModalRequestOpen,\n} from './Dialog.shared';\nimport {\n DrawerContext,\n DrawerHeaderContext,\n DrawerPartContext,\n DrawerScrollStateContext,\n type DrawerContextValue,\n type DrawerModalType,\n type DrawerOpenChangeDetails,\n type DrawerPosition,\n type DrawerSize,\n type DrawerType,\n} from './Drawer.context';\nimport { DrawerPanel, useDrawerOpen } from './Drawer.panel';\nimport {\n DrawerBody,\n DrawerCloseButton,\n DrawerFooter,\n DrawerHeader,\n DrawerTrigger,\n NESTED_TRIGGER_WARNING,\n NESTED_TRIGGER_WARNING_KEY,\n type DrawerBodyProps,\n} from './Drawer.parts';\nimport { scrollSeparatorClasses, useScrollState } from './Drawer.scroll';\n\n/*\n * The Drawer root: its props, the child scan, the layout and the development checks, on the drawer\n * panel shell (`DrawerPanel`), which renders the panel element and its machinery. Imports the\n * parts, panel, scroll and context modules (never `Drawer.tsx`, which holds the compound).\n */\n\n/** Properties for the Drawer component. */\nexport interface DrawerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n /**\n * Controlled open state of the drawer. An overlay drawer's panel renders only in the browser:\n * open, it is closed in the server HTML and opens once it has hydrated. An inline drawer renders\n * in the server HTML: open, or hidden when kept mounted (`unmountOnClose={false}`).\n */\n open?: boolean;\n /**\n * Default open state for uncontrolled usage. An overlay drawer open by default is closed in the\n * server HTML and opens once it has hydrated; an inline one is open in the server HTML.\n * @default false\n */\n defaultOpen?: boolean;\n /**\n * Called with the new open state when it changes. `details.reason` tells how — `trigger`,\n * `close` (a `.Close` part), `close-button` (the built-in Close button), `escape` or\n * `outside-press` (the backdrop) — so a controlled drawer can refuse only some ways of closing\n * (for example keep a form with unsaved changes open on `outside-press`); `details.event` is the\n * DOM event behind the request. WaveUI always passes `details`; it is typed optional until 1.0\n * so that code which calls this prop itself keeps compiling. An inline drawer asks only with\n * `trigger` (its `Drawer.Trigger` toggles it), `close` and `close-button`: Escape and presses\n * outside it never close it.\n *\n * Fires only when the value changes; a controlled drawer stays as it is until the parent updates\n * `open`.\n */\n onOpenChange?: (open: boolean, details?: DrawerOpenChangeDetails) => void;\n /**\n * How the drawer sits on the page (Fluent's `type`).\n * - `overlay`: a panel over the page, rendered in a portal while open: modal by default (focus\n * moves in and stays there, toasts included; the rest of the page is `inert` and does not\n * scroll; Escape and a backdrop press close it), or `modalType=\"non-modal\"`.\n * - `inline`: a panel in the page layout, rendered where the Drawer is (after its direct\n * `Drawer.Trigger`s) as an `<aside>`, a complementary landmark named by its title. The page\n * stays usable around it: no backdrop, no focus trap, no portal, no scroll lock; Escape and\n * presses outside do not close it. Opening it leaves focus where it is; closing it while focus\n * is inside returns focus to `finalFocusRef`, else the element that opened it, else the\n * trigger. `position` and `size` pick its inner edge and its width (its height at the bottom);\n * where it sits is up to your layout (a flex row of panel and content, for example).\n * `modalType` and `backdrop` do not apply to it, and toasts do not move out of its way: it is\n * page content.\n *\n * Changing `type` remounts the panel and its content (what was typed in it is lost); focus\n * inside an overlay that becomes inline returns to the trigger, and focus inside an inline panel\n * that becomes an overlay moves into the overlay. Rendered as `data-type`.\n * @default 'overlay'\n */\n type?: DrawerType;\n /**\n * Inline drawers: draws a line on the panel's inner edge, the edge facing the page content\n * (`data-separator`). An overlay drawer always draws that edge and ignores this prop. In forced\n * colours an inline drawer's inner edge is always drawn. Fluent's `separator`.\n * @default false\n */\n separator?: boolean;\n /**\n * Side of the screen the drawer is attached to. `start`/`end` follow the text direction;\n * `left`/`right` are physical sides; `bottom` runs along the bottom edge (`size` sets its\n * height). An inline drawer takes its place from your layout: `position` picks its inner edge\n * (the one facing the page content: the end edge of a `start` panel, the top edge of a `bottom`\n * one) and the axis `size` sets. Rendered as `data-position`.\n * @default 'end'\n */\n position?: DrawerPosition;\n /**\n * The panel's width at a side — `small` 320px, `medium` 592px, `large` 940px, `full` the\n * viewport's width — or its height at the bottom (the same values; `full` the viewport's height).\n * It never exceeds the viewport. An inline panel takes the same sizes, where `full` is its\n * container's width (height), and never grows past its container. A width class in `className`\n * (a height class for `bottom`) replaces it. Rendered as `data-size`. Fluent's `size`.\n * @default 'small'\n */\n size?: DrawerSize;\n /**\n * `modal`, `alert` or `non-modal`, as Dialog's `modalType`. `modal`: the page behind is `inert`\n * and does not scroll; a backdrop press, Escape, the Close button and `Drawer.Close` close it.\n * `alert`: `role=\"alertdialog\"` (a `role` you pass wins), and a backdrop press does not close it\n * (Escape still does). `non-modal`: no backdrop, and the page stays usable — no focus trap,\n * nothing inert, the page scrolls; Tab and Shift+Tab leave the drawer in the page's order right\n * after the element that opened it, Escape closes it while focus is inside it, presses on the\n * page never close it, and focus returns to the opener only when it was inside the drawer. A\n * non-modal drawer covers the page under it while Tab still reaches that page: reserve its width\n * (its height at the bottom) in your layout while it is open, or use `modal`, or, for a panel\n * beside the content, an inline drawer (`type=\"inline\"`) (with `size=\"full\"` it covers\n * everything, and a development warning says so). Every type moves focus to the first focusable\n * element on open. Rendered as `data-modal-type`. Ignored by an inline drawer, which is never\n * modal and renders no `data-modal-type`. Fluent's `modalType`.\n * @default 'modal'\n */\n modalType?: DrawerModalType;\n /**\n * The backdrop of a modal or alert drawer, as `Dialog.Content`'s `backdrop`: a `div` behind the\n * panel, `aria-hidden`. Shorthand content renders inside it; a slot object's `className` (merged\n * last), `style`, data attributes, `ref` and handlers go to it, and its `appearance`\n * (`'dimmed'` or `'transparent'`) overrides the automatic one: while another modal Dialog or\n * Drawer is open below this one the backdrop is transparent, so the page is dimmed once. `null`\n * renders no backdrop (the page stays inert, and a press outside still closes a modal drawer); a\n * boolean is no slot. Ignored with `modalType=\"non-modal\"` and by an inline drawer (a\n * development warning says so). Fluent's `backdrop`.\n */\n backdrop?: Slot<'div'> | (SlotObject<'div'> & { appearance?: BackdropAppearance });\n /**\n * Content of the built-in Close button, in the built-in header and in every\n * `Drawer.HeaderTitle`, as `Dialog.Content`'s `closeButton`: decorative content inside the button\n * (the dismiss glyph by default), so the button keeps the name `closeLabel`; a slot object's\n * `aria-label`, `aria-labelledby` or `title` names it instead, and its handlers run before the\n * close (`preventDefault()` keeps the drawer open). `null` hides them all (`Drawer.Close`, and\n * Escape on an overlay, still close); a boolean is no slot; content that renders nothing keeps the\n * default glyph. A `<button>` or Wave `Button` passed here is merged into the built-in button,\n * never nested (a development warning says so), and its text label names the button. Fluent's\n * `DrawerHeaderTitle` `action` holds Fluent's close button; WaveUI renders its own.\n */\n closeButton?: Slot<'span'>;\n /**\n * Header buttons for the `title` prop form, between the heading and the built-in Close button in\n * DOM and Tab order. Ignored, with a development warning, next to a `Drawer.Header` (use the\n * `action` of `Drawer.HeaderTitle`). Interactive: name icon-only buttons. Renders nothing when\n * empty. Fluent's `DrawerHeaderTitle` `action`, for the `title` prop form.\n */\n titleAction?: Slot<'span'>;\n /**\n * Title displayed in the built-in header; it names the drawer (`aria-labelledby`). Without it,\n * render a `Drawer.HeaderTitle` (in a `Drawer.Header`) or a `Drawer.Title`, or pass\n * `aria-label`/`aria-labelledby`. A title that renders nothing (`''`, `[]`, `true`) counts as\n * none. Ignored, with a development warning, when the children hold a `Drawer.Header`, which\n * replaces the built-in header. The heading is an `<h2>`; for another level use\n * `Drawer.HeaderTitle` with `headingLevel`. In the server HTML of an inline drawer only `title`\n * (or `aria-label`/`aria-labelledby`) names the panel: a `Drawer.HeaderTitle` or `Drawer.Title`\n * names it once the page has hydrated.\n */\n title?: React.ReactNode;\n /**\n * Accessible name of the built-in Close button (an icon-only button), in the built-in header and\n * in every `Drawer.HeaderTitle`. Localize it with the page's language. A text label of a button\n * merged into `closeButton` names it instead.\n * @default 'Close'\n */\n closeLabel?: string;\n /**\n * Where focus goes when the drawer closes, if it can take focus. Otherwise focus returns to the\n * element that had focus when the drawer opened, then to the trigger, then to an element next to\n * where that opener was. An inline or non-modal drawer moves focus on close only when focus was\n * inside it.\n */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * Removes the panel and its content when the drawer closes. `false` keeps them mounted while\n * closed, `hidden` and `inert` (out of the layout, the Tab order and the accessibility tree), so\n * what was typed and the state of the components inside survive closing and opening again; the\n * content then mounts with the Drawer, closed, and an `autoFocus` inside it never applies (an\n * overlay focuses its first focusable element on each open). An overlay panel still renders only\n * in the browser; a kept inline panel is in the server HTML, hidden. Kept content still belongs\n * to its form: a `required` empty field in a closed inline drawer inside a page `<form>` blocks\n * its submission without a visible message. A popup opened inside that is still open when the\n * drawer closes stays open over the page (a development warning says so): close it first. A\n * `key` on the Drawer resets the kept content. Fluent's `unmountOnClose`.\n * @default true\n */\n unmountOnClose?: boolean;\n /**\n * The drawer's content, placed by the Drawer, also from a Fragment (`{isMobile && <>…</>}`) and\n * when written in a Server Component: `Drawer.Trigger` children render in place (outside the\n * panel); a `Drawer.Header` replaces the built-in header (the `title` and Close button row); a\n * `Drawer.Body` gives the scrolling body its props; `Drawer.Footer` renders below the scrolling\n * body, outside it, wherever it is written among the children; everything else renders in the\n * scrolling body. A part nested in another element (a `<form>`) or rendered by a component of\n * yours renders where it is, in the body (a development warning says so). A `Drawer.Trigger`\n * nested in another element, or rendered by a component, is panel content, so it is not rendered\n * (or, kept mounted, is hidden) while the drawer is closed (development warnings say so, also\n * when an uncontrolled drawer still has no direct trigger a second after it mounts and therefore\n * cannot open; a controlled drawer whose trigger a component such as a Tooltip wraps warns only\n * once it renders in the panel).\n * Put wrappers inside the trigger instead: see `Drawer.Trigger`.\n */\n children: React.ReactNode;\n /**\n * Ref to the panel: the `role=\"dialog\"` element of an overlay drawer (`alertdialog` with\n * `modalType=\"alert\"`), the `<aside>` of an inline one. A ref to a `div` still type-checks.\n */\n ref?: React.Ref<HTMLElement>;\n}\n\nconst UNREACHABLE_WARNING_KEY = 'Drawer:unreachable';\nconst UNREACHABLE_WARNING =\n 'Drawer has no way to open: a second after mounting it is still uncontrolled (no `open` prop), closed, and has no Drawer.Trigger as a direct child (or in a Fragment there). A Drawer.Trigger rendered by a component or nested in an element is panel content, which is not rendered or is hidden while the drawer is closed. Make the trigger a direct child of Drawer, or control the Drawer with `open`/`onOpenChange`.';\n\n/**\n * How long after mount (ms) the development check for a drawer without a trigger waits: long\n * enough for a trigger that a conditional Fragment renders once the page knows its layout.\n */\nconst REACHABILITY_CHECK_DELAY = 1000;\n\n/** Deepest element level the development check for nested triggers looks at. */\nconst NESTED_TRIGGER_MAX_DEPTH = 32;\n\n/**\n * Development check: whether the Drawer's children hold a `Drawer.Trigger` inside a host element\n * (at any depth, also through Fragments), which would become panel content; a trigger inside\n * Fragments only is direct (see `splitChildren`). Walks the element tree the consumer wrote, not\n * rendered output, so it descends only into host elements (`<div>`, `<span>`, …) and Fragments,\n * which render their `children` as written. A component's\n * output is unknown here — a wrapper that renders its own Drawer around its children, for one —\n * so components are not walked; a trigger rendered by a component is caught when it renders in the\n * open panel, or, while the drawer cannot open, by the unreachable-drawer check.\n */\nfunction hasNestedTrigger(children: React.ReactNode): boolean {\n // `depth` counts host elements only: a Fragment adds no level, as `splitChildren` flattens it.\n const visit = (node: unknown, depth: number, level: number): boolean => {\n if (level > NESTED_TRIGGER_MAX_DEPTH || typeof node !== 'object' || node === null) return false;\n if (Array.isArray(node)) return node.some((item) => visit(item, depth, level));\n if (!React.isValidElement(node)) return false;\n // A part written in a Server Component has a lazy type. The walk runs in effects, outside\n // render: a lazy part that is still loading must not throw its thenable there, so it counts\n // as no trigger (`suspend: false` returns the lazy itself, which matches nothing).\n const type = getElementType(node, { suspend: false });\n if (type === DrawerTrigger) return depth > 0;\n const isFragment = type === React.Fragment;\n if (typeof type !== 'string' && !isFragment) return false;\n const { children: nested } = node.props as { children?: unknown };\n return visit(nested, isFragment ? depth : depth + 1, level + 1);\n };\n return visit(children, 0, 0);\n}\n\nconst TITLE_IGNORED_WARNING_KEY = 'Drawer:title-ignored';\nconst TITLE_IGNORED_WARNING =\n 'Drawer: `title` and `titleAction` are ignored because a Drawer.Header is among the children. Put a Drawer.HeaderTitle (with its `action`) in the header instead.';\n\nconst BODY_DUPLICATE_WARNING_KEY = 'Drawer.Body:duplicate';\nconst BODY_DUPLICATE_WARNING =\n 'Drawer has more than one Drawer.Body: the props of the first one apply to the scrolling body, and the children of every one render in their place. Render one Drawer.Body.';\n\n/** How the Drawer sorts its direct children ({@link splitChildren}). */\ninterface DrawerPartition {\n /** The direct `Drawer.Trigger` elements, rendered in place. */\n triggers: React.ReactNode[];\n /** The direct `Drawer.Header` elements, rendered in the header area in written order. */\n headers: React.ReactNode[];\n /** The props of the first direct `Drawer.Body` (its `children` render in `content`). */\n bodyProps: DrawerBodyProps | undefined;\n /** How many direct `Drawer.Body` elements there are. */\n bodyCount: number;\n /** The body content in written order; a `Drawer.Body` is replaced by its children. */\n content: React.ReactNode[];\n /** The direct `Drawer.Footer` elements, rendered after the body in written order. */\n footers: React.ReactNode[];\n}\n\n/**\n * Sorts the Drawer's children: its direct `Drawer.Trigger`, `Drawer.Header`, `Drawer.Body` and\n * `Drawer.Footer` elements and the body content. Fragments are flattened (recursively), so a part\n * in a Fragment — `{isMobile && <><Drawer.Trigger>…</Drawer.Trigger><Filters /></>}` — counts as a\n * direct child. Every element keeps the key `flattenChildren` gives it: unique across Fragments and\n * stable when a sibling Fragment toggles, so body content keeps its state when a part appears. A\n * part is recognised also when it was written in a Server Component (a lazy type). Runs during\n * render, so the placement is the same on the server.\n */\nfunction splitChildren(children: React.ReactNode): DrawerPartition {\n const partition: DrawerPartition = {\n triggers: [],\n headers: [],\n bodyProps: undefined,\n bodyCount: 0,\n content: [],\n footers: [],\n };\n for (const { key, node } of flattenChildren(children)) {\n if (isElementOfType<DrawerBodyProps>(node, DrawerBody)) {\n // The first Body's props go on the scrolling body; every Body's children render in place.\n partition.bodyCount += 1;\n if (partition.bodyCount === 1) partition.bodyProps = node.props;\n partition.content.push(<React.Fragment key={key}>{node.props.children}</React.Fragment>);\n continue;\n }\n const keyed = React.isValidElement(node) ? React.cloneElement(node, { key }) : node;\n if (isElementOfType(node, DrawerTrigger)) partition.triggers.push(keyed);\n else if (isElementOfType(node, DrawerHeader)) partition.headers.push(keyed);\n else if (isElementOfType(node, DrawerFooter)) partition.footers.push(keyed);\n else partition.content.push(keyed);\n }\n return partition;\n}\n\n/** Properties of the built-in header ({@link DrawerBuiltInHeader}). */\ninterface DrawerBuiltInHeaderProps {\n /** The `title` prop, when it renders content. */\n title: React.ReactNode;\n /** Whether `title` renders content (else no heading renders). */\n hasTitle: boolean;\n /** The heading's id (the panel's `aria-labelledby`). */\n titleId: string;\n /** The `titleAction` slot. */\n titleAction: Slot<'span'> | undefined;\n requestOpen: ModalRequestOpen;\n closeLabel: string;\n /** The `closeButton` slot (`null`: no Close button). */\n closeButton: Slot<'span'> | undefined;\n}\n\n/**\n * The 0.10 header row of the `title` form (no `Drawer.Header` among the children): the `title`\n * heading, the `titleAction` content and the Close button as its direct children. The title action\n * takes the free room (`ms-auto`), so the Close button follows it through the row's gap; without\n * one the Close button does. It reads the body's scroll state for its separator. A row with\n * nothing in it (no title, no title action, `closeButton={null}`) renders no element.\n */\nfunction DrawerBuiltInHeader({\n title,\n hasTitle,\n titleId,\n titleAction,\n requestOpen,\n closeLabel,\n closeButton,\n}: DrawerBuiltInHeaderProps) {\n const scrollState = React.useContext(DrawerScrollStateContext) ?? 'none';\n const hasTitleAction = slotRendersContent(titleAction);\n if (!hasTitle && !hasTitleAction && closeButton === null) return null;\n return (\n <div\n data-scroll-state={scrollState}\n className={cn(\n drawerClassNames.header,\n 'flex shrink-0 items-center justify-between gap-2 p-4',\n scrollSeparatorClasses.header,\n )}\n >\n {hasTitle && (\n <h2\n id={titleId}\n className={cn(drawerTitleClassNames.root, 'text-subtitle-1 font-semibold')}\n >\n {title}\n </h2>\n )}\n {hasTitleAction\n ? renderSlot(\n titleAction,\n 'span',\n cn(drawerClassNames.titleAction, 'ms-auto flex shrink-0 items-center gap-1'),\n )\n : null}\n <DrawerCloseButton\n requestOpen={requestOpen}\n label={closeLabel}\n closeButton={closeButton}\n className={cn(!hasTitleAction && 'ms-auto', 'text-muted-foreground')}\n />\n </div>\n );\n}\nDrawerBuiltInHeader.displayName = 'DrawerBuiltInHeader';\n\n/** Properties of {@link DrawerLayout}. */\ninterface DrawerLayoutProps {\n /** The header area: the built-in header, or the placed `Drawer.Header` elements. */\n header: React.ReactNode;\n /** The props of the placed `Drawer.Body`, put on the scrolling body. */\n bodyProps: DrawerBodyProps | undefined;\n /** The body content. */\n content: React.ReactNode;\n /** The placed `Drawer.Footer` elements. */\n footers: React.ReactNode;\n}\n\n/**\n * The panel's layout (internal): the header area, the scrolling body and the footers. It owns the\n * body's scroll state (`useScrollState`), so a change of the state re-renders this component, the\n * body element and the parts that read the state (the header area and the footers), never the\n * consumer's content: the elements it receives as props are the same objects, so React skips them.\n */\nfunction DrawerLayout({ header, bodyProps, content, footers }: DrawerLayoutProps) {\n const [body, setBody] = React.useState<HTMLDivElement | null>(null);\n const scrollState = useScrollState(body);\n const { children: _children, className, ref, ...bodyRest } = bodyProps ?? {};\n const bodyRef = useMergedRefs<HTMLDivElement>(setBody, ref);\n return (\n <DrawerScrollStateContext.Provider value={scrollState}>\n <DrawerHeaderContext.Provider value={false}>\n <DrawerPartContext.Provider value=\"placed\">{header}</DrawerPartContext.Provider>\n <div\n data-scroll-state={scrollState}\n {...bodyRest}\n ref={bodyRef}\n className={cn(\n drawerClassNames.body,\n bodyProps && drawerBodyClassNames.root,\n 'min-h-0 flex-1 overflow-y-auto p-4',\n focusRingInset,\n className,\n )}\n >\n <DrawerPartContext.Provider value=\"content\">{content}</DrawerPartContext.Provider>\n </div>\n <DrawerPartContext.Provider value=\"placed\">{footers}</DrawerPartContext.Provider>\n </DrawerHeaderContext.Provider>\n </DrawerScrollStateContext.Provider>\n );\n}\nDrawerLayout.displayName = 'DrawerLayout';\n\n// The root of `Drawer` (documented on the export in Drawer.tsx).\nexport const DrawerRoot = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n type = 'overlay',\n separator = false,\n position = 'end',\n size = 'small',\n modalType = 'modal',\n backdrop,\n closeButton,\n titleAction,\n title,\n closeLabel = 'Close',\n finalFocusRef,\n unmountOnClose = true,\n children,\n id,\n ref,\n ...rest\n}: DrawerProps) => {\n const [openState, requestOpen] = useModalOpenState(openProp, defaultOpen, onOpenChange);\n // An overlay's panel lives in a portal, which renders only in the browser: until then (the\n // server HTML, hydration) it reports itself closed, so the trigger's aria-expanded and\n // aria-controls never describe a panel that is not there. An inline panel renders in place, also\n // on the server (D107).\n const open = useDrawerOpen(type, openState);\n const trigger = useModalTrigger();\n const generatedId = useId('wave-drawer');\n const panelId = id ?? generatedId;\n const propTitleId = useId('wave-drawer-title');\n const titles = useTitleRegistry();\n // The mounted panel (the shell's element of either type), for the unnamed-drawer check.\n const [panel, setPanel] = React.useState<HTMLElement | null>(null);\n const panelRef = useMergedRefs<HTMLElement>(ref, setPanel);\n useUnnamedModalWarning(\n open ? panel : null,\n titles.hasTitle,\n 'Drawer',\n 'Drawer.HeaderTitle or a Drawer.Title',\n );\n\n const { triggers, headers, bodyProps, bodyCount, content, footers } = splitChildren(children);\n const hasHeader = headers.length > 0;\n // A Drawer.Header replaces the built-in header, whose `title` it cannot show.\n const titleRendersContent = slotRendersContent(title);\n const hasTitle = titleRendersContent && !hasHeader;\n const titleIgnored = (titleRendersContent || slotRendersContent(titleAction)) && hasHeader;\n React.useEffect(() => {\n if (titleIgnored) warnOnce(TITLE_IGNORED_WARNING_KEY, TITLE_IGNORED_WARNING);\n }, [titleIgnored]);\n const duplicateBody = bodyCount > 1;\n React.useEffect(() => {\n if (duplicateBody) warnOnce(BODY_DUPLICATE_WARNING_KEY, BODY_DUPLICATE_WARNING);\n }, [duplicateBody]);\n\n // A trigger nested in the children is panel content: not rendered (or, kept mounted, hidden) while\n // the drawer is closed.\n // The children change on every parent render; once this drawer has warned, it stops walking.\n const nestedWarnedRef = React.useRef(false);\n React.useEffect(() => {\n if (!isDev || nestedWarnedRef.current || !hasNestedTrigger(children)) return;\n nestedWarnedRef.current = true;\n warnOnce(NESTED_TRIGGER_WARNING_KEY, NESTED_TRIGGER_WARNING);\n }, [children]);\n\n // An uncontrolled closed drawer without a direct trigger cannot open (e.g.\n // `<Drawer><FilterTrigger /></Drawer>`, whose trigger is panel content). Checked once, a moment\n // after mount, against the latest render: a trigger that a conditional Fragment adds right after\n // mount (`{isMobile && <>…</>}` with an SSR-safe media query) counts. A trigger nested in an\n // element already has the more specific warning above.\n const unreachable = openProp === undefined && !defaultOpen && triggers.length === 0;\n const latestRef = React.useRef({ unreachable, children });\n React.useLayoutEffect(() => {\n latestRef.current = { unreachable, children };\n });\n React.useEffect(() => {\n if (!isDev || !latestRef.current.unreachable) return;\n const timer = setTimeout(() => {\n const latest = latestRef.current;\n if (latest.unreachable && !hasNestedTrigger(latest.children)) {\n warnOnce(UNREACHABLE_WARNING_KEY, UNREACHABLE_WARNING);\n }\n }, REACHABILITY_CHECK_DELAY);\n return () => clearTimeout(timer);\n }, []);\n\n const context = React.useMemo<DrawerContextValue>(\n () => ({ open, requestOpen, trigger, panelId, type, inPanel: false, closeLabel, closeButton }),\n [open, requestOpen, trigger, panelId, type, closeLabel, closeButton],\n );\n const panelContext = React.useMemo<DrawerContextValue>(\n () => ({ ...context, inPanel: true }),\n [context],\n );\n\n // The panel's content: the header area, the scrolling body and the footers, for both types.\n const layout = (\n <DrawerContext.Provider value={panelContext}>\n <ModalSurfaceContext.Provider value={titles.context}>\n <DrawerLayout\n header={\n hasHeader ? (\n headers\n ) : (\n <DrawerBuiltInHeader\n title={title}\n hasTitle={hasTitle}\n titleId={propTitleId}\n titleAction={titleAction}\n requestOpen={requestOpen}\n closeLabel={closeLabel}\n closeButton={closeButton}\n />\n )\n }\n bodyProps={bodyProps}\n content={content}\n footers={footers}\n />\n </ModalSurfaceContext.Provider>\n </DrawerContext.Provider>\n );\n const labelledBy = hasTitle ? propTitleId : titles.titleId;\n\n // The panel and its machinery (portal, backdrop, presence, layer, trap, restore, Tab order) come\n // from the shell (D108); the root names it and fills it with its layout.\n const panelElement = (\n <DrawerPanel\n componentName=\"Drawer\"\n type={type}\n open={open}\n requestOpen={requestOpen}\n position={position}\n size={size}\n separator={separator}\n modalType={modalType}\n unmountOnClose={unmountOnClose}\n inlineAs=\"aside\"\n trigger={trigger}\n finalFocusRef={finalFocusRef}\n rootClassName={drawerClassNames.root}\n backdropClassName={drawerClassNames.backdrop}\n backdrop={backdrop}\n id={panelId}\n aria-labelledby={labelledBy}\n {...rest}\n ref={panelRef}\n >\n {layout}\n </DrawerPanel>\n );\n // After the shell's focus restores (its effects run before the root's), start the trigger\n // session, or end it and forget the trigger that opened it.\n useModalTriggerSession(trigger, open);\n\n return (\n <DrawerContext.Provider value={context}>\n {triggers}\n {panelElement}\n </DrawerContext.Provider>\n );\n};\nDrawerRoot.displayName = 'Drawer';\n"],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../../lib/cn.mjs";
|
|
3
|
+
import { flattenChildren as t, getElementType as n, isElementOfType as r } from "../../lib/children.mjs";
|
|
4
|
+
import { isDev as i, warnOnce as a } from "../../lib/dev.mjs";
|
|
5
|
+
import { renderSlot as o, slotRendersContent as s } from "../../lib/slot.mjs";
|
|
6
|
+
import { drawerBodyClassNames as c, drawerClassNames as l, drawerTitleClassNames as u } from "../../lib/classNames.mjs";
|
|
7
|
+
import { useId as d } from "../../hooks/useId.mjs";
|
|
8
|
+
import { useMergedRefs as f } from "../../hooks/useMergedRefs.mjs";
|
|
9
|
+
import { focusRingInset as p } from "../../lib/styles.mjs";
|
|
10
|
+
import { ModalSurfaceContext as m, useModalOpenState as h, useModalTrigger as g, useModalTriggerSession as _, useTitleRegistry as ee, useUnnamedModalWarning as te } from "./Dialog.shared.mjs";
|
|
11
|
+
import { DrawerPanel as ne, useDrawerOpen as re } from "./Drawer.panel.mjs";
|
|
12
|
+
import { scrollSeparatorClasses as v, useScrollState as y } from "./Drawer.scroll.mjs";
|
|
13
|
+
import { DrawerContext as b, DrawerHeaderContext as x, DrawerPartContext as S, DrawerScrollStateContext as C } from "./Drawer.context.mjs";
|
|
14
|
+
import { DrawerBody as w, DrawerCloseButton as T, DrawerFooter as E, DrawerHeader as D, DrawerTrigger as O, NESTED_TRIGGER_WARNING as ie, NESTED_TRIGGER_WARNING_KEY as ae } from "./Drawer.parts.mjs";
|
|
15
|
+
import * as k from "react";
|
|
16
|
+
import { jsx as A, jsxs as j } from "react/jsx-runtime";
|
|
17
|
+
//#region src/components/overlays/Drawer.root.tsx
|
|
18
|
+
var oe = "Drawer:unreachable", se = "Drawer has no way to open: a second after mounting it is still uncontrolled (no `open` prop), closed, and has no Drawer.Trigger as a direct child (or in a Fragment there). A Drawer.Trigger rendered by a component or nested in an element is panel content, which is not rendered or is hidden while the drawer is closed. Make the trigger a direct child of Drawer, or control the Drawer with `open`/`onOpenChange`.", ce = 1e3, M = 32;
|
|
19
|
+
function N(e) {
|
|
20
|
+
let t = (e, r, i) => {
|
|
21
|
+
if (i > M || typeof e != "object" || !e) return !1;
|
|
22
|
+
if (Array.isArray(e)) return e.some((e) => t(e, r, i));
|
|
23
|
+
if (!k.isValidElement(e)) return !1;
|
|
24
|
+
let a = n(e, { suspend: !1 });
|
|
25
|
+
if (a === O) return r > 0;
|
|
26
|
+
let o = a === k.Fragment;
|
|
27
|
+
if (typeof a != "string" && !o) return !1;
|
|
28
|
+
let { children: s } = e.props;
|
|
29
|
+
return t(s, o ? r : r + 1, i + 1);
|
|
30
|
+
};
|
|
31
|
+
return t(e, 0, 0);
|
|
32
|
+
}
|
|
33
|
+
var le = "Drawer:title-ignored", ue = "Drawer: `title` and `titleAction` are ignored because a Drawer.Header is among the children. Put a Drawer.HeaderTitle (with its `action`) in the header instead.", de = "Drawer.Body:duplicate", fe = "Drawer has more than one Drawer.Body: the props of the first one apply to the scrolling body, and the children of every one render in their place. Render one Drawer.Body.";
|
|
34
|
+
function pe(e) {
|
|
35
|
+
let n = {
|
|
36
|
+
triggers: [],
|
|
37
|
+
headers: [],
|
|
38
|
+
bodyProps: void 0,
|
|
39
|
+
bodyCount: 0,
|
|
40
|
+
content: [],
|
|
41
|
+
footers: []
|
|
42
|
+
};
|
|
43
|
+
for (let { key: i, node: a } of t(e)) {
|
|
44
|
+
if (r(a, w)) {
|
|
45
|
+
n.bodyCount += 1, n.bodyCount === 1 && (n.bodyProps = a.props), n.content.push(/* @__PURE__ */ A(k.Fragment, { children: a.props.children }, i));
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
let e = k.isValidElement(a) ? k.cloneElement(a, { key: i }) : a;
|
|
49
|
+
r(a, O) ? n.triggers.push(e) : r(a, D) ? n.headers.push(e) : r(a, E) ? n.footers.push(e) : n.content.push(e);
|
|
50
|
+
}
|
|
51
|
+
return n;
|
|
52
|
+
}
|
|
53
|
+
function P({ title: t, hasTitle: n, titleId: r, titleAction: i, requestOpen: a, closeLabel: c, closeButton: d }) {
|
|
54
|
+
let f = k.useContext(C) ?? "none", p = s(i);
|
|
55
|
+
return !n && !p && d === null ? null : /* @__PURE__ */ j("div", {
|
|
56
|
+
"data-scroll-state": f,
|
|
57
|
+
className: e(l.header, "flex shrink-0 items-center justify-between gap-2 p-4", v.header),
|
|
58
|
+
children: [
|
|
59
|
+
n && /* @__PURE__ */ A("h2", {
|
|
60
|
+
id: r,
|
|
61
|
+
className: e(u.root, "text-subtitle-1 font-semibold"),
|
|
62
|
+
children: t
|
|
63
|
+
}),
|
|
64
|
+
p ? o(i, "span", e(l.titleAction, "ms-auto flex shrink-0 items-center gap-1")) : null,
|
|
65
|
+
/* @__PURE__ */ A(T, {
|
|
66
|
+
requestOpen: a,
|
|
67
|
+
label: c,
|
|
68
|
+
closeButton: d,
|
|
69
|
+
className: e(!p && "ms-auto", "text-muted-foreground")
|
|
70
|
+
})
|
|
71
|
+
]
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
P.displayName = "DrawerBuiltInHeader";
|
|
75
|
+
function F({ header: t, bodyProps: n, content: r, footers: i }) {
|
|
76
|
+
let [a, o] = k.useState(null), s = y(a), { children: u, className: d, ref: m, ...h } = n ?? {}, g = f(o, m);
|
|
77
|
+
return /* @__PURE__ */ A(C.Provider, {
|
|
78
|
+
value: s,
|
|
79
|
+
children: /* @__PURE__ */ j(x.Provider, {
|
|
80
|
+
value: !1,
|
|
81
|
+
children: [
|
|
82
|
+
/* @__PURE__ */ A(S.Provider, {
|
|
83
|
+
value: "placed",
|
|
84
|
+
children: t
|
|
85
|
+
}),
|
|
86
|
+
/* @__PURE__ */ A("div", {
|
|
87
|
+
"data-scroll-state": s,
|
|
88
|
+
...h,
|
|
89
|
+
ref: g,
|
|
90
|
+
className: e(l.body, n && c.root, "min-h-0 flex-1 overflow-y-auto p-4", p, d),
|
|
91
|
+
children: /* @__PURE__ */ A(S.Provider, {
|
|
92
|
+
value: "content",
|
|
93
|
+
children: r
|
|
94
|
+
})
|
|
95
|
+
}),
|
|
96
|
+
/* @__PURE__ */ A(S.Provider, {
|
|
97
|
+
value: "placed",
|
|
98
|
+
children: i
|
|
99
|
+
})
|
|
100
|
+
]
|
|
101
|
+
})
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
F.displayName = "DrawerLayout";
|
|
105
|
+
var I = ({ open: e, defaultOpen: t, onOpenChange: n, type: r = "overlay", separator: o = !1, position: c = "end", size: u = "small", modalType: p = "modal", backdrop: v, closeButton: y, titleAction: x, title: S, closeLabel: C = "Close", finalFocusRef: w, unmountOnClose: T = !0, children: E, id: D, ref: O, ...M }) => {
|
|
106
|
+
let [I, L] = h(e, t, n), R = re(r, I), z = g(), me = d("wave-drawer"), B = D ?? me, V = d("wave-drawer-title"), H = ee(), [he, ge] = k.useState(null), _e = f(O, ge);
|
|
107
|
+
te(R ? he : null, H.hasTitle, "Drawer", "Drawer.HeaderTitle or a Drawer.Title");
|
|
108
|
+
let { triggers: U, headers: W, bodyProps: ve, bodyCount: ye, content: be, footers: xe } = pe(E), G = W.length > 0, K = s(S), q = K && !G, J = (K || s(x)) && G;
|
|
109
|
+
k.useEffect(() => {
|
|
110
|
+
J && a(le, ue);
|
|
111
|
+
}, [J]);
|
|
112
|
+
let Y = ye > 1;
|
|
113
|
+
k.useEffect(() => {
|
|
114
|
+
Y && a(de, fe);
|
|
115
|
+
}, [Y]);
|
|
116
|
+
let X = k.useRef(!1);
|
|
117
|
+
k.useEffect(() => {
|
|
118
|
+
i && !X.current && N(E) && (X.current = !0, a(ae, ie));
|
|
119
|
+
}, [E]);
|
|
120
|
+
let Z = e === void 0 && !t && U.length === 0, Q = k.useRef({
|
|
121
|
+
unreachable: Z,
|
|
122
|
+
children: E
|
|
123
|
+
});
|
|
124
|
+
k.useLayoutEffect(() => {
|
|
125
|
+
Q.current = {
|
|
126
|
+
unreachable: Z,
|
|
127
|
+
children: E
|
|
128
|
+
};
|
|
129
|
+
}), k.useEffect(() => {
|
|
130
|
+
if (!i || !Q.current.unreachable) return;
|
|
131
|
+
let e = setTimeout(() => {
|
|
132
|
+
let e = Q.current;
|
|
133
|
+
e.unreachable && !N(e.children) && a(oe, se);
|
|
134
|
+
}, ce);
|
|
135
|
+
return () => clearTimeout(e);
|
|
136
|
+
}, []);
|
|
137
|
+
let $ = k.useMemo(() => ({
|
|
138
|
+
open: R,
|
|
139
|
+
requestOpen: L,
|
|
140
|
+
trigger: z,
|
|
141
|
+
panelId: B,
|
|
142
|
+
type: r,
|
|
143
|
+
inPanel: !1,
|
|
144
|
+
closeLabel: C,
|
|
145
|
+
closeButton: y
|
|
146
|
+
}), [
|
|
147
|
+
R,
|
|
148
|
+
L,
|
|
149
|
+
z,
|
|
150
|
+
B,
|
|
151
|
+
r,
|
|
152
|
+
C,
|
|
153
|
+
y
|
|
154
|
+
]), Se = k.useMemo(() => ({
|
|
155
|
+
...$,
|
|
156
|
+
inPanel: !0
|
|
157
|
+
}), [$]), Ce = /* @__PURE__ */ A(b.Provider, {
|
|
158
|
+
value: Se,
|
|
159
|
+
children: /* @__PURE__ */ A(m.Provider, {
|
|
160
|
+
value: H.context,
|
|
161
|
+
children: /* @__PURE__ */ A(F, {
|
|
162
|
+
header: G ? W : /* @__PURE__ */ A(P, {
|
|
163
|
+
title: S,
|
|
164
|
+
hasTitle: q,
|
|
165
|
+
titleId: V,
|
|
166
|
+
titleAction: x,
|
|
167
|
+
requestOpen: L,
|
|
168
|
+
closeLabel: C,
|
|
169
|
+
closeButton: y
|
|
170
|
+
}),
|
|
171
|
+
bodyProps: ve,
|
|
172
|
+
content: be,
|
|
173
|
+
footers: xe
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
}), we = q ? V : H.titleId, Te = /* @__PURE__ */ A(ne, {
|
|
177
|
+
componentName: "Drawer",
|
|
178
|
+
type: r,
|
|
179
|
+
open: R,
|
|
180
|
+
requestOpen: L,
|
|
181
|
+
position: c,
|
|
182
|
+
size: u,
|
|
183
|
+
separator: o,
|
|
184
|
+
modalType: p,
|
|
185
|
+
unmountOnClose: T,
|
|
186
|
+
inlineAs: "aside",
|
|
187
|
+
trigger: z,
|
|
188
|
+
finalFocusRef: w,
|
|
189
|
+
rootClassName: l.root,
|
|
190
|
+
backdropClassName: l.backdrop,
|
|
191
|
+
backdrop: v,
|
|
192
|
+
id: B,
|
|
193
|
+
"aria-labelledby": we,
|
|
194
|
+
...M,
|
|
195
|
+
ref: _e,
|
|
196
|
+
children: Ce
|
|
197
|
+
});
|
|
198
|
+
return _(z, R), /* @__PURE__ */ j(b.Provider, {
|
|
199
|
+
value: $,
|
|
200
|
+
children: [U, Te]
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
I.displayName = "Drawer";
|
|
204
|
+
//#endregion
|
|
205
|
+
export { I as DrawerRoot };
|
|
206
|
+
|
|
207
|
+
//# sourceMappingURL=Drawer.root.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Drawer.root.mjs","names":["useId","useId$1","React","UNREACHABLE_WARNING_KEY","UNREACHABLE_WARNING","REACHABILITY_CHECK_DELAY","NESTED_TRIGGER_MAX_DEPTH","hasNestedTrigger","visit","level","node","item","depth","type","getElementType","DrawerTrigger","isFragment","nested","children","TITLE_IGNORED_WARNING_KEY","TITLE_IGNORED_WARNING","BODY_DUPLICATE_WARNING_KEY","BODY_DUPLICATE_WARNING","splitChildren","partition","flattenChildren","isElementOfType","DrawerBody","key","keyed","DrawerHeader","DrawerFooter","DrawerBuiltInHeader","scrollState","DrawerScrollStateContext","hasTitleAction","slotRendersContent","titleAction","hasTitle","closeButton","cn","drawerClassNames","scrollSeparatorClasses","titleId","drawerTitleClassNames","title","renderSlot","DrawerCloseButton","closeLabel","DrawerLayout","body","setBody","useScrollState","_children","bodyRest","bodyProps","bodyRef","useMergedRefs","ref","DrawerHeaderContext","DrawerPartContext","header","drawerBodyClassNames","focusRingInset","className","content","footers","DrawerRoot","openProp","rest","openState","requestOpen","useModalOpenState","defaultOpen","onOpenChange","open","useDrawerOpen","trigger","useModalTrigger","generatedId","panelId","id","propTitleId","titles","useTitleRegistry","panel","setPanel","panelRef","hasHeader","headers","titleRendersContent","titleIgnored","warnOnce","duplicateBody","bodyCount","nestedWarnedRef","isDev","NESTED_TRIGGER_WARNING_KEY","NESTED_TRIGGER_WARNING","unreachable","triggers","latestRef","timer","latest","context","panelContext","layout","DrawerContext","ModalSurfaceContext","labelledBy","panelElement","DrawerPanel","useModalTriggerSession"],"sources":["../../../src/components/overlays/Drawer.root.tsx"],"sourcesContent":["import * as React from 'react';\nimport { flattenChildren, getElementType, isElementOfType } from '../../lib/children';\nimport { cn } from '../../lib/cn';\nimport {\n drawerBodyClassNames,\n drawerClassNames,\n drawerTitleClassNames,\n} from '../../lib/classNames';\nimport { isDev, warnOnce } from '../../lib/dev';\nimport { renderSlot, slotRendersContent, type Slot, type SlotObject } from '../../lib/slot';\nimport { focusRingInset } from '../../lib/styles';\nimport type { BackdropAppearance } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport {\n ModalSurfaceContext,\n useModalOpenState,\n useModalTrigger,\n useModalTriggerSession,\n useTitleRegistry,\n useUnnamedModalWarning,\n type ModalRequestOpen,\n} from './Dialog.shared';\nimport {\n DrawerContext,\n DrawerHeaderContext,\n DrawerPartContext,\n DrawerScrollStateContext,\n type DrawerContextValue,\n type DrawerModalType,\n type DrawerOpenChangeDetails,\n type DrawerPosition,\n type DrawerSize,\n type DrawerType,\n} from './Drawer.context';\nimport { DrawerPanel, useDrawerOpen } from './Drawer.panel';\nimport {\n DrawerBody,\n DrawerCloseButton,\n DrawerFooter,\n DrawerHeader,\n DrawerTrigger,\n NESTED_TRIGGER_WARNING,\n NESTED_TRIGGER_WARNING_KEY,\n type DrawerBodyProps,\n} from './Drawer.parts';\nimport { scrollSeparatorClasses, useScrollState } from './Drawer.scroll';\n\n/*\n * The Drawer root: its props, the child scan, the layout and the development checks, on the drawer\n * panel shell (`DrawerPanel`), which renders the panel element and its machinery. Imports the\n * parts, panel, scroll and context modules (never `Drawer.tsx`, which holds the compound).\n */\n\n/** Properties for the Drawer component. */\nexport interface DrawerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n /**\n * Controlled open state of the drawer. An overlay drawer's panel renders only in the browser:\n * open, it is closed in the server HTML and opens once it has hydrated. An inline drawer renders\n * in the server HTML: open, or hidden when kept mounted (`unmountOnClose={false}`).\n */\n open?: boolean;\n /**\n * Default open state for uncontrolled usage. An overlay drawer open by default is closed in the\n * server HTML and opens once it has hydrated; an inline one is open in the server HTML.\n * @default false\n */\n defaultOpen?: boolean;\n /**\n * Called with the new open state when it changes. `details.reason` tells how — `trigger`,\n * `close` (a `.Close` part), `close-button` (the built-in Close button), `escape` or\n * `outside-press` (the backdrop) — so a controlled drawer can refuse only some ways of closing\n * (for example keep a form with unsaved changes open on `outside-press`); `details.event` is the\n * DOM event behind the request. WaveUI always passes `details`; it is typed optional until 1.0\n * so that code which calls this prop itself keeps compiling. An inline drawer asks only with\n * `trigger` (its `Drawer.Trigger` toggles it), `close` and `close-button`: Escape and presses\n * outside it never close it.\n *\n * Fires only when the value changes; a controlled drawer stays as it is until the parent updates\n * `open`.\n */\n onOpenChange?: (open: boolean, details?: DrawerOpenChangeDetails) => void;\n /**\n * How the drawer sits on the page (Fluent's `type`).\n * - `overlay`: a panel over the page, rendered in a portal while open: modal by default (focus\n * moves in and stays there, toasts included; the rest of the page is `inert` and does not\n * scroll; Escape and a backdrop press close it), or `modalType=\"non-modal\"`.\n * - `inline`: a panel in the page layout, rendered where the Drawer is (after its direct\n * `Drawer.Trigger`s) as an `<aside>`, a complementary landmark named by its title. The page\n * stays usable around it: no backdrop, no focus trap, no portal, no scroll lock; Escape and\n * presses outside do not close it. Opening it leaves focus where it is; closing it while focus\n * is inside returns focus to `finalFocusRef`, else the element that opened it, else the\n * trigger. `position` and `size` pick its inner edge and its width (its height at the bottom);\n * where it sits is up to your layout (a flex row of panel and content, for example).\n * `modalType` and `backdrop` do not apply to it, and toasts do not move out of its way: it is\n * page content.\n *\n * Changing `type` remounts the panel and its content (what was typed in it is lost); focus\n * inside an overlay that becomes inline returns to the trigger, and focus inside an inline panel\n * that becomes an overlay moves into the overlay. Rendered as `data-type`.\n * @default 'overlay'\n */\n type?: DrawerType;\n /**\n * Inline drawers: draws a line on the panel's inner edge, the edge facing the page content\n * (`data-separator`). An overlay drawer always draws that edge and ignores this prop. In forced\n * colours an inline drawer's inner edge is always drawn. Fluent's `separator`.\n * @default false\n */\n separator?: boolean;\n /**\n * Side of the screen the drawer is attached to. `start`/`end` follow the text direction;\n * `left`/`right` are physical sides; `bottom` runs along the bottom edge (`size` sets its\n * height). An inline drawer takes its place from your layout: `position` picks its inner edge\n * (the one facing the page content: the end edge of a `start` panel, the top edge of a `bottom`\n * one) and the axis `size` sets. Rendered as `data-position`.\n * @default 'end'\n */\n position?: DrawerPosition;\n /**\n * The panel's width at a side — `small` 320px, `medium` 592px, `large` 940px, `full` the\n * viewport's width — or its height at the bottom (the same values; `full` the viewport's height).\n * It never exceeds the viewport. An inline panel takes the same sizes, where `full` is its\n * container's width (height), and never grows past its container. A width class in `className`\n * (a height class for `bottom`) replaces it. Rendered as `data-size`. Fluent's `size`.\n * @default 'small'\n */\n size?: DrawerSize;\n /**\n * `modal`, `alert` or `non-modal`, as Dialog's `modalType`. `modal`: the page behind is `inert`\n * and does not scroll; a backdrop press, Escape, the Close button and `Drawer.Close` close it.\n * `alert`: `role=\"alertdialog\"` (a `role` you pass wins), and a backdrop press does not close it\n * (Escape still does). `non-modal`: no backdrop, and the page stays usable — no focus trap,\n * nothing inert, the page scrolls; Tab and Shift+Tab leave the drawer in the page's order right\n * after the element that opened it, Escape closes it while focus is inside it, presses on the\n * page never close it, and focus returns to the opener only when it was inside the drawer. A\n * non-modal drawer covers the page under it while Tab still reaches that page: reserve its width\n * (its height at the bottom) in your layout while it is open, or use `modal`, or, for a panel\n * beside the content, an inline drawer (`type=\"inline\"`) (with `size=\"full\"` it covers\n * everything, and a development warning says so). Every type moves focus to the first focusable\n * element on open. Rendered as `data-modal-type`. Ignored by an inline drawer, which is never\n * modal and renders no `data-modal-type`. Fluent's `modalType`.\n * @default 'modal'\n */\n modalType?: DrawerModalType;\n /**\n * The backdrop of a modal or alert drawer, as `Dialog.Content`'s `backdrop`: a `div` behind the\n * panel, `aria-hidden`. Shorthand content renders inside it; a slot object's `className` (merged\n * last), `style`, data attributes, `ref` and handlers go to it, and its `appearance`\n * (`'dimmed'` or `'transparent'`) overrides the automatic one: while another modal Dialog or\n * Drawer is open below this one the backdrop is transparent, so the page is dimmed once. `null`\n * renders no backdrop (the page stays inert, and a press outside still closes a modal drawer); a\n * boolean is no slot. Ignored with `modalType=\"non-modal\"` and by an inline drawer (a\n * development warning says so). Fluent's `backdrop`.\n */\n backdrop?: Slot<'div'> | (SlotObject<'div'> & { appearance?: BackdropAppearance });\n /**\n * Content of the built-in Close button, in the built-in header and in every\n * `Drawer.HeaderTitle`, as `Dialog.Content`'s `closeButton`: decorative content inside the button\n * (the dismiss glyph by default), so the button keeps the name `closeLabel`; a slot object's\n * `aria-label`, `aria-labelledby` or `title` names it instead, and its handlers run before the\n * close (`preventDefault()` keeps the drawer open). `null` hides them all (`Drawer.Close`, and\n * Escape on an overlay, still close); a boolean is no slot; content that renders nothing keeps the\n * default glyph. A `<button>` or Wave `Button` passed here is merged into the built-in button,\n * never nested (a development warning says so), and its text label names the button. Fluent's\n * `DrawerHeaderTitle` `action` holds Fluent's close button; WaveUI renders its own.\n */\n closeButton?: Slot<'span'>;\n /**\n * Header buttons for the `title` prop form, between the heading and the built-in Close button in\n * DOM and Tab order. Ignored, with a development warning, next to a `Drawer.Header` (use the\n * `action` of `Drawer.HeaderTitle`). Interactive: name icon-only buttons. Renders nothing when\n * empty. Fluent's `DrawerHeaderTitle` `action`, for the `title` prop form.\n */\n titleAction?: Slot<'span'>;\n /**\n * Title displayed in the built-in header; it names the drawer (`aria-labelledby`). Without it,\n * render a `Drawer.HeaderTitle` (in a `Drawer.Header`) or a `Drawer.Title`, or pass\n * `aria-label`/`aria-labelledby`. A title that renders nothing (`''`, `[]`, `true`) counts as\n * none. Ignored, with a development warning, when the children hold a `Drawer.Header`, which\n * replaces the built-in header. The heading is an `<h2>`; for another level use\n * `Drawer.HeaderTitle` with `headingLevel`. In the server HTML of an inline drawer only `title`\n * (or `aria-label`/`aria-labelledby`) names the panel: a `Drawer.HeaderTitle` or `Drawer.Title`\n * names it once the page has hydrated.\n */\n title?: React.ReactNode;\n /**\n * Accessible name of the built-in Close button (an icon-only button), in the built-in header and\n * in every `Drawer.HeaderTitle`. Localize it with the page's language. A text label of a button\n * merged into `closeButton` names it instead.\n * @default 'Close'\n */\n closeLabel?: string;\n /**\n * Where focus goes when the drawer closes, if it can take focus. Otherwise focus returns to the\n * element that had focus when the drawer opened, then to the trigger, then to an element next to\n * where that opener was. An inline or non-modal drawer moves focus on close only when focus was\n * inside it.\n */\n finalFocusRef?: React.RefObject<HTMLElement | null>;\n /**\n * Removes the panel and its content when the drawer closes. `false` keeps them mounted while\n * closed, `hidden` and `inert` (out of the layout, the Tab order and the accessibility tree), so\n * what was typed and the state of the components inside survive closing and opening again; the\n * content then mounts with the Drawer, closed, and an `autoFocus` inside it never applies (an\n * overlay focuses its first focusable element on each open). An overlay panel still renders only\n * in the browser; a kept inline panel is in the server HTML, hidden. Kept content still belongs\n * to its form: a `required` empty field in a closed inline drawer inside a page `<form>` blocks\n * its submission without a visible message. A popup opened inside that is still open when the\n * drawer closes stays open over the page (a development warning says so): close it first. A\n * `key` on the Drawer resets the kept content. Fluent's `unmountOnClose`.\n * @default true\n */\n unmountOnClose?: boolean;\n /**\n * The drawer's content, placed by the Drawer, also from a Fragment (`{isMobile && <>…</>}`) and\n * when written in a Server Component: `Drawer.Trigger` children render in place (outside the\n * panel); a `Drawer.Header` replaces the built-in header (the `title` and Close button row); a\n * `Drawer.Body` gives the scrolling body its props; `Drawer.Footer` renders below the scrolling\n * body, outside it, wherever it is written among the children; everything else renders in the\n * scrolling body. A part nested in another element (a `<form>`) or rendered by a component of\n * yours renders where it is, in the body (a development warning says so). A `Drawer.Trigger`\n * nested in another element, or rendered by a component, is panel content, so it is not rendered\n * (or, kept mounted, is hidden) while the drawer is closed (development warnings say so, also\n * when an uncontrolled drawer still has no direct trigger a second after it mounts and therefore\n * cannot open; a controlled drawer whose trigger a component such as a Tooltip wraps warns only\n * once it renders in the panel).\n * Put wrappers inside the trigger instead: see `Drawer.Trigger`.\n */\n children: React.ReactNode;\n /**\n * Ref to the panel: the `role=\"dialog\"` element of an overlay drawer (`alertdialog` with\n * `modalType=\"alert\"`), the `<aside>` of an inline one. A ref to a `div` still type-checks.\n */\n ref?: React.Ref<HTMLElement>;\n}\n\nconst UNREACHABLE_WARNING_KEY = 'Drawer:unreachable';\nconst UNREACHABLE_WARNING =\n 'Drawer has no way to open: a second after mounting it is still uncontrolled (no `open` prop), closed, and has no Drawer.Trigger as a direct child (or in a Fragment there). A Drawer.Trigger rendered by a component or nested in an element is panel content, which is not rendered or is hidden while the drawer is closed. Make the trigger a direct child of Drawer, or control the Drawer with `open`/`onOpenChange`.';\n\n/**\n * How long after mount (ms) the development check for a drawer without a trigger waits: long\n * enough for a trigger that a conditional Fragment renders once the page knows its layout.\n */\nconst REACHABILITY_CHECK_DELAY = 1000;\n\n/** Deepest element level the development check for nested triggers looks at. */\nconst NESTED_TRIGGER_MAX_DEPTH = 32;\n\n/**\n * Development check: whether the Drawer's children hold a `Drawer.Trigger` inside a host element\n * (at any depth, also through Fragments), which would become panel content; a trigger inside\n * Fragments only is direct (see `splitChildren`). Walks the element tree the consumer wrote, not\n * rendered output, so it descends only into host elements (`<div>`, `<span>`, …) and Fragments,\n * which render their `children` as written. A component's\n * output is unknown here — a wrapper that renders its own Drawer around its children, for one —\n * so components are not walked; a trigger rendered by a component is caught when it renders in the\n * open panel, or, while the drawer cannot open, by the unreachable-drawer check.\n */\nfunction hasNestedTrigger(children: React.ReactNode): boolean {\n // `depth` counts host elements only: a Fragment adds no level, as `splitChildren` flattens it.\n const visit = (node: unknown, depth: number, level: number): boolean => {\n if (level > NESTED_TRIGGER_MAX_DEPTH || typeof node !== 'object' || node === null) return false;\n if (Array.isArray(node)) return node.some((item) => visit(item, depth, level));\n if (!React.isValidElement(node)) return false;\n // A part written in a Server Component has a lazy type. The walk runs in effects, outside\n // render: a lazy part that is still loading must not throw its thenable there, so it counts\n // as no trigger (`suspend: false` returns the lazy itself, which matches nothing).\n const type = getElementType(node, { suspend: false });\n if (type === DrawerTrigger) return depth > 0;\n const isFragment = type === React.Fragment;\n if (typeof type !== 'string' && !isFragment) return false;\n const { children: nested } = node.props as { children?: unknown };\n return visit(nested, isFragment ? depth : depth + 1, level + 1);\n };\n return visit(children, 0, 0);\n}\n\nconst TITLE_IGNORED_WARNING_KEY = 'Drawer:title-ignored';\nconst TITLE_IGNORED_WARNING =\n 'Drawer: `title` and `titleAction` are ignored because a Drawer.Header is among the children. Put a Drawer.HeaderTitle (with its `action`) in the header instead.';\n\nconst BODY_DUPLICATE_WARNING_KEY = 'Drawer.Body:duplicate';\nconst BODY_DUPLICATE_WARNING =\n 'Drawer has more than one Drawer.Body: the props of the first one apply to the scrolling body, and the children of every one render in their place. Render one Drawer.Body.';\n\n/** How the Drawer sorts its direct children ({@link splitChildren}). */\ninterface DrawerPartition {\n /** The direct `Drawer.Trigger` elements, rendered in place. */\n triggers: React.ReactNode[];\n /** The direct `Drawer.Header` elements, rendered in the header area in written order. */\n headers: React.ReactNode[];\n /** The props of the first direct `Drawer.Body` (its `children` render in `content`). */\n bodyProps: DrawerBodyProps | undefined;\n /** How many direct `Drawer.Body` elements there are. */\n bodyCount: number;\n /** The body content in written order; a `Drawer.Body` is replaced by its children. */\n content: React.ReactNode[];\n /** The direct `Drawer.Footer` elements, rendered after the body in written order. */\n footers: React.ReactNode[];\n}\n\n/**\n * Sorts the Drawer's children: its direct `Drawer.Trigger`, `Drawer.Header`, `Drawer.Body` and\n * `Drawer.Footer` elements and the body content. Fragments are flattened (recursively), so a part\n * in a Fragment — `{isMobile && <><Drawer.Trigger>…</Drawer.Trigger><Filters /></>}` — counts as a\n * direct child. Every element keeps the key `flattenChildren` gives it: unique across Fragments and\n * stable when a sibling Fragment toggles, so body content keeps its state when a part appears. A\n * part is recognised also when it was written in a Server Component (a lazy type). Runs during\n * render, so the placement is the same on the server.\n */\nfunction splitChildren(children: React.ReactNode): DrawerPartition {\n const partition: DrawerPartition = {\n triggers: [],\n headers: [],\n bodyProps: undefined,\n bodyCount: 0,\n content: [],\n footers: [],\n };\n for (const { key, node } of flattenChildren(children)) {\n if (isElementOfType<DrawerBodyProps>(node, DrawerBody)) {\n // The first Body's props go on the scrolling body; every Body's children render in place.\n partition.bodyCount += 1;\n if (partition.bodyCount === 1) partition.bodyProps = node.props;\n partition.content.push(<React.Fragment key={key}>{node.props.children}</React.Fragment>);\n continue;\n }\n const keyed = React.isValidElement(node) ? React.cloneElement(node, { key }) : node;\n if (isElementOfType(node, DrawerTrigger)) partition.triggers.push(keyed);\n else if (isElementOfType(node, DrawerHeader)) partition.headers.push(keyed);\n else if (isElementOfType(node, DrawerFooter)) partition.footers.push(keyed);\n else partition.content.push(keyed);\n }\n return partition;\n}\n\n/** Properties of the built-in header ({@link DrawerBuiltInHeader}). */\ninterface DrawerBuiltInHeaderProps {\n /** The `title` prop, when it renders content. */\n title: React.ReactNode;\n /** Whether `title` renders content (else no heading renders). */\n hasTitle: boolean;\n /** The heading's id (the panel's `aria-labelledby`). */\n titleId: string;\n /** The `titleAction` slot. */\n titleAction: Slot<'span'> | undefined;\n requestOpen: ModalRequestOpen;\n closeLabel: string;\n /** The `closeButton` slot (`null`: no Close button). */\n closeButton: Slot<'span'> | undefined;\n}\n\n/**\n * The 0.10 header row of the `title` form (no `Drawer.Header` among the children): the `title`\n * heading, the `titleAction` content and the Close button as its direct children. The title action\n * takes the free room (`ms-auto`), so the Close button follows it through the row's gap; without\n * one the Close button does. It reads the body's scroll state for its separator. A row with\n * nothing in it (no title, no title action, `closeButton={null}`) renders no element.\n */\nfunction DrawerBuiltInHeader({\n title,\n hasTitle,\n titleId,\n titleAction,\n requestOpen,\n closeLabel,\n closeButton,\n}: DrawerBuiltInHeaderProps) {\n const scrollState = React.useContext(DrawerScrollStateContext) ?? 'none';\n const hasTitleAction = slotRendersContent(titleAction);\n if (!hasTitle && !hasTitleAction && closeButton === null) return null;\n return (\n <div\n data-scroll-state={scrollState}\n className={cn(\n drawerClassNames.header,\n 'flex shrink-0 items-center justify-between gap-2 p-4',\n scrollSeparatorClasses.header,\n )}\n >\n {hasTitle && (\n <h2\n id={titleId}\n className={cn(drawerTitleClassNames.root, 'text-subtitle-1 font-semibold')}\n >\n {title}\n </h2>\n )}\n {hasTitleAction\n ? renderSlot(\n titleAction,\n 'span',\n cn(drawerClassNames.titleAction, 'ms-auto flex shrink-0 items-center gap-1'),\n )\n : null}\n <DrawerCloseButton\n requestOpen={requestOpen}\n label={closeLabel}\n closeButton={closeButton}\n className={cn(!hasTitleAction && 'ms-auto', 'text-muted-foreground')}\n />\n </div>\n );\n}\nDrawerBuiltInHeader.displayName = 'DrawerBuiltInHeader';\n\n/** Properties of {@link DrawerLayout}. */\ninterface DrawerLayoutProps {\n /** The header area: the built-in header, or the placed `Drawer.Header` elements. */\n header: React.ReactNode;\n /** The props of the placed `Drawer.Body`, put on the scrolling body. */\n bodyProps: DrawerBodyProps | undefined;\n /** The body content. */\n content: React.ReactNode;\n /** The placed `Drawer.Footer` elements. */\n footers: React.ReactNode;\n}\n\n/**\n * The panel's layout (internal): the header area, the scrolling body and the footers. It owns the\n * body's scroll state (`useScrollState`), so a change of the state re-renders this component, the\n * body element and the parts that read the state (the header area and the footers), never the\n * consumer's content: the elements it receives as props are the same objects, so React skips them.\n */\nfunction DrawerLayout({ header, bodyProps, content, footers }: DrawerLayoutProps) {\n const [body, setBody] = React.useState<HTMLDivElement | null>(null);\n const scrollState = useScrollState(body);\n const { children: _children, className, ref, ...bodyRest } = bodyProps ?? {};\n const bodyRef = useMergedRefs<HTMLDivElement>(setBody, ref);\n return (\n <DrawerScrollStateContext.Provider value={scrollState}>\n <DrawerHeaderContext.Provider value={false}>\n <DrawerPartContext.Provider value=\"placed\">{header}</DrawerPartContext.Provider>\n <div\n data-scroll-state={scrollState}\n {...bodyRest}\n ref={bodyRef}\n className={cn(\n drawerClassNames.body,\n bodyProps && drawerBodyClassNames.root,\n 'min-h-0 flex-1 overflow-y-auto p-4',\n focusRingInset,\n className,\n )}\n >\n <DrawerPartContext.Provider value=\"content\">{content}</DrawerPartContext.Provider>\n </div>\n <DrawerPartContext.Provider value=\"placed\">{footers}</DrawerPartContext.Provider>\n </DrawerHeaderContext.Provider>\n </DrawerScrollStateContext.Provider>\n );\n}\nDrawerLayout.displayName = 'DrawerLayout';\n\n// The root of `Drawer` (documented on the export in Drawer.tsx).\nexport const DrawerRoot = ({\n open: openProp,\n defaultOpen,\n onOpenChange,\n type = 'overlay',\n separator = false,\n position = 'end',\n size = 'small',\n modalType = 'modal',\n backdrop,\n closeButton,\n titleAction,\n title,\n closeLabel = 'Close',\n finalFocusRef,\n unmountOnClose = true,\n children,\n id,\n ref,\n ...rest\n}: DrawerProps) => {\n const [openState, requestOpen] = useModalOpenState(openProp, defaultOpen, onOpenChange);\n // An overlay's panel lives in a portal, which renders only in the browser: until then (the\n // server HTML, hydration) it reports itself closed, so the trigger's aria-expanded and\n // aria-controls never describe a panel that is not there. An inline panel renders in place, also\n // on the server (D107).\n const open = useDrawerOpen(type, openState);\n const trigger = useModalTrigger();\n const generatedId = useId('wave-drawer');\n const panelId = id ?? generatedId;\n const propTitleId = useId('wave-drawer-title');\n const titles = useTitleRegistry();\n // The mounted panel (the shell's element of either type), for the unnamed-drawer check.\n const [panel, setPanel] = React.useState<HTMLElement | null>(null);\n const panelRef = useMergedRefs<HTMLElement>(ref, setPanel);\n useUnnamedModalWarning(\n open ? panel : null,\n titles.hasTitle,\n 'Drawer',\n 'Drawer.HeaderTitle or a Drawer.Title',\n );\n\n const { triggers, headers, bodyProps, bodyCount, content, footers } = splitChildren(children);\n const hasHeader = headers.length > 0;\n // A Drawer.Header replaces the built-in header, whose `title` it cannot show.\n const titleRendersContent = slotRendersContent(title);\n const hasTitle = titleRendersContent && !hasHeader;\n const titleIgnored = (titleRendersContent || slotRendersContent(titleAction)) && hasHeader;\n React.useEffect(() => {\n if (titleIgnored) warnOnce(TITLE_IGNORED_WARNING_KEY, TITLE_IGNORED_WARNING);\n }, [titleIgnored]);\n const duplicateBody = bodyCount > 1;\n React.useEffect(() => {\n if (duplicateBody) warnOnce(BODY_DUPLICATE_WARNING_KEY, BODY_DUPLICATE_WARNING);\n }, [duplicateBody]);\n\n // A trigger nested in the children is panel content: not rendered (or, kept mounted, hidden) while\n // the drawer is closed.\n // The children change on every parent render; once this drawer has warned, it stops walking.\n const nestedWarnedRef = React.useRef(false);\n React.useEffect(() => {\n if (!isDev || nestedWarnedRef.current || !hasNestedTrigger(children)) return;\n nestedWarnedRef.current = true;\n warnOnce(NESTED_TRIGGER_WARNING_KEY, NESTED_TRIGGER_WARNING);\n }, [children]);\n\n // An uncontrolled closed drawer without a direct trigger cannot open (e.g.\n // `<Drawer><FilterTrigger /></Drawer>`, whose trigger is panel content). Checked once, a moment\n // after mount, against the latest render: a trigger that a conditional Fragment adds right after\n // mount (`{isMobile && <>…</>}` with an SSR-safe media query) counts. A trigger nested in an\n // element already has the more specific warning above.\n const unreachable = openProp === undefined && !defaultOpen && triggers.length === 0;\n const latestRef = React.useRef({ unreachable, children });\n React.useLayoutEffect(() => {\n latestRef.current = { unreachable, children };\n });\n React.useEffect(() => {\n if (!isDev || !latestRef.current.unreachable) return;\n const timer = setTimeout(() => {\n const latest = latestRef.current;\n if (latest.unreachable && !hasNestedTrigger(latest.children)) {\n warnOnce(UNREACHABLE_WARNING_KEY, UNREACHABLE_WARNING);\n }\n }, REACHABILITY_CHECK_DELAY);\n return () => clearTimeout(timer);\n }, []);\n\n const context = React.useMemo<DrawerContextValue>(\n () => ({ open, requestOpen, trigger, panelId, type, inPanel: false, closeLabel, closeButton }),\n [open, requestOpen, trigger, panelId, type, closeLabel, closeButton],\n );\n const panelContext = React.useMemo<DrawerContextValue>(\n () => ({ ...context, inPanel: true }),\n [context],\n );\n\n // The panel's content: the header area, the scrolling body and the footers, for both types.\n const layout = (\n <DrawerContext.Provider value={panelContext}>\n <ModalSurfaceContext.Provider value={titles.context}>\n <DrawerLayout\n header={\n hasHeader ? (\n headers\n ) : (\n <DrawerBuiltInHeader\n title={title}\n hasTitle={hasTitle}\n titleId={propTitleId}\n titleAction={titleAction}\n requestOpen={requestOpen}\n closeLabel={closeLabel}\n closeButton={closeButton}\n />\n )\n }\n bodyProps={bodyProps}\n content={content}\n footers={footers}\n />\n </ModalSurfaceContext.Provider>\n </DrawerContext.Provider>\n );\n const labelledBy = hasTitle ? propTitleId : titles.titleId;\n\n // The panel and its machinery (portal, backdrop, presence, layer, trap, restore, Tab order) come\n // from the shell (D108); the root names it and fills it with its layout.\n const panelElement = (\n <DrawerPanel\n componentName=\"Drawer\"\n type={type}\n open={open}\n requestOpen={requestOpen}\n position={position}\n size={size}\n separator={separator}\n modalType={modalType}\n unmountOnClose={unmountOnClose}\n inlineAs=\"aside\"\n trigger={trigger}\n finalFocusRef={finalFocusRef}\n rootClassName={drawerClassNames.root}\n backdropClassName={drawerClassNames.backdrop}\n backdrop={backdrop}\n id={panelId}\n aria-labelledby={labelledBy}\n {...rest}\n ref={panelRef}\n >\n {layout}\n </DrawerPanel>\n );\n // After the shell's focus restores (its effects run before the root's), start the trigger\n // session, or end it and forget the trigger that opened it.\n useModalTriggerSession(trigger, open);\n\n return (\n <DrawerContext.Provider value={context}>\n {triggers}\n {panelElement}\n </DrawerContext.Provider>\n );\n};\nDrawerRoot.displayName = 'Drawer';\n"],"mappings":"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"}
|