huaira-ui 0.4.0 → 0.4.1
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/components/drawer/drawer.d.ts +1 -1
- package/components/drawer/drawer.js +54 -54
- package/components/drawer/drawer.js.map +1 -1
- package/components/drawer/drawer.types.d.ts +15 -5
- package/components/modal/modal.d.ts +1 -1
- package/components/modal/modal.js +70 -70
- package/components/modal/modal.js.map +1 -1
- package/components/modal/modal.types.d.ts +15 -5
- package/lib/use-modality.d.ts +16 -3
- package/lib/use-modality.js +21 -16
- package/lib/use-modality.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { DrawerProps } from './drawer.types.js';
|
|
2
|
-
export declare function Drawer({ size, side, dismissible, title, description, footer, closeLabel, open, defaultOpen, unstyled, className, id, ref, "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy,
|
|
2
|
+
export declare function Drawer({ size, side, dismissible, title, description, footer, closeLabel, open, defaultOpen, unstyled, className, id, ref, "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy, onClose, onOpen, children, ...props }: Readonly<DrawerProps>): import("react").JSX.Element;
|
|
@@ -3,78 +3,78 @@ import { composeClassName as e, partClassName as t } from "../../lib/class-name.
|
|
|
3
3
|
import { hasRenderableContent as n } from "../../lib/field-wiring.js";
|
|
4
4
|
import { mergeRefs as ee } from "../../lib/merge-refs.js";
|
|
5
5
|
import { CLOSE_GLYPH as te } from "../../lib/glyphs.js";
|
|
6
|
-
import { useModality as
|
|
7
|
-
import { c as
|
|
8
|
-
import { useId as
|
|
9
|
-
import { jsx as
|
|
6
|
+
import { useModality as r } from "../../lib/use-modality.js";
|
|
7
|
+
import { c as ne } from "react/compiler-runtime";
|
|
8
|
+
import { useId as re, useState as ie } from "react";
|
|
9
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
10
10
|
//#region src/components/drawer/drawer.tsx
|
|
11
|
-
function
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
let
|
|
15
|
-
open:
|
|
16
|
-
onOpenChange:
|
|
17
|
-
dismissible:
|
|
18
|
-
}),
|
|
19
|
-
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
let
|
|
23
|
-
|
|
24
|
-
let
|
|
25
|
-
function
|
|
26
|
-
|
|
11
|
+
function o(o) {
|
|
12
|
+
let s = ne(66), c, l, u, d, f, p, m, h, g, _, v, y, b, x, S, C, w, T, E;
|
|
13
|
+
s[0] === o ? (c = s[1], l = s[2], u = s[3], d = s[4], f = s[5], p = s[6], m = s[7], h = s[8], g = s[9], _ = s[10], v = s[11], y = s[12], b = s[13], x = s[14], S = s[15], C = s[16], w = s[17], T = s[18], E = s[19]) : ({size: x, side: S, dismissible: C, title: E, description: p, footer: m, closeLabel: f, open: v, defaultOpen: w, unstyled: T, className: d, id: h, ref: b, "aria-describedby": c, "aria-labelledby": l, onClose: g, onOpen: _, children: u, ...y} = o, s[0] = o, s[1] = c, s[2] = l, s[3] = u, s[4] = d, s[5] = f, s[6] = p, s[7] = m, s[8] = h, s[9] = g, s[10] = _, s[11] = v, s[12] = y, s[13] = b, s[14] = x, s[15] = S, s[16] = C, s[17] = w, s[18] = T, s[19] = E);
|
|
14
|
+
let D = x === void 0 ? "md" : x, O = S === void 0 ? "start" : S, ae = C === void 0 || C, oe = w !== void 0 && w, k = T !== void 0 && T, se = re(), [ce, le] = ie(oe), A = r({
|
|
15
|
+
open: v ?? ce,
|
|
16
|
+
onOpenChange: ue,
|
|
17
|
+
dismissible: ae
|
|
18
|
+
}), j = h ?? se, M;
|
|
19
|
+
s[20] === E ? M = s[21] : (M = n(E), s[20] = E, s[21] = M);
|
|
20
|
+
let N = M, P;
|
|
21
|
+
s[22] === p ? P = s[23] : (P = n(p), s[22] = p, s[23] = P);
|
|
22
|
+
let F = P, I = N ? `${j}-title` : void 0, L = F ? `${j}-desc` : void 0, R = L ? c ? `${c} ${L}` : L : c, z;
|
|
23
|
+
s[24] === f ? z = s[25] : (z = n(f), s[24] = f, s[25] = z);
|
|
24
|
+
let B = z, V = N || F || B;
|
|
25
|
+
function ue(e) {
|
|
26
|
+
v === void 0 && le(e), e ? _?.() : g?.();
|
|
27
27
|
}
|
|
28
28
|
let H;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
let U = H, W =
|
|
33
|
-
|
|
29
|
+
s[26] === A ? H = s[27] : (H = function() {
|
|
30
|
+
A.close();
|
|
31
|
+
}, s[26] = A, s[27] = H);
|
|
32
|
+
let U = H, W = D === "md" ? void 0 : D, G = O === "start" ? void 0 : O, K = l ?? I, q;
|
|
33
|
+
s[28] !== d || s[29] !== k ? (q = e("huaira-drawer", d, k), s[28] = d, s[29] = k, s[30] = q) : q = s[30];
|
|
34
34
|
let J;
|
|
35
|
-
|
|
35
|
+
s[31] !== A.ref || s[32] !== b ? (J = ee(b, A.ref), s[31] = A.ref, s[32] = b, s[33] = J) : J = s[33];
|
|
36
36
|
let Y;
|
|
37
|
-
|
|
38
|
-
className: t("huaira-drawer-header",
|
|
37
|
+
s[34] !== f || s[35] !== p || s[36] !== L || s[37] !== U || s[38] !== B || s[39] !== F || s[40] !== V || s[41] !== N || s[42] !== E || s[43] !== I || s[44] !== k ? (Y = V && /* @__PURE__ */ a("header", {
|
|
38
|
+
className: t("huaira-drawer-header", k),
|
|
39
39
|
children: [
|
|
40
|
-
|
|
41
|
-
id: F,
|
|
42
|
-
className: t("huaira-drawer-title", D),
|
|
43
|
-
children: w
|
|
44
|
-
}),
|
|
45
|
-
P && /* @__PURE__ */ r("p", {
|
|
40
|
+
N && /* @__PURE__ */ i("h2", {
|
|
46
41
|
id: I,
|
|
47
|
-
className: t("huaira-drawer-
|
|
48
|
-
children:
|
|
42
|
+
className: t("huaira-drawer-title", k),
|
|
43
|
+
children: E
|
|
44
|
+
}),
|
|
45
|
+
F && /* @__PURE__ */ i("p", {
|
|
46
|
+
id: L,
|
|
47
|
+
className: t("huaira-drawer-desc", k),
|
|
48
|
+
children: p
|
|
49
49
|
}),
|
|
50
|
-
|
|
50
|
+
B && /* @__PURE__ */ i("button", {
|
|
51
51
|
type: "button",
|
|
52
|
-
"aria-label":
|
|
53
|
-
className: t("huaira-drawer-close",
|
|
52
|
+
"aria-label": f,
|
|
53
|
+
className: t("huaira-drawer-close", k),
|
|
54
54
|
onClick: U,
|
|
55
55
|
children: te
|
|
56
56
|
})
|
|
57
57
|
]
|
|
58
|
-
}),
|
|
58
|
+
}), s[34] = f, s[35] = p, s[36] = L, s[37] = U, s[38] = B, s[39] = F, s[40] = V, s[41] = N, s[42] = E, s[43] = I, s[44] = k, s[45] = Y) : Y = s[45];
|
|
59
59
|
let X;
|
|
60
|
-
|
|
60
|
+
s[46] === k ? X = s[47] : (X = t("huaira-drawer-body", k), s[46] = k, s[47] = X);
|
|
61
61
|
let Z;
|
|
62
|
-
|
|
62
|
+
s[48] !== u || s[49] !== X ? (Z = /* @__PURE__ */ i("div", {
|
|
63
63
|
className: X,
|
|
64
|
-
children:
|
|
65
|
-
}),
|
|
64
|
+
children: u
|
|
65
|
+
}), s[48] = u, s[49] = X, s[50] = Z) : Z = s[50];
|
|
66
66
|
let Q;
|
|
67
|
-
|
|
68
|
-
className: t("huaira-drawer-footer",
|
|
69
|
-
children:
|
|
70
|
-
}),
|
|
67
|
+
s[51] !== m || s[52] !== k ? (Q = n(m) && /* @__PURE__ */ i("footer", {
|
|
68
|
+
className: t("huaira-drawer-footer", k),
|
|
69
|
+
children: m
|
|
70
|
+
}), s[51] = m, s[52] = k, s[53] = Q) : Q = s[53];
|
|
71
71
|
let $;
|
|
72
|
-
return
|
|
73
|
-
...
|
|
72
|
+
return s[54] !== R || s[55] !== h || s[56] !== y || s[57] !== W || s[58] !== G || s[59] !== K || s[60] !== q || s[61] !== J || s[62] !== Y || s[63] !== Z || s[64] !== Q ? ($ = /* @__PURE__ */ a("dialog", {
|
|
73
|
+
...y,
|
|
74
74
|
"data-size": W,
|
|
75
75
|
"data-side": G,
|
|
76
|
-
id:
|
|
77
|
-
"aria-describedby":
|
|
76
|
+
id: h,
|
|
77
|
+
"aria-describedby": R,
|
|
78
78
|
"aria-labelledby": K,
|
|
79
79
|
className: q,
|
|
80
80
|
ref: J,
|
|
@@ -83,9 +83,9 @@ function a(a) {
|
|
|
83
83
|
Z,
|
|
84
84
|
Q
|
|
85
85
|
]
|
|
86
|
-
}),
|
|
86
|
+
}), s[54] = R, s[55] = h, s[56] = y, s[57] = W, s[58] = G, s[59] = K, s[60] = q, s[61] = J, s[62] = Y, s[63] = Z, s[64] = Q, s[65] = $) : $ = s[65], $;
|
|
87
87
|
}
|
|
88
88
|
//#endregion
|
|
89
|
-
export {
|
|
89
|
+
export { o as Drawer };
|
|
90
90
|
|
|
91
91
|
//# sourceMappingURL=drawer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.js","names":["useId","useState","composeClassName","partClassName","hasRenderableContent","CLOSE_GLYPH","mergeRefs","useModality","DrawerProps","Drawer","t0","$","_c","ariaDescribedBy","ariaLabelledBy","children","className","closeLabel","description","footer","id","
|
|
1
|
+
{"version":3,"file":"drawer.js","names":["useId","useState","composeClassName","partClassName","hasRenderableContent","CLOSE_GLYPH","mergeRefs","useModality","DrawerProps","Drawer","t0","$","_c","ariaDescribedBy","ariaLabelledBy","children","className","closeLabel","description","footer","id","onClose","onOpen","open","props","ref","t1","t2","t3","t4","t5","title","size","side","dismissible","defaultOpen","unstyled","undefined","generatedId","uncontrolled","setUncontrolled","isOpen","modality","onOpenChange","handleOpenChange","idBase","t6","hasTitle","t7","hasDescription","titleId","descriptionId","describedBy","t8","hasClose","hasHeader","next","t9","handleCloseClick","close","t10","t11","t12","t13","t14","t15","t16","t17","t18","t19"],"sources":["../../../src/components/drawer/drawer.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport { composeClassName, partClassName } from \"../../lib/class-name\";\nimport { hasRenderableContent } from \"../../lib/field-wiring\";\nimport { CLOSE_GLYPH } from \"../../lib/glyphs\";\nimport { mergeRefs } from \"../../lib/merge-refs\";\nimport { useModality } from \"../../lib/use-modality\";\nimport type { DrawerProps } from \"./drawer.types\";\n\nexport function Drawer({\n size = \"md\",\n side = \"start\",\n dismissible = true,\n title,\n description,\n footer,\n closeLabel,\n open,\n defaultOpen = false,\n unstyled = false,\n className,\n id,\n ref,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-labelledby\": ariaLabelledBy,\n onClose,\n onOpen,\n children,\n ...props\n}: Readonly<DrawerProps>) {\n const generatedId = useId();\n const [uncontrolled, setUncontrolled] = useState(defaultOpen);\n const isOpen = open ?? uncontrolled;\n const modality = useModality<HTMLDialogElement>({\n open: isOpen,\n onOpenChange: handleOpenChange,\n dismissible,\n });\n\n const idBase = id ?? generatedId;\n const hasTitle = hasRenderableContent(title);\n const hasDescription = hasRenderableContent(description);\n const titleId = hasTitle ? `${idBase}-title` : undefined;\n const descriptionId = hasDescription ? `${idBase}-desc` : undefined;\n // A consumer description is kept and this one joins it, the way a field\n // merges its hint id (lib/field-wiring.ts).\n const describedBy = descriptionId\n ? ariaDescribedBy\n ? `${ariaDescribedBy} ${descriptionId}`\n : descriptionId\n : ariaDescribedBy;\n // `hasRenderableContent` also rejects `closeLabel=\"\"`, which would render a\n // button with no accessible name.\n const hasClose = hasRenderableContent(closeLabel);\n const hasHeader = hasTitle || hasDescription || hasClose;\n\n // The hook reports the state the panel reached, whoever moved it, so both\n // callbacks fire from here exactly once per transition.\n function handleOpenChange(next: boolean) {\n if (open === undefined) {\n setUncontrolled(next);\n }\n if (next) {\n onOpen?.();\n } else {\n onClose?.();\n }\n }\n\n // Closes through the platform rather than through state: the `close` event\n // is then the one place the transition is reported, and a controlled panel\n // whose consumer has not moved `open` yet still closes.\n function handleCloseClick() {\n modality.close();\n }\n\n // No attribute for `dismissible`: refusing to close is behaviour, and what\n // it produces on screen is the `data-deny` the hook writes.\n return (\n <dialog\n {...props}\n data-size={size === \"md\" ? undefined : size}\n data-side={side === \"start\" ? undefined : side}\n id={id}\n aria-describedby={describedBy}\n aria-labelledby={ariaLabelledBy ?? titleId}\n className={composeClassName(\"huaira-drawer\", className, unstyled)}\n ref={mergeRefs(ref, modality.ref)}\n >\n {hasHeader && (\n <header className={partClassName(\"huaira-drawer-header\", unstyled)}>\n {hasTitle && (\n <h2\n id={titleId}\n className={partClassName(\"huaira-drawer-title\", unstyled)}\n >\n {title}\n </h2>\n )}\n {hasDescription && (\n <p\n id={descriptionId}\n className={partClassName(\"huaira-drawer-desc\", unstyled)}\n >\n {description}\n </p>\n )}\n {hasClose && (\n <button\n type=\"button\"\n aria-label={closeLabel}\n className={partClassName(\"huaira-drawer-close\", unstyled)}\n onClick={handleCloseClick}\n >\n {CLOSE_GLYPH}\n </button>\n )}\n </header>\n )}\n {/* Always rendered: it is the row that scrolls, and the grid places it\n by class rather than by whichever siblings showed up. */}\n <div className={partClassName(\"huaira-drawer-body\", unstyled)}>\n {children}\n </div>\n {hasRenderableContent(footer) && (\n <footer className={partClassName(\"huaira-drawer-footer\", unstyled)}>\n {footer}\n </footer>\n )}\n </dialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ export type DrawerSide = "start" | "end" | "block-start" | "block-end";
|
|
|
18
18
|
* hand-written markup paints the same panel and a consumer's own
|
|
19
19
|
* `showModal()` opens it.
|
|
20
20
|
*/
|
|
21
|
-
export interface DrawerProps extends Omit<ComponentProps<"dialog">, "
|
|
21
|
+
export interface DrawerProps extends Omit<ComponentProps<"dialog">, "onClose" | "open" | "title">, StyleableProps {
|
|
22
22
|
/**
|
|
23
23
|
* Size step from the modality ladder. On `start` and `end` it is the width
|
|
24
24
|
* of the panel; on the two block edges the panel spans the viewport and this
|
|
@@ -68,7 +68,7 @@ export interface DrawerProps extends Omit<ComponentProps<"dialog">, "title" | "o
|
|
|
68
68
|
*/
|
|
69
69
|
closeLabel?: string;
|
|
70
70
|
/**
|
|
71
|
-
* Open state, controlled. Pair it with `
|
|
71
|
+
* Open state, controlled. Pair it with `onClose`: Escape and a backdrop
|
|
72
72
|
* click close the panel without asking React first, and that callback is how
|
|
73
73
|
* the two stay in step.
|
|
74
74
|
*/
|
|
@@ -79,10 +79,20 @@ export interface DrawerProps extends Omit<ComponentProps<"dialog">, "title" | "o
|
|
|
79
79
|
*/
|
|
80
80
|
defaultOpen?: boolean;
|
|
81
81
|
/**
|
|
82
|
-
* Fires
|
|
83
|
-
*
|
|
82
|
+
* Fires once whenever the panel has closed, whoever closed it: Escape, a
|
|
83
|
+
* backdrop click, the close button and the consumer moving `open` to false
|
|
84
|
+
* all arrive here, because the dialog's own `close` event is the single
|
|
85
|
+
* place the transition is read from. It takes the name of the native
|
|
86
|
+
* `close` handler, which the props drop — the same event, minus the one an
|
|
87
|
+
* unmount would raise.
|
|
84
88
|
*/
|
|
85
|
-
|
|
89
|
+
onClose?: () => void;
|
|
90
|
+
/**
|
|
91
|
+
* Fires once whenever the panel has opened, after `showModal()` — including
|
|
92
|
+
* the first render under `defaultOpen`. A panel never opens by itself, so
|
|
93
|
+
* this is a notification, not a state the consumer has to answer.
|
|
94
|
+
*/
|
|
95
|
+
onOpen?: () => void;
|
|
86
96
|
/**
|
|
87
97
|
* The body of the panel: the one row that scrolls when the content is taller
|
|
88
98
|
* than the surface. A body that scrolls needs something focusable inside it,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ModalProps } from './modal.types.js';
|
|
2
|
-
export declare function Modal({ variant, color, size, dismissible, mobileSheet, icon, title, description, footer, closeLabel, open, defaultOpen, unstyled, className, id, ref, "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy,
|
|
2
|
+
export declare function Modal({ variant, color, size, dismissible, mobileSheet, icon, title, description, footer, closeLabel, open, defaultOpen, unstyled, className, id, ref, "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy, onClose, onOpen, children, ...props }: Readonly<ModalProps>): import("react").JSX.Element;
|
|
@@ -1,90 +1,90 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { composeClassName as
|
|
3
|
-
import { hasRenderableContent as
|
|
4
|
-
import { mergeRefs as
|
|
5
|
-
import { CLOSE_GLYPH as
|
|
6
|
-
import { useModality as
|
|
7
|
-
import { c as
|
|
8
|
-
import { useId as
|
|
9
|
-
import { jsx as
|
|
2
|
+
import { composeClassName as e, partClassName as t } from "../../lib/class-name.js";
|
|
3
|
+
import { hasRenderableContent as n } from "../../lib/field-wiring.js";
|
|
4
|
+
import { mergeRefs as ee } from "../../lib/merge-refs.js";
|
|
5
|
+
import { CLOSE_GLYPH as te } from "../../lib/glyphs.js";
|
|
6
|
+
import { useModality as ne } from "../../lib/use-modality.js";
|
|
7
|
+
import { c as re } from "react/compiler-runtime";
|
|
8
|
+
import { useId as ie, useState as ae } from "react";
|
|
9
|
+
import { jsx as r, jsxs as oe } from "react/jsx-runtime";
|
|
10
10
|
//#region src/components/modal/modal.tsx
|
|
11
|
-
function
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
let
|
|
15
|
-
open:
|
|
16
|
-
onOpenChange:
|
|
17
|
-
dismissible:
|
|
18
|
-
}),
|
|
19
|
-
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
let
|
|
23
|
-
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
let
|
|
27
|
-
function
|
|
28
|
-
|
|
11
|
+
function i(i) {
|
|
12
|
+
let a = re(76), o, s, c, l, u, d, f, p, m, h, g, _, v, y, b, x, S, C, w, T, E, D;
|
|
13
|
+
a[0] === i ? (o = a[1], s = a[2], c = a[3], l = a[4], u = a[5], d = a[6], f = a[7], p = a[8], m = a[9], h = a[10], g = a[11], _ = a[12], v = a[13], y = a[14], b = a[15], x = a[16], S = a[17], C = a[18], w = a[19], T = a[20], E = a[21], D = a[22]) : ({variant: x, color: d, size: S, dismissible: C, mobileSheet: w, icon: m, title: D, description: f, footer: p, closeLabel: u, open: v, defaultOpen: T, unstyled: E, className: l, id: h, ref: b, "aria-describedby": o, "aria-labelledby": s, onClose: g, onOpen: _, children: c, ...y} = i, a[0] = i, a[1] = o, a[2] = s, a[3] = c, a[4] = l, a[5] = u, a[6] = d, a[7] = f, a[8] = p, a[9] = m, a[10] = h, a[11] = g, a[12] = _, a[13] = v, a[14] = y, a[15] = b, a[16] = x, a[17] = S, a[18] = C, a[19] = w, a[20] = T, a[21] = E, a[22] = D);
|
|
14
|
+
let O = x === void 0 ? "dialog" : x, se = S === void 0 ? "md" : S, ce = C === void 0 || C, le = w !== void 0 && w, ue = T !== void 0 && T, k = E !== void 0 && E, de = ie(), [fe, pe] = ae(ue), A = ne({
|
|
15
|
+
open: v ?? fe,
|
|
16
|
+
onOpenChange: he,
|
|
17
|
+
dismissible: ce
|
|
18
|
+
}), me = h ?? de, j;
|
|
19
|
+
a[23] === m ? j = a[24] : (j = n(m), a[23] = m, a[24] = j);
|
|
20
|
+
let M = j, N;
|
|
21
|
+
a[25] === D ? N = a[26] : (N = n(D), a[25] = D, a[26] = N);
|
|
22
|
+
let P = N, F;
|
|
23
|
+
a[27] === f ? F = a[28] : (F = n(f), a[27] = f, a[28] = F);
|
|
24
|
+
let I = F, L = P ? `${me}-title` : void 0, R = I ? `${me}-desc` : void 0, z = R ? o ? `${o} ${R}` : R : o, B;
|
|
25
|
+
a[29] === u ? B = a[30] : (B = n(u), a[29] = u, a[30] = B);
|
|
26
|
+
let V = B, H = M || P || I || V;
|
|
27
|
+
function he(e) {
|
|
28
|
+
v === void 0 && pe(e), e ? _?.() : g?.();
|
|
29
29
|
}
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
let
|
|
35
|
-
|
|
30
|
+
let U;
|
|
31
|
+
a[31] === A ? U = a[32] : (U = function() {
|
|
32
|
+
A.close();
|
|
33
|
+
}, a[31] = A, a[32] = U);
|
|
34
|
+
let W = U, ge = O === "alert" ? "alertdialog" : void 0, _e = O === "dialog" ? void 0 : O, ve = se === "md" ? void 0 : se, G = le ? "sheet" : void 0, K = s ?? L, q;
|
|
35
|
+
a[33] !== l || a[34] !== k ? (q = e("huaira-modal", l, k), a[33] = l, a[34] = k, a[35] = q) : q = a[35];
|
|
36
36
|
let J;
|
|
37
|
-
|
|
37
|
+
a[36] !== A.ref || a[37] !== b ? (J = ee(b, A.ref), a[36] = A.ref, a[37] = b, a[38] = J) : J = a[38];
|
|
38
38
|
let Y;
|
|
39
|
-
|
|
40
|
-
className:
|
|
39
|
+
a[39] !== u || a[40] !== f || a[41] !== R || a[42] !== W || a[43] !== V || a[44] !== I || a[45] !== H || a[46] !== M || a[47] !== P || a[48] !== m || a[49] !== D || a[50] !== L || a[51] !== k ? (Y = H && /* @__PURE__ */ oe("header", {
|
|
40
|
+
className: t("huaira-modal-header", k),
|
|
41
41
|
children: [
|
|
42
|
-
|
|
42
|
+
M && /* @__PURE__ */ r("span", {
|
|
43
43
|
"aria-hidden": "true",
|
|
44
|
-
className:
|
|
45
|
-
children:
|
|
44
|
+
className: t("huaira-modal-icon", k),
|
|
45
|
+
children: m
|
|
46
46
|
}),
|
|
47
|
-
|
|
48
|
-
id:
|
|
49
|
-
className:
|
|
50
|
-
children:
|
|
47
|
+
P && /* @__PURE__ */ r("h2", {
|
|
48
|
+
id: L,
|
|
49
|
+
className: t("huaira-modal-title", k),
|
|
50
|
+
children: D
|
|
51
51
|
}),
|
|
52
|
-
|
|
53
|
-
id:
|
|
54
|
-
className:
|
|
55
|
-
children:
|
|
52
|
+
I && /* @__PURE__ */ r("p", {
|
|
53
|
+
id: R,
|
|
54
|
+
className: t("huaira-modal-desc", k),
|
|
55
|
+
children: f
|
|
56
56
|
}),
|
|
57
|
-
|
|
57
|
+
V && /* @__PURE__ */ r("button", {
|
|
58
58
|
type: "button",
|
|
59
|
-
"aria-label":
|
|
60
|
-
className:
|
|
61
|
-
onClick:
|
|
62
|
-
children:
|
|
59
|
+
"aria-label": u,
|
|
60
|
+
className: t("huaira-modal-close", k),
|
|
61
|
+
onClick: W,
|
|
62
|
+
children: te
|
|
63
63
|
})
|
|
64
64
|
]
|
|
65
|
-
}),
|
|
65
|
+
}), a[39] = u, a[40] = f, a[41] = R, a[42] = W, a[43] = V, a[44] = I, a[45] = H, a[46] = M, a[47] = P, a[48] = m, a[49] = D, a[50] = L, a[51] = k, a[52] = Y) : Y = a[52];
|
|
66
66
|
let X;
|
|
67
|
-
|
|
67
|
+
a[53] === k ? X = a[54] : (X = t("huaira-modal-body", k), a[53] = k, a[54] = X);
|
|
68
68
|
let Z;
|
|
69
|
-
|
|
69
|
+
a[55] !== c || a[56] !== X ? (Z = /* @__PURE__ */ r("div", {
|
|
70
70
|
className: X,
|
|
71
|
-
children:
|
|
72
|
-
}),
|
|
71
|
+
children: c
|
|
72
|
+
}), a[55] = c, a[56] = X, a[57] = Z) : Z = a[57];
|
|
73
73
|
let Q;
|
|
74
|
-
|
|
75
|
-
className:
|
|
76
|
-
children:
|
|
77
|
-
}),
|
|
74
|
+
a[58] !== p || a[59] !== k ? (Q = n(p) && /* @__PURE__ */ r("footer", {
|
|
75
|
+
className: t("huaira-modal-footer", k),
|
|
76
|
+
children: p
|
|
77
|
+
}), a[58] = p, a[59] = k, a[60] = Q) : Q = a[60];
|
|
78
78
|
let $;
|
|
79
|
-
return
|
|
80
|
-
...
|
|
81
|
-
role:
|
|
82
|
-
"data-variant":
|
|
83
|
-
"data-color":
|
|
84
|
-
"data-size":
|
|
79
|
+
return a[61] !== d || a[62] !== z || a[63] !== h || a[64] !== y || a[65] !== ge || a[66] !== _e || a[67] !== ve || a[68] !== G || a[69] !== K || a[70] !== q || a[71] !== J || a[72] !== Y || a[73] !== Z || a[74] !== Q ? ($ = /* @__PURE__ */ oe("dialog", {
|
|
80
|
+
...y,
|
|
81
|
+
role: ge,
|
|
82
|
+
"data-variant": _e,
|
|
83
|
+
"data-color": d,
|
|
84
|
+
"data-size": ve,
|
|
85
85
|
"data-mobile": G,
|
|
86
|
-
id:
|
|
87
|
-
"aria-describedby":
|
|
86
|
+
id: h,
|
|
87
|
+
"aria-describedby": z,
|
|
88
88
|
"aria-labelledby": K,
|
|
89
89
|
className: q,
|
|
90
90
|
ref: J,
|
|
@@ -93,9 +93,9 @@ function r(r) {
|
|
|
93
93
|
Z,
|
|
94
94
|
Q
|
|
95
95
|
]
|
|
96
|
-
}),
|
|
96
|
+
}), a[61] = d, a[62] = z, a[63] = h, a[64] = y, a[65] = ge, a[66] = _e, a[67] = ve, a[68] = G, a[69] = K, a[70] = q, a[71] = J, a[72] = Y, a[73] = Z, a[74] = Q, a[75] = $) : $ = a[75], $;
|
|
97
97
|
}
|
|
98
98
|
//#endregion
|
|
99
|
-
export {
|
|
99
|
+
export { i as Modal };
|
|
100
100
|
|
|
101
101
|
//# sourceMappingURL=modal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.js","names":["useId","useState","composeClassName","partClassName","hasRenderableContent","CLOSE_GLYPH","mergeRefs","useModality","ModalProps","Modal","t0","$","_c","ariaDescribedBy","ariaLabelledBy","children","className","closeLabel","color","description","footer","icon","id","onOpenChange","open","props","ref","t1","t2","t3","t4","t5","t6","title","variant","size","dismissible","mobileSheet","defaultOpen","unstyled","undefined","generatedId","uncontrolled","setUncontrolled","isOpen","modality","handleOpenChange","idBase","t7","hasIcon","t8","hasTitle","t9","hasDescription","titleId","descriptionId","describedBy","t10","hasClose","hasHeader","next","t11","handleClose","t12","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23"],"sources":["../../../src/components/modal/modal.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport { composeClassName, partClassName } from \"../../lib/class-name\";\nimport { hasRenderableContent } from \"../../lib/field-wiring\";\nimport { CLOSE_GLYPH } from \"../../lib/glyphs\";\nimport { mergeRefs } from \"../../lib/merge-refs\";\nimport { useModality } from \"../../lib/use-modality\";\nimport type { ModalProps } from \"./modal.types\";\n\nexport function Modal({\n variant = \"dialog\",\n color,\n size = \"md\",\n dismissible = true,\n mobileSheet = false,\n icon,\n title,\n description,\n footer,\n closeLabel,\n open,\n defaultOpen = false,\n unstyled = false,\n className,\n id,\n ref,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-labelledby\": ariaLabelledBy,\n onOpenChange,\n children,\n ...props\n}: Readonly<ModalProps>) {\n const generatedId = useId();\n const [uncontrolled, setUncontrolled] = useState(defaultOpen);\n const isOpen = open ?? uncontrolled;\n const modality = useModality<HTMLDialogElement>({\n open: isOpen,\n onOpenChange: handleOpenChange,\n dismissible,\n });\n\n const idBase = id ?? generatedId;\n const hasIcon = hasRenderableContent(icon);\n const hasTitle = hasRenderableContent(title);\n const hasDescription = hasRenderableContent(description);\n const titleId = hasTitle ? `${idBase}-title` : undefined;\n const descriptionId = hasDescription ? `${idBase}-desc` : undefined;\n // A consumer description is kept and this one joins it, the way a field\n // merges its hint id (lib/field-wiring.ts).\n const describedBy = descriptionId\n ? ariaDescribedBy\n ? `${ariaDescribedBy} ${descriptionId}`\n : descriptionId\n : ariaDescribedBy;\n // `hasRenderableContent` also rejects `closeLabel=\"\"`, which would render a\n // button with no accessible name.\n const hasClose = hasRenderableContent(closeLabel);\n const hasHeader = hasIcon || hasTitle || hasDescription || hasClose;\n\n function handleOpenChange(next: boolean) {\n if (open === undefined) {\n setUncontrolled(next);\n }\n onOpenChange?.(next);\n }\n\n function handleClose() {\n handleOpenChange(false);\n }\n\n // No attribute for `dismissible`: refusing to close is behaviour, and what\n // it produces on screen is the `data-deny` the hook writes.\n return (\n <dialog\n {...props}\n role={variant === \"alert\" ? \"alertdialog\" : undefined}\n data-variant={variant === \"dialog\" ? undefined : variant}\n data-color={color}\n data-size={size === \"md\" ? undefined : size}\n data-mobile={mobileSheet ? \"sheet\" : undefined}\n id={id}\n aria-describedby={describedBy}\n aria-labelledby={ariaLabelledBy ?? titleId}\n className={composeClassName(\"huaira-modal\", className, unstyled)}\n ref={mergeRefs(ref, modality.ref)}\n >\n {hasHeader && (\n <header className={partClassName(\"huaira-modal-header\", unstyled)}>\n {hasIcon && (\n <span\n aria-hidden=\"true\"\n className={partClassName(\"huaira-modal-icon\", unstyled)}\n >\n {icon}\n </span>\n )}\n {hasTitle && (\n <h2\n id={titleId}\n className={partClassName(\"huaira-modal-title\", unstyled)}\n >\n {title}\n </h2>\n )}\n {hasDescription && (\n <p\n id={descriptionId}\n className={partClassName(\"huaira-modal-desc\", unstyled)}\n >\n {description}\n </p>\n )}\n {hasClose && (\n <button\n type=\"button\"\n aria-label={closeLabel}\n className={partClassName(\"huaira-modal-close\", unstyled)}\n onClick={handleClose}\n >\n {CLOSE_GLYPH}\n </button>\n )}\n </header>\n )}\n {/* Always rendered: it is the row that scrolls, and the grid places it\n by class rather than by whichever siblings showed up. */}\n <div className={partClassName(\"huaira-modal-body\", unstyled)}>\n {children}\n </div>\n {hasRenderableContent(footer) && (\n <footer className={partClassName(\"huaira-modal-footer\", unstyled)}>\n {footer}\n </footer>\n )}\n </dialog>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"modal.js","names":["useId","useState","composeClassName","partClassName","hasRenderableContent","CLOSE_GLYPH","mergeRefs","useModality","ModalProps","Modal","t0","$","_c","ariaDescribedBy","ariaLabelledBy","children","className","closeLabel","color","description","footer","icon","id","onClose","onOpen","open","props","ref","t1","t2","t3","t4","t5","t6","title","variant","size","dismissible","mobileSheet","defaultOpen","unstyled","undefined","generatedId","uncontrolled","setUncontrolled","isOpen","modality","onOpenChange","handleOpenChange","idBase","t7","hasIcon","t8","hasTitle","t9","hasDescription","titleId","descriptionId","describedBy","t10","hasClose","hasHeader","next","t11","handleCloseClick","close","t12","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23"],"sources":["../../../src/components/modal/modal.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport { composeClassName, partClassName } from \"../../lib/class-name\";\nimport { hasRenderableContent } from \"../../lib/field-wiring\";\nimport { CLOSE_GLYPH } from \"../../lib/glyphs\";\nimport { mergeRefs } from \"../../lib/merge-refs\";\nimport { useModality } from \"../../lib/use-modality\";\nimport type { ModalProps } from \"./modal.types\";\n\nexport function Modal({\n variant = \"dialog\",\n color,\n size = \"md\",\n dismissible = true,\n mobileSheet = false,\n icon,\n title,\n description,\n footer,\n closeLabel,\n open,\n defaultOpen = false,\n unstyled = false,\n className,\n id,\n ref,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-labelledby\": ariaLabelledBy,\n onClose,\n onOpen,\n children,\n ...props\n}: Readonly<ModalProps>) {\n const generatedId = useId();\n const [uncontrolled, setUncontrolled] = useState(defaultOpen);\n const isOpen = open ?? uncontrolled;\n const modality = useModality<HTMLDialogElement>({\n open: isOpen,\n onOpenChange: handleOpenChange,\n dismissible,\n });\n\n const idBase = id ?? generatedId;\n const hasIcon = hasRenderableContent(icon);\n const hasTitle = hasRenderableContent(title);\n const hasDescription = hasRenderableContent(description);\n const titleId = hasTitle ? `${idBase}-title` : undefined;\n const descriptionId = hasDescription ? `${idBase}-desc` : undefined;\n // A consumer description is kept and this one joins it, the way a field\n // merges its hint id (lib/field-wiring.ts).\n const describedBy = descriptionId\n ? ariaDescribedBy\n ? `${ariaDescribedBy} ${descriptionId}`\n : descriptionId\n : ariaDescribedBy;\n // `hasRenderableContent` also rejects `closeLabel=\"\"`, which would render a\n // button with no accessible name.\n const hasClose = hasRenderableContent(closeLabel);\n const hasHeader = hasIcon || hasTitle || hasDescription || hasClose;\n\n // The hook reports the state the dialog reached, whoever moved it, so both\n // callbacks fire from here exactly once per transition.\n function handleOpenChange(next: boolean) {\n if (open === undefined) {\n setUncontrolled(next);\n }\n if (next) {\n onOpen?.();\n } else {\n onClose?.();\n }\n }\n\n // Closes through the platform rather than through state: the `close` event\n // is then the one place the transition is reported, and a controlled dialog\n // whose consumer has not moved `open` yet still closes.\n function handleCloseClick() {\n modality.close();\n }\n\n // No attribute for `dismissible`: refusing to close is behaviour, and what\n // it produces on screen is the `data-deny` the hook writes.\n return (\n <dialog\n {...props}\n role={variant === \"alert\" ? \"alertdialog\" : undefined}\n data-variant={variant === \"dialog\" ? undefined : variant}\n data-color={color}\n data-size={size === \"md\" ? undefined : size}\n data-mobile={mobileSheet ? \"sheet\" : undefined}\n id={id}\n aria-describedby={describedBy}\n aria-labelledby={ariaLabelledBy ?? titleId}\n className={composeClassName(\"huaira-modal\", className, unstyled)}\n ref={mergeRefs(ref, modality.ref)}\n >\n {hasHeader && (\n <header className={partClassName(\"huaira-modal-header\", unstyled)}>\n {hasIcon && (\n <span\n aria-hidden=\"true\"\n className={partClassName(\"huaira-modal-icon\", unstyled)}\n >\n {icon}\n </span>\n )}\n {hasTitle && (\n <h2\n id={titleId}\n className={partClassName(\"huaira-modal-title\", unstyled)}\n >\n {title}\n </h2>\n )}\n {hasDescription && (\n <p\n id={descriptionId}\n className={partClassName(\"huaira-modal-desc\", unstyled)}\n >\n {description}\n </p>\n )}\n {hasClose && (\n <button\n type=\"button\"\n aria-label={closeLabel}\n className={partClassName(\"huaira-modal-close\", unstyled)}\n onClick={handleCloseClick}\n >\n {CLOSE_GLYPH}\n </button>\n )}\n </header>\n )}\n {/* Always rendered: it is the row that scrolls, and the grid places it\n by class rather than by whichever siblings showed up. */}\n <div className={partClassName(\"huaira-modal-body\", unstyled)}>\n {children}\n </div>\n {hasRenderableContent(footer) && (\n <footer className={partClassName(\"huaira-modal-footer\", unstyled)}>\n {footer}\n </footer>\n )}\n </dialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ import { HuairaColor, HuairaSize, StyleableProps } from '../../types.js';
|
|
|
21
21
|
* `closedby` attribute would replace that plumbing wholesale once they clear
|
|
22
22
|
* the browser floor. Neither is used here yet.
|
|
23
23
|
*/
|
|
24
|
-
export interface ModalProps extends Omit<ComponentProps<"dialog">, "open" | "role" | "title">, StyleableProps {
|
|
24
|
+
export interface ModalProps extends Omit<ComponentProps<"dialog">, "onClose" | "open" | "role" | "title">, StyleableProps {
|
|
25
25
|
/**
|
|
26
26
|
* `alert` is the APG Alert Dialog: `role="alertdialog"`, centred content and
|
|
27
27
|
* a footer of equal actions, for a question that has to be answered before
|
|
@@ -88,7 +88,7 @@ export interface ModalProps extends Omit<ComponentProps<"dialog">, "open" | "rol
|
|
|
88
88
|
*/
|
|
89
89
|
closeLabel?: string;
|
|
90
90
|
/**
|
|
91
|
-
* Open state, controlled. Pair it with `
|
|
91
|
+
* Open state, controlled. Pair it with `onClose`: Escape and a backdrop
|
|
92
92
|
* click close the dialog without asking React first, and that callback is
|
|
93
93
|
* how the two stay in step.
|
|
94
94
|
*/
|
|
@@ -99,10 +99,20 @@ export interface ModalProps extends Omit<ComponentProps<"dialog">, "open" | "rol
|
|
|
99
99
|
*/
|
|
100
100
|
defaultOpen?: boolean;
|
|
101
101
|
/**
|
|
102
|
-
* Fires
|
|
103
|
-
* the
|
|
102
|
+
* Fires once whenever the dialog has closed, whoever closed it: Escape, a
|
|
103
|
+
* backdrop click, the close button and the consumer moving `open` to false
|
|
104
|
+
* all arrive here, because the dialog's own `close` event is the single
|
|
105
|
+
* place the transition is read from. It takes the name of the native
|
|
106
|
+
* `close` handler, which the props drop — the same event, minus the one an
|
|
107
|
+
* unmount would raise.
|
|
104
108
|
*/
|
|
105
|
-
|
|
109
|
+
onClose?: () => void;
|
|
110
|
+
/**
|
|
111
|
+
* Fires once whenever the dialog has opened, after `showModal()` — including
|
|
112
|
+
* the first render under `defaultOpen`. A dialog never opens by itself, so
|
|
113
|
+
* this is a notification, not a state the consumer has to answer.
|
|
114
|
+
*/
|
|
115
|
+
onOpen?: () => void;
|
|
106
116
|
/**
|
|
107
117
|
* The body of the dialog: the one row that scrolls when the content is
|
|
108
118
|
* taller than the surface. A body that scrolls needs something focusable
|
package/lib/use-modality.d.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { RefObject } from 'react';
|
|
|
2
2
|
export interface ModalityOptions {
|
|
3
3
|
/** React's idea of whether the dialog is open. */
|
|
4
4
|
open: boolean;
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Called once with the state the dialog has actually reached, from the
|
|
7
|
+
* `showModal()` that opened it and from its own `close` event. Every path
|
|
8
|
+
* ends there — Escape, the backdrop, a `form method="dialog"`, the consumer
|
|
9
|
+
* flipping `open` — so a caller reports each transition exactly once and
|
|
10
|
+
* never has to tell them apart.
|
|
11
|
+
*/
|
|
6
12
|
onOpenChange: (open: boolean) => void;
|
|
7
13
|
/** False refuses Escape and the backdrop, and shakes the surface instead. */
|
|
8
14
|
dismissible: boolean;
|
|
@@ -10,6 +16,13 @@ export interface ModalityOptions {
|
|
|
10
16
|
export interface Modality<E extends HTMLDialogElement> {
|
|
11
17
|
/** Attach to the dialog element; merge it with your own ref. */
|
|
12
18
|
ref: RefObject<E | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Closes the dialog through the platform rather than through React, which
|
|
21
|
+
* is what a close button calls: the `close` event is then the single place
|
|
22
|
+
* the transition is reported, and a controlled surface whose consumer has
|
|
23
|
+
* not moved `open` yet still closes.
|
|
24
|
+
*/
|
|
25
|
+
close: () => void;
|
|
13
26
|
}
|
|
14
27
|
/**
|
|
15
28
|
* Keeps React's `open` and a `<dialog>`'s own idea of it from drifting apart,
|
|
@@ -17,8 +30,8 @@ export interface Modality<E extends HTMLDialogElement> {
|
|
|
17
30
|
*
|
|
18
31
|
* `showModal()` is the whole mechanism: top layer, focus trap, `inert` on the
|
|
19
32
|
* rest of the page, scrim, Escape and focus restoration all come from it. This
|
|
20
|
-
* hook opens and closes the element, reports
|
|
21
|
-
* and turns a refused dismissal into the `data-deny` animation.
|
|
33
|
+
* hook opens and closes the element, reports every transition the DOM actually
|
|
34
|
+
* made, and turns a refused dismissal into the `data-deny` animation.
|
|
22
35
|
*
|
|
23
36
|
* There is no document-level key listener on purpose: Escape arrives as the
|
|
24
37
|
* `cancel` event, and a popup inside the dialog consumes its own Escape first.
|
package/lib/use-modality.js
CHANGED
|
@@ -16,34 +16,39 @@ function o() {
|
|
|
16
16
|
document.documentElement.style.setProperty("--huaira-modality-scrollbar-comp", `${e}px`);
|
|
17
17
|
}
|
|
18
18
|
function s(r) {
|
|
19
|
-
let i = e(
|
|
20
|
-
i[0] !== l || i[1] !== c
|
|
21
|
-
d.current =
|
|
22
|
-
}, i[0] = l, i[1] = c, i[2] =
|
|
23
|
-
let
|
|
24
|
-
i[
|
|
19
|
+
let i = e(9), { open: s, onOpenChange: c, dismissible: l } = r, u = n(null), d = n(c), f = n(l), p;
|
|
20
|
+
i[0] !== l || i[1] !== c ? (p = () => {
|
|
21
|
+
d.current = c, f.current = l;
|
|
22
|
+
}, i[0] = l, i[1] = c, i[2] = p) : p = i[2], t(p);
|
|
23
|
+
let m, h;
|
|
24
|
+
i[3] === Symbol.for("react.memo_cache_sentinel") ? (m = () => {
|
|
25
25
|
let e = u.current;
|
|
26
26
|
if (e === null) return;
|
|
27
27
|
let t = (t) => {
|
|
28
|
-
|
|
28
|
+
f.current || (t.preventDefault(), a(e));
|
|
29
29
|
}, n = () => {
|
|
30
|
-
d.current
|
|
30
|
+
d.current(!1);
|
|
31
31
|
}, r = (t) => {
|
|
32
32
|
if (t.target !== e) return;
|
|
33
33
|
let n = e.getBoundingClientRect(), { clientX: r, clientY: i } = t;
|
|
34
|
-
n.width > 0 && n.height > 0 && r >= n.left && r <= n.right && i >= n.top && i <= n.bottom || (
|
|
34
|
+
n.width > 0 && n.height > 0 && r >= n.left && r <= n.right && i >= n.top && i <= n.bottom || (f.current ? e.close() : a(e));
|
|
35
35
|
};
|
|
36
36
|
return e.addEventListener("cancel", t), e.addEventListener("close", n), e.addEventListener("click", r), () => {
|
|
37
37
|
e.removeEventListener("cancel", t), e.removeEventListener("close", n), e.removeEventListener("click", r), e.open && e.close();
|
|
38
38
|
};
|
|
39
|
-
},
|
|
40
|
-
let
|
|
41
|
-
i[
|
|
39
|
+
}, h = [], i[3] = m, i[4] = h) : (m = i[3], h = i[4]), t(m, h);
|
|
40
|
+
let g, _;
|
|
41
|
+
i[5] === s ? (g = i[6], _ = i[7]) : (g = () => {
|
|
42
42
|
let e = u.current;
|
|
43
|
-
e === null || typeof e.showModal != "function" || !e.isConnected || (s && !e.open ? (o(), e.showModal()) : !s && e.open && e.close());
|
|
44
|
-
},
|
|
45
|
-
let
|
|
46
|
-
return i[
|
|
43
|
+
e === null || typeof e.showModal != "function" || !e.isConnected || (s && !e.open ? (o(), e.showModal(), d.current(!0)) : !s && e.open && e.close());
|
|
44
|
+
}, _ = [s], i[5] = s, i[6] = g, i[7] = _), t(g, _);
|
|
45
|
+
let v;
|
|
46
|
+
return i[8] === Symbol.for("react.memo_cache_sentinel") ? (v = {
|
|
47
|
+
ref: u,
|
|
48
|
+
close: () => {
|
|
49
|
+
u.current?.close();
|
|
50
|
+
}
|
|
51
|
+
}, i[8] = v) : v = i[8], v;
|
|
47
52
|
}
|
|
48
53
|
//#endregion
|
|
49
54
|
export { s as useModality };
|
package/lib/use-modality.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-modality.js","names":["RefObject","useEffect","useRef","ModalityOptions","open","onOpenChange","dismissible","Modality","HTMLDialogElement","ref","E","DENY_ATTRIBUTE","clearDeny","event","Event","element","currentTarget","HTMLElement","target","removeAttribute","removeEventListener","deny","offsetWidth","setAttribute","addEventListener","publishScrollbarWidth","document","querySelector","width","window","innerWidth","documentElement","clientWidth","style","setProperty","useModality","t0","$","_c","openRef","onOpenChangeRef","dismissibleRef","t1","current","t2","t3","Symbol","for","handleCancel","preventDefault","handleClose","handleClick","event_0","box","getBoundingClientRect","clientX","clientY","MouseEvent","inSurface","height","left","right","top","bottom","close","t4","t5","element_0","showModal","isConnected","t6"],"sources":["../../src/lib/use-modality.ts"],"sourcesContent":["import { type RefObject, useEffect, useRef } from \"react\";\n\nexport interface ModalityOptions {\n /** React's idea of whether the dialog is open. */\n open: boolean;\n /** Called when the dialog closed or opened on its own. */\n onOpenChange: (open: boolean) => void;\n /** False refuses Escape and the backdrop, and shakes the surface instead. */\n dismissible: boolean;\n}\n\nexport interface Modality<E extends HTMLDialogElement> {\n /** Attach to the dialog element; merge it with your own ref. */\n ref: RefObject<E | null>;\n}\n\n/** Presence attribute, written on the element and read by modality.css. */\nconst DENY_ATTRIBUTE = \"data-deny\";\n\nfunction clearDeny(event: Event): void {\n const element = event.currentTarget;\n // Animations inside the dialog bubble up here too; only the surface's own\n // shake ends the refusal.\n if (!(element instanceof HTMLElement) || event.target !== element) {\n return;\n }\n element.removeAttribute(DENY_ATTRIBUTE);\n element.removeEventListener(\"animationend\", clearDeny);\n}\n\n/**\n * Marks the dialog as refusing a dismissal. A DOM write rather than state:\n * re-rendering the surface would disturb whatever the user is doing inside.\n * The animation clears the mark again under reduced motion too — modality.css\n * swaps the keyframes for a still one, so `animationend` always arrives.\n * Without the stylesheet (`unstyled`, or styles.css not loaded) no animation\n * starts and the attribute simply stays until the next refusal: it is inert\n * data there, and a consumer animation ending on the root clears it the same\n * way.\n */\nfunction deny(element: HTMLDialogElement): void {\n element.removeAttribute(DENY_ATTRIBUTE);\n // Reading a layout box is the point here, not the value: it flushes the\n // removal, so a second refusal replays the shake (tabs.tsx reads the same).\n if (element.offsetWidth >= 0) {\n element.setAttribute(DENY_ATTRIBUTE, \"\");\n }\n // The same function twice is one listener in the DOM, so refusals never\n // stack; it takes itself off once the animation it belongs to has ended.\n element.addEventListener(\"animationend\", clearDeny);\n}\n\n/**\n * Publishes the classic scrollbar's width as `--huaira-modality-scrollbar-comp`\n * on the root element, which modality.css reads to compensate the drawer's\n * scroll lock. The lock takes the root scrollbar away and no CSS can know how\n * wide it was, so this is the one thing the native-first ladder leaves to\n * JavaScript here: a measurement. Modal reserves the space with\n * `scrollbar-gutter` instead; a drawer cannot, because the reservation narrows\n * the top layer's containing block (backlog.port-order.md, row 20).\n *\n * The knob is public because padding on the root element cannot reach a\n * `position: fixed` consumer element, which sizes against the viewport: a site\n * with a fixed toolbar reads this value and compensates its own bar. The\n * drawer page documents that use.\n *\n * Nothing is written while a modal dialog is already open: the lock has\n * already removed the scrollbar, so the reading would be a false 0 that\n * overwrote the right value when a second surface opens over the first. The\n * property is never removed either — it is inert once the `:has()` lock stops\n * matching, and the next open with no lock measures it again.\n */\nfunction publishScrollbarWidth(): void {\n if (document.querySelector(\":modal\") !== null) {\n return;\n }\n const width = window.innerWidth - document.documentElement.clientWidth;\n document.documentElement.style.setProperty(\n \"--huaira-modality-scrollbar-comp\",\n `${width}px`,\n );\n}\n\n/**\n * Keeps React's `open` and a `<dialog>`'s own idea of it from drifting apart,\n * and owns the three events the platform raises around a modal dialog.\n *\n * `showModal()` is the whole mechanism: top layer, focus trap, `inert` on the\n * rest of the page, scrim, Escape and focus restoration all come from it. This\n * hook opens and closes the element, reports the closes React did not start,\n * and turns a refused dismissal into the `data-deny` animation.\n *\n * There is no document-level key listener on purpose: Escape arrives as the\n * `cancel` event, and a popup inside the dialog consumes its own Escape first.\n */\nexport function useModality<E extends HTMLDialogElement>({\n open,\n onOpenChange,\n dismissible,\n}: ModalityOptions): Modality<E> {\n const ref = useRef<E | null>(null);\n const openRef = useRef(open);\n const onOpenChangeRef = useRef(onOpenChange);\n const dismissibleRef = useRef(dismissible);\n\n // Latest values for the listeners below, written in an effect and never\n // during render: a render-time ref write bails the React Compiler out.\n useEffect(() => {\n openRef.current = open;\n onOpenChangeRef.current = onOpenChange;\n dismissibleRef.current = dismissible;\n });\n\n // Declared before the reconcile effect so the listeners are attached before\n // the first `showModal`, and so their cleanup runs before the close below:\n // a dialog taken down while open must not report a close nobody asked for.\n useEffect(() => {\n const element = ref.current;\n if (element === null) {\n return;\n }\n\n // Arrows rather than declarations: a hoisted function is analysed before\n // the null check above, so it would lose that narrowing (tabs.tsx).\n const handleCancel = (event: Event) => {\n if (dismissibleRef.current) {\n return;\n }\n // The platform's Escape path. Cancelling it leaves the dialog open, and\n // the shake is the answer the user gets.\n event.preventDefault();\n deny(element);\n };\n\n const handleClose = () => {\n if (openRef.current) {\n onOpenChangeRef.current(false);\n }\n };\n\n const handleClick = (event: Event) => {\n // A backdrop click targets the dialog element itself, but so does a\n // click on any surface the rows leave uncovered — the block drawer\n // sides keep their own gutters beside the centred column. Only a point\n // outside the border box is the backdrop. A zero-size box (jsdom) keeps\n // the target check alone.\n if (event.target !== element) {\n return;\n }\n const box = element.getBoundingClientRect();\n const { clientX, clientY } = event as MouseEvent;\n const inSurface =\n box.width > 0 &&\n box.height > 0 &&\n clientX >= box.left &&\n clientX <= box.right &&\n clientY >= box.top &&\n clientY <= box.bottom;\n if (inSurface) {\n return;\n }\n if (dismissibleRef.current) {\n element.close();\n } else {\n deny(element);\n }\n };\n\n element.addEventListener(\"cancel\", handleCancel);\n element.addEventListener(\"close\", handleClose);\n element.addEventListener(\"click\", handleClick);\n return () => {\n element.removeEventListener(\"cancel\", handleCancel);\n element.removeEventListener(\"close\", handleClose);\n element.removeEventListener(\"click\", handleClick);\n // The top layer does not clean itself up when React drops the element.\n if (element.open) {\n element.close();\n }\n };\n }, []);\n\n useEffect(() => {\n const element = ref.current;\n if (\n element === null ||\n typeof element.showModal !== \"function\" ||\n !element.isConnected\n ) {\n return;\n }\n // Reconcile against the DOM: `showModal` on an open dialog throws\n // InvalidStateError, and Escape can have closed it already.\n if (open && !element.open) {\n publishScrollbarWidth();\n element.showModal();\n } else if (!open && element.open) {\n element.close();\n }\n }, [open]);\n\n return { ref };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-modality.js","names":["RefObject","useEffect","useRef","ModalityOptions","open","onOpenChange","dismissible","Modality","HTMLDialogElement","ref","E","close","DENY_ATTRIBUTE","clearDeny","event","Event","element","currentTarget","HTMLElement","target","removeAttribute","removeEventListener","deny","offsetWidth","setAttribute","addEventListener","publishScrollbarWidth","document","querySelector","width","window","innerWidth","documentElement","clientWidth","style","setProperty","useModality","t0","$","_c","onOpenChangeRef","dismissibleRef","t1","current","t2","t3","Symbol","for","handleCancel","preventDefault","handleClose","handleClick","event_0","box","getBoundingClientRect","clientX","clientY","MouseEvent","inSurface","height","left","right","top","bottom","t4","t5","element_0","showModal","isConnected","t6"],"sources":["../../src/lib/use-modality.ts"],"sourcesContent":["import { type RefObject, useEffect, useRef } from \"react\";\n\nexport interface ModalityOptions {\n /** React's idea of whether the dialog is open. */\n open: boolean;\n /**\n * Called once with the state the dialog has actually reached, from the\n * `showModal()` that opened it and from its own `close` event. Every path\n * ends there — Escape, the backdrop, a `form method=\"dialog\"`, the consumer\n * flipping `open` — so a caller reports each transition exactly once and\n * never has to tell them apart.\n */\n onOpenChange: (open: boolean) => void;\n /** False refuses Escape and the backdrop, and shakes the surface instead. */\n dismissible: boolean;\n}\n\nexport interface Modality<E extends HTMLDialogElement> {\n /** Attach to the dialog element; merge it with your own ref. */\n ref: RefObject<E | null>;\n /**\n * Closes the dialog through the platform rather than through React, which\n * is what a close button calls: the `close` event is then the single place\n * the transition is reported, and a controlled surface whose consumer has\n * not moved `open` yet still closes.\n */\n close: () => void;\n}\n\n/** Presence attribute, written on the element and read by modality.css. */\nconst DENY_ATTRIBUTE = \"data-deny\";\n\nfunction clearDeny(event: Event): void {\n const element = event.currentTarget;\n // Animations inside the dialog bubble up here too; only the surface's own\n // shake ends the refusal.\n if (!(element instanceof HTMLElement) || event.target !== element) {\n return;\n }\n element.removeAttribute(DENY_ATTRIBUTE);\n element.removeEventListener(\"animationend\", clearDeny);\n}\n\n/**\n * Marks the dialog as refusing a dismissal. A DOM write rather than state:\n * re-rendering the surface would disturb whatever the user is doing inside.\n * The animation clears the mark again under reduced motion too — modality.css\n * swaps the keyframes for a still one, so `animationend` always arrives.\n * Without the stylesheet (`unstyled`, or styles.css not loaded) no animation\n * starts and the attribute simply stays until the next refusal: it is inert\n * data there, and a consumer animation ending on the root clears it the same\n * way.\n */\nfunction deny(element: HTMLDialogElement): void {\n element.removeAttribute(DENY_ATTRIBUTE);\n // Reading a layout box is the point here, not the value: it flushes the\n // removal, so a second refusal replays the shake (tabs.tsx reads the same).\n if (element.offsetWidth >= 0) {\n element.setAttribute(DENY_ATTRIBUTE, \"\");\n }\n // The same function twice is one listener in the DOM, so refusals never\n // stack; it takes itself off once the animation it belongs to has ended.\n element.addEventListener(\"animationend\", clearDeny);\n}\n\n/**\n * Publishes the classic scrollbar's width as `--huaira-modality-scrollbar-comp`\n * on the root element, which modality.css reads to compensate the drawer's\n * scroll lock. The lock takes the root scrollbar away and no CSS can know how\n * wide it was, so this is the one thing the native-first ladder leaves to\n * JavaScript here: a measurement. Modal reserves the space with\n * `scrollbar-gutter` instead; a drawer cannot, because the reservation narrows\n * the top layer's containing block (backlog.port-order.md, row 20).\n *\n * The knob is public because padding on the root element cannot reach a\n * `position: fixed` consumer element, which sizes against the viewport: a site\n * with a fixed toolbar reads this value and compensates its own bar. The\n * drawer page documents that use.\n *\n * Nothing is written while a modal dialog is already open: the lock has\n * already removed the scrollbar, so the reading would be a false 0 that\n * overwrote the right value when a second surface opens over the first. The\n * property is never removed either — it is inert once the `:has()` lock stops\n * matching, and the next open with no lock measures it again.\n */\nfunction publishScrollbarWidth(): void {\n if (document.querySelector(\":modal\") !== null) {\n return;\n }\n const width = window.innerWidth - document.documentElement.clientWidth;\n document.documentElement.style.setProperty(\n \"--huaira-modality-scrollbar-comp\",\n `${width}px`,\n );\n}\n\n/**\n * Keeps React's `open` and a `<dialog>`'s own idea of it from drifting apart,\n * and owns the three events the platform raises around a modal dialog.\n *\n * `showModal()` is the whole mechanism: top layer, focus trap, `inert` on the\n * rest of the page, scrim, Escape and focus restoration all come from it. This\n * hook opens and closes the element, reports every transition the DOM actually\n * made, and turns a refused dismissal into the `data-deny` animation.\n *\n * There is no document-level key listener on purpose: Escape arrives as the\n * `cancel` event, and a popup inside the dialog consumes its own Escape first.\n */\nexport function useModality<E extends HTMLDialogElement>({\n open,\n onOpenChange,\n dismissible,\n}: ModalityOptions): Modality<E> {\n const ref = useRef<E | null>(null);\n const onOpenChangeRef = useRef(onOpenChange);\n const dismissibleRef = useRef(dismissible);\n\n // Latest values for the listeners below, written in an effect and never\n // during render: a render-time ref write bails the React Compiler out.\n useEffect(() => {\n onOpenChangeRef.current = onOpenChange;\n dismissibleRef.current = dismissible;\n });\n\n // Declared before the reconcile effect so the listeners are attached before\n // the first `showModal`, and so their cleanup runs before the close below:\n // a dialog taken down while open must not report a close nobody asked for.\n useEffect(() => {\n const element = ref.current;\n if (element === null) {\n return;\n }\n\n // Arrows rather than declarations: a hoisted function is analysed before\n // the null check above, so it would lose that narrowing (tabs.tsx).\n const handleCancel = (event: Event) => {\n if (dismissibleRef.current) {\n return;\n }\n // The platform's Escape path. Cancelling it leaves the dialog open, and\n // the shake is the answer the user gets.\n event.preventDefault();\n deny(element);\n };\n\n // Unconditional: the event fires for the closes React started and for the\n // ones it did not, and both are the same transition to a caller. The\n // cleanup below takes this listener off before it closes the element, so\n // an unmount reports nothing.\n const handleClose = () => {\n onOpenChangeRef.current(false);\n };\n\n const handleClick = (event: Event) => {\n // A backdrop click targets the dialog element itself, but so does a\n // click on any surface the rows leave uncovered — the block drawer\n // sides keep their own gutters beside the centred column. Only a point\n // outside the border box is the backdrop. A zero-size box (jsdom) keeps\n // the target check alone.\n if (event.target !== element) {\n return;\n }\n const box = element.getBoundingClientRect();\n const { clientX, clientY } = event as MouseEvent;\n const inSurface =\n box.width > 0 &&\n box.height > 0 &&\n clientX >= box.left &&\n clientX <= box.right &&\n clientY >= box.top &&\n clientY <= box.bottom;\n if (inSurface) {\n return;\n }\n if (dismissibleRef.current) {\n element.close();\n } else {\n deny(element);\n }\n };\n\n element.addEventListener(\"cancel\", handleCancel);\n element.addEventListener(\"close\", handleClose);\n element.addEventListener(\"click\", handleClick);\n return () => {\n element.removeEventListener(\"cancel\", handleCancel);\n element.removeEventListener(\"close\", handleClose);\n element.removeEventListener(\"click\", handleClick);\n // The top layer does not clean itself up when React drops the element.\n if (element.open) {\n element.close();\n }\n };\n }, []);\n\n useEffect(() => {\n const element = ref.current;\n if (\n element === null ||\n typeof element.showModal !== \"function\" ||\n !element.isConnected\n ) {\n return;\n }\n // Reconcile against the DOM: `showModal` on an open dialog throws\n // InvalidStateError, and Escape can have closed it already.\n if (open && !element.open) {\n publishScrollbarWidth();\n element.showModal();\n // The one transition with no event of its own: a dialog never opens by\n // itself, so this is where an open is reported from.\n onOpenChangeRef.current(true);\n } else if (!open && element.open) {\n element.close();\n }\n }, [open]);\n\n return {\n ref,\n close: () => {\n ref.current?.close();\n },\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "huaira-ui",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "React 19 components with a CSS-custom-property design system: a theme is a block of CSS, the styling API works on hand-written markup, and every field is wired to react-hook-form.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|