@mortenbrudvik/waveui 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +758 -152
- 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/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 +213 -181
- package/dist/components/feedback/Toaster.mjs.map +1 -1
- package/dist/components/input/Calendar.cjs +2 -0
- package/dist/components/input/Calendar.cjs.map +1 -0
- package/dist/components/input/Calendar.mjs +352 -0
- package/dist/components/input/Calendar.mjs.map +1 -0
- package/dist/components/input/Calendar.views.cjs +2 -0
- package/dist/components/input/Calendar.views.cjs.map +1 -0
- package/dist/components/input/Calendar.views.mjs +194 -0
- package/dist/components/input/Calendar.views.mjs.map +1 -0
- package/dist/components/input/ColorArea.cjs +1 -1
- package/dist/components/input/ColorArea.cjs.map +1 -1
- package/dist/components/input/ColorArea.mjs +18 -18
- package/dist/components/input/ColorArea.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 +232 -156
- package/dist/components/input/Combobox.mjs.map +1 -1
- package/dist/components/input/Combobox.text.cjs +2 -0
- package/dist/components/input/Combobox.text.cjs.map +1 -0
- package/dist/components/input/Combobox.text.mjs +24 -0
- package/dist/components/input/Combobox.text.mjs.map +1 -0
- package/dist/components/input/DatePicker.cjs +1 -1
- package/dist/components/input/DatePicker.cjs.map +1 -1
- package/dist/components/input/DatePicker.mjs +203 -288
- 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 +135 -109
- package/dist/components/input/Dropdown.mjs.map +1 -1
- package/dist/components/input/Listbox.cjs +2 -0
- package/dist/components/input/Listbox.cjs.map +1 -0
- package/dist/components/input/Listbox.mjs +134 -0
- package/dist/components/input/Listbox.mjs.map +1 -0
- package/dist/components/input/Option.cjs +1 -1
- package/dist/components/input/Option.cjs.map +1 -1
- package/dist/components/input/Option.mjs +163 -97
- package/dist/components/input/Option.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.cjs +1 -1
- package/dist/components/input/SwatchPicker.cjs.map +1 -1
- package/dist/components/input/SwatchPicker.context.cjs +2 -0
- package/dist/components/input/SwatchPicker.context.cjs.map +1 -0
- package/dist/components/input/SwatchPicker.context.mjs +35 -0
- package/dist/components/input/SwatchPicker.context.mjs.map +1 -0
- package/dist/components/input/SwatchPicker.mjs +131 -103
- package/dist/components/input/SwatchPicker.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.swatches.cjs +2 -0
- package/dist/components/input/SwatchPicker.swatches.cjs.map +1 -0
- package/dist/components/input/SwatchPicker.swatches.mjs +207 -0
- package/dist/components/input/SwatchPicker.swatches.mjs.map +1 -0
- 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 -274
- 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 +416 -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 +77 -77
- package/dist/components/input/TimePicker.mjs.map +1 -1
- package/dist/components/input/dateUtils.cjs +1 -1
- package/dist/components/input/dateUtils.cjs.map +1 -1
- package/dist/components/input/dateUtils.mjs +114 -96
- package/dist/components/input/dateUtils.mjs.map +1 -1
- package/dist/components/input/pickerLabels.cjs +2 -0
- package/dist/components/input/pickerLabels.cjs.map +1 -0
- package/dist/components/input/pickerLabels.mjs +16 -0
- package/dist/components/input/pickerLabels.mjs.map +1 -0
- package/dist/components/input/pickerValues.cjs +2 -0
- package/dist/components/input/pickerValues.cjs.map +1 -0
- package/dist/components/input/pickerValues.mjs +24 -0
- package/dist/components/input/pickerValues.mjs.map +1 -0
- 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/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 +190 -125
- 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/table/useGridNavigation.cjs +1 -1
- package/dist/components/table/useGridNavigation.cjs.map +1 -1
- package/dist/components/table/useGridNavigation.mjs +67 -70
- package/dist/components/table/useGridNavigation.mjs.map +1 -1
- package/dist/hooks/useActiveDescendant.cjs +2 -0
- package/dist/hooks/useActiveDescendant.cjs.map +1 -0
- package/dist/hooks/useActiveDescendant.mjs +56 -0
- package/dist/hooks/useActiveDescendant.mjs.map +1 -0
- 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/useListbox.cjs +1 -1
- package/dist/hooks/useListbox.cjs.map +1 -1
- package/dist/hooks/useListbox.mjs +250 -210
- package/dist/hooks/useListbox.mjs.map +1 -1
- package/dist/hooks/useModalLayer.cjs +1 -1
- package/dist/hooks/useModalLayer.cjs.map +1 -1
- package/dist/hooks/useModalLayer.mjs +35 -22
- package/dist/hooks/useModalLayer.mjs.map +1 -1
- 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 +2 -0
- package/dist/hooks/useRovingGrid.cjs.map +1 -0
- package/dist/hooks/useRovingGrid.mjs +69 -0
- package/dist/hooks/useRovingGrid.mjs.map +1 -0
- package/dist/hooks/useRovingTabIndex.cjs +1 -1
- package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.mjs +102 -78
- package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4391 -394
- package/dist/index.d.ts +4391 -394
- package/dist/index.mjs +115 -101
- package/dist/lib/classNames.cjs +1 -1
- package/dist/lib/classNames.cjs.map +1 -1
- package/dist/lib/classNames.mjs +170 -74
- package/dist/lib/classNames.mjs.map +1 -1
- package/dist/lib/date.cjs +2 -0
- package/dist/lib/date.cjs.map +1 -0
- package/dist/lib/date.mjs +44 -0
- package/dist/lib/date.mjs.map +1 -0
- package/dist/lib/focus.cjs +1 -1
- package/dist/lib/focus.cjs.map +1 -1
- package/dist/lib/focus.mjs +5 -2
- package/dist/lib/focus.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 +53 -47
- package/dist/lib/layers.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/styles/tokens.css +25 -0
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { useControllable as
|
|
4
|
-
import { useId as
|
|
5
|
-
import { focusElement as
|
|
6
|
-
import { useMergedRefs as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
2
|
+
import { isDev as e, reportMissingContext as t, warnOnce as n } from "../../lib/dev.mjs";
|
|
3
|
+
import { useControllable as r } from "../../hooks/useControllable.mjs";
|
|
4
|
+
import { useId as i } from "../../hooks/useId.mjs";
|
|
5
|
+
import { focusElement as a } from "../../lib/focus.mjs";
|
|
6
|
+
import { useMergedRefs as o } from "../../hooks/useMergedRefs.mjs";
|
|
7
|
+
import { getOpenLayers as s, isDescendantLayer as c } from "../../lib/layers.mjs";
|
|
8
|
+
import { mergeProps as l } from "../../lib/mergeProps.mjs";
|
|
9
|
+
import { STATE_ARIA as u } from "../../lib/renderTrigger.mjs";
|
|
10
|
+
import { getTriggerFocusTarget as d, useTriggerElement as f } from "../../hooks/useTriggerElement.mjs";
|
|
11
|
+
import * as p from "react";
|
|
11
12
|
//#region src/components/overlays/Dialog.shared.tsx
|
|
12
|
-
function
|
|
13
|
-
let i =
|
|
14
|
-
return [a,
|
|
13
|
+
function m(e, t, n) {
|
|
14
|
+
let i = p.useRef(void 0), [a, o] = r(e, t ?? !1, (e) => n?.(e, i.current));
|
|
15
|
+
return [a, p.useCallback((e, t) => {
|
|
15
16
|
i.current = t;
|
|
16
17
|
try {
|
|
17
18
|
o(e);
|
|
@@ -20,8 +21,8 @@ function d(e, t, r) {
|
|
|
20
21
|
}
|
|
21
22
|
}, [o])];
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
-
return
|
|
24
|
+
function h(e, t, r) {
|
|
25
|
+
return p.useCallback((i, a) => {
|
|
25
26
|
switch (i) {
|
|
26
27
|
case "escape":
|
|
27
28
|
e(!1, {
|
|
@@ -36,59 +37,67 @@ function f(e, n, r) {
|
|
|
36
37
|
}), r?.();
|
|
37
38
|
break;
|
|
38
39
|
case "focus-outside":
|
|
39
|
-
|
|
40
|
+
n(`${t}:focus-outside`, `${t} ignored a focus-outside dismissal: a modal surface does not close when focus leaves it.`);
|
|
40
41
|
break;
|
|
41
42
|
default: return i;
|
|
42
43
|
}
|
|
43
44
|
}, [
|
|
44
45
|
e,
|
|
45
|
-
|
|
46
|
+
t,
|
|
46
47
|
r
|
|
47
48
|
]);
|
|
48
49
|
}
|
|
49
|
-
function
|
|
50
|
-
let n =
|
|
50
|
+
function g(e, t) {
|
|
51
|
+
let n = p.useRef(null);
|
|
51
52
|
return {
|
|
52
|
-
onMouseDown:
|
|
53
|
-
if (r.
|
|
53
|
+
onMouseDown: p.useCallback((r) => {
|
|
54
|
+
if (!r.currentTarget.contains(r.target)) return;
|
|
54
55
|
if (!t) {
|
|
55
56
|
r.preventDefault();
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
|
-
let i =
|
|
59
|
+
let i = C();
|
|
59
60
|
n.current = i && e.current?.contains(i) ? i : null;
|
|
60
61
|
}, [t, e]),
|
|
61
|
-
afterOutsidePress:
|
|
62
|
+
afterOutsidePress: p.useCallback(() => {
|
|
62
63
|
let t = n.current;
|
|
63
64
|
n.current = null, t && queueMicrotask(() => {
|
|
64
|
-
|
|
65
|
+
C() === null && e.current?.contains(t) && a(t, { preventScroll: !0 });
|
|
65
66
|
});
|
|
66
67
|
}, [e])
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
|
-
function
|
|
70
|
+
function _(e) {
|
|
70
71
|
return typeof e == "object" && !!e && typeof e.type == "string" && typeof e.stopPropagation == "function" && !("nativeEvent" in e);
|
|
71
72
|
}
|
|
72
|
-
function
|
|
73
|
+
function v(e) {
|
|
73
74
|
let t = typeof e == "object" && e ? e.nativeEvent : void 0;
|
|
74
|
-
return
|
|
75
|
+
return _(t) ? t : _(e) ? e : new Event("click");
|
|
75
76
|
}
|
|
76
|
-
var
|
|
77
|
+
var y = {
|
|
77
78
|
attach: () => void 0,
|
|
78
79
|
activate: () => {},
|
|
79
80
|
startSession: () => {},
|
|
80
81
|
endSession: () => {},
|
|
81
82
|
focusRef: { current: null }
|
|
82
83
|
};
|
|
83
|
-
function
|
|
84
|
+
function b(e) {
|
|
84
85
|
return typeof e == "object" && !!e && e.nodeType === 1;
|
|
85
86
|
}
|
|
86
|
-
function
|
|
87
|
+
function x(e) {
|
|
88
|
+
if (typeof e != "object" || !e) return !1;
|
|
89
|
+
let { currentTarget: t, target: n } = e;
|
|
90
|
+
return !S(t) || !S(n) ? !1 : !t.contains(n);
|
|
91
|
+
}
|
|
92
|
+
function S(e) {
|
|
93
|
+
return typeof e == "object" && !!e && typeof e.nodeType == "number" && typeof e.contains == "function";
|
|
94
|
+
}
|
|
95
|
+
function C() {
|
|
87
96
|
if (typeof document > "u") return null;
|
|
88
97
|
let e = document.activeElement;
|
|
89
98
|
return !e || e === document.body || e === document.documentElement ? null : e.isConnected ? e : null;
|
|
90
99
|
}
|
|
91
|
-
function
|
|
100
|
+
function w() {
|
|
92
101
|
let e = /* @__PURE__ */ new Set(), t = null, n = !1;
|
|
93
102
|
return {
|
|
94
103
|
attach: (n) => {
|
|
@@ -97,7 +106,7 @@ function y() {
|
|
|
97
106
|
};
|
|
98
107
|
},
|
|
99
108
|
activate: (e) => {
|
|
100
|
-
|
|
109
|
+
b(e) && (t = e, !n && setTimeout(() => {
|
|
101
110
|
!n && t === e && (t = null);
|
|
102
111
|
}, 0));
|
|
103
112
|
},
|
|
@@ -108,23 +117,23 @@ function y() {
|
|
|
108
117
|
n = !1, t = null;
|
|
109
118
|
},
|
|
110
119
|
focusRef: { get current() {
|
|
111
|
-
let n =
|
|
112
|
-
if (n) return e.has(n) ?
|
|
113
|
-
if (t?.isConnected) return
|
|
120
|
+
let n = C();
|
|
121
|
+
if (n) return e.has(n) ? d(n) : null;
|
|
122
|
+
if (t?.isConnected) return d(t);
|
|
114
123
|
for (let t of e) {
|
|
115
124
|
if (!t.isConnected) continue;
|
|
116
|
-
let e =
|
|
125
|
+
let e = d(t);
|
|
117
126
|
if (e) return e;
|
|
118
127
|
}
|
|
119
128
|
return null;
|
|
120
129
|
} }
|
|
121
130
|
};
|
|
122
131
|
}
|
|
123
|
-
function
|
|
124
|
-
let [e] =
|
|
132
|
+
function T() {
|
|
133
|
+
let [e] = p.useState(w);
|
|
125
134
|
return e;
|
|
126
135
|
}
|
|
127
|
-
function
|
|
136
|
+
function E(e) {
|
|
128
137
|
let t = null;
|
|
129
138
|
return {
|
|
130
139
|
attach: (n) => {
|
|
@@ -141,54 +150,121 @@ function x(e) {
|
|
|
141
150
|
}
|
|
142
151
|
};
|
|
143
152
|
}
|
|
144
|
-
function
|
|
145
|
-
return
|
|
153
|
+
function D(e) {
|
|
154
|
+
return p.useMemo(() => E(e), [e]);
|
|
146
155
|
}
|
|
147
|
-
function
|
|
148
|
-
let { open:
|
|
149
|
-
_(e),
|
|
156
|
+
function O(e, { children: t, asChild: n, ref: r, ...i }, a) {
|
|
157
|
+
let { open: s, requestOpen: c, trigger: d, controlsId: m, popup: h = "dialog" } = e, { attach: g, activate: _ } = D(d), y = o(g, r), b = p.useCallback((e) => {
|
|
158
|
+
x(e) || (s || _(e), c(!s, {
|
|
150
159
|
reason: "trigger",
|
|
151
|
-
event:
|
|
152
|
-
});
|
|
153
|
-
}, [
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
event: v(e)
|
|
161
|
+
}));
|
|
162
|
+
}, [
|
|
163
|
+
s,
|
|
164
|
+
_,
|
|
165
|
+
c
|
|
166
|
+
]), S = {
|
|
167
|
+
...h !== !1 && { "aria-haspopup": h },
|
|
168
|
+
"aria-expanded": s,
|
|
169
|
+
"aria-controls": s ? m : void 0
|
|
170
|
+
}, C = l({
|
|
171
|
+
...S,
|
|
172
|
+
onClick: b,
|
|
173
|
+
ref: y
|
|
174
|
+
}, i, { oursWin: u });
|
|
175
|
+
return f(t, C, {
|
|
176
|
+
componentName: a,
|
|
162
177
|
asChild: n
|
|
163
178
|
});
|
|
164
179
|
}
|
|
165
|
-
function
|
|
166
|
-
let
|
|
180
|
+
function k(e, { children: t, asChild: n, ref: r, ...i }, a) {
|
|
181
|
+
let s = o(r), c = p.useCallback((t) => e(!1, {
|
|
167
182
|
reason: "close",
|
|
168
|
-
event:
|
|
169
|
-
}), [e]),
|
|
170
|
-
onClick:
|
|
171
|
-
ref:
|
|
183
|
+
event: v(t)
|
|
184
|
+
}), [e]), u = l({
|
|
185
|
+
onClick: c,
|
|
186
|
+
ref: s
|
|
172
187
|
}, i);
|
|
173
|
-
return
|
|
174
|
-
componentName:
|
|
188
|
+
return f(t, u, {
|
|
189
|
+
componentName: a,
|
|
175
190
|
asChild: n
|
|
176
191
|
});
|
|
177
192
|
}
|
|
178
|
-
function
|
|
179
|
-
|
|
193
|
+
function A() {
|
|
194
|
+
let e = null;
|
|
195
|
+
return {
|
|
196
|
+
set: (t) => {
|
|
197
|
+
e = t;
|
|
198
|
+
},
|
|
199
|
+
ref: { get current() {
|
|
200
|
+
return e?.isConnected ? e : null;
|
|
201
|
+
} }
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function j(e, t, n) {
|
|
205
|
+
let [r] = p.useState(A), i = p.useRef(!1);
|
|
206
|
+
return p.useInsertionEffect(() => {
|
|
207
|
+
let a = i.current;
|
|
208
|
+
if (i.current = e, e === a) return;
|
|
209
|
+
if (!e) {
|
|
210
|
+
r.set(null);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
let o = t.focusRef.current;
|
|
214
|
+
if (o) {
|
|
215
|
+
r.set(o);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
let s = C();
|
|
219
|
+
r.set(s && !n?.contains(s) ? s : null);
|
|
220
|
+
}), r.ref;
|
|
221
|
+
}
|
|
222
|
+
function M(e, t) {
|
|
223
|
+
p.useLayoutEffect(() => {
|
|
180
224
|
t ? e.startSession() : e.endSession();
|
|
181
225
|
}, [e, t]);
|
|
182
226
|
}
|
|
183
|
-
function
|
|
184
|
-
let
|
|
185
|
-
|
|
227
|
+
function N(e, t, n) {
|
|
228
|
+
let r = p.useRef(!1);
|
|
229
|
+
p.useLayoutEffect(() => {
|
|
230
|
+
let i = r.current;
|
|
231
|
+
if (r.current = e, !e || i || !t) return;
|
|
232
|
+
let a = n.current, o = a?.parentElement;
|
|
233
|
+
a && o && o.lastElementChild !== a && o.appendChild(a);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
function P(t, r, i, a, o) {
|
|
237
|
+
let l = p.useRef(t);
|
|
238
|
+
p.useEffect(() => {
|
|
239
|
+
let u = l.current;
|
|
240
|
+
if (l.current = t, !e || t || !u || !r) return;
|
|
241
|
+
let d = setTimeout(() => {
|
|
242
|
+
let e = o?.current ?? null;
|
|
243
|
+
s().some((t) => {
|
|
244
|
+
if (t.kind === "tooltip") return !1;
|
|
245
|
+
if (c(t.id, i)) return !0;
|
|
246
|
+
let n = t.getAnchor();
|
|
247
|
+
return !!e && !!n && e.contains(n);
|
|
248
|
+
}) && n(`${a}:open-inside`, `${a} closed while a popup opened inside it is still open. With \`unmountOnClose={false}\` the popup stays open over the page: close it first, or keep the default \`unmountOnClose\`.`);
|
|
249
|
+
}, 0);
|
|
250
|
+
return () => clearTimeout(d);
|
|
251
|
+
}, [
|
|
252
|
+
t,
|
|
253
|
+
r,
|
|
254
|
+
i,
|
|
255
|
+
a,
|
|
256
|
+
o
|
|
257
|
+
]);
|
|
258
|
+
}
|
|
259
|
+
function F(e, n, r, i) {
|
|
260
|
+
let a = p.useContext(e);
|
|
261
|
+
return a === null ? (t(n, r), i()) : a;
|
|
186
262
|
}
|
|
187
|
-
var
|
|
188
|
-
|
|
189
|
-
var
|
|
190
|
-
function
|
|
191
|
-
let [e, t] =
|
|
263
|
+
var I = p.createContext(null);
|
|
264
|
+
I.displayName = "ModalSurfaceContext";
|
|
265
|
+
var L = { registerTitle: () => () => {} };
|
|
266
|
+
function R() {
|
|
267
|
+
let [e, t] = p.useState([]), n = p.useRef(0), r = p.useCallback((e) => {
|
|
192
268
|
n.current += 1, t((t) => [...t, e]);
|
|
193
269
|
let r = !0;
|
|
194
270
|
return () => {
|
|
@@ -197,31 +273,31 @@ function k() {
|
|
|
197
273
|
return n === -1 ? t : [...t.slice(0, n), ...t.slice(n + 1)];
|
|
198
274
|
}));
|
|
199
275
|
};
|
|
200
|
-
}, []), i =
|
|
276
|
+
}, []), i = p.useCallback(() => n.current > 0, []), a = p.useMemo(() => ({ registerTitle: r }), [r]);
|
|
201
277
|
return {
|
|
202
278
|
titleId: e[0],
|
|
203
279
|
hasTitle: i,
|
|
204
280
|
context: a
|
|
205
281
|
};
|
|
206
282
|
}
|
|
207
|
-
function
|
|
208
|
-
let { registerTitle:
|
|
283
|
+
function z(e, t, n, r) {
|
|
284
|
+
let { registerTitle: a } = F(I, e, t, () => L), s = i("wave-modal-title"), c = n ?? s, l = p.useCallback((e) => e ? a(c) : void 0, [a, c]);
|
|
209
285
|
return {
|
|
210
286
|
id: c,
|
|
211
|
-
ref:
|
|
287
|
+
ref: o(r, l)
|
|
212
288
|
};
|
|
213
289
|
}
|
|
214
|
-
function
|
|
215
|
-
|
|
216
|
-
e && (e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby") ||
|
|
290
|
+
function B(e, t, r, i) {
|
|
291
|
+
p.useEffect(() => {
|
|
292
|
+
e && (e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby") || t() || n(`${r}:unnamed`, `${r} has no accessible name. Pass \`title\`, render a ${i} inside it, or give it \`aria-label\` or \`aria-labelledby\`.`));
|
|
217
293
|
}, [
|
|
218
294
|
e,
|
|
219
|
-
|
|
295
|
+
t,
|
|
220
296
|
r,
|
|
221
297
|
i
|
|
222
298
|
]);
|
|
223
299
|
}
|
|
224
300
|
//#endregion
|
|
225
|
-
export {
|
|
301
|
+
export { I as ModalSurfaceContext, v as getNativeEvent, y as inertModalTrigger, g as useBackdropPress, k as useModalClosePart, h as useModalDismiss, m as useModalOpenState, j as useModalOpener, z as useModalTitle, T as useModalTrigger, O as useModalTriggerPart, M as useModalTriggerSession, P as useOpenInsideWarning, N as useRaiseOnOpen, F as useRequiredContext, R as useTitleRegistry, B as useUnnamedModalWarning };
|
|
226
302
|
|
|
227
303
|
//# sourceMappingURL=Dialog.shared.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.shared.mjs","names":["unmapped","useId","useId$1","React","useModalOpenState","detailsRef","value","setOpen","useControllable","open","defaultOpen","onOpenChange","next","details","useModalDismiss","reason","requestOpen","afterOutsidePress","componentName","useBackdropPress","pressFocusRef","event","closesOnPress","focused","getFocusedElement","surfaceRef","element","focusElement","isDomEvent","getNativeEvent","native","inertModalTrigger","isElementTarget","target","active","createModalTrigger","attached","activated","sessionOpen","getTriggerFocusTarget","useModalTrigger","trigger","createModalTriggerElement","node","detach","currentTarget","useModalTriggerElement","useModalTriggerPart","rest","modal","mergedRef","useMergedRefs","attach","ref","openModal","activate","triggerProps","mergeProps","controlsId","STATE_ARIA","useTriggerElement","children","useModalClosePart","close","closeProps","useModalTriggerSession","useRequiredContext","context","reportMissingContext","parentName","getInert","ModalSurfaceContext","inertSurface","useTitleRegistry","ids","setIds","countRef","registerTitle","current","id","registered","index","hasTitle","useModalTitle","generatedId","idProp","register","useUnnamedModalWarning","surface","warnOnce","titleName"],"sources":["../../../src/components/overlays/Dialog.shared.tsx"],"sourcesContent":["import * as React from 'react';\nimport { reportMissingContext, warnOnce } from '../../lib/dev';\nimport { focusElement } from '../../lib/focus';\nimport type { DismissReason } from '../../lib/layers';\nimport { mergeProps } from '../../lib/mergeProps';\nimport { STATE_ARIA } from '../../lib/renderTrigger';\nimport type { ModalOpenChangeReason, OpenChangeDetails } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { getTriggerFocusTarget, useTriggerElement } from '../../hooks/useTriggerElement';\n\n/*\n * Internal helpers shared by Dialog and Drawer (P15). Not exported from the package.\n */\n\n/** Why a modal root asks to open or close, and the event (`DialogOpenChangeDetails`). */\nexport type ModalOpenChangeDetails = OpenChangeDetails<ModalOpenChangeReason>;\n\n/** Asks a modal root to open or close; see {@link useModalOpenState}. */\nexport type ModalRequestOpen = (open: boolean, details: ModalOpenChangeDetails) => void;\n\n/**\n * The open state of a modal root (`Dialog`, `Drawer`): `useControllable`, plus the details of the\n * request behind each change. Every internal path asks through `requestOpen(next, details)`, which\n * writes `details` to a ref, calls the setter and clears the ref once the setter returns.\n * `useControllable` calls its `onChange` synchronously inside the setter, only when the value\n * changes, and that `onChange` passes the ref's details on as `onOpenChange(next, details)`.\n * Clearing the ref afterwards means a change that no request caused can never report a stale\n * reason.\n */\nexport function useModalOpenState(\n open: boolean | undefined,\n defaultOpen: boolean | undefined,\n onOpenChange: ((open: boolean, details?: ModalOpenChangeDetails) => void) | undefined,\n): [open: boolean, requestOpen: ModalRequestOpen] {\n const detailsRef = React.useRef<ModalOpenChangeDetails | undefined>(undefined);\n const [value, setOpen] = useControllable(open, defaultOpen ?? false, (next: boolean) =>\n onOpenChange?.(next, detailsRef.current),\n );\n const requestOpen = React.useCallback<ModalRequestOpen>(\n (next, details) => {\n detailsRef.current = details;\n try {\n setOpen(next);\n } finally {\n detailsRef.current = undefined;\n }\n },\n [setOpen],\n );\n return [value, requestOpen];\n}\n\n/**\n * The `onDismiss` of a modal root's layer (`useModalLayer`): Escape and a backdrop press ask the\n * root to close, with their reason and event. `focus-outside` never reaches a modal layer (only a\n * layer registered with `focusOutside: true` gets it), so it is ignored with a development warning.\n *\n * @param requestOpen The root's request function, from {@link useModalOpenState}.\n * @param componentName The public name for the warning, e.g. `'Dialog'`.\n * @param afterOutsidePress Called right after an `outside-press` request (see\n * {@link useBackdropPress}).\n */\nexport function useModalDismiss(\n requestOpen: ModalRequestOpen,\n componentName: string,\n afterOutsidePress?: () => void,\n): (reason: DismissReason, event: Event) => void {\n return React.useCallback(\n (reason: DismissReason, event: Event) => {\n switch (reason) {\n case 'escape':\n requestOpen(false, { reason, event });\n break;\n case 'outside-press':\n requestOpen(false, { reason, event });\n afterOutsidePress?.();\n break;\n case 'focus-outside':\n warnOnce(\n `${componentName}:focus-outside`,\n `${componentName} ignored a focus-outside dismissal: a modal surface does not close when focus leaves it.`,\n );\n break;\n default: {\n // Exhaustive: a new DismissReason does not compile here until it is mapped.\n const unmapped: never = reason;\n return unmapped;\n }\n }\n },\n [requestOpen, componentName, afterOutsidePress],\n );\n}\n\n/** Returned by {@link useBackdropPress}. */\nexport interface BackdropPress {\n /** `onMouseDown` of the backdrop element. Stable while `closesOnPress` stays the same. */\n onMouseDown: (event: React.MouseEvent<HTMLElement>) => void;\n /** Pass it to {@link useModalDismiss}, which calls it after an `outside-press` request. Stable. */\n afterOutsidePress: () => void;\n}\n\n/**\n * What a press on a modal's backdrop does to focus (`Dialog.Content`, the Drawer panel). Presses\n * that start inside the surface bubble through unchanged.\n *\n * - When the press closes the modal (`closesOnPress`), the browser moves focus to `<body>` as\n * usual, so the focused control blurs while it is still mounted and its blur-time commit runs\n * (the typed text of a SpinButton or a picker, a consumer's `onBlur` autosave or validation)\n * before the click closes the surface. The element inside the surface that had focus is\n * remembered: when the surface is still open after the `outside-press` request (a controlled\n * modal refused it), it gets focus back, in a microtask that runs after React has committed the\n * request, and only while focus is still on `<body>` (a confirm dialog the refusal opened keeps\n * its focus).\n * - When the press never closes the modal (an alert dialog), the press does not move focus at all\n * (`preventDefault()`), so nothing blurs.\n *\n * @param surfaceRef The surface element (the dialog or the drawer panel).\n * @param closesOnPress Whether a backdrop press asks the modal to close (its layer's `outsidePress`).\n */\nexport function useBackdropPress(\n surfaceRef: React.RefObject<HTMLElement | null>,\n closesOnPress: boolean,\n): BackdropPress {\n // The element inside the surface that had focus when the last backdrop press started.\n const pressFocusRef = React.useRef<HTMLElement | null>(null);\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n if (event.target !== event.currentTarget) return;\n if (!closesOnPress) {\n event.preventDefault();\n return;\n }\n const focused = getFocusedElement();\n pressFocusRef.current = focused && surfaceRef.current?.contains(focused) ? focused : null;\n },\n [closesOnPress, surfaceRef],\n );\n\n const afterOutsidePress = React.useCallback(() => {\n const element = pressFocusRef.current;\n pressFocusRef.current = null;\n if (!element) return;\n // A close requested from the click is committed first (React flushes the update in a\n // microtask queued before this one), so a closed surface no longer contains the element.\n queueMicrotask(() => {\n if (getFocusedElement() !== null || !surfaceRef.current?.contains(element)) return;\n focusElement(element, { preventScroll: true });\n });\n }, [surfaceRef]);\n\n return { onMouseDown, afterOutsidePress };\n}\n\n/** Whether `value` is a DOM event (duck-typed, so an event from another window counts too). */\nfunction isDomEvent(value: unknown): value is Event {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<Event>).type === 'string' &&\n typeof (value as Partial<Event>).stopPropagation === 'function' &&\n !('nativeEvent' in value)\n );\n}\n\n/**\n * The DOM event behind a part's click handler call: a React event's `nativeEvent`, or a DOM event\n * passed as is. A render-prop child that calls the handler without its event (or with another\n * value) gets a new `click` event, so `details.event` is always an event.\n */\nexport function getNativeEvent(value: unknown): Event {\n const native =\n typeof value === 'object' && value !== null\n ? (value as { nativeEvent?: unknown }).nativeEvent\n : undefined;\n if (isDomEvent(native)) return native;\n if (isDomEvent(value)) return value;\n return new Event('click');\n}\n\n/** Returned by {@link useModalTrigger}. */\nexport interface ModalTrigger {\n /**\n * Callback ref for the element a trigger renders: the consumer's child, or the wrapper `<span>`\n * of `asChild={false}` and of the automatic fallback for a child that does not forward its ref.\n * Every trigger of the root attaches it (a root may have several). It returns a React 19 cleanup\n * that forgets that one element, so a trigger that unmounts never unregisters another. Stable.\n */\n attach: React.RefCallback<HTMLElement>;\n /**\n * Records the trigger that is opening the modal, for the open session that follows (anything that\n * is not an element is ignored). Focus returns to that trigger, not to another one of the same\n * root. Triggers call it through {@link useModalTriggerPart}.\n *\n * An activation the modal did not open for by the end of the task (a click that the parent of a\n * controlled modal rejected) is dropped, so it does not decide where focus returns after a later\n * open that no trigger started. React commits an accepted open within the same task.\n */\n activate: (target: unknown) => void;\n /**\n * Starts the open session: the activated trigger belongs to it until {@link endSession}.\n * {@link useModalTriggerSession} calls it when the modal opens.\n */\n startSession: () => void;\n /**\n * Ends the open session: forgets the activated trigger, so it does not decide where focus\n * returns after a later open that no trigger started. {@link useModalTriggerSession} calls it\n * when the modal closes.\n */\n endSession: () => void;\n /**\n * The focus-restore target, for the modal layer's `triggerRef`. Its `current` is resolved when it\n * is read (when the modal opens, and again on close if the opener captured then cannot take\n * focus any more):\n *\n * 1. `null` while an element other than `<body>` has focus: that element opened the modal (the\n * clicked trigger, the button inside a trigger's wrapper span, or the parent's own button of\n * a controlled modal), and the restore captures it. A trigger element itself with focus (a\n * `tabIndex={-1}` wrapper span that a press focused, as Safari does for a click on the button\n * inside it) resolves like any trigger instead.\n * 2. Otherwise (Safari does not focus a clicked button; a modal opened from code), the trigger\n * activated in this open session while it is still in the document.\n * 3. Otherwise the first mounted trigger that can take focus.\n *\n * A trigger resolves with `getTriggerFocusTarget`, the rule of every trigger's focus return: the\n * element that carries the state ARIA (the button inside a wrapper span, the span when you made\n * it the trigger), else the first tabbable element inside it, else itself when it can take\n * focus, else `null`. Read-only.\n */\n focusRef: React.RefObject<HTMLElement | null>;\n}\n\n/** A trigger for components rendered outside their root (C-CONTEXT inert fallback). */\nexport const inertModalTrigger: ModalTrigger = {\n attach: () => undefined,\n activate: () => {},\n startSession: () => {},\n endSession: () => {},\n focusRef: { current: null },\n};\n\nfunction isElementTarget(target: unknown): target is HTMLElement {\n return typeof target === 'object' && target !== null && (target as Partial<Node>).nodeType === 1;\n}\n\n/** The element that has focus, or `null` when focus is on `<body>` (or nowhere). */\nfunction getFocusedElement(): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n const active = document.activeElement;\n if (!active || active === document.body || active === document.documentElement) return null;\n return active.isConnected ? (active as HTMLElement) : null;\n}\n\nfunction createModalTrigger(): ModalTrigger {\n // Every mounted trigger element, in the order they attached.\n const attached = new Set<HTMLElement>();\n // The trigger clicked in the current open session (or in the task that is opening it);\n // forgotten when the modal closes, when the element detaches, or when no open followed the click.\n let activated: HTMLElement | null = null;\n // Whether an open session is running (between startSession and endSession).\n let sessionOpen = false;\n return {\n attach: (element) => {\n // Detaching runs the cleanup below (React 19 and useMergedRefs call it instead of passing\n // `null`), which knows which element leaves.\n if (!element) return undefined;\n attached.add(element);\n return () => {\n attached.delete(element);\n if (activated === element) activated = null;\n };\n },\n activate: (target) => {\n if (!isElementTarget(target)) return;\n activated = target;\n if (sessionOpen) return;\n // An accepted open commits before the next task starts; a rejected click leaves the modal\n // closed, and its activation must not outlive the task.\n setTimeout(() => {\n if (!sessionOpen && activated === target) activated = null;\n }, 0);\n },\n startSession: () => {\n sessionOpen = true;\n },\n endSession: () => {\n sessionOpen = false;\n activated = null;\n },\n focusRef: {\n get current() {\n // A focused element is the opener: the restore captures it (see ModalTrigger.focusRef),\n // unless it is a trigger element, which resolves like any trigger.\n const focused = getFocusedElement();\n if (focused) return attached.has(focused) ? getTriggerFocusTarget(focused) : null;\n // The trigger that opened the modal decides, also when it cannot take focus any more.\n if (activated?.isConnected) return getTriggerFocusTarget(activated);\n for (const element of attached) {\n if (!element.isConnected) continue;\n const target = getTriggerFocusTarget(element);\n if (target) return target;\n }\n return null;\n },\n },\n };\n}\n\n/**\n * The triggers of a modal root (`Dialog`, `Drawer`), overlays#9. Each `Dialog.Trigger`/\n * `Drawer.Trigger` attaches its element and activates it from its click handler through\n * {@link useModalTriggerPart}; the root passes `focusRef` to `useModalLayer` as its\n * `triggerRef` and scopes the activation to one open session with {@link useModalTriggerSession}.\n * Focus returns to the element that had focus when the modal opened; when nothing had focus, to\n * the trigger that opened it, else to the first mounted trigger. For a wrapper `<span>`, the\n * restore target is the element inside it that carries the state ARIA. Resolving when the ref is\n * read, not when it attaches, keeps a trigger that was disabled at mount (or whose content\n * changed) a valid target.\n */\nexport function useModalTrigger(): ModalTrigger {\n const [trigger] = React.useState(createModalTrigger);\n return trigger;\n}\n\n/** Returned by {@link useModalTriggerElement}. */\ninterface ModalTriggerElement {\n /**\n * Callback ref for the element one trigger renders (merge it with the consumer's ref): registers\n * it with the root's triggers and remembers it for `activate`. Stable.\n */\n attach: React.RefCallback<HTMLElement>;\n /**\n * Records this trigger as the one opening the modal: call it from the click handler, before\n * opening, with whatever the handler received. The element `attach` received wins, else the\n * event's `currentTarget`, so a render-prop child that calls `onClick()` without the event (or\n * with another value) is still recorded. Stable.\n */\n activate: (event?: unknown) => void;\n}\n\nfunction createModalTriggerElement(trigger: ModalTrigger): ModalTriggerElement {\n // The element this trigger rendered; a closure variable, not a React ref, so the click handler\n // that reads it can be passed around during render (C-HOOKS).\n let element: HTMLElement | null = null;\n return {\n attach: (node) => {\n if (!node) return undefined;\n element = node;\n const detach = trigger.attach(node);\n return () => {\n if (element === node) element = null;\n if (typeof detach === 'function') detach();\n };\n },\n activate: (event) => {\n const currentTarget =\n typeof event === 'object' && event !== null\n ? (event as { currentTarget?: unknown }).currentTarget\n : undefined;\n trigger.activate(element ?? currentTarget);\n },\n };\n}\n\n/**\n * One `Dialog.Trigger`/`Drawer.Trigger` of a modal root (overlays#9): attach `attach` to the\n * element the trigger renders and call `activate` from its click handler.\n */\nfunction useModalTriggerElement(trigger: ModalTrigger): ModalTriggerElement {\n return React.useMemo(() => createModalTriggerElement(trigger), [trigger]);\n}\n\n/** The props of a trigger or close part (`Dialog.Trigger`, `Drawer.Close`, …). */\nexport interface ModalPartProps<RenderProps> extends Omit<\n React.HTMLAttributes<HTMLElement>,\n 'children'\n> {\n /** A single element that receives the part's props, or a function that receives them. */\n children: React.ReactNode | ((props: RenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` carrying the click handler. */\n asChild?: boolean;\n /** Ref to the element the part renders. */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** What {@link useModalTriggerPart} reads from the modal root. */\nexport interface ModalTriggerState {\n open: boolean;\n /** Asks the root to open (reason `trigger`). */\n requestOpen: ModalRequestOpen;\n trigger: ModalTrigger;\n /** The surface's id for `aria-controls` while the modal is open. */\n controlsId: string | undefined;\n}\n\n/**\n * Renders a `Dialog.Trigger`/`Drawer.Trigger`: its element gets `aria-haspopup=\"dialog\"`,\n * `aria-expanded`, `aria-controls` (while open; these always win over the child's own), a click\n * handler that records the trigger (for the focus return) and asks the root to open (reason\n * `trigger`, with the click event), and a ref that registers it with the root's triggers. On a\n * wrapper span (`asChild={false}`, the automatic fallback), the state ARIA goes to the first\n * element in the tab order inside it (`useTriggerElement`).\n *\n * @param modal The root's state, from its context.\n * @param props The part's props.\n * @param componentName The public name for development warnings, e.g. `'Dialog.Trigger'`.\n */\nexport function useModalTriggerPart<RenderProps>(\n modal: ModalTriggerState,\n { children, asChild, ref, ...rest }: ModalPartProps<RenderProps>,\n componentName: string,\n): React.ReactNode {\n const { open, requestOpen, trigger, controlsId } = modal;\n const { attach, activate } = useModalTriggerElement(trigger);\n const mergedRef = useMergedRefs<HTMLElement>(attach, ref);\n const openModal = React.useCallback(\n (event?: React.MouseEvent<HTMLElement>) => {\n // Focus returns to this trigger, also when the root has several (overlays#9), and also when\n // a render-prop child calls `onClick()` without the event.\n activate(event);\n requestOpen(true, { reason: 'trigger', event: getNativeEvent(event) });\n },\n [activate, requestOpen],\n );\n\n const stateAria = {\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': open,\n 'aria-controls': open ? controlsId : undefined,\n };\n const triggerProps = mergeProps({ ...stateAria, onClick: openModal, ref: mergedRef }, rest, {\n oursWin: STATE_ARIA,\n });\n\n return useTriggerElement(children, triggerProps as RenderProps, { componentName, asChild });\n}\n\n/**\n * Renders a `Dialog.Close`/`Drawer.Close`: composes a click handler that asks the root to close\n * (reason `close`, with the click event) onto its element (the child's own `onClick` runs first;\n * `preventDefault()` there keeps the modal open).\n *\n * @param requestOpen The root's request function, from its context.\n * @param props The part's props.\n * @param componentName The public name for development warnings, e.g. `'Dialog.Close'`.\n */\nexport function useModalClosePart<RenderProps>(\n requestOpen: ModalRequestOpen,\n { children, asChild, ref, ...rest }: ModalPartProps<RenderProps>,\n componentName: string,\n): React.ReactNode {\n const mergedRef = useMergedRefs<HTMLElement>(ref);\n const close = React.useCallback(\n (event?: React.MouseEvent<HTMLElement>) =>\n requestOpen(false, { reason: 'close', event: getNativeEvent(event) }),\n [requestOpen],\n );\n const closeProps = mergeProps({ onClick: close, ref: mergedRef }, rest);\n return useTriggerElement(children, closeProps as RenderProps, { componentName, asChild });\n}\n\n/**\n * Scopes a trigger's activation to one open session (overlays#9): when the modal opens, the\n * activated trigger joins the session; when it closes, the trigger is forgotten, so a later open\n * that no trigger started (a controlled modal opened by the parent) does not return focus to it.\n *\n * It updates the session in a layout effect, after the modal's focus restore has used the\n * activation: call it in the root component (whose effects run after its children's) and, when\n * that component also calls `useModalLayer`, after that call (a component's effects run in order).\n */\nexport function useModalTriggerSession(trigger: ModalTrigger, open: boolean): void {\n React.useLayoutEffect(() => {\n if (open) trigger.startSession();\n else trigger.endSession();\n }, [trigger, open]);\n}\n\n/**\n * C-CONTEXT: reads a compound component's context. Outside its root it throws\n * `[WaveUI] <componentName> must be used within <parentName>` in development, and in production\n * logs the same message once per page (`reportMissingContext`) and returns the inert value from\n * `getInert`.\n */\nexport function useRequiredContext<T>(\n context: React.Context<T | null>,\n componentName: string,\n parentName: string,\n getInert: () => T,\n): T {\n const value = React.useContext(context);\n if (value !== null) return value;\n reportMissingContext(componentName, parentName);\n return getInert();\n}\n\n/** What a modal surface (`Dialog.Content`, the Drawer panel) provides to its descendants. */\nexport interface ModalSurfaceContextValue {\n /**\n * Registers the id of a title element (`Dialog.Title`, `Drawer.Title`) for the surface's\n * `aria-labelledby`. Returns the unregister function.\n */\n registerTitle: (id: string) => () => void;\n /**\n * Receives the measured border-box height of the surface's sticky footer (`Dialog.Footer`) in\n * px, or `null` once it unmounts; the surface reserves it as the scroll padding of its body.\n * Absent on a surface without a footer part (the Drawer panel).\n */\n setFooterHeight?: (px: number | null) => void;\n}\n\n/**\n * Provided by every modal surface; `null` outside one. Titles register with it, and\n * `Dialog.Footer` reads it to report its height and to warn when it is rendered outside\n * `Dialog.Content`.\n */\nexport const ModalSurfaceContext = React.createContext<ModalSurfaceContextValue | null>(null);\nModalSurfaceContext.displayName = 'ModalSurfaceContext';\n\nconst inertSurface: ModalSurfaceContextValue = { registerTitle: () => () => {} };\n\n/** Returned by {@link useTitleRegistry}. */\nexport interface TitleRegistry {\n /** The id of the first registered title, for `aria-labelledby`. */\n titleId: string | undefined;\n /** Whether a title is registered right now. Read it in effects and handlers, not during render. */\n hasTitle: () => boolean;\n /** The memoised value for `ModalSurfaceContext.Provider`. */\n context: ModalSurfaceContextValue;\n}\n\n/**\n * The title registry of a modal surface. A title registers its id from its ref callback (when its\n * element attaches), so the surface's `aria-labelledby` follows the title elements that are\n * actually rendered.\n */\nexport function useTitleRegistry(): TitleRegistry {\n const [ids, setIds] = React.useState<readonly string[]>([]);\n const countRef = React.useRef(0);\n\n const registerTitle = React.useCallback((id: string) => {\n countRef.current += 1;\n setIds((current) => [...current, id]);\n let registered = true;\n return () => {\n if (!registered) return;\n registered = false;\n countRef.current -= 1;\n setIds((current) => {\n const index = current.indexOf(id);\n return index === -1 ? current : [...current.slice(0, index), ...current.slice(index + 1)];\n });\n };\n }, []);\n\n const hasTitle = React.useCallback(() => countRef.current > 0, []);\n const context = React.useMemo(() => ({ registerTitle }), [registerTitle]);\n return { titleId: ids[0], hasTitle, context };\n}\n\n/**\n * The `id` and `ref` of a title sub-component (`Dialog.Title`, `Drawer.Title`): the consumer's\n * `id` (or a generated one), registered with the enclosing surface while the element is mounted.\n */\nexport function useModalTitle(\n componentName: string,\n parentName: string,\n idProp: string | undefined,\n ref: React.Ref<HTMLHeadingElement> | undefined,\n): { id: string; ref: React.RefCallback<HTMLHeadingElement> } {\n const { registerTitle } = useRequiredContext(\n ModalSurfaceContext,\n componentName,\n parentName,\n () => inertSurface,\n );\n const generatedId = useId('wave-modal-title');\n const id = idProp ?? generatedId;\n const register = React.useCallback(\n (node: HTMLHeadingElement | null) => (node ? registerTitle(id) : undefined),\n [registerTitle, id],\n );\n const mergedRef = useMergedRefs<HTMLHeadingElement>(ref, register);\n return { id, ref: mergedRef };\n}\n\n/**\n * Development warning (once per component) when an open modal surface has no accessible name:\n * no `title`, no registered title element, no `aria-label` and no `aria-labelledby`.\n *\n * @param surface The open surface element (`null` while closed).\n * @param hasTitle From {@link useTitleRegistry}.\n * @param componentName The public name, e.g. `'Dialog.Content'`.\n * @param titleName The title sub-component to recommend, e.g. `'Dialog.Title'`.\n */\nexport function useUnnamedModalWarning(\n surface: HTMLElement | null,\n hasTitle: () => boolean,\n componentName: string,\n titleName: string,\n): void {\n React.useEffect(() => {\n if (!surface) return;\n if (\n surface.hasAttribute('aria-label') ||\n surface.hasAttribute('aria-labelledby') ||\n hasTitle()\n ) {\n return;\n }\n warnOnce(\n `${componentName}:unnamed`,\n `${componentName} has no accessible name. Pass \\`title\\`, render a ${titleName} inside it, or give it \\`aria-label\\` or \\`aria-labelledby\\`.`,\n );\n }, [surface, hasTitle, componentName, titleName]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Dialog.shared.mjs","names":["unmapped","useId","useId$1","React","useModalOpenState","detailsRef","value","setOpen","useControllable","open","defaultOpen","onOpenChange","next","details","useModalDismiss","reason","requestOpen","afterOutsidePress","componentName","useBackdropPress","pressFocusRef","event","closesOnPress","focused","getFocusedElement","surfaceRef","element","focusElement","isDomEvent","getNativeEvent","native","inertModalTrigger","isElementTarget","target","isPortaledClick","isNode","currentTarget","active","createModalTrigger","attached","activated","sessionOpen","getTriggerFocusTarget","useModalTrigger","trigger","createModalTriggerElement","node","detach","useModalTriggerElement","useModalTriggerPart","rest","modal","mergedRef","useMergedRefs","attach","ref","toggleModal","activate","stateAria","popup","controlsId","triggerProps","mergeProps","STATE_ARIA","useTriggerElement","children","useModalClosePart","close","closeProps","createModalOpener","useModalOpener","opener","enabledRef","wasEnabled","enabled","fromTrigger","surface","useModalTriggerSession","useRaiseOnOpen","wasOpenRef","wasOpen","keptMounted","wrapper","wrapperRef","container","useOpenInsideWarning","isDev","timer","getOpenLayers","layer","isDescendantLayer","layerId","anchor","warnOnce","useRequiredContext","context","reportMissingContext","parentName","getInert","ModalSurfaceContext","inertSurface","useTitleRegistry","ids","setIds","countRef","registerTitle","current","id","registered","index","hasTitle","useModalTitle","generatedId","idProp","register","useUnnamedModalWarning","titleName"],"sources":["../../../src/components/overlays/Dialog.shared.tsx"],"sourcesContent":["import * as React from 'react';\nimport { isDev, reportMissingContext, warnOnce } from '../../lib/dev';\nimport { focusElement } from '../../lib/focus';\nimport { getOpenLayers, isDescendantLayer, type DismissReason } from '../../lib/layers';\nimport { mergeProps } from '../../lib/mergeProps';\nimport { STATE_ARIA } from '../../lib/renderTrigger';\nimport type { ModalOpenChangeReason, OpenChangeDetails } from '../../lib/types';\nimport { useControllable } from '../../hooks/useControllable';\nimport { useId } from '../../hooks/useId';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { getTriggerFocusTarget, useTriggerElement } from '../../hooks/useTriggerElement';\n\n/*\n * Internal helpers shared by Dialog and Drawer (P15). Not exported from the package.\n */\n\n/** Why a modal root asks to open or close, and the event (`DialogOpenChangeDetails`). */\nexport type ModalOpenChangeDetails = OpenChangeDetails<ModalOpenChangeReason>;\n\n/** Asks a modal root to open or close; see {@link useModalOpenState}. */\nexport type ModalRequestOpen = (open: boolean, details: ModalOpenChangeDetails) => void;\n\n/**\n * The open state of a modal root (`Dialog`, `Drawer`): `useControllable`, plus the details of the\n * request behind each change. Every internal path asks through `requestOpen(next, details)`, which\n * writes `details` to a ref, calls the setter and clears the ref once the setter returns.\n * `useControllable` calls its `onChange` synchronously inside the setter, only when the value\n * changes, and that `onChange` passes the ref's details on as `onOpenChange(next, details)`.\n * Clearing the ref afterwards means a change that no request caused can never report a stale\n * reason.\n */\nexport function useModalOpenState(\n open: boolean | undefined,\n defaultOpen: boolean | undefined,\n onOpenChange: ((open: boolean, details?: ModalOpenChangeDetails) => void) | undefined,\n): [open: boolean, requestOpen: ModalRequestOpen] {\n const detailsRef = React.useRef<ModalOpenChangeDetails | undefined>(undefined);\n const [value, setOpen] = useControllable(open, defaultOpen ?? false, (next: boolean) =>\n onOpenChange?.(next, detailsRef.current),\n );\n const requestOpen = React.useCallback<ModalRequestOpen>(\n (next, details) => {\n detailsRef.current = details;\n try {\n setOpen(next);\n } finally {\n detailsRef.current = undefined;\n }\n },\n [setOpen],\n );\n return [value, requestOpen];\n}\n\n/**\n * The `onDismiss` of a modal root's layer (`useModalLayer`): Escape and a backdrop press ask the\n * root to close, with their reason and event. `focus-outside` never reaches a modal layer (only a\n * layer registered with `focusOutside: true` gets it), so it is ignored with a development warning.\n *\n * @param requestOpen The root's request function, from {@link useModalOpenState}.\n * @param componentName The public name for the warning, e.g. `'Dialog'`.\n * @param afterOutsidePress Called right after an `outside-press` request (see\n * {@link useBackdropPress}).\n */\nexport function useModalDismiss(\n requestOpen: ModalRequestOpen,\n componentName: string,\n afterOutsidePress?: () => void,\n): (reason: DismissReason, event: Event) => void {\n return React.useCallback(\n (reason: DismissReason, event: Event) => {\n switch (reason) {\n case 'escape':\n requestOpen(false, { reason, event });\n break;\n case 'outside-press':\n requestOpen(false, { reason, event });\n afterOutsidePress?.();\n break;\n case 'focus-outside':\n warnOnce(\n `${componentName}:focus-outside`,\n `${componentName} ignored a focus-outside dismissal: a modal surface does not close when focus leaves it.`,\n );\n break;\n default: {\n // Exhaustive: a new DismissReason does not compile here until it is mapped.\n const unmapped: never = reason;\n return unmapped;\n }\n }\n },\n [requestOpen, componentName, afterOutsidePress],\n );\n}\n\n/** Returned by {@link useBackdropPress}. */\nexport interface BackdropPress {\n /** `onMouseDown` of the backdrop element. Stable while `closesOnPress` stays the same. */\n onMouseDown: (event: React.MouseEvent<HTMLElement>) => void;\n /** Pass it to {@link useModalDismiss}, which calls it after an `outside-press` request. Stable. */\n afterOutsidePress: () => void;\n}\n\n/**\n * What a press on a modal's backdrop does to focus (`Dialog.Content`, the Drawer panel). The\n * backdrop is the surface's sibling, so every mouse press on it, its content included, is a\n * backdrop press (a press that a portal opened from the backdrop's content bubbles through the\n * React tree is not).\n *\n * - When the press closes the modal (`closesOnPress`), the browser moves focus to `<body>` as\n * usual, so the focused control blurs while it is still mounted and its blur-time commit runs\n * (the typed text of a SpinButton or a picker, a consumer's `onBlur` autosave or validation)\n * before the click closes the surface. The element inside the surface that had focus is\n * remembered: when the surface is still open after the `outside-press` request (a controlled\n * modal refused it), it gets focus back, in a microtask that runs after React has committed the\n * request, and only while focus is still on `<body>` (a confirm dialog the refusal opened keeps\n * its focus).\n * - When the press never closes the modal (an alert dialog), the press does not move focus at all\n * (`preventDefault()`), so nothing blurs.\n *\n * @param surfaceRef The surface element (the dialog or the drawer panel).\n * @param closesOnPress Whether a backdrop press asks the modal to close (its layer's `outsidePress`).\n */\nexport function useBackdropPress(\n surfaceRef: React.RefObject<HTMLElement | null>,\n closesOnPress: boolean,\n): BackdropPress {\n // The element inside the surface that had focus when the last backdrop press started.\n const pressFocusRef = React.useRef<HTMLElement | null>(null);\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n // C-COMPOSE: only presses on the backdrop element or its content in the DOM.\n if (!event.currentTarget.contains(event.target as Node)) return;\n if (!closesOnPress) {\n event.preventDefault();\n return;\n }\n const focused = getFocusedElement();\n pressFocusRef.current = focused && surfaceRef.current?.contains(focused) ? focused : null;\n },\n [closesOnPress, surfaceRef],\n );\n\n const afterOutsidePress = React.useCallback(() => {\n const element = pressFocusRef.current;\n pressFocusRef.current = null;\n if (!element) return;\n // A close requested from the click is committed first (React flushes the update in a\n // microtask queued before this one): a closed surface no longer contains the element, or\n // (exiting, or kept mounted) is inert, so the element cannot take focus.\n queueMicrotask(() => {\n if (getFocusedElement() !== null || !surfaceRef.current?.contains(element)) return;\n focusElement(element, { preventScroll: true });\n });\n }, [surfaceRef]);\n\n return { onMouseDown, afterOutsidePress };\n}\n\n/** Whether `value` is a DOM event (duck-typed, so an event from another window counts too). */\nfunction isDomEvent(value: unknown): value is Event {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<Event>).type === 'string' &&\n typeof (value as Partial<Event>).stopPropagation === 'function' &&\n !('nativeEvent' in value)\n );\n}\n\n/**\n * The DOM event behind a part's click handler call: a React event's `nativeEvent`, or a DOM event\n * passed as is. A render-prop child that calls the handler without its event (or with another\n * value) gets a new `click` event, so `details.event` is always an event.\n */\nexport function getNativeEvent(value: unknown): Event {\n const native =\n typeof value === 'object' && value !== null\n ? (value as { nativeEvent?: unknown }).nativeEvent\n : undefined;\n if (isDomEvent(native)) return native;\n if (isDomEvent(value)) return value;\n return new Event('click');\n}\n\n/** Returned by {@link useModalTrigger}. */\nexport interface ModalTrigger {\n /**\n * Callback ref for the element a trigger renders: the consumer's child, or the wrapper `<span>`\n * of `asChild={false}` and of the automatic fallback for a child that does not forward its ref.\n * Every trigger of the root attaches it (a root may have several). It returns a React 19 cleanup\n * that forgets that one element, so a trigger that unmounts never unregisters another. Stable.\n */\n attach: React.RefCallback<HTMLElement>;\n /**\n * Records the trigger that is opening the modal, for the open session that follows (anything that\n * is not an element is ignored). Focus returns to that trigger, not to another one of the same\n * root. Triggers call it through {@link useModalTriggerPart}.\n *\n * An activation the modal did not open for by the end of the task (a click that the parent of a\n * controlled modal rejected) is dropped, so it does not decide where focus returns after a later\n * open that no trigger started. React commits an accepted open within the same task.\n */\n activate: (target: unknown) => void;\n /**\n * Starts the open session: the activated trigger belongs to it until {@link endSession}.\n * {@link useModalTriggerSession} calls it when the modal opens.\n */\n startSession: () => void;\n /**\n * Ends the open session: forgets the activated trigger, so it does not decide where focus\n * returns after a later open that no trigger started. {@link useModalTriggerSession} calls it\n * when the modal closes.\n */\n endSession: () => void;\n /**\n * The focus-restore target, for the modal layer's `triggerRef`. Its `current` is resolved when it\n * is read (when the modal opens, and again on close if the opener captured then cannot take\n * focus any more):\n *\n * 1. `null` while an element other than `<body>` has focus: that element opened the modal (the\n * clicked trigger, the button inside a trigger's wrapper span, or the parent's own button of\n * a controlled modal), and the restore captures it. A trigger element itself with focus (a\n * `tabIndex={-1}` wrapper span that a press focused, as Safari does for a click on the button\n * inside it) resolves like any trigger instead.\n * 2. Otherwise (Safari does not focus a clicked button; a modal opened from code), the trigger\n * activated in this open session while it is still in the document.\n * 3. Otherwise the first mounted trigger that can take focus.\n *\n * A trigger resolves with `getTriggerFocusTarget`, the rule of every trigger's focus return: the\n * element that carries the state ARIA (the button inside a wrapper span, the span when you made\n * it the trigger), else the first tabbable element inside it, else itself when it can take\n * focus, else `null`. Read-only.\n */\n focusRef: React.RefObject<HTMLElement | null>;\n}\n\n/** A trigger for components rendered outside their root (C-CONTEXT inert fallback). */\nexport const inertModalTrigger: ModalTrigger = {\n attach: () => undefined,\n activate: () => {},\n startSession: () => {},\n endSession: () => {},\n focusRef: { current: null },\n};\n\nfunction isElementTarget(target: unknown): target is HTMLElement {\n return typeof target === 'object' && target !== null && (target as Partial<Node>).nodeType === 1;\n}\n\n/**\n * Whether a click handler's event came from outside its element in the DOM: it bubbled through the\n * React tree from a portal (a popup opened inside a trigger). `false` without an event (a\n * render-prop child that calls `onClick()` bare) or without DOM nodes to compare.\n */\nfunction isPortaledClick(event: unknown): boolean {\n if (typeof event !== 'object' || event === null) return false;\n const { currentTarget, target } = event as { currentTarget?: unknown; target?: unknown };\n if (!isNode(currentTarget) || !isNode(target)) return false;\n return !currentTarget.contains(target);\n}\n\nfunction isNode(value: unknown): value is Node {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Partial<Node>).nodeType === 'number' &&\n typeof (value as Partial<Node>).contains === 'function'\n );\n}\n\n/** The element that has focus, or `null` when focus is on `<body>` (or nowhere). */\nfunction getFocusedElement(): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n const active = document.activeElement;\n if (!active || active === document.body || active === document.documentElement) return null;\n return active.isConnected ? (active as HTMLElement) : null;\n}\n\nfunction createModalTrigger(): ModalTrigger {\n // Every mounted trigger element, in the order they attached.\n const attached = new Set<HTMLElement>();\n // The trigger clicked in the current open session (or in the task that is opening it);\n // forgotten when the modal closes, when the element detaches, or when no open followed the click.\n let activated: HTMLElement | null = null;\n // Whether an open session is running (between startSession and endSession).\n let sessionOpen = false;\n return {\n attach: (element) => {\n // Detaching runs the cleanup below (React 19 and useMergedRefs call it instead of passing\n // `null`), which knows which element leaves.\n if (!element) return undefined;\n attached.add(element);\n return () => {\n attached.delete(element);\n if (activated === element) activated = null;\n };\n },\n activate: (target) => {\n if (!isElementTarget(target)) return;\n activated = target;\n if (sessionOpen) return;\n // An accepted open commits before the next task starts; a rejected click leaves the modal\n // closed, and its activation must not outlive the task.\n setTimeout(() => {\n if (!sessionOpen && activated === target) activated = null;\n }, 0);\n },\n startSession: () => {\n sessionOpen = true;\n },\n endSession: () => {\n sessionOpen = false;\n activated = null;\n },\n focusRef: {\n get current() {\n // A focused element is the opener: the restore captures it (see ModalTrigger.focusRef),\n // unless it is a trigger element, which resolves like any trigger.\n const focused = getFocusedElement();\n if (focused) return attached.has(focused) ? getTriggerFocusTarget(focused) : null;\n // The trigger that opened the modal decides, also when it cannot take focus any more.\n if (activated?.isConnected) return getTriggerFocusTarget(activated);\n for (const element of attached) {\n if (!element.isConnected) continue;\n const target = getTriggerFocusTarget(element);\n if (target) return target;\n }\n return null;\n },\n },\n };\n}\n\n/**\n * The triggers of a modal root (`Dialog`, `Drawer`), overlays#9. Each `Dialog.Trigger`/\n * `Drawer.Trigger` attaches its element and activates it from its click handler through\n * {@link useModalTriggerPart}; the root passes `focusRef` to `useModalLayer` as its\n * `triggerRef` and scopes the activation to one open session with {@link useModalTriggerSession}.\n * Focus returns to the element that had focus when the modal opened; when nothing had focus, to\n * the trigger that opened it, else to the first mounted trigger. For a wrapper `<span>`, the\n * restore target is the element inside it that carries the state ARIA. Resolving when the ref is\n * read, not when it attaches, keeps a trigger that was disabled at mount (or whose content\n * changed) a valid target.\n */\nexport function useModalTrigger(): ModalTrigger {\n const [trigger] = React.useState(createModalTrigger);\n return trigger;\n}\n\n/** Returned by {@link useModalTriggerElement}. */\ninterface ModalTriggerElement {\n /**\n * Callback ref for the element one trigger renders (merge it with the consumer's ref): registers\n * it with the root's triggers and remembers it for `activate`. Stable.\n */\n attach: React.RefCallback<HTMLElement>;\n /**\n * Records this trigger as the one opening the modal: call it from the click handler, before\n * opening, with whatever the handler received. The element `attach` received wins, else the\n * event's `currentTarget`, so a render-prop child that calls `onClick()` without the event (or\n * with another value) is still recorded. Stable.\n */\n activate: (event?: unknown) => void;\n}\n\nfunction createModalTriggerElement(trigger: ModalTrigger): ModalTriggerElement {\n // The element this trigger rendered; a closure variable, not a React ref, so the click handler\n // that reads it can be passed around during render (C-HOOKS).\n let element: HTMLElement | null = null;\n return {\n attach: (node) => {\n if (!node) return undefined;\n element = node;\n const detach = trigger.attach(node);\n return () => {\n if (element === node) element = null;\n if (typeof detach === 'function') detach();\n };\n },\n activate: (event) => {\n const currentTarget =\n typeof event === 'object' && event !== null\n ? (event as { currentTarget?: unknown }).currentTarget\n : undefined;\n trigger.activate(element ?? currentTarget);\n },\n };\n}\n\n/**\n * One `Dialog.Trigger`/`Drawer.Trigger` of a modal root (overlays#9): attach `attach` to the\n * element the trigger renders and call `activate` from its click handler.\n */\nfunction useModalTriggerElement(trigger: ModalTrigger): ModalTriggerElement {\n return React.useMemo(() => createModalTriggerElement(trigger), [trigger]);\n}\n\n/** The props of a trigger or close part (`Dialog.Trigger`, `Drawer.Close`, …). */\nexport interface ModalPartProps<RenderProps> extends Omit<\n React.HTMLAttributes<HTMLElement>,\n 'children'\n> {\n /** A single element that receives the part's props, or a function that receives them. */\n children: React.ReactNode | ((props: RenderProps) => React.ReactNode);\n /** `false` renders a wrapper `<span>` carrying the click handler. */\n asChild?: boolean;\n /** Ref to the element the part renders. */\n ref?: React.Ref<HTMLElement>;\n}\n\n/** What {@link useModalTriggerPart} reads from the modal root. */\nexport interface ModalTriggerState {\n open: boolean;\n /**\n * Asks the root to open or close (reason `trigger`): to open while it is closed, to close while\n * it is open.\n */\n requestOpen: ModalRequestOpen;\n trigger: ModalTrigger;\n /** The surface's id for `aria-controls` while the modal is open. */\n controlsId: string | undefined;\n /**\n * `'dialog'` renders `aria-haspopup=\"dialog\"`; `false` renders none (an inline drawer, whose\n * trigger shows and hides a panel in place).\n * @default 'dialog'\n */\n popup?: 'dialog' | false;\n}\n\n/**\n * Renders a `Dialog.Trigger`/`Drawer.Trigger`: its element gets `aria-haspopup=\"dialog\"` (none\n * with `popup: false`, an inline drawer's trigger), `aria-expanded`, `aria-controls` (while open;\n * these always win over the child's own), a click handler that opens and closes the root (reason\n * `trigger`, with the click event: a click while it is open asks it to close) and records the\n * trigger that opens it (for the focus return), and a ref that registers it with the root's\n * triggers. On a wrapper span (`asChild={false}`, the automatic fallback), the state ARIA goes to\n * the first element in the tab order inside it (`useTriggerElement`).\n *\n * @param modal The root's state, from its context.\n * @param props The part's props.\n * @param componentName The public name for development warnings, e.g. `'Dialog.Trigger'`.\n */\nexport function useModalTriggerPart<RenderProps>(\n modal: ModalTriggerState,\n { children, asChild, ref, ...rest }: ModalPartProps<RenderProps>,\n componentName: string,\n): React.ReactNode {\n const { open, requestOpen, trigger, controlsId, popup = 'dialog' } = modal;\n const { attach, activate } = useModalTriggerElement(trigger);\n const mergedRef = useMergedRefs<HTMLElement>(attach, ref);\n const toggleModal = React.useCallback(\n (event?: React.MouseEvent<HTMLElement>) => {\n // A click that bubbled through the React tree from a portal opened inside the trigger (a\n // Popover in a wrapper span) is not a click on it (C-COMPOSE).\n if (isPortaledClick(event)) return;\n // Focus returns to this trigger, also when the root has several (overlays#9), and also when\n // a render-prop child calls `onClick()` without the event.\n if (!open) activate(event);\n requestOpen(!open, { reason: 'trigger', event: getNativeEvent(event) });\n },\n [open, activate, requestOpen],\n );\n\n // An inline drawer's trigger gets no `aria-haspopup` key at all, so a render-prop child that\n // spreads the props has none either.\n const stateAria = {\n ...(popup !== false && { 'aria-haspopup': popup }),\n 'aria-expanded': open,\n 'aria-controls': open ? controlsId : undefined,\n };\n const triggerProps = mergeProps({ ...stateAria, onClick: toggleModal, ref: mergedRef }, rest, {\n oursWin: STATE_ARIA,\n });\n\n return useTriggerElement(children, triggerProps as RenderProps, { componentName, asChild });\n}\n\n/**\n * Renders a `Dialog.Close`/`Drawer.Close`: composes a click handler that asks the root to close\n * (reason `close`, with the click event) onto its element (the child's own `onClick` runs first;\n * `preventDefault()` there keeps the modal open).\n *\n * @param requestOpen The root's request function, from its context.\n * @param props The part's props.\n * @param componentName The public name for development warnings, e.g. `'Dialog.Close'`.\n */\nexport function useModalClosePart<RenderProps>(\n requestOpen: ModalRequestOpen,\n { children, asChild, ref, ...rest }: ModalPartProps<RenderProps>,\n componentName: string,\n): React.ReactNode {\n const mergedRef = useMergedRefs<HTMLElement>(ref);\n const close = React.useCallback(\n (event?: React.MouseEvent<HTMLElement>) =>\n requestOpen(false, { reason: 'close', event: getNativeEvent(event) }),\n [requestOpen],\n );\n const closeProps = mergeProps({ onClick: close, ref: mergedRef }, rest);\n return useTriggerElement(children, closeProps as RenderProps, { componentName, asChild });\n}\n\n/** The element {@link useModalOpener} captured, while it is in the document. */\ninterface ModalOpener {\n /** Records the opener (or forgets it, `null`). */\n set: (element: HTMLElement | null) => void;\n /** The captured opener while it is in the document, else `null`. Read-only. */\n ref: React.RefObject<HTMLElement | null>;\n}\n\nfunction createModalOpener(): ModalOpener {\n let element: HTMLElement | null = null;\n return {\n set: (next) => {\n element = next;\n },\n ref: {\n get current() {\n return element?.isConnected ? element : null;\n },\n },\n };\n}\n\n/**\n * The element a non-modal surface takes its keyboard place after (`usePopoverTabOrder`'s\n * `anchorRef`). Pass the surface's open state as `enabled`, whatever its `modalType`, so a surface\n * that turns non-modal while open (focus already inside it) still knows its opener. It is\n * captured in the insertion phase of the commit in which `enabled` becomes true,\n * before focus moves in: `trigger.focusRef.current`, which with nothing focused is the activated\n * or first trigger's focus target and is `null` while an element other than `<body>` has focus\n * (`ModalTrigger.focusRef` rule 1; a focused `tabIndex={-1}` trigger wrapper span resolves as a\n * trigger), so a focused trigger, the button inside a trigger's span or a controlled surface's own\n * opener is taken by the next step: else the focused element when it is not `<body>` and not\n * inside `surface`, else `null`. Cleared when `enabled` becomes false. An opener removed from the\n * document since reads as `null`, so the surface keeps its portal's place (the end of the page).\n */\nexport function useModalOpener(\n enabled: boolean,\n trigger: ModalTrigger,\n surface: HTMLElement | null,\n): React.RefObject<HTMLElement | null> {\n const [opener] = React.useState(createModalOpener);\n const enabledRef = React.useRef(false);\n React.useInsertionEffect(() => {\n const wasEnabled = enabledRef.current;\n enabledRef.current = enabled;\n if (enabled === wasEnabled) return;\n if (!enabled) {\n opener.set(null);\n return;\n }\n const fromTrigger = trigger.focusRef.current;\n if (fromTrigger) {\n opener.set(fromTrigger);\n return;\n }\n const focused = getFocusedElement();\n opener.set(focused && !surface?.contains(focused) ? focused : null);\n });\n return opener.ref;\n}\n\n/**\n * Scopes a trigger's activation to one open session (overlays#9): when the modal opens, the\n * activated trigger joins the session; when it closes, the trigger is forgotten, so a later open\n * that no trigger started (a controlled modal opened by the parent) does not return focus to it.\n *\n * It updates the session in a layout effect, after the modal's focus restore has used the\n * activation: call it in the root component (whose effects run after its children's) and, when\n * that component also calls `useModalLayer`, after that call (a component's effects run in order).\n */\nexport function useModalTriggerSession(trigger: ModalTrigger, open: boolean): void {\n React.useLayoutEffect(() => {\n if (open) trigger.startSession();\n else trigger.endSession();\n }, [trigger, open]);\n}\n\n/**\n * Moves a kept-mounted surface to the top of its stack when it opens (D104). A portal's z-index is\n * its layer plus its nesting depth, so at equal depth the wrapper later in the document paints\n * above: a surface kept mounted since before another overlay opened (a confirm Dialog rendered\n * next to a Drawer) would open under it. In the commit in which `open` becomes `true`, a layout\n * effect moves the portal wrapper to the end of its container when it is not the container's last\n * element child (`container.appendChild(wrapper)`). The closed content is hidden, so the move loses\n * no visible state, and React removes the wrapper from the same parent later. An unmounting surface\n * is appended when it opens already, so pass `keptMounted: false` for it: it is never moved.\n *\n * Call it before `useModalLayer` (a component's layout effects run in order), so the move happens\n * before the layer registers, before other modals re-plan their isolation and before the focus\n * trap moves focus in.\n *\n * @param open Whether the surface is open.\n * @param keptMounted `true` with `unmountOnClose={false}`.\n * @param wrapperRef The `Portal`'s `ref` (its wrapper element).\n */\nexport function useRaiseOnOpen(\n open: boolean,\n keptMounted: boolean,\n wrapperRef: React.RefObject<HTMLElement | null>,\n): void {\n // The open state of the previous commit: the move happens only in the opening commit, never\n // while the surface is open (a move would blur the element inside that has focus).\n const wasOpenRef = React.useRef(false);\n React.useLayoutEffect(() => {\n const wasOpen = wasOpenRef.current;\n wasOpenRef.current = open;\n if (!open || wasOpen || !keptMounted) return;\n const wrapper = wrapperRef.current;\n const container = wrapper?.parentElement;\n if (wrapper && container && container.lastElementChild !== wrapper) {\n container.appendChild(wrapper);\n }\n });\n}\n\n/**\n * Development check of a kept-mounted surface (D106): a popup opened inside it (a Popover, a Menu,\n * a nested Dialog) that is still open when the surface closes stays open over the page, because\n * the content that would unmount it stays mounted. After each close of a kept-mounted surface it\n * schedules one check in a new task (`setTimeout(0)`, so a popup that the closing press itself\n * dismisses does not count) and warns once (`<componentName>:open-inside`) when an open layer\n * other than a tooltip descends from the surface's layer (`isDescendantLayer` follows the popup's\n * `parentId`, also after the surface's own layer unregistered) or has its anchor inside\n * `surfaceRef`'s element (an inline drawer, which registers no layer of its own, so a popup\n * opened inside it descends from no layer of the surface). Nothing runs with the default\n * `unmountOnClose`, where the popups unmount with the content, or in production.\n *\n * @param open Whether the surface is open.\n * @param keptMounted `true` with `unmountOnClose={false}`.\n * @param layerId The surface's dismiss layer (`useModalLayer`'s `layerId`).\n * @param componentName The public name for the warning key and text: `'Dialog'`, `'Drawer'`.\n * @param surfaceRef The surface element, for the anchor check (optional).\n */\nexport function useOpenInsideWarning(\n open: boolean,\n keptMounted: boolean,\n layerId: string,\n componentName: string,\n surfaceRef?: React.RefObject<HTMLElement | null>,\n): void {\n const wasOpenRef = React.useRef(open);\n React.useEffect(() => {\n const wasOpen = wasOpenRef.current;\n wasOpenRef.current = open;\n if (!isDev || open || !wasOpen || !keptMounted) return undefined;\n const timer = setTimeout(() => {\n const surface = surfaceRef?.current ?? null;\n const leftOpen = getOpenLayers().some((layer) => {\n if (layer.kind === 'tooltip') return false;\n if (isDescendantLayer(layer.id, layerId)) return true;\n const anchor = layer.getAnchor();\n return !!surface && !!anchor && surface.contains(anchor);\n });\n if (!leftOpen) return;\n warnOnce(\n `${componentName}:open-inside`,\n `${componentName} closed while a popup opened inside it is still open. With \\`unmountOnClose={false}\\` the popup stays open over the page: close it first, or keep the default \\`unmountOnClose\\`.`,\n );\n }, 0);\n return () => clearTimeout(timer);\n }, [open, keptMounted, layerId, componentName, surfaceRef]);\n}\n\n/**\n * C-CONTEXT: reads a compound component's context. Outside its root it throws\n * `[WaveUI] <componentName> must be used within <parentName>` in development, and in production\n * logs the same message once per page (`reportMissingContext`) and returns the inert value from\n * `getInert`.\n */\nexport function useRequiredContext<T>(\n context: React.Context<T | null>,\n componentName: string,\n parentName: string,\n getInert: () => T,\n): T {\n const value = React.useContext(context);\n if (value !== null) return value;\n reportMissingContext(componentName, parentName);\n return getInert();\n}\n\n/** What a modal surface (`Dialog.Content`, the Drawer panel) provides to its descendants. */\nexport interface ModalSurfaceContextValue {\n /**\n * Registers the id of a title element (`Dialog.Title`, `Drawer.Title`) for the surface's\n * `aria-labelledby`. Returns the unregister function.\n */\n registerTitle: (id: string) => () => void;\n /**\n * Receives the measured border-box height of the surface's sticky footer (`Dialog.Footer`) in\n * px, or `null` once it unmounts; the surface reserves it as the scroll padding of its body.\n * Absent on a surface without a footer part (the Drawer panel).\n */\n setFooterHeight?: (px: number | null) => void;\n /**\n * The element `Dialog.Title` actions portal into: the outlet in `Dialog.Content`'s title-actions\n * area, `null` until it is attached. Absent outside `Dialog.Content` (the Drawer panel), where a\n * title renders its action right after its heading.\n */\n titleActionsOutlet?: HTMLElement | null;\n}\n\n/**\n * Provided by every modal surface; `null` outside one. Titles register with it, and\n * `Dialog.Footer` reads it to report its height and to warn when it is rendered outside\n * `Dialog.Content`.\n */\nexport const ModalSurfaceContext = React.createContext<ModalSurfaceContextValue | null>(null);\nModalSurfaceContext.displayName = 'ModalSurfaceContext';\n\nconst inertSurface: ModalSurfaceContextValue = { registerTitle: () => () => {} };\n\n/** Returned by {@link useTitleRegistry}. */\nexport interface TitleRegistry {\n /** The id of the first registered title, for `aria-labelledby`. */\n titleId: string | undefined;\n /** Whether a title is registered right now. Read it in effects and handlers, not during render. */\n hasTitle: () => boolean;\n /** The memoised value for `ModalSurfaceContext.Provider`. */\n context: ModalSurfaceContextValue;\n}\n\n/**\n * The title registry of a modal surface. A title registers its id from its ref callback (when its\n * element attaches), so the surface's `aria-labelledby` follows the title elements that are\n * actually rendered.\n */\nexport function useTitleRegistry(): TitleRegistry {\n const [ids, setIds] = React.useState<readonly string[]>([]);\n const countRef = React.useRef(0);\n\n const registerTitle = React.useCallback((id: string) => {\n countRef.current += 1;\n setIds((current) => [...current, id]);\n let registered = true;\n return () => {\n if (!registered) return;\n registered = false;\n countRef.current -= 1;\n setIds((current) => {\n const index = current.indexOf(id);\n return index === -1 ? current : [...current.slice(0, index), ...current.slice(index + 1)];\n });\n };\n }, []);\n\n const hasTitle = React.useCallback(() => countRef.current > 0, []);\n const context = React.useMemo(() => ({ registerTitle }), [registerTitle]);\n return { titleId: ids[0], hasTitle, context };\n}\n\n/**\n * The `id` and `ref` of a title sub-component (`Dialog.Title`, `Drawer.Title`): the consumer's\n * `id` (or a generated one), registered with the enclosing surface while the element is mounted.\n */\nexport function useModalTitle(\n componentName: string,\n parentName: string,\n idProp: string | undefined,\n ref: React.Ref<HTMLHeadingElement> | undefined,\n): { id: string; ref: React.RefCallback<HTMLHeadingElement> } {\n const { registerTitle } = useRequiredContext(\n ModalSurfaceContext,\n componentName,\n parentName,\n () => inertSurface,\n );\n const generatedId = useId('wave-modal-title');\n const id = idProp ?? generatedId;\n const register = React.useCallback(\n (node: HTMLHeadingElement | null) => (node ? registerTitle(id) : undefined),\n [registerTitle, id],\n );\n const mergedRef = useMergedRefs<HTMLHeadingElement>(ref, register);\n return { id, ref: mergedRef };\n}\n\n/**\n * Development warning (once per component) when an open modal surface has no accessible name:\n * no `title`, no registered title element, no `aria-label` and no `aria-labelledby`.\n *\n * @param surface The open surface element (`null` while closed).\n * @param hasTitle From {@link useTitleRegistry}.\n * @param componentName The public name, e.g. `'Dialog.Content'`.\n * @param titleName The title sub-component to recommend, e.g. `'Dialog.Title'`.\n */\nexport function useUnnamedModalWarning(\n surface: HTMLElement | null,\n hasTitle: () => boolean,\n componentName: string,\n titleName: string,\n): void {\n React.useEffect(() => {\n if (!surface) return;\n if (\n surface.hasAttribute('aria-label') ||\n surface.hasAttribute('aria-labelledby') ||\n hasTitle()\n ) {\n return;\n }\n warnOnce(\n `${componentName}:unnamed`,\n `${componentName} has no accessible name. Pass \\`title\\`, render a ${titleName} inside it, or give it \\`aria-label\\` or \\`aria-labelledby\\`.`,\n );\n }, [surface, hasTitle, componentName, titleName]);\n}\n"],"mappings":"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"}
|
|
@@ -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/composeEventHandlers.cjs"),o=require("../../hooks/useMergedRefs.cjs"),s=require("../../lib/layers.cjs"),c=require("../button/Button.cjs"),l=require("../button/Button.slots.cjs"),u=require("../../lib/icons.cjs"),d=require("../../lib/labelInName.cjs");let f=require("react");f=e.__toESM(f,1);let p=require("react/jsx-runtime");var m=new Set([`aria-label`,`aria-labelledby`,`title`]),h=/^on[A-Z]/,g=()=>{},_=()=>(0,p.jsx)(u.DismissIcon,{});function v(){return{buttonProps:{},icon:_(),iconPosition:void 0,children:void 0,contentMayName:!1,literalTextLabel:!1,disabledFocusable:!1,merged:null}}function y(e){return e===`button`||e===c.Button}function b(e,t,n,r){let a={};for(let[t,n]of Object.entries(e))t===`children`||t===`dangerouslySetInnerHTML`||l.BUTTON_OWN_PROP_KEYS.has(t)||(a[t]=n);let o=e.dangerouslySetInnerHTML,s=o==null?i.materialiseSlotContent(t):(0,p.jsx)(`span`,{className:`inline-flex items-center`,dangerouslySetInnerHTML:o}),c=n&&i.slotRendersContent(e.icon)?e.icon:null,u=c!==null||i.slotRendersContent(s);return{buttonProps:a,icon:u?c??void 0:_(),iconPosition:n?e.iconPosition:void 0,children:u?s:void 0,contentMayName:!0,literalTextLabel:d.hasTextLabel(s),disabledFocusable:n&&!!e.disabledFocusable,merged:r}}function x(e){if(e===null)return null;if(e===void 0||typeof e==`boolean`)return v();let t=e;if(n.isElementOfType(t,`button`,c.Button))return b(t.props,t.props.children,n.isElementOfType(t,c.Button),`a button element`);let r=i.resolveSlot(e,`span`);if(!r)return v();let{Component:a,props:o,children:s}=r;if(y(a))return b(o,s,a===c.Button,`a slot object that renders a button`);let l={},u={};for(let[e,t]of Object.entries(o))m.has(e)||h.test(e)?l[e]=t:u[e]=t;let d;return i.slotRendersContent(s)?d=s:i.slotWrapsDefaultContent(a,{...u,children:s})&&(d=_()),{buttonProps:l,icon:{...u,as:a,children:d},iconPosition:void 0,children:void 0,contentMayName:!1,literalTextLabel:!1,disabledFocusable:!1,merged:null}}function S({componentName:e,closeButton:n,closeLabel:i,onClose:s,className:l}){let u=x(n),h=u?.merged??null;f.useEffect(()=>{h!==null&&r.warnOnce(`${e}:closeButton-button-element`,`${e}: \`closeButton\` received ${h}; its props were merged into the built-in Close button (buttons cannot be nested). Pass icon content instead, e.g. \`closeButton={<CloseIcon />}\`.`)},[h,e]);let{ref:_,onClick:v,className:y,...b}=u?.buttonProps??{},S=Object.keys(b).some(e=>m.has(e)&&b[e]!=null),C=u!==null&&u.contentMayName&&!S,w=u?.literalTextLabel??!1,[T,E]=f.useState(null),D=f.useCallback(e=>T?d.observeTextLabel(T,e):g,[T]),O=f.useSyncExternalStore(D,()=>T?d.hasRenderedTextLabel(T):w,()=>w),k=C&&O,A=o.useMergedRefs(_,C?E:void 0);return u===null?null:(0,p.jsx)(c.Button,{appearance:`subtle`,size:`small`,"aria-label":S||k?void 0:i,...b,ref:A,icon:u.icon,iconPosition:u.iconPosition,disabledFocusable:u.disabledFocusable,onClick:a.composeEventHandlers(v,e=>s(e.nativeEvent)),className:t.cn(l,y),children:u.children})}S.displayName=`ModalCloseButton`;var C=()=>`dimmed`;function w(e,t){let n=f.useCallback(()=>t&&s.hasIsolatingModalBelow(e)?`transparent`:`dimmed`,[e,t]);return f.useSyncExternalStore(s.subscribeLayers,n,C)}function T({backdrop:e,className:n,layerId:r,open:s,onMouseDown:c,presenceProps:l}){let u=w(r,s),d=e===null||typeof e==`boolean`?void 0:e,f=d===void 0?null:i.resolveSlot(d,`div`),{appearance:m,className:h,onMouseDown:g,ref:_,...v}=f?.props??{},y=o.useMergedRefs(_);if(e===null)return null;let b=m===`dimmed`||m===`transparent`?m:u,x=f?.Component??`div`;return(0,p.jsx)(x,{"data-appearance":b,...v,...l,ref:y,"aria-hidden":`true`,onMouseDown:a.composeEventHandlers(g,c),className:t.cn(n,`fixed inset-0`,b===`transparent`?`bg-transparent`:`bg-backdrop`,h),children:f?.children})}T.displayName=`ModalBackdrop`,exports.ModalBackdrop=T,exports.ModalCloseButton=S,exports.useBackdropAppearance=w;
|
|
2
|
+
//# sourceMappingURL=Dialog.slots.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dialog.slots.cjs","names":["DismissIcon","Button","BUTTON_OWN_PROP_KEYS","materialiseSlotContent","slotRendersContent","hasTextLabel","isElementOfType","resolveSlot","slotWrapsDefaultContent","React","observeTextLabel","hasRenderedTextLabel","useMergedRefs","composeEventHandlers","cn","hasIsolatingModalBelow","subscribeLayers","require_runtime","require_cn","require_children","require_dev","require_slot","require_composeEventHandlers","require_useMergedRefs","require_layers","require_Button","require_Button_slots","require_icons","require_labelInName","react","react_jsx_runtime","NAMING_KEYS","HANDLER_KEY","noop","defaultGlyph","defaultParts","isButtonType","type","mergedParts","buttonProps","key","value","props","markup","content","children","icon","isWaveButton","hasContent","resolveCloseButton","closeButton","element","resolved","Component","contentProps","inner","ModalCloseButton","parts","merged","componentName","slotRef","slotOnClick","slotClassName","slotButtonProps","hasOwnName","checksContent","literalTextLabel","labelTarget","setLabelTarget","subscribeToContent","onChange","contentHasTextLabel","namedByContent","ref","closeLabel","onClose","event","className","getServerAppearance","useBackdropAppearance","getSnapshot","open","layerId","ModalBackdrop","automatic","slot","backdrop","ownAppearance","slotOnMouseDown","slotProps","appearance","presenceProps","onMouseDown"],"sources":["../../../src/components/overlays/Dialog.slots.tsx"],"sourcesContent":["import * as React from 'react';\nimport { isElementOfType } from '../../lib/children';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { DismissIcon } from '../../lib/icons';\nimport { hasRenderedTextLabel, hasTextLabel, observeTextLabel } from '../../lib/labelInName';\nimport { hasIsolatingModalBelow, subscribeLayers } from '../../lib/layers';\nimport {\n materialiseSlotContent,\n resolveSlot,\n slotRendersContent,\n slotWrapsDefaultContent,\n type Slot,\n type SlotObject,\n} from '../../lib/slot';\nimport type { BackdropAppearance, IconPosition } from '../../lib/types';\nimport type { PresenceAttributes } from '../../hooks/usePresence';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { Button } from '../button/Button';\nimport { BUTTON_OWN_PROP_KEYS, type UnwrappedButton } from '../button/Button.slots';\n\n/*\n * The Close button and backdrop slots of Dialog and Drawer (P6-06 D93–D95). Internal (not\n * exported from the package). Imports Button, never the reverse.\n */\n\ntype UnknownProps = Record<string, unknown>;\n\n/** The `backdrop` slot of `Dialog.Content`, `Drawer` and the drawer panel shell. */\nexport type ModalBackdropSlot =\n Slot<'div'> | (SlotObject<'div'> & { appearance?: BackdropAppearance });\n\n/** Attributes of a `closeButton` slot that name the Close button instead of `closeLabel`. */\nconst NAMING_KEYS: ReadonlySet<string> = new Set(['aria-label', 'aria-labelledby', 'title']);\n\nconst HANDLER_KEY = /^on[A-Z]/;\n\nconst noop = () => {};\n\n/** How the `closeButton` slot splits between the built-in Button and the content inside it. */\ninterface CloseButtonParts {\n /**\n * Props for the built-in Button: every prop of a merged button (except Wave Button's own), or a\n * slot object's naming attributes and handlers.\n */\n buttonProps: UnknownProps;\n /** The Button's decorative `icon`: the slot's content, a merged Button's icon, or the glyph. */\n icon: Slot<'span'> | undefined;\n /** A merged Wave Button's `iconPosition`. */\n iconPosition: IconPosition | undefined;\n /** The Button's children: the content of a merged button (it may name the button). */\n children: React.ReactNode;\n /** `true` for a merged button: a text label in its content names the Close button. */\n contentMayName: boolean;\n /** Whether a merged button's literal content holds a text label (the server and first render). */\n literalTextLabel: boolean;\n /** A merged Wave Button's `disabledFocusable`. */\n disabledFocusable: boolean;\n /** What was merged, for the development warning (`null`: nothing). */\n merged: UnwrappedButton | null;\n}\n\n/** The decorative default glyph of the Close button. */\nconst defaultGlyph = () => <DismissIcon />;\n\nfunction defaultParts(): CloseButtonParts {\n return {\n buttonProps: {},\n icon: defaultGlyph(),\n iconPosition: undefined,\n children: undefined,\n contentMayName: false,\n literalTextLabel: false,\n disabledFocusable: false,\n merged: null,\n };\n}\n\nfunction isButtonType(type: unknown): boolean {\n return type === 'button' || type === Button;\n}\n\n/**\n * The parts of a `<button>` or Wave `Button` merged into the built-in Close button: its props go\n * to the Button (Wave Button's own props are applied or dropped), its content becomes the Button's\n * children, and a Wave Button's `icon` stays its icon. Without content of either kind the\n * default glyph stays.\n */\nfunction mergedParts(\n props: UnknownProps,\n children: unknown,\n isWaveButton: boolean,\n merged: UnwrappedButton,\n): CloseButtonParts {\n const buttonProps: UnknownProps = {};\n for (const [key, value] of Object.entries(props)) {\n if (key === 'children' || key === 'dangerouslySetInnerHTML' || BUTTON_OWN_PROP_KEYS.has(key)) {\n continue;\n }\n buttonProps[key] = value;\n }\n // Markup of the merged button is its content too, in a span inside the Button.\n const markup = props.dangerouslySetInnerHTML as\n React.HTMLAttributes<HTMLElement>['dangerouslySetInnerHTML'] | undefined;\n const content =\n markup != null ? (\n <span className=\"inline-flex items-center\" dangerouslySetInnerHTML={markup} />\n ) : (\n materialiseSlotContent(children)\n );\n const icon = isWaveButton && slotRendersContent(props.icon) ? (props.icon as Slot<'span'>) : null;\n const hasContent = icon !== null || slotRendersContent(content);\n return {\n buttonProps,\n icon: hasContent ? (icon ?? undefined) : defaultGlyph(),\n iconPosition: isWaveButton ? (props.iconPosition as IconPosition | undefined) : undefined,\n children: hasContent ? content : undefined,\n contentMayName: true,\n literalTextLabel: hasTextLabel(content),\n disabledFocusable: isWaveButton && Boolean(props.disabledFocusable),\n merged,\n };\n}\n\n/**\n * Splits the `closeButton` slot (D95): `null` means no Close button; `undefined` and booleans keep\n * the default; a `<button>`/`Button` element, or a slot object whose `as` is one, is merged; other\n * content is the Button's decorative icon, whose element takes a slot object's other attributes\n * while its naming attributes and handlers go to the Button. Content that renders nothing keeps\n * the default glyph, as does a slot object whose element wraps the default content.\n */\nfunction resolveCloseButton(closeButton: Slot<'span'> | undefined): CloseButtonParts | null {\n if (closeButton === null) return null;\n if (closeButton === undefined || typeof closeButton === 'boolean') return defaultParts();\n\n // A Button written in a Server Component (a lazy client reference) is merged too.\n const element = closeButton as React.ReactNode;\n if (isElementOfType<UnknownProps>(element, 'button', Button)) {\n return mergedParts(\n element.props,\n element.props.children,\n isElementOfType(element, Button),\n 'a button element',\n );\n }\n\n const resolved = resolveSlot(closeButton, 'span');\n if (!resolved) return defaultParts();\n const { Component, props, children } = resolved;\n if (isButtonType(Component)) {\n return mergedParts(\n props,\n children,\n Component === Button,\n 'a slot object that renders a button',\n );\n }\n\n const buttonProps: UnknownProps = {};\n const contentProps: UnknownProps = {};\n for (const [key, value] of Object.entries(props)) {\n if (NAMING_KEYS.has(key) || HANDLER_KEY.test(key)) buttonProps[key] = value;\n else contentProps[key] = value;\n }\n let inner: React.ReactNode;\n if (slotRendersContent(children)) inner = children;\n else if (slotWrapsDefaultContent(Component, { ...contentProps, children }))\n inner = defaultGlyph();\n return {\n buttonProps,\n // The content element, as a slot object of the Button's icon: Button adds its icon classes\n // and `aria-hidden`.\n icon: { ...contentProps, as: Component, children: inner } as SlotObject<'span'>,\n iconPosition: undefined,\n children: undefined,\n contentMayName: false,\n literalTextLabel: false,\n disabledFocusable: false,\n merged: null,\n };\n}\n\n/** Properties of {@link ModalCloseButton}. */\nexport interface ModalCloseButtonProps {\n /** `'Dialog.Content'` or `'Drawer'`: the warning key and text. */\n componentName: string;\n /** The `closeButton` slot. */\n closeButton: Slot<'span'> | undefined;\n /** The Button's name unless the slot names it (`closeLabel`). */\n closeLabel: string;\n /** Asks to close with `'close-button'`. */\n onClose: (event: Event) => void;\n /** The part class and layout classes, after Button's own (`drawerClassNames.closeButton`, …). */\n className: string;\n}\n\n/**\n * The built-in Close button with the `closeButton` slot rules (D95), shared by `Dialog.Content`,\n * the built-in Drawer header and every `Drawer.HeaderTitle`: a subtle, small Wave `Button` named\n * by `closeLabel`, holding the dismiss glyph or the slot's decorative content; a merged button's\n * text label (two letters or digits, `labelInName.ts`) names it instead, from the literal content\n * on the server and the first render and from the rendered text after mount. `null` when hidden.\n * Warns once, from an effect, when a button was merged.\n */\nexport function ModalCloseButton({\n componentName,\n closeButton,\n closeLabel,\n onClose,\n className,\n}: ModalCloseButtonProps): React.ReactNode {\n const parts = resolveCloseButton(closeButton);\n const merged = parts?.merged ?? null;\n React.useEffect(() => {\n if (merged === null) return;\n warnOnce(\n `${componentName}:closeButton-button-element`,\n `${componentName}: \\`closeButton\\` received ${merged}; its props were merged into the built-in Close button (buttons cannot be nested). Pass icon content instead, e.g. \\`closeButton={<CloseIcon />}\\`.`,\n );\n }, [merged, componentName]);\n\n const {\n ref: slotRef,\n onClick: slotOnClick,\n className: slotClassName,\n ...slotButtonProps\n } = parts?.buttonProps ?? {};\n const hasOwnName = Object.keys(slotButtonProps).some(\n (key) => NAMING_KEYS.has(key) && slotButtonProps[key] != null,\n );\n\n // WCAG 2.5.3 (Label in Name): a merged button's text label names the Close button, which then\n // drops `closeLabel`. The literal content decides on the server and the first render; after\n // mount the rendered text does (text from components, e.g. translations, and later changes).\n const checksContent = parts !== null && parts.contentMayName && !hasOwnName;\n const literalTextLabel = parts?.literalTextLabel ?? false;\n const [labelTarget, setLabelTarget] = React.useState<HTMLButtonElement | null>(null);\n const subscribeToContent = React.useCallback(\n (onChange: () => void) => (labelTarget ? observeTextLabel(labelTarget, onChange) : noop),\n [labelTarget],\n );\n const contentHasTextLabel = React.useSyncExternalStore(\n subscribeToContent,\n () => (labelTarget ? hasRenderedTextLabel(labelTarget) : literalTextLabel),\n () => literalTextLabel,\n );\n const namedByContent = checksContent && contentHasTextLabel;\n const ref = useMergedRefs<HTMLButtonElement>(\n slotRef as React.Ref<HTMLButtonElement> | undefined,\n checksContent ? setLabelTarget : undefined,\n );\n\n if (parts === null) return null;\n return (\n <Button\n appearance=\"subtle\"\n size=\"small\"\n aria-label={hasOwnName || namedByContent ? undefined : closeLabel}\n {...slotButtonProps}\n ref={ref}\n icon={parts.icon}\n iconPosition={parts.iconPosition}\n disabledFocusable={parts.disabledFocusable}\n onClick={composeEventHandlers(\n slotOnClick as React.MouseEventHandler<HTMLButtonElement> | undefined,\n (event: React.MouseEvent<HTMLButtonElement>) => onClose(event.nativeEvent),\n )}\n className={cn(className, slotClassName as string | undefined)}\n >\n {parts.children}\n </Button>\n );\n}\nModalCloseButton.displayName = 'ModalCloseButton';\n\n/** The server snapshot of {@link useBackdropAppearance}: nothing is stacked on the server. */\nconst getServerAppearance = (): BackdropAppearance => 'dimmed';\n\n/**\n * The automatic look of a modal surface's backdrop (D94): `'transparent'` while the surface is\n * open and another open modal surface whose isolation is active is stacked below it (nested in its\n * content or opened beside it), so the page is dimmed once; `'dimmed'` otherwise. Derived during\n * render from the layer stack (`hasIsolatingModalBelow`), re-read whenever a layer or an isolation\n * changes, so the upper surface dims when the lower one closes. A modal layer without isolation\n * (the DatePicker calendar) never counts.\n */\nexport function useBackdropAppearance(layerId: string, open: boolean): BackdropAppearance {\n const getSnapshot = React.useCallback(\n (): BackdropAppearance => (open && hasIsolatingModalBelow(layerId) ? 'transparent' : 'dimmed'),\n [layerId, open],\n );\n return React.useSyncExternalStore(subscribeLayers, getSnapshot, getServerAppearance);\n}\n\n/** Properties of {@link ModalBackdrop}. */\nexport interface ModalBackdropProps {\n /** The `backdrop` slot. */\n backdrop: ModalBackdropSlot | undefined;\n /**\n * The stable class (`dialogContentClassNames.backdrop`, `drawerClassNames.backdrop`, plus a\n * variant's), first in the backdrop's classes.\n */\n className: string;\n /** The surface's dismiss layer (for the automatic appearance). */\n layerId: string;\n /** Whether the surface is open. */\n open: boolean;\n /** The surface's backdrop press handling (`useBackdropPress`), after the slot's own handler. */\n onMouseDown: (event: React.MouseEvent<HTMLElement>) => void;\n /** The presence attributes of the surface's top-level elements (P6-07). */\n presenceProps: PresenceAttributes;\n}\n\n/**\n * The backdrop element of a modal or alert surface with the `backdrop` slot rules (D93) and the\n * automatic appearance (D94): `aria-hidden`, `fixed inset-0`, rendered as `data-appearance` and\n * filled with the backdrop token, or transparent. `null` renders none; `undefined` and booleans\n * the default; shorthand content renders inside it; a slot object's attributes, `className`\n * (merged last), `style`, `ref` and handlers (composed, the slot's first) go to it, its children\n * render inside it, and its `appearance` overrides the automatic one. `aria-hidden=\"true\"` always\n * wins.\n */\nexport function ModalBackdrop({\n backdrop,\n className,\n layerId,\n open,\n onMouseDown,\n presenceProps,\n}: ModalBackdropProps): React.ReactNode {\n const automatic = useBackdropAppearance(layerId, open);\n const slot = backdrop === null || typeof backdrop === 'boolean' ? undefined : backdrop;\n const resolved = slot === undefined ? null : resolveSlot<'div'>(slot as Slot<'div'>, 'div');\n const {\n appearance: ownAppearance,\n className: slotClassName,\n onMouseDown: slotOnMouseDown,\n ref: slotRef,\n ...slotProps\n } = resolved?.props ?? {};\n const ref = useMergedRefs<HTMLElement>(slotRef as React.Ref<HTMLElement> | undefined);\n if (backdrop === null) return null;\n\n const appearance: BackdropAppearance =\n ownAppearance === 'dimmed' || ownAppearance === 'transparent' ? ownAppearance : automatic;\n const Component: React.ElementType = resolved?.Component ?? 'div';\n return (\n <Component\n data-appearance={appearance}\n {...slotProps}\n {...presenceProps}\n ref={ref}\n aria-hidden=\"true\"\n onMouseDown={composeEventHandlers(\n slotOnMouseDown as React.MouseEventHandler<HTMLElement> | undefined,\n onMouseDown,\n )}\n className={cn(\n className,\n 'fixed inset-0',\n appearance === 'transparent' ? 'bg-transparent' : 'bg-backdrop',\n slotClassName as string | undefined,\n )}\n >\n {resolved?.children}\n </Component>\n );\n}\nModalBackdrop.displayName = 'ModalBackdrop';\n"],"mappings":"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"}
|