@ada-cx/lovelace 1.4.0 → 1.6.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/dist/components/Banner/Banner.css.d.ts +1 -0
- package/dist/components/Banner/Banner.css.js +7 -0
- package/dist/components/Banner/Banner.css.js.map +1 -0
- package/dist/components/Banner/Banner.d.ts +51 -0
- package/dist/components/Banner/Banner.js +25 -0
- package/dist/components/Banner/Banner.js.map +1 -0
- package/dist/components/Banner/BannerSurface.d.ts +17 -0
- package/dist/components/Banner/BannerSurface.js +65 -0
- package/dist/components/Banner/BannerSurface.js.map +1 -0
- package/dist/components/Banner/index.d.ts +1 -0
- package/dist/components/BubbleOverlay/BubbleOverlay.js +21 -20
- package/dist/components/BubbleOverlay/BubbleOverlay.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.css.d.ts +1 -0
- package/dist/components/Checkbox/Checkbox.css.js +6 -6
- package/dist/components/Checkbox/Checkbox.css.js.map +1 -1
- package/dist/components/Checkbox/CheckboxGroup.d.ts +15 -0
- package/dist/components/Checkbox/CheckboxGroup.js +16 -0
- package/dist/components/Checkbox/CheckboxGroup.js.map +1 -0
- package/dist/components/Checkbox/index.d.ts +1 -0
- package/dist/components/Dialog/DialogIcon.js +5 -5
- package/dist/components/DialogOverlay/DialogOverlay.js +23 -22
- package/dist/components/DialogOverlay/DialogOverlay.js.map +1 -1
- package/dist/components/FullscreenOverlay/FullscreenOverlay.js +21 -20
- package/dist/components/FullscreenOverlay/FullscreenOverlay.js.map +1 -1
- package/dist/components/Input/InputRoot.js +4 -4
- package/dist/components/Input/InputTextArea.js +7 -7
- package/dist/components/MenuItem/MenuItemRoot.js +9 -9
- package/dist/components/SheetOverlay/SheetOverlay.js +22 -21
- package/dist/components/SheetOverlay/SheetOverlay.js.map +1 -1
- package/dist/components/ToastNotification/ToastNotification.css.d.ts +1 -14
- package/dist/components/ToastNotification/ToastNotification.css.js +1 -9
- package/dist/components/ToastNotification/ToastNotification.css.js.map +1 -1
- package/dist/components/ToastNotification/ToastNotification.d.ts +30 -11
- package/dist/components/ToastNotification/ToastNotification.js +29 -18
- package/dist/components/ToastNotification/ToastNotification.js.map +1 -1
- package/dist/components/ToastNotification/index.d.ts +1 -1
- package/dist/components/ToastRegion/ToastContent.d.ts +9 -0
- package/dist/components/ToastRegion/ToastRegion.css.d.ts +2 -0
- package/dist/components/ToastRegion/ToastRegion.css.js +7 -0
- package/dist/components/ToastRegion/ToastRegion.css.js.map +1 -0
- package/dist/components/ToastRegion/ToastRegion.d.ts +45 -0
- package/dist/components/ToastRegion/ToastRegion.js +38 -0
- package/dist/components/ToastRegion/ToastRegion.js.map +1 -0
- package/dist/components/ToastRegion/ToastRegionItem.d.ts +13 -0
- package/dist/components/ToastRegion/ToastRegionItem.js +49 -0
- package/dist/components/ToastRegion/ToastRegionItem.js.map +1 -0
- package/dist/components/ToastRegion/ToastRegionLandmark.d.ts +15 -0
- package/dist/components/ToastRegion/ToastRegionLandmark.js +62 -0
- package/dist/components/ToastRegion/ToastRegionLandmark.js.map +1 -0
- package/dist/components/ToastRegion/index.d.ts +4 -0
- package/dist/components/ToastRegion/index.js +3 -0
- package/dist/components/Tooltip/Tooltip.js +8 -8
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/overlayRegistry.d.ts +22 -0
- package/dist/hooks/overlayRegistry.js +32 -0
- package/dist/hooks/overlayRegistry.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +77 -72
- package/dist/runtime/LovelaceProvider.js +12 -12
- package/dist/style.css +1 -1
- package/dist/utils/animation.d.ts +28 -0
- package/dist/utils/animation.js +68 -0
- package/dist/utils/animation.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const bannerSurface: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Banner.css.js","names":[],"sources":["../../../src/components/Banner/Banner.css.ts"],"sourcesContent":["import { style } from \"@vanilla-extract/css\";\nimport { t } from \"../../tokens/index.js\";\n\n// Typed as a plain string: `t()` returns a union of every token name, and a\n// two-property template literal over two of them explodes past what tsc can\n// represent.\nconst surfaceTransition: string = `transform ${t(\"duration-medium\")} ${t(\n\t\"easing-standard\",\n)}, height ${t(\"duration-medium\")} ${t(\"easing-standard\")}, opacity ${t(\n\t\"duration-fast\",\n)} ${t(\"easing-standard\")}`;\n\n// Arrives and leaves by animating its own height, with the message held against\n// the bottom edge so it slides while the box grows or shrinks around it. The two\n// have to move together: a box that holds its full height for the whole travel\n// pushes whatever is below it a full height at once and then leaves it staring at\n// a gap until the message catches up.\nexport const bannerSurface = style({\n\tposition: \"relative\",\n\tdisplay: \"flex\",\n\talignItems: \"flex-end\",\n\toverflow: \"hidden\",\n\tselectors: {\n\t\t// Also translated on the way out, so the message clears the edge above it\n\t\t// rather than only being clipped away.\n\t\t\"&[data-exiting]\": { transform: \"translateY(-100%)\" },\n\t\t// One condition replacing another is a change of message on the same slot,\n\t\t// so the surface fades through the change instead of sliding. Sliding would\n\t\t// report a condition leaving and another arriving, which is not what the\n\t\t// chatter's situation did.\n\t\t\"&[data-swapping]\": { opacity: 0 },\n\t},\n\t\"@media\": {\n\t\t\"(prefers-reduced-motion: no-preference)\": {\n\t\t\ttransition: surfaceTransition,\n\t\t},\n\t},\n});\n"],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { CSSProperties, Ref } from "react";
|
|
2
|
+
import type { ToastStatus } from "../ToastNotification/ToastNotification.js";
|
|
3
|
+
export interface BannerProps {
|
|
4
|
+
/**
|
|
5
|
+
* The condition to report. Text, not nodes: the surface fades through a change
|
|
6
|
+
* of message, and it can only tell one message from another by comparing them.
|
|
7
|
+
*/
|
|
8
|
+
message: string;
|
|
9
|
+
/**
|
|
10
|
+
* The outcome being reported. Also picks the urgency: `error` interrupts as an
|
|
11
|
+
* assertive `alert`, anything else waits its turn as a polite `status`.
|
|
12
|
+
*/
|
|
13
|
+
status?: ToastStatus;
|
|
14
|
+
/** Whether the condition currently holds. */
|
|
15
|
+
visible: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* A counter that advances whenever the condition is reported again. Pass it for
|
|
18
|
+
* a condition that can repeat with the same wording: without it the second
|
|
19
|
+
* report changes nothing in the live region, so a reader never hears it.
|
|
20
|
+
*/
|
|
21
|
+
revision?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Runs when the reader presses dismiss, and renders the button. Clear the state
|
|
24
|
+
* behind `visible` here, or the next change to that state raises the banner
|
|
25
|
+
* again. Omit it for a condition the reader cannot act on.
|
|
26
|
+
*/
|
|
27
|
+
onDismiss?: () => void;
|
|
28
|
+
/** Accessible name for the dismiss button. Localize it. */
|
|
29
|
+
dismissLabel?: string;
|
|
30
|
+
className?: string;
|
|
31
|
+
style?: CSSProperties;
|
|
32
|
+
ref?: Ref<HTMLDivElement>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Reports a condition for as long as it holds — an outage, a lost connection, a
|
|
36
|
+
* failed send. It never queues and never times out, so nothing transient can push
|
|
37
|
+
* it out of view and the message is still there when the reader reaches for it.
|
|
38
|
+
*
|
|
39
|
+
* Pass `onDismiss` only when the reader is meant to act on the condition; a banner
|
|
40
|
+
* bound purely to state offers no control, because only that state takes it down.
|
|
41
|
+
* Either way, read a durable field, never one a dismissal elsewhere can clear — a
|
|
42
|
+
* banner wired to a dismissible field disappears while its condition still holds.
|
|
43
|
+
*
|
|
44
|
+
* One at a time. On a narrow surface a second banner buries the content behind it,
|
|
45
|
+
* so pick the condition to show rather than stacking them. For a finished event
|
|
46
|
+
* rather than a condition, use `ToastRegion`.
|
|
47
|
+
*
|
|
48
|
+
* Mount it unconditionally and drive it with `visible`. Give the container
|
|
49
|
+
* `overflow: hidden` — the banner slides in from the container's leading edge.
|
|
50
|
+
*/
|
|
51
|
+
export declare function Banner({ message, status, visible, revision, onDismiss, dismissLabel, className, style, ref, }: BannerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BannerSurface as e } from "./BannerSurface.js";
|
|
2
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback as n, useState as r } from "react";
|
|
4
|
+
//#region src/components/Banner/Banner.tsx
|
|
5
|
+
function i({ message: i, status: a = "success", visible: o, revision: s, onDismiss: c, dismissLabel: l, className: u, style: d, ref: f }) {
|
|
6
|
+
let [p, m] = r(!1), [h, g] = r(o);
|
|
7
|
+
h !== o && (g(o), m(!o));
|
|
8
|
+
let _ = n(() => m(!1), []);
|
|
9
|
+
return !o && !p ? null : /* @__PURE__ */ t(e, {
|
|
10
|
+
message: i,
|
|
11
|
+
status: a,
|
|
12
|
+
visible: o,
|
|
13
|
+
revision: s,
|
|
14
|
+
onExited: _,
|
|
15
|
+
onDismiss: c,
|
|
16
|
+
dismissLabel: l,
|
|
17
|
+
className: u,
|
|
18
|
+
style: d,
|
|
19
|
+
ref: f
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { i as Banner };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=Banner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Banner.js","names":[],"sources":["../../../src/components/Banner/Banner.tsx"],"sourcesContent":["import type { CSSProperties, Ref } from \"react\";\nimport { useCallback, useState } from \"react\";\nimport type { ToastStatus } from \"../ToastNotification/ToastNotification.js\";\nimport { BannerSurface } from \"./BannerSurface.js\";\n\nexport interface BannerProps {\n\t/**\n\t * The condition to report. Text, not nodes: the surface fades through a change\n\t * of message, and it can only tell one message from another by comparing them.\n\t */\n\tmessage: string;\n\t/**\n\t * The outcome being reported. Also picks the urgency: `error` interrupts as an\n\t * assertive `alert`, anything else waits its turn as a polite `status`.\n\t */\n\tstatus?: ToastStatus;\n\t/** Whether the condition currently holds. */\n\tvisible: boolean;\n\t/**\n\t * A counter that advances whenever the condition is reported again. Pass it for\n\t * a condition that can repeat with the same wording: without it the second\n\t * report changes nothing in the live region, so a reader never hears it.\n\t */\n\trevision?: number;\n\t/**\n\t * Runs when the reader presses dismiss, and renders the button. Clear the state\n\t * behind `visible` here, or the next change to that state raises the banner\n\t * again. Omit it for a condition the reader cannot act on.\n\t */\n\tonDismiss?: () => void;\n\t/** Accessible name for the dismiss button. Localize it. */\n\tdismissLabel?: string;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\tref?: Ref<HTMLDivElement>;\n}\n\n/**\n * Reports a condition for as long as it holds — an outage, a lost connection, a\n * failed send. It never queues and never times out, so nothing transient can push\n * it out of view and the message is still there when the reader reaches for it.\n *\n * Pass `onDismiss` only when the reader is meant to act on the condition; a banner\n * bound purely to state offers no control, because only that state takes it down.\n * Either way, read a durable field, never one a dismissal elsewhere can clear — a\n * banner wired to a dismissible field disappears while its condition still holds.\n *\n * One at a time. On a narrow surface a second banner buries the content behind it,\n * so pick the condition to show rather than stacking them. For a finished event\n * rather than a condition, use `ToastRegion`.\n *\n * Mount it unconditionally and drive it with `visible`. Give the container\n * `overflow: hidden` — the banner slides in from the container's leading edge.\n */\nexport function Banner({\n\tmessage,\n\tstatus = \"success\",\n\tvisible,\n\trevision,\n\tonDismiss,\n\tdismissLabel,\n\tclassName,\n\tstyle,\n\tref,\n}: BannerProps) {\n\tconst [isExiting, setIsExiting] = useState(false);\n\tconst [wasVisible, setWasVisible] = useState(visible);\n\n\t// Derive during render rather than in a layout effect. An effect runs after\n\t// the commit that already returned null, so the surface would unmount and\n\t// come back with its exit animation missed. The previous value is state\n\t// rather than a ref because React can discard a render, which would keep a\n\t// ref write but drop the update beside it.\n\tif (wasVisible !== visible) {\n\t\tsetWasVisible(visible);\n\t\tsetIsExiting(!visible);\n\t}\n\n\tconst handleExited = useCallback(() => setIsExiting(false), []);\n\n\tif (!visible && !isExiting) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<BannerSurface\n\t\t\tmessage={message}\n\t\t\tstatus={status}\n\t\t\tvisible={visible}\n\t\t\trevision={revision}\n\t\t\tonExited={handleExited}\n\t\t\tonDismiss={onDismiss}\n\t\t\tdismissLabel={dismissLabel}\n\t\t\tclassName={className}\n\t\t\tstyle={style}\n\t\t\tref={ref}\n\t\t/>\n\t);\n}\n"],"mappings":";;;;AAsDA,SAAgB,EAAO,EACtB,YACA,YAAS,WACT,YACA,aACA,cACA,iBACA,cACA,UACA,UACe;CACf,IAAM,CAAC,GAAW,KAAgB,EAAS,GAAM,EAC3C,CAAC,GAAY,KAAiB,EAAS,EAAQ;AAOrD,CAAI,MAAe,MAClB,EAAc,EAAQ,EACtB,EAAa,CAAC,EAAQ;CAGvB,IAAM,IAAe,QAAkB,EAAa,GAAM,EAAE,EAAE,CAAC;AAM/D,QAJI,CAAC,KAAW,CAAC,IACT,OAIP,kBAAC,GAAD;EACU;EACD;EACC;EACC;EACV,UAAU;EACC;EACG;EACH;EACJ;EACF;EACJ,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CSSProperties, Ref } from "react";
|
|
2
|
+
import type { ToastStatus } from "../ToastNotification/ToastNotification.js";
|
|
3
|
+
export interface BannerSurfaceProps {
|
|
4
|
+
message: string;
|
|
5
|
+
status: ToastStatus;
|
|
6
|
+
visible: boolean;
|
|
7
|
+
revision?: number;
|
|
8
|
+
/** Runs when the exit animation finishes and the surface can be unmounted. */
|
|
9
|
+
onExited: () => void;
|
|
10
|
+
/** Omit it on a banner that only its condition takes down. */
|
|
11
|
+
onDismiss?: () => void;
|
|
12
|
+
dismissLabel?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
style?: CSSProperties;
|
|
15
|
+
ref?: Ref<HTMLDivElement>;
|
|
16
|
+
}
|
|
17
|
+
export declare function BannerSurface({ message, status, visible, revision, onExited, onDismiss, dismissLabel, className, style, ref: forwardedRef, }: BannerSurfaceProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useExitAnimation as e, useSlideHeight as t } from "../../utils/animation.js";
|
|
2
|
+
import { ToastNotification as n } from "../ToastNotification/ToastNotification.js";
|
|
3
|
+
import { bannerSurface as r } from "./Banner.css.js";
|
|
4
|
+
import { jsx as i } from "react/jsx-runtime";
|
|
5
|
+
import { useEffect as a, useLayoutEffect as o, useRef as s, useState as c } from "react";
|
|
6
|
+
import { useObjectRef as l } from "react-aria/useObjectRef";
|
|
7
|
+
//#region src/components/Banner/BannerSurface.tsx
|
|
8
|
+
function u(e) {
|
|
9
|
+
let [t, n] = c(!1), [r, i] = c(e);
|
|
10
|
+
return r !== e && (i(e), n(!0)), a(() => {
|
|
11
|
+
if (!t) return;
|
|
12
|
+
let e = 0, r = requestAnimationFrame(() => {
|
|
13
|
+
e = requestAnimationFrame(() => n(!1));
|
|
14
|
+
});
|
|
15
|
+
return () => {
|
|
16
|
+
cancelAnimationFrame(r), cancelAnimationFrame(e);
|
|
17
|
+
};
|
|
18
|
+
}, [t]), t;
|
|
19
|
+
}
|
|
20
|
+
function d({ message: d, status: f, visible: p, revision: m, onExited: h, onDismiss: g, dismissLabel: _, className: v, style: y, ref: b }) {
|
|
21
|
+
let x = l(b), S = e(x, p), C = u(d), w = t(x, p), [T, E] = c(!1);
|
|
22
|
+
o(() => {
|
|
23
|
+
E(p);
|
|
24
|
+
}, [p]);
|
|
25
|
+
let D = s(m);
|
|
26
|
+
a(() => {
|
|
27
|
+
if (!p || m === D.current) return;
|
|
28
|
+
D.current = m, E(!1);
|
|
29
|
+
let e = requestAnimationFrame(() => E(!0));
|
|
30
|
+
return () => cancelAnimationFrame(e);
|
|
31
|
+
}, [p, m]), a(() => {
|
|
32
|
+
!p && !S && h();
|
|
33
|
+
}, [
|
|
34
|
+
p,
|
|
35
|
+
S,
|
|
36
|
+
h
|
|
37
|
+
]);
|
|
38
|
+
let O = f === "error";
|
|
39
|
+
return /* @__PURE__ */ i("div", {
|
|
40
|
+
ref: x,
|
|
41
|
+
className: r,
|
|
42
|
+
"data-exiting": S || void 0,
|
|
43
|
+
"data-swapping": C || void 0,
|
|
44
|
+
style: w === null ? void 0 : { height: w },
|
|
45
|
+
children: /* @__PURE__ */ i(n, {
|
|
46
|
+
status: f,
|
|
47
|
+
className: v,
|
|
48
|
+
style: y,
|
|
49
|
+
onDismiss: g,
|
|
50
|
+
dismissDisabled: !p,
|
|
51
|
+
dismissLabel: _,
|
|
52
|
+
messageProps: {
|
|
53
|
+
role: O ? "alert" : "status",
|
|
54
|
+
"aria-live": O ? "assertive" : "polite",
|
|
55
|
+
"aria-atomic": "true",
|
|
56
|
+
"aria-hidden": T ? void 0 : "true"
|
|
57
|
+
},
|
|
58
|
+
children: d
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { d as BannerSurface };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=BannerSurface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BannerSurface.js","names":[],"sources":["../../../src/components/Banner/BannerSurface.tsx"],"sourcesContent":["import type { CSSProperties, Ref } from \"react\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { useObjectRef } from \"react-aria/useObjectRef\";\nimport { useExitAnimation, useSlideHeight } from \"../../utils/animation.js\";\nimport type { ToastStatus } from \"../ToastNotification/ToastNotification.js\";\nimport { ToastNotification } from \"../ToastNotification/ToastNotification.js\";\nimport { bannerSurface } from \"./Banner.css.js\";\n\nexport interface BannerSurfaceProps {\n\tmessage: string;\n\tstatus: ToastStatus;\n\tvisible: boolean;\n\trevision?: number;\n\t/** Runs when the exit animation finishes and the surface can be unmounted. */\n\tonExited: () => void;\n\t/** Omit it on a banner that only its condition takes down. */\n\tonDismiss?: () => void;\n\tdismissLabel?: string;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\tref?: Ref<HTMLDivElement>;\n}\n\n/**\n * Reports one frame of \"the message just changed\", which the surface fades\n * through. Derived from the message rather than an effect: an effect runs after\n * the commit that already painted the new text, so the fade would start from it.\n */\nfunction useSwapAnimation(message: string): boolean {\n\tconst [isSwapping, setIsSwapping] = useState(false);\n\tconst [previousMessage, setPreviousMessage] = useState(message);\n\n\tif (previousMessage !== message) {\n\t\tsetPreviousMessage(message);\n\t\tsetIsSwapping(true);\n\t}\n\n\tuseEffect(() => {\n\t\tif (!isSwapping) {\n\t\t\treturn;\n\t\t}\n\t\t// Two frames: the first is the one the faded-out state paints in, and clearing\n\t\t// the flag before that paint leaves the fade with nothing to run from.\n\t\tlet secondFrame = 0;\n\t\tconst frame = requestAnimationFrame(() => {\n\t\t\tsecondFrame = requestAnimationFrame(() => setIsSwapping(false));\n\t\t});\n\t\treturn () => {\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tcancelAnimationFrame(secondFrame);\n\t\t};\n\t}, [isSwapping]);\n\n\treturn isSwapping;\n}\n\nexport function BannerSurface({\n\tmessage,\n\tstatus,\n\tvisible,\n\trevision,\n\tonExited,\n\tonDismiss,\n\tdismissLabel,\n\tclassName,\n\tstyle,\n\tref: forwardedRef,\n}: BannerSurfaceProps) {\n\t// The animation hooks measure this element, so the consumer's ref has to be the\n\t// same object rather than a second one attached beside it.\n\tconst ref = useObjectRef(forwardedRef);\n\tconst isExiting = useExitAnimation(ref, visible);\n\tconst isSwapping = useSwapAnimation(message);\n\tconst slideHeight = useSlideHeight(ref, visible);\n\n\t// A live region that mounts with its text already in place is missed, so\n\t// reveal the message a beat later and let the mutation be what gets announced.\n\t// react-aria's own toast implementation resorts to the same two-phase flip.\n\t//\n\t// Keyed on `visible` rather than on mount: a condition that clears and returns\n\t// before its exit finishes reuses this surface, and re-revealing the message is\n\t// what makes the second arrival a mutation the reader hears.\n\tconst [isAnnounced, setIsAnnounced] = useState(false);\n\tuseLayoutEffect(() => {\n\t\tsetIsAnnounced(visible);\n\t}, [visible]);\n\n\t// A condition reported again with the same wording leaves the region's text\n\t// untouched, so hide it and reveal it once more: the reveal is the mutation the\n\t// reader hears. Kept apart from the effect above so a first arrival is still\n\t// revealed in the commit that follows it, rather than a frame later.\n\tconst announcedRevision = useRef(revision);\n\tuseEffect(() => {\n\t\tif (!visible || revision === announcedRevision.current) {\n\t\t\treturn;\n\t\t}\n\t\tannouncedRevision.current = revision;\n\t\tsetIsAnnounced(false);\n\t\tconst frame = requestAnimationFrame(() => setIsAnnounced(true));\n\t\treturn () => cancelAnimationFrame(frame);\n\t}, [visible, revision]);\n\n\tuseEffect(() => {\n\t\tif (!visible && !isExiting) {\n\t\t\tonExited();\n\t\t}\n\t}, [visible, isExiting, onExited]);\n\n\tconst isError = status === \"error\";\n\n\treturn (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={bannerSurface}\n\t\t\tdata-exiting={isExiting || undefined}\n\t\t\tdata-swapping={isSwapping || undefined}\n\t\t\tstyle={slideHeight === null ? undefined : { height: slideHeight }}\n\t\t>\n\t\t\t<ToastNotification\n\t\t\t\tstatus={status}\n\t\t\t\tclassName={className}\n\t\t\t\tstyle={style}\n\t\t\t\tonDismiss={onDismiss}\n\t\t\t\t// The condition is already gone by the time the surface is leaving, so\n\t\t\t\t// the press has nothing left to act on.\n\t\t\t\tdismissDisabled={!visible}\n\t\t\t\tdismissLabel={dismissLabel}\n\t\t\t\tmessageProps={{\n\t\t\t\t\trole: isError ? \"alert\" : \"status\",\n\t\t\t\t\t\"aria-live\": isError ? \"assertive\" : \"polite\",\n\t\t\t\t\t\"aria-atomic\": \"true\",\n\t\t\t\t\t\"aria-hidden\": isAnnounced ? undefined : \"true\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{message}\n\t\t\t</ToastNotification>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;;;AA4BA,SAAS,EAAiB,GAA0B;CACnD,IAAM,CAAC,GAAY,KAAiB,EAAS,GAAM,EAC7C,CAAC,GAAiB,KAAsB,EAAS,EAAQ;AAuB/D,QArBI,MAAoB,MACvB,EAAmB,EAAQ,EAC3B,EAAc,GAAK,GAGpB,QAAgB;AACf,MAAI,CAAC,EACJ;EAID,IAAI,IAAc,GACZ,IAAQ,4BAA4B;AACzC,OAAc,4BAA4B,EAAc,GAAM,CAAC;IAC9D;AACF,eAAa;AAEZ,GADA,qBAAqB,EAAM,EAC3B,qBAAqB,EAAY;;IAEhC,CAAC,EAAW,CAAC,EAET;;AAGR,SAAgB,EAAc,EAC7B,YACA,WACA,YACA,aACA,aACA,cACA,iBACA,cACA,UACA,KAAK,KACiB;CAGtB,IAAM,IAAM,EAAa,EAAa,EAChC,IAAY,EAAiB,GAAK,EAAQ,EAC1C,IAAa,EAAiB,EAAQ,EACtC,IAAc,EAAe,GAAK,EAAQ,EAS1C,CAAC,GAAa,KAAkB,EAAS,GAAM;AACrD,SAAsB;AACrB,IAAe,EAAQ;IACrB,CAAC,EAAQ,CAAC;CAMb,IAAM,IAAoB,EAAO,EAAS;AAW1C,CAVA,QAAgB;AACf,MAAI,CAAC,KAAW,MAAa,EAAkB,QAC9C;AAGD,EADA,EAAkB,UAAU,GAC5B,EAAe,GAAM;EACrB,IAAM,IAAQ,4BAA4B,EAAe,GAAK,CAAC;AAC/D,eAAa,qBAAqB,EAAM;IACtC,CAAC,GAAS,EAAS,CAAC,EAEvB,QAAgB;AACf,EAAI,CAAC,KAAW,CAAC,KAChB,GAAU;IAET;EAAC;EAAS;EAAW;EAAS,CAAC;CAElC,IAAM,IAAU,MAAW;AAE3B,QACC,kBAAC,OAAD;EACM;EACL,WAAW;EACX,gBAAc,KAAa,KAAA;EAC3B,iBAAe,KAAc,KAAA;EAC7B,OAAO,MAAgB,OAAO,KAAA,IAAY,EAAE,QAAQ,GAAa;YAEjE,kBAAC,GAAD;GACS;GACG;GACJ;GACI;GAGX,iBAAiB,CAAC;GACJ;GACd,cAAc;IACb,MAAM,IAAU,UAAU;IAC1B,aAAa,IAAU,cAAc;IACrC,eAAe;IACf,eAAe,IAAc,KAAA,IAAY;IACzC;aAEA;GACkB,CAAA;EACf,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Banner, type BannerProps } from "./Banner.js";
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { cx as e } from "../../utils/cx.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Dialog as
|
|
2
|
+
import { OverlayRegistration as t } from "../../hooks/overlayRegistry.js";
|
|
3
|
+
import { bubbleDialog as n, bubbleModal as r, bubbleScrim as i } from "./BubbleOverlay.css.js";
|
|
4
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
5
|
+
import { Dialog as s, Modal as c, ModalOverlay as l } from "react-aria-components";
|
|
6
|
+
import { useLocale as u } from "react-aria";
|
|
6
7
|
//#region src/components/BubbleOverlay/BubbleOverlay.tsx
|
|
7
|
-
function
|
|
8
|
-
let { direction:
|
|
9
|
-
return /* @__PURE__ */
|
|
10
|
-
isOpen:
|
|
11
|
-
onOpenChange:
|
|
12
|
-
isDismissable:
|
|
13
|
-
className:
|
|
14
|
-
dir:
|
|
15
|
-
children: /* @__PURE__ */
|
|
16
|
-
className:
|
|
17
|
-
children: /* @__PURE__ */
|
|
18
|
-
"aria-label":
|
|
19
|
-
className: e(
|
|
20
|
-
children:
|
|
8
|
+
function d({ isOpen: d, onOpenChange: f, isDismissable: p = !0, "aria-label": m, className: h, children: g }) {
|
|
9
|
+
let { direction: _ } = u();
|
|
10
|
+
return /* @__PURE__ */ o(l, {
|
|
11
|
+
isOpen: d,
|
|
12
|
+
onOpenChange: f,
|
|
13
|
+
isDismissable: p,
|
|
14
|
+
className: i,
|
|
15
|
+
dir: _,
|
|
16
|
+
children: [/* @__PURE__ */ a(t, {}), /* @__PURE__ */ a(c, {
|
|
17
|
+
className: r,
|
|
18
|
+
children: /* @__PURE__ */ a(s, {
|
|
19
|
+
"aria-label": m,
|
|
20
|
+
className: e(n, h),
|
|
21
|
+
children: g
|
|
21
22
|
})
|
|
22
|
-
})
|
|
23
|
+
})]
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
26
|
//#endregion
|
|
26
|
-
export {
|
|
27
|
+
export { d as BubbleOverlay };
|
|
27
28
|
|
|
28
29
|
//# sourceMappingURL=BubbleOverlay.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BubbleOverlay.js","names":[],"sources":["../../../src/components/BubbleOverlay/BubbleOverlay.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useLocale } from \"react-aria\";\nimport {\n\tDialog as AriaDialog,\n\tModal,\n\tModalOverlay,\n} from \"react-aria-components\";\nimport { cx } from \"../../utils/cx.js\";\nimport { bubbleDialog, bubbleModal, bubbleScrim } from \"./BubbleOverlay.css.js\";\n\nexport interface BubbleOverlayProps {\n\t/** Whether the bubble is open. */\n\tisOpen: boolean;\n\t/** Called with the next open state on dismiss (outside tap, Escape) or programmatic close. */\n\tonOpenChange: (isOpen: boolean) => void;\n\t/** Dismiss on outside tap. Escape always cancels (RAC default). Defaults to `true`. */\n\tisDismissable?: boolean;\n\t/** Accessible name fallback when the child has no `Sheet.Header` title. */\n\t\"aria-label\"?: string;\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\n/**\n * Non-dimming, near-bottom popover presentation. A compact card centered\n * horizontally near the bottom edge, with a **transparent** backdrop — the chat\n * behind it stays visible. It is still modal (focus-trap + dismiss on outside tap\n * / Escape), matching legacy chat's non-dimming anytime-survey bubble. For a\n * dimming bottom sheet use `SheetOverlay`.\n *\n * Give the dialog an accessible name via a `Sheet.Header` title or the\n * `aria-label` prop.\n */\nexport function BubbleOverlay({\n\tisOpen,\n\tonOpenChange,\n\tisDismissable = true,\n\t\"aria-label\": ariaLabel,\n\tclassName,\n\tchildren,\n}: BubbleOverlayProps) {\n\t// Stated, not inherited: this renders through a portal, so its direction must\n\t// not depend on where the portal lands. See the portalled-surface scenario\n\t// under the RTL requirement in openspec/specs/accessibility/spec.md.\n\tconst { direction } = useLocale();\n\n\treturn (\n\t\t<ModalOverlay\n\t\t\tisOpen={isOpen}\n\t\t\tonOpenChange={onOpenChange}\n\t\t\tisDismissable={isDismissable}\n\t\t\tclassName={bubbleScrim}\n\t\t\tdir={direction}\n\t\t>\n\t\t\t<Modal className={bubbleModal}>\n\t\t\t\t<AriaDialog\n\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\tclassName={cx(bubbleDialog, className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</AriaDialog>\n\t\t\t</Modal>\n\t\t</ModalOverlay>\n\t);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"BubbleOverlay.js","names":[],"sources":["../../../src/components/BubbleOverlay/BubbleOverlay.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useLocale } from \"react-aria\";\nimport {\n\tDialog as AriaDialog,\n\tModal,\n\tModalOverlay,\n} from \"react-aria-components\";\nimport { OverlayRegistration } from \"../../hooks/overlayRegistry.js\";\nimport { cx } from \"../../utils/cx.js\";\nimport { bubbleDialog, bubbleModal, bubbleScrim } from \"./BubbleOverlay.css.js\";\n\nexport interface BubbleOverlayProps {\n\t/** Whether the bubble is open. */\n\tisOpen: boolean;\n\t/** Called with the next open state on dismiss (outside tap, Escape) or programmatic close. */\n\tonOpenChange: (isOpen: boolean) => void;\n\t/** Dismiss on outside tap. Escape always cancels (RAC default). Defaults to `true`. */\n\tisDismissable?: boolean;\n\t/** Accessible name fallback when the child has no `Sheet.Header` title. */\n\t\"aria-label\"?: string;\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\n/**\n * Non-dimming, near-bottom popover presentation. A compact card centered\n * horizontally near the bottom edge, with a **transparent** backdrop — the chat\n * behind it stays visible. It is still modal (focus-trap + dismiss on outside tap\n * / Escape), matching legacy chat's non-dimming anytime-survey bubble. For a\n * dimming bottom sheet use `SheetOverlay`.\n *\n * Give the dialog an accessible name via a `Sheet.Header` title or the\n * `aria-label` prop.\n */\nexport function BubbleOverlay({\n\tisOpen,\n\tonOpenChange,\n\tisDismissable = true,\n\t\"aria-label\": ariaLabel,\n\tclassName,\n\tchildren,\n}: BubbleOverlayProps) {\n\t// Stated, not inherited: this renders through a portal, so its direction must\n\t// not depend on where the portal lands. See the portalled-surface scenario\n\t// under the RTL requirement in openspec/specs/accessibility/spec.md.\n\tconst { direction } = useLocale();\n\n\treturn (\n\t\t<ModalOverlay\n\t\t\tisOpen={isOpen}\n\t\t\tonOpenChange={onOpenChange}\n\t\t\tisDismissable={isDismissable}\n\t\t\tclassName={bubbleScrim}\n\t\t\tdir={direction}\n\t\t>\n\t\t\t<OverlayRegistration />\n\t\t\t<Modal className={bubbleModal}>\n\t\t\t\t<AriaDialog\n\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\tclassName={cx(bubbleDialog, className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</AriaDialog>\n\t\t\t</Modal>\n\t\t</ModalOverlay>\n\t);\n}\n"],"mappings":";;;;;;;AAkCA,SAAgB,EAAc,EAC7B,WACA,iBACA,mBAAgB,IAChB,cAAc,GACd,cACA,eACsB;CAItB,IAAM,EAAE,iBAAc,GAAW;AAEjC,QACC,kBAAC,GAAD;EACS;EACM;EACC;EACf,WAAW;EACX,KAAK;YALN,CAOC,kBAAC,GAAD,EAAuB,CAAA,EACvB,kBAAC,GAAD;GAAO,WAAW;aACjB,kBAAC,GAAD;IACC,cAAY;IACZ,WAAW,EAAG,GAAc,EAAU;IAErC;IACW,CAAA;GACN,CAAA,CACM"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createRuntimeFn as e } from "../../vendor/@vanilla-extract/recipes/dist/createRuntimeFn-62c9670f.esm.js";
|
|
2
2
|
/* empty css */
|
|
3
3
|
//#region src/components/Checkbox/Checkbox.css.ts
|
|
4
|
-
var t = e({
|
|
5
|
-
defaultClassName: "
|
|
4
|
+
var t = "s7h2sn0", n = e({
|
|
5
|
+
defaultClassName: "s7h2sn2",
|
|
6
6
|
variantClassNames: { variant: {
|
|
7
|
-
inline: "
|
|
8
|
-
row: "
|
|
7
|
+
inline: "s7h2sn3",
|
|
8
|
+
row: "s7h2sn4 s7h2sn1"
|
|
9
9
|
} },
|
|
10
10
|
defaultVariants: { variant: "inline" },
|
|
11
11
|
compoundVariants: []
|
|
12
|
-
}),
|
|
12
|
+
}), r = "s7h2sn5", i = "s7h2sn6";
|
|
13
13
|
//#endregion
|
|
14
|
-
export {
|
|
14
|
+
export { r as checkboxBox, i as checkboxGlyph, t as checkboxGroup, n as checkboxRoot };
|
|
15
15
|
|
|
16
16
|
//# sourceMappingURL=Checkbox.css.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.css.js","names":[],"sources":["../../../src/components/Checkbox/Checkbox.css.ts"],"sourcesContent":["import { globalStyle, style } from \"@vanilla-extract/css\";\nimport { recipe } from \"@vanilla-extract/recipes\";\nimport { rowFrame, rowSlotRules } from \"../../styles/row.js\";\nimport { t } from \"../../tokens/index.js\";\n\n// 24px box + 16px glyph mirror Figma's fixed frame sizes (button-size/xs,\n// icon-size/md), which the token set does not expose as spacing values.\nconst BOX_SIZE = \"24px\";\nconst GLYPH_SIZE = \"16px\";\n\n// Empty handle classes: a recipe can't target a descendant, so the row variant's\n// slot rules are attached to a stable class instead (same trick as Button's base).\nconst checkboxRowBase = style({});\n\n/**\n * The RAC `Checkbox` label. `inline` lays the box out beside an optional label;\n * `row` is the 40px selectable row Figma draws for a menu item, for a\n * `CheckboxGroup` rendered as a list of options.\n */\nexport const checkboxRoot = recipe({\n\tbase: {\n\t\tfontFamily: t(\"font-family-body\"),\n\t\tfontWeight: t(\"font-weight-regular\"),\n\t\tfontSize: t(\"font-size-body\"),\n\t\tlineHeight: t(\"line-height-body\"),\n\t\tcolor: t(\"color-content-default\"),\n\t\tcursor: \"pointer\",\n\t\tuserSelect: \"none\",\n\t\toutline: \"none\",\n\t\tselectors: {\n\t\t\t\"&[data-disabled]\": {\n\t\t\t\tcursor: \"not-allowed\",\n\t\t\t\tcolor: t(\"color-content-disabled\"),\n\t\t\t},\n\t\t},\n\t},\n\tvariants: {\n\t\tvariant: {\n\t\t\tinline: {\n\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\talignItems: \"center\",\n\t\t\t\tgap: t(\"gap-12\"),\n\t\t\t},\n\t\t\trow: [checkboxRowBase, rowFrame],\n\t\t},\n\t},\n\tdefaultVariants: { variant: \"inline\" },\n});\n\nglobalStyle(`${checkboxRowBase} > [data-slot=\"icon\"]`, rowSlotRules.icon);\nglobalStyle(`${checkboxRowBase} > [data-slot=\"label\"]`, rowSlotRules.label);\n\n/**\n * The 24px indicator. Its geometry is fixed in every state — a rigid `border-box`\n * square with an always-present 1px border (transparent when filled) and a\n * `box-shadow` focus ring — so selecting/focusing never reflows it.\n *\n * Selection/interaction state lives on the host element (the RAC label, or a\n * `MenuItem` row), so the state rules below are child selectors driven from\n * whichever host carries React Aria's `data-*`. `color` is the inverse content\n * color: it feeds both the glyph stroke and the `currentColor` state-layer\n * overlay, so the overlay is invisible over the light unchecked box (Figma changes\n * only the border on hover) yet lightens the dark filled box.\n */\nexport const checkboxBox = style({\n\tposition: \"relative\",\n\tisolation: \"isolate\",\n\tboxSizing: \"border-box\",\n\tflexShrink: 0,\n\twidth: BOX_SIZE,\n\theight: BOX_SIZE,\n\tborderRadius: t(\"border-radius-6\"),\n\tborderStyle: \"solid\",\n\tborderWidth: t(\"border-width-default\"),\n\tborderColor: t(\"color-border-default\"),\n\tbackgroundColor: t(\"color-background-default\"),\n\tcolor: t(\"color-content-inverse\"),\n\t// No background-color transition, so the fill flips instantly and lands with the glyph.\n\ttransitionProperty: \"border-color, box-shadow\",\n\ttransitionDuration: t(\"duration-fast\"),\n\ttransitionTimingFunction: t(\"easing-standard\"),\n\t\"::after\": {\n\t\tcontent: '\"\"',\n\t\tposition: \"absolute\",\n\t\tinset: 0,\n\t\tborderRadius: \"inherit\",\n\t\tbackgroundColor: \"currentColor\",\n\t\topacity: 0,\n\t\tpointerEvents: \"none\",\n\t\tzIndex: -1,\n\t\ttransition: `opacity ${t(\"duration-fast\")} ${t(\"easing-standard\")}`,\n\t},\n});\n\n/**\n * Checkmark / dash glyph — absolutely centered and toggled by opacity, never\n * in-flow, so revealing it can never shift the box.\n */\nexport const checkboxGlyph = style({\n\tposition: \"absolute\",\n\tinset: 0,\n\tmargin: \"auto\",\n\twidth: GLYPH_SIZE,\n\theight: GLYPH_SIZE,\n\tcolor: \"currentColor\",\n\topacity: 0,\n\tpointerEvents: \"none\",\n});\n\n// Selection and disabled are host-agnostic: any element carrying React Aria's\n// `data-*` drives the box directly below it. Interaction (hover border, state\n// layer, focus ring) additionally requires `[data-state-layer]`, which the\n// indicator sets only when it is the sole affordance — inside a row the row\n// paints those itself.\n\n// Border goes transparent when filled so it folds into the fill (no ring).\nglobalStyle(\n\t`[data-selected] > ${checkboxBox}, [data-indeterminate] > ${checkboxBox}`,\n\t{\n\t\tbackgroundColor: t(\"color-background-inverse\"),\n\t\tborderColor: \"transparent\",\n\t},\n);\n\n// Unchecked hover darkens the border (Figma color/border/medium).\nglobalStyle(\n\t`[data-hovered]:not([data-disabled]):not([data-selected]):not([data-indeterminate]) > ${checkboxBox}[data-state-layer]`,\n\t{ borderColor: t(\"color-border-medium\") },\n);\n\n// State layer — currentColor overlay at per-state opacity, tracking box content color.\nglobalStyle(\n\t`[data-hovered]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-hover\") },\n);\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-focus\") },\n);\nglobalStyle(\n\t`[data-pressed]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-pressed\") },\n);\n\n// Focus ring — box-shadow, so it never changes the box's size.\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]`,\n\t{ boxShadow: `0 0 0 ${t(\"border-width-focus\")} ${t(\"color-border-focus\")}` },\n);\n\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]`,\n\t{\n\t\t\"@media\": {\n\t\t\t\"(forced-colors: active)\": {\n\t\t\t\toutline: \"2px solid Highlight\",\n\t\t\t\toutlineOffset: \"2px\",\n\t\t\t},\n\t\t},\n\t},\n);\n\n// Disabled wins over the filled rule: light fill, default border, faded glyph\n// (Figma color/content/disabled).\nglobalStyle(`[data-disabled] > ${checkboxBox}`, {\n\tbackgroundColor: t(\"color-background-disabled\"),\n\tborderColor: t(\"color-border-default\"),\n\tcolor: t(\"color-content-disabled\"),\n});\n\n// Reveal the matching glyph. Dash wins for the mixed state; the check shows only\n// when selected and not indeterminate.\nglobalStyle(\n\t`[data-selected]:not([data-indeterminate]) > ${checkboxBox} > ${checkboxGlyph}[data-glyph=\"check\"]`,\n\t{ opacity: 1 },\n);\nglobalStyle(\n\t`[data-indeterminate] > ${checkboxBox} > ${checkboxGlyph}[data-glyph=\"dash\"]`,\n\t{ opacity: 1 },\n);\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Checkbox.css.js","names":[],"sources":["../../../src/components/Checkbox/Checkbox.css.ts"],"sourcesContent":["import { globalStyle, style } from \"@vanilla-extract/css\";\nimport { recipe } from \"@vanilla-extract/recipes\";\nimport { rowFrame, rowSlotRules } from \"../../styles/row.js\";\nimport { t } from \"../../tokens/index.js\";\n\n// 24px box + 16px glyph mirror Figma's fixed frame sizes (button-size/xs,\n// icon-size/md), which the token set does not expose as spacing values.\nconst BOX_SIZE = \"24px\";\nconst GLYPH_SIZE = \"16px\";\n\nexport const checkboxGroup = style({\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tgap: t(\"gap-20\"),\n});\n\n// Empty handle classes: a recipe can't target a descendant, so the row variant's\n// slot rules are attached to a stable class instead (same trick as Button's base).\nconst checkboxRowBase = style({});\n\n/**\n * The RAC `Checkbox` label. `inline` lays the box out beside an optional label;\n * `row` is the 40px selectable row Figma draws for a menu item, for a\n * `CheckboxGroup` rendered as a list of options.\n */\nexport const checkboxRoot = recipe({\n\tbase: {\n\t\tfontFamily: t(\"font-family-body\"),\n\t\tfontWeight: t(\"font-weight-regular\"),\n\t\tfontSize: t(\"font-size-body\"),\n\t\tlineHeight: t(\"line-height-body\"),\n\t\tcolor: t(\"color-content-default\"),\n\t\tcursor: \"pointer\",\n\t\tuserSelect: \"none\",\n\t\toutline: \"none\",\n\t\tselectors: {\n\t\t\t\"&[data-disabled]\": {\n\t\t\t\tcursor: \"not-allowed\",\n\t\t\t\tcolor: t(\"color-content-disabled\"),\n\t\t\t},\n\t\t},\n\t},\n\tvariants: {\n\t\tvariant: {\n\t\t\tinline: {\n\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\talignItems: \"center\",\n\t\t\t\tgap: t(\"gap-12\"),\n\t\t\t},\n\t\t\trow: [checkboxRowBase, rowFrame],\n\t\t},\n\t},\n\tdefaultVariants: { variant: \"inline\" },\n});\n\nglobalStyle(`${checkboxRowBase} > [data-slot=\"icon\"]`, rowSlotRules.icon);\nglobalStyle(`${checkboxRowBase} > [data-slot=\"label\"]`, rowSlotRules.label);\n\n/**\n * The 24px indicator. Its geometry is fixed in every state — a rigid `border-box`\n * square with an always-present 1px border (transparent when filled) and a\n * `box-shadow` focus ring — so selecting/focusing never reflows it.\n *\n * Selection/interaction state lives on the host element (the RAC label, or a\n * `MenuItem` row), so the state rules below are child selectors driven from\n * whichever host carries React Aria's `data-*`. `color` is the inverse content\n * color: it feeds both the glyph stroke and the `currentColor` state-layer\n * overlay, so the overlay is invisible over the light unchecked box (Figma changes\n * only the border on hover) yet lightens the dark filled box.\n */\nexport const checkboxBox = style({\n\tposition: \"relative\",\n\tisolation: \"isolate\",\n\tboxSizing: \"border-box\",\n\tflexShrink: 0,\n\twidth: BOX_SIZE,\n\theight: BOX_SIZE,\n\tborderRadius: t(\"border-radius-6\"),\n\tborderStyle: \"solid\",\n\tborderWidth: t(\"border-width-default\"),\n\tborderColor: t(\"color-border-default\"),\n\tbackgroundColor: t(\"color-background-default\"),\n\tcolor: t(\"color-content-inverse\"),\n\t// No background-color transition, so the fill flips instantly and lands with the glyph.\n\ttransitionProperty: \"border-color, box-shadow\",\n\ttransitionDuration: t(\"duration-fast\"),\n\ttransitionTimingFunction: t(\"easing-standard\"),\n\t\"::after\": {\n\t\tcontent: '\"\"',\n\t\tposition: \"absolute\",\n\t\tinset: 0,\n\t\tborderRadius: \"inherit\",\n\t\tbackgroundColor: \"currentColor\",\n\t\topacity: 0,\n\t\tpointerEvents: \"none\",\n\t\tzIndex: -1,\n\t\ttransition: `opacity ${t(\"duration-fast\")} ${t(\"easing-standard\")}`,\n\t},\n});\n\n/**\n * Checkmark / dash glyph — absolutely centered and toggled by opacity, never\n * in-flow, so revealing it can never shift the box.\n */\nexport const checkboxGlyph = style({\n\tposition: \"absolute\",\n\tinset: 0,\n\tmargin: \"auto\",\n\twidth: GLYPH_SIZE,\n\theight: GLYPH_SIZE,\n\tcolor: \"currentColor\",\n\topacity: 0,\n\tpointerEvents: \"none\",\n});\n\n// Selection and disabled are host-agnostic: any element carrying React Aria's\n// `data-*` drives the box directly below it. Interaction (hover border, state\n// layer, focus ring) additionally requires `[data-state-layer]`, which the\n// indicator sets only when it is the sole affordance — inside a row the row\n// paints those itself.\n\n// Border goes transparent when filled so it folds into the fill (no ring).\nglobalStyle(\n\t`[data-selected] > ${checkboxBox}, [data-indeterminate] > ${checkboxBox}`,\n\t{\n\t\tbackgroundColor: t(\"color-background-inverse\"),\n\t\tborderColor: \"transparent\",\n\t},\n);\n\n// Unchecked hover darkens the border (Figma color/border/medium).\nglobalStyle(\n\t`[data-hovered]:not([data-disabled]):not([data-selected]):not([data-indeterminate]) > ${checkboxBox}[data-state-layer]`,\n\t{ borderColor: t(\"color-border-medium\") },\n);\n\n// State layer — currentColor overlay at per-state opacity, tracking box content color.\nglobalStyle(\n\t`[data-hovered]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-hover\") },\n);\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-focus\") },\n);\nglobalStyle(\n\t`[data-pressed]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-pressed\") },\n);\n\n// Focus ring — box-shadow, so it never changes the box's size.\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]`,\n\t{ boxShadow: `0 0 0 ${t(\"border-width-focus\")} ${t(\"color-border-focus\")}` },\n);\n\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]`,\n\t{\n\t\t\"@media\": {\n\t\t\t\"(forced-colors: active)\": {\n\t\t\t\toutline: \"2px solid Highlight\",\n\t\t\t\toutlineOffset: \"2px\",\n\t\t\t},\n\t\t},\n\t},\n);\n\n// Disabled wins over the filled rule: light fill, default border, faded glyph\n// (Figma color/content/disabled).\nglobalStyle(`[data-disabled] > ${checkboxBox}`, {\n\tbackgroundColor: t(\"color-background-disabled\"),\n\tborderColor: t(\"color-border-default\"),\n\tcolor: t(\"color-content-disabled\"),\n});\n\n// Reveal the matching glyph. Dash wins for the mixed state; the check shows only\n// when selected and not indeterminate.\nglobalStyle(\n\t`[data-selected]:not([data-indeterminate]) > ${checkboxBox} > ${checkboxGlyph}[data-glyph=\"check\"]`,\n\t{ opacity: 1 },\n);\nglobalStyle(\n\t`[data-indeterminate] > ${checkboxBox} > ${checkboxGlyph}[data-glyph=\"dash\"]`,\n\t{ opacity: 1 },\n);\n"],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode, Ref } from "react";
|
|
2
|
+
import type { CheckboxGroupProps as AriaCheckboxGroupProps } from "react-aria-components";
|
|
3
|
+
export interface CheckboxGroupProps extends Omit<AriaCheckboxGroupProps, "className" | "style" | "children"> {
|
|
4
|
+
className?: string;
|
|
5
|
+
style?: CSSProperties;
|
|
6
|
+
ref?: Ref<HTMLDivElement>;
|
|
7
|
+
/** The `Checkbox` options for this group. */
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Multi-select group: any number of child `Checkbox` options may be selected.
|
|
12
|
+
* Owns the selected values (`value`/`onChange`) and the group's accessible
|
|
13
|
+
* name — supply `aria-label` or `aria-labelledby`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function CheckboxGroup({ className, children, ...rest }: CheckboxGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { cx as e } from "../../utils/cx.js";
|
|
2
|
+
import { checkboxGroup as t } from "./Checkbox.css.js";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
4
|
+
import { CheckboxGroup as r } from "react-aria-components";
|
|
5
|
+
//#region src/components/Checkbox/CheckboxGroup.tsx
|
|
6
|
+
function i({ className: i, children: a, ...o }) {
|
|
7
|
+
return /* @__PURE__ */ n(r, {
|
|
8
|
+
...o,
|
|
9
|
+
className: e(t, i),
|
|
10
|
+
children: a
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { i as CheckboxGroup };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=CheckboxGroup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CheckboxGroup.js","names":[],"sources":["../../../src/components/Checkbox/CheckboxGroup.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode, Ref } from \"react\";\nimport type { CheckboxGroupProps as AriaCheckboxGroupProps } from \"react-aria-components\";\nimport { CheckboxGroup as AriaCheckboxGroup } from \"react-aria-components\";\nimport { cx } from \"../../utils/cx.js\";\nimport { checkboxGroup } from \"./Checkbox.css.js\";\n\nexport interface CheckboxGroupProps\n\textends Omit<AriaCheckboxGroupProps, \"className\" | \"style\" | \"children\"> {\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\tref?: Ref<HTMLDivElement>;\n\t/** The `Checkbox` options for this group. */\n\tchildren: ReactNode;\n}\n\n/**\n * Multi-select group: any number of child `Checkbox` options may be selected.\n * Owns the selected values (`value`/`onChange`) and the group's accessible\n * name — supply `aria-label` or `aria-labelledby`.\n */\nexport function CheckboxGroup({\n\tclassName,\n\tchildren,\n\t...rest\n}: CheckboxGroupProps) {\n\treturn (\n\t\t<AriaCheckboxGroup {...rest} className={cx(checkboxGroup, className)}>\n\t\t\t{children}\n\t\t</AriaCheckboxGroup>\n\t);\n}\n"],"mappings":";;;;;AAoBA,SAAgB,EAAc,EAC7B,cACA,aACA,GAAG,KACmB;AACtB,QACC,kBAAC,GAAD;EAAmB,GAAI;EAAM,WAAW,EAAG,GAAe,EAAU;EAClE;EACkB,CAAA"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { cx as e } from "../../utils/cx.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { Checkmark as t } from "../Icon/icons/Checkmark.js";
|
|
3
|
+
import { ExclamationTriangle as n } from "../Icon/icons/ExclamationTriangle.js";
|
|
4
|
+
import { dialogIcon as r } from "./Dialog.css.js";
|
|
5
5
|
import { jsx as i } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/Dialog/DialogIcon.tsx
|
|
7
7
|
function a({ intent: a, className: o }) {
|
|
8
|
-
let s = a === "warning" ?
|
|
8
|
+
let s = a === "warning" ? n : t;
|
|
9
9
|
return /* @__PURE__ */ i("span", {
|
|
10
10
|
"data-intent": a,
|
|
11
|
-
className: e(
|
|
11
|
+
className: e(r({ intent: a }), o),
|
|
12
12
|
children: /* @__PURE__ */ i(s, {})
|
|
13
13
|
});
|
|
14
14
|
}
|
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
import { cx as e } from "../../utils/cx.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Dialog as
|
|
2
|
+
import { OverlayRegistration as t } from "../../hooks/overlayRegistry.js";
|
|
3
|
+
import { dialogOverlayCard as n, dialogOverlayScrim as r, dialogOverlaySurface as i } from "./DialogOverlay.css.js";
|
|
4
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
5
|
+
import { Dialog as s, Modal as c, ModalOverlay as l } from "react-aria-components";
|
|
6
|
+
import { useLocale as u } from "react-aria";
|
|
6
7
|
//#region src/components/DialogOverlay/DialogOverlay.tsx
|
|
7
|
-
function
|
|
8
|
-
let { direction:
|
|
9
|
-
return /* @__PURE__ */
|
|
10
|
-
isOpen:
|
|
11
|
-
onOpenChange:
|
|
12
|
-
isDismissable:
|
|
13
|
-
className:
|
|
14
|
-
dir:
|
|
15
|
-
children: /* @__PURE__ */
|
|
16
|
-
className:
|
|
17
|
-
children: /* @__PURE__ */
|
|
18
|
-
role:
|
|
19
|
-
"aria-label":
|
|
20
|
-
"aria-describedby":
|
|
21
|
-
className: e(
|
|
22
|
-
children:
|
|
8
|
+
function d({ isOpen: d, onOpenChange: f, isDismissable: p = !0, role: m = "dialog", "aria-label": h, "aria-describedby": g, className: _, children: v }) {
|
|
9
|
+
let { direction: y } = u();
|
|
10
|
+
return /* @__PURE__ */ o(l, {
|
|
11
|
+
isOpen: d,
|
|
12
|
+
onOpenChange: f,
|
|
13
|
+
isDismissable: p,
|
|
14
|
+
className: r,
|
|
15
|
+
dir: y,
|
|
16
|
+
children: [/* @__PURE__ */ a(t, {}), /* @__PURE__ */ a(c, {
|
|
17
|
+
className: n,
|
|
18
|
+
children: /* @__PURE__ */ a(s, {
|
|
19
|
+
role: m,
|
|
20
|
+
"aria-label": h,
|
|
21
|
+
"aria-describedby": g,
|
|
22
|
+
className: e(i, _),
|
|
23
|
+
children: v
|
|
23
24
|
})
|
|
24
|
-
})
|
|
25
|
+
})]
|
|
25
26
|
});
|
|
26
27
|
}
|
|
27
28
|
//#endregion
|
|
28
|
-
export {
|
|
29
|
+
export { d as DialogOverlay };
|
|
29
30
|
|
|
30
31
|
//# sourceMappingURL=DialogOverlay.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DialogOverlay.js","names":[],"sources":["../../../src/components/DialogOverlay/DialogOverlay.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useLocale } from \"react-aria\";\nimport {\n\tDialog as AriaDialog,\n\tModal,\n\tModalOverlay,\n} from \"react-aria-components\";\nimport { cx } from \"../../utils/cx.js\";\nimport {\n\tdialogOverlayCard,\n\tdialogOverlayScrim,\n\tdialogOverlaySurface,\n} from \"./DialogOverlay.css.js\";\n\nexport interface DialogOverlayProps {\n\t/** Whether the dialog is open. */\n\tisOpen: boolean;\n\t/** Called with the next open state on dismiss (scrim tap, Escape) or programmatic close. */\n\tonOpenChange: (isOpen: boolean) => void;\n\t/** Dismiss on scrim tap. Escape always cancels (RAC default). Defaults to `true`. */\n\tisDismissable?: boolean;\n\t/**\n\t * `alertdialog` for an interruption that must not be dismissed by tapping away;\n\t * `dialog` otherwise. Defaults to `dialog`.\n\t */\n\trole?: \"dialog\" | \"alertdialog\";\n\t/** Accessible name fallback when the children supply no `slot=\"title\"` heading. */\n\t\"aria-label\"?: string;\n\t/**\n\t * Id of the element describing the dialog — the `alertdialog` pattern expects\n\t * one, so point it at the `Dialog.Body` carrying the message.\n\t */\n\t\"aria-describedby\"?: string;\n\t/** Extends the focus-trap surface (e.g. content arrangement). */\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\n/**\n * Centered modal-dialog presentation: dark scrim, centered card, focus-trap,\n * dismiss-on-tap/Escape, scale-in. Wraps arbitrary children (typically a `Dialog`\n * content stack). For a bottom sheet use `SheetOverlay`; for a full-window surface\n * `FullscreenOverlay`; for a non-dimming bubble `BubbleOverlay`.\n *\n * `role=\"alertdialog\"` + `isDismissable={false}` for an interruption that must not\n * be dismissed by tapping away (Escape still cancels); the `dialog` defaults\n * otherwise. Give it an accessible name via a `Dialog.Title` or `aria-label`.\n */\nexport function DialogOverlay({\n\tisOpen,\n\tonOpenChange,\n\tisDismissable = true,\n\trole = \"dialog\",\n\t\"aria-label\": ariaLabel,\n\t\"aria-describedby\": ariaDescribedBy,\n\tclassName,\n\tchildren,\n}: DialogOverlayProps) {\n\t// Stated, not inherited: this renders through a portal, so its direction must\n\t// not depend on where the portal lands. See the portalled-surface scenario\n\t// under the RTL requirement in openspec/specs/accessibility/spec.md.\n\tconst { direction } = useLocale();\n\n\treturn (\n\t\t<ModalOverlay\n\t\t\tisOpen={isOpen}\n\t\t\tonOpenChange={onOpenChange}\n\t\t\tisDismissable={isDismissable}\n\t\t\tclassName={dialogOverlayScrim}\n\t\t\tdir={direction}\n\t\t>\n\t\t\t<Modal className={dialogOverlayCard}>\n\t\t\t\t<AriaDialog\n\t\t\t\t\trole={role}\n\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\taria-describedby={ariaDescribedBy}\n\t\t\t\t\tclassName={cx(dialogOverlaySurface, className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</AriaDialog>\n\t\t\t</Modal>\n\t\t</ModalOverlay>\n\t);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"DialogOverlay.js","names":[],"sources":["../../../src/components/DialogOverlay/DialogOverlay.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useLocale } from \"react-aria\";\nimport {\n\tDialog as AriaDialog,\n\tModal,\n\tModalOverlay,\n} from \"react-aria-components\";\nimport { OverlayRegistration } from \"../../hooks/overlayRegistry.js\";\nimport { cx } from \"../../utils/cx.js\";\nimport {\n\tdialogOverlayCard,\n\tdialogOverlayScrim,\n\tdialogOverlaySurface,\n} from \"./DialogOverlay.css.js\";\n\nexport interface DialogOverlayProps {\n\t/** Whether the dialog is open. */\n\tisOpen: boolean;\n\t/** Called with the next open state on dismiss (scrim tap, Escape) or programmatic close. */\n\tonOpenChange: (isOpen: boolean) => void;\n\t/** Dismiss on scrim tap. Escape always cancels (RAC default). Defaults to `true`. */\n\tisDismissable?: boolean;\n\t/**\n\t * `alertdialog` for an interruption that must not be dismissed by tapping away;\n\t * `dialog` otherwise. Defaults to `dialog`.\n\t */\n\trole?: \"dialog\" | \"alertdialog\";\n\t/** Accessible name fallback when the children supply no `slot=\"title\"` heading. */\n\t\"aria-label\"?: string;\n\t/**\n\t * Id of the element describing the dialog — the `alertdialog` pattern expects\n\t * one, so point it at the `Dialog.Body` carrying the message.\n\t */\n\t\"aria-describedby\"?: string;\n\t/** Extends the focus-trap surface (e.g. content arrangement). */\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\n/**\n * Centered modal-dialog presentation: dark scrim, centered card, focus-trap,\n * dismiss-on-tap/Escape, scale-in. Wraps arbitrary children (typically a `Dialog`\n * content stack). For a bottom sheet use `SheetOverlay`; for a full-window surface\n * `FullscreenOverlay`; for a non-dimming bubble `BubbleOverlay`.\n *\n * `role=\"alertdialog\"` + `isDismissable={false}` for an interruption that must not\n * be dismissed by tapping away (Escape still cancels); the `dialog` defaults\n * otherwise. Give it an accessible name via a `Dialog.Title` or `aria-label`.\n */\nexport function DialogOverlay({\n\tisOpen,\n\tonOpenChange,\n\tisDismissable = true,\n\trole = \"dialog\",\n\t\"aria-label\": ariaLabel,\n\t\"aria-describedby\": ariaDescribedBy,\n\tclassName,\n\tchildren,\n}: DialogOverlayProps) {\n\t// Stated, not inherited: this renders through a portal, so its direction must\n\t// not depend on where the portal lands. See the portalled-surface scenario\n\t// under the RTL requirement in openspec/specs/accessibility/spec.md.\n\tconst { direction } = useLocale();\n\n\treturn (\n\t\t<ModalOverlay\n\t\t\tisOpen={isOpen}\n\t\t\tonOpenChange={onOpenChange}\n\t\t\tisDismissable={isDismissable}\n\t\t\tclassName={dialogOverlayScrim}\n\t\t\tdir={direction}\n\t\t>\n\t\t\t<OverlayRegistration />\n\t\t\t<Modal className={dialogOverlayCard}>\n\t\t\t\t<AriaDialog\n\t\t\t\t\trole={role}\n\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\taria-describedby={ariaDescribedBy}\n\t\t\t\t\tclassName={cx(dialogOverlaySurface, className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</AriaDialog>\n\t\t\t</Modal>\n\t\t</ModalOverlay>\n\t);\n}\n"],"mappings":";;;;;;;AAiDA,SAAgB,EAAc,EAC7B,WACA,iBACA,mBAAgB,IAChB,UAAO,UACP,cAAc,GACd,oBAAoB,GACpB,cACA,eACsB;CAItB,IAAM,EAAE,iBAAc,GAAW;AAEjC,QACC,kBAAC,GAAD;EACS;EACM;EACC;EACf,WAAW;EACX,KAAK;YALN,CAOC,kBAAC,GAAD,EAAuB,CAAA,EACvB,kBAAC,GAAD;GAAO,WAAW;aACjB,kBAAC,GAAD;IACO;IACN,cAAY;IACZ,oBAAkB;IAClB,WAAW,EAAG,GAAsB,EAAU;IAE7C;IACW,CAAA;GACN,CAAA,CACM"}
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { cx as e } from "../../utils/cx.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Dialog as
|
|
2
|
+
import { OverlayRegistration as t } from "../../hooks/overlayRegistry.js";
|
|
3
|
+
import { fullscreenDialog as n, fullscreenModal as r, fullscreenScrim as i } from "./FullscreenOverlay.css.js";
|
|
4
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
5
|
+
import { Dialog as s, Modal as c, ModalOverlay as l } from "react-aria-components";
|
|
6
|
+
import { useLocale as u } from "react-aria";
|
|
6
7
|
//#region src/components/FullscreenOverlay/FullscreenOverlay.tsx
|
|
7
|
-
function
|
|
8
|
-
let { direction:
|
|
9
|
-
return /* @__PURE__ */
|
|
10
|
-
isOpen:
|
|
11
|
-
onOpenChange:
|
|
12
|
-
isDismissable:
|
|
13
|
-
className:
|
|
14
|
-
dir:
|
|
15
|
-
children: /* @__PURE__ */
|
|
16
|
-
className:
|
|
17
|
-
children: /* @__PURE__ */
|
|
18
|
-
"aria-label":
|
|
19
|
-
className: e(
|
|
20
|
-
children:
|
|
8
|
+
function d({ isOpen: d, onOpenChange: f, isDismissable: p = !0, "aria-label": m, className: h, children: g }) {
|
|
9
|
+
let { direction: _ } = u();
|
|
10
|
+
return /* @__PURE__ */ o(l, {
|
|
11
|
+
isOpen: d,
|
|
12
|
+
onOpenChange: f,
|
|
13
|
+
isDismissable: p,
|
|
14
|
+
className: i,
|
|
15
|
+
dir: _,
|
|
16
|
+
children: [/* @__PURE__ */ a(t, {}), /* @__PURE__ */ a(c, {
|
|
17
|
+
className: r,
|
|
18
|
+
children: /* @__PURE__ */ a(s, {
|
|
19
|
+
"aria-label": m,
|
|
20
|
+
className: e(n, h),
|
|
21
|
+
children: g
|
|
21
22
|
})
|
|
22
|
-
})
|
|
23
|
+
})]
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
26
|
//#endregion
|
|
26
|
-
export {
|
|
27
|
+
export { d as FullscreenOverlay };
|
|
27
28
|
|
|
28
29
|
//# sourceMappingURL=FullscreenOverlay.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FullscreenOverlay.js","names":[],"sources":["../../../src/components/FullscreenOverlay/FullscreenOverlay.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useLocale } from \"react-aria\";\nimport {\n\tDialog as AriaDialog,\n\tModal,\n\tModalOverlay,\n} from \"react-aria-components\";\nimport { cx } from \"../../utils/cx.js\";\nimport {\n\tfullscreenDialog,\n\tfullscreenModal,\n\tfullscreenScrim,\n} from \"./FullscreenOverlay.css.js\";\n\nexport interface FullscreenOverlayProps {\n\t/** Whether the overlay is open. */\n\tisOpen: boolean;\n\t/** Called with the next open state on dismiss (Escape) or programmatic close. */\n\tonOpenChange: (isOpen: boolean) => void;\n\t/** Dismiss on outside tap. Escape always cancels (RAC default). Defaults to `true`. (The surface fills the window, so there is no scrim to tap.) */\n\tisDismissable?: boolean;\n\t/** Accessible name fallback when the child has no `Sheet.Header` title. */\n\t\"aria-label\"?: string;\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\n/**\n * Modal presentation that fills the whole chat window — no size cap, no rounded\n * corners, focus-trap, slide-up. Wraps arbitrary children (typically a `Sheet`).\n * For a bottom card use `SheetOverlay`; for a centered dialog `Dialog`.\n *\n * Give the dialog an accessible name via a `Sheet.Header` title or the\n * `aria-label` prop.\n */\nexport function FullscreenOverlay({\n\tisOpen,\n\tonOpenChange,\n\tisDismissable = true,\n\t\"aria-label\": ariaLabel,\n\tclassName,\n\tchildren,\n}: FullscreenOverlayProps) {\n\t// Stated, not inherited: this renders through a portal, so its direction must\n\t// not depend on where the portal lands. See the portalled-surface scenario\n\t// under the RTL requirement in openspec/specs/accessibility/spec.md.\n\tconst { direction } = useLocale();\n\n\treturn (\n\t\t<ModalOverlay\n\t\t\tisOpen={isOpen}\n\t\t\tonOpenChange={onOpenChange}\n\t\t\tisDismissable={isDismissable}\n\t\t\tclassName={fullscreenScrim}\n\t\t\tdir={direction}\n\t\t>\n\t\t\t<Modal className={fullscreenModal}>\n\t\t\t\t<AriaDialog\n\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\tclassName={cx(fullscreenDialog, className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</AriaDialog>\n\t\t\t</Modal>\n\t\t</ModalOverlay>\n\t);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"FullscreenOverlay.js","names":[],"sources":["../../../src/components/FullscreenOverlay/FullscreenOverlay.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useLocale } from \"react-aria\";\nimport {\n\tDialog as AriaDialog,\n\tModal,\n\tModalOverlay,\n} from \"react-aria-components\";\nimport { OverlayRegistration } from \"../../hooks/overlayRegistry.js\";\nimport { cx } from \"../../utils/cx.js\";\nimport {\n\tfullscreenDialog,\n\tfullscreenModal,\n\tfullscreenScrim,\n} from \"./FullscreenOverlay.css.js\";\n\nexport interface FullscreenOverlayProps {\n\t/** Whether the overlay is open. */\n\tisOpen: boolean;\n\t/** Called with the next open state on dismiss (Escape) or programmatic close. */\n\tonOpenChange: (isOpen: boolean) => void;\n\t/** Dismiss on outside tap. Escape always cancels (RAC default). Defaults to `true`. (The surface fills the window, so there is no scrim to tap.) */\n\tisDismissable?: boolean;\n\t/** Accessible name fallback when the child has no `Sheet.Header` title. */\n\t\"aria-label\"?: string;\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\n/**\n * Modal presentation that fills the whole chat window — no size cap, no rounded\n * corners, focus-trap, slide-up. Wraps arbitrary children (typically a `Sheet`).\n * For a bottom card use `SheetOverlay`; for a centered dialog `Dialog`.\n *\n * Give the dialog an accessible name via a `Sheet.Header` title or the\n * `aria-label` prop.\n */\nexport function FullscreenOverlay({\n\tisOpen,\n\tonOpenChange,\n\tisDismissable = true,\n\t\"aria-label\": ariaLabel,\n\tclassName,\n\tchildren,\n}: FullscreenOverlayProps) {\n\t// Stated, not inherited: this renders through a portal, so its direction must\n\t// not depend on where the portal lands. See the portalled-surface scenario\n\t// under the RTL requirement in openspec/specs/accessibility/spec.md.\n\tconst { direction } = useLocale();\n\n\treturn (\n\t\t<ModalOverlay\n\t\t\tisOpen={isOpen}\n\t\t\tonOpenChange={onOpenChange}\n\t\t\tisDismissable={isDismissable}\n\t\t\tclassName={fullscreenScrim}\n\t\t\tdir={direction}\n\t\t>\n\t\t\t<OverlayRegistration />\n\t\t\t<Modal className={fullscreenModal}>\n\t\t\t\t<AriaDialog\n\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\tclassName={cx(fullscreenDialog, className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</AriaDialog>\n\t\t\t</Modal>\n\t\t</ModalOverlay>\n\t);\n}\n"],"mappings":";;;;;;;AAoCA,SAAgB,EAAkB,EACjC,WACA,iBACA,mBAAgB,IAChB,cAAc,GACd,cACA,eAC0B;CAI1B,IAAM,EAAE,iBAAc,GAAW;AAEjC,QACC,kBAAC,GAAD;EACS;EACM;EACC;EACf,WAAW;EACX,KAAK;YALN,CAOC,kBAAC,GAAD,EAAuB,CAAA,EACvB,kBAAC,GAAD;GAAO,WAAW;aACjB,kBAAC,GAAD;IACC,cAAY;IACZ,WAAW,EAAG,GAAkB,EAAU;IAEzC;IACW,CAAA;GACN,CAAA,CACM"}
|
|
@@ -2,11 +2,11 @@ import { cx as e } from "../../utils/cx.js";
|
|
|
2
2
|
import { InputContext as t } from "./Input.context.js";
|
|
3
3
|
import { inputRoot as n } from "./Input.css.js";
|
|
4
4
|
import { jsx as r } from "react/jsx-runtime";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { useMemo as i } from "react";
|
|
6
|
+
import { TextField as a } from "react-aria-components";
|
|
7
7
|
//#region src/components/Input/InputRoot.tsx
|
|
8
8
|
function o({ className: o, children: s, variant: c = "default", ...l }) {
|
|
9
|
-
let u = l.isDisabled ?? !1, d = l.isInvalid ?? !1, f =
|
|
9
|
+
let u = l.isDisabled ?? !1, d = l.isInvalid ?? !1, f = i(() => ({
|
|
10
10
|
isDisabled: u,
|
|
11
11
|
isInvalid: d,
|
|
12
12
|
variant: c
|
|
@@ -15,7 +15,7 @@ function o({ className: o, children: s, variant: c = "default", ...l }) {
|
|
|
15
15
|
d,
|
|
16
16
|
c
|
|
17
17
|
]);
|
|
18
|
-
return /* @__PURE__ */ r(
|
|
18
|
+
return /* @__PURE__ */ r(a, {
|
|
19
19
|
...l,
|
|
20
20
|
className: e(n, o),
|
|
21
21
|
children: /* @__PURE__ */ r(t.Provider, {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { cx as e } from "../../utils/cx.js";
|
|
2
2
|
import { inputTextArea as t } from "./Input.css.js";
|
|
3
3
|
import { jsx as n } from "react/jsx-runtime";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { useCallback as r, useLayoutEffect as i } from "react";
|
|
5
|
+
import { useObjectRef as a } from "react-aria/useObjectRef";
|
|
6
|
+
import { TextArea as o } from "react-aria-components";
|
|
7
7
|
//#region src/components/Input/InputTextArea.tsx
|
|
8
8
|
function s({ className: s, ref: c, minRows: l = 1, maxRows: u, rows: d, onInput: f, ...p }) {
|
|
9
|
-
let m =
|
|
9
|
+
let m = a(c), h = r(() => {
|
|
10
10
|
let e = m.current;
|
|
11
11
|
if (!e) return;
|
|
12
12
|
let t = Number.parseFloat(getComputedStyle(e).lineHeight);
|
|
@@ -19,13 +19,13 @@ function s({ className: s, ref: c, minRows: l = 1, maxRows: u, rows: d, onInput:
|
|
|
19
19
|
l,
|
|
20
20
|
u
|
|
21
21
|
]);
|
|
22
|
-
|
|
22
|
+
i(() => {
|
|
23
23
|
h();
|
|
24
24
|
});
|
|
25
|
-
let g =
|
|
25
|
+
let g = r((e) => {
|
|
26
26
|
h(), f?.(e);
|
|
27
27
|
}, [h, f]);
|
|
28
|
-
return /* @__PURE__ */ n(
|
|
28
|
+
return /* @__PURE__ */ n(o, {
|
|
29
29
|
...p,
|
|
30
30
|
ref: m,
|
|
31
31
|
rows: d ?? l,
|