@kanso-labs/kanso-ui 0.40.9 → 0.41.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/color-scheme.d.ts +6 -0
- package/dist/color-scheme.js +9 -2
- package/dist/color-scheme.js.map +1 -1
- package/dist/components/app-bar/index.d.ts +11 -2
- package/dist/components/app-bar/index.js +53 -46
- package/dist/components/app-bar/index.js.map +1 -1
- package/dist/components/card/index.d.ts +12 -1
- package/dist/components/card/index.js +136 -66
- package/dist/components/card/index.js.map +1 -1
- package/dist/components/dialog/index.js +3 -2
- package/dist/components/dialog/index.js.map +1 -1
- package/dist/components/popover/index.js +3 -2
- package/dist/components/popover/index.js.map +1 -1
- package/dist/components/segmented-button/index.d.ts +3 -0
- package/dist/components/segmented-button/index.js +131 -65
- package/dist/components/segmented-button/index.js.map +1 -1
- package/dist/components/separator/index.js +2 -2
- package/dist/components/separator/index.js.map +1 -1
- package/dist/components/sheet/index.js +17 -16
- package/dist/components/sheet/index.js.map +1 -1
- package/dist/components/snackbar/index.d.ts +10 -3
- package/dist/components/snackbar/index.js +32 -12
- package/dist/components/snackbar/index.js.map +1 -1
- package/dist/components/switch/index.js +12 -3
- package/dist/components/switch/index.js.map +1 -1
- package/dist/components/toolbar/index.d.ts +3 -2
- package/dist/components/toolbar/index.js +3 -2
- package/dist/components/toolbar/index.js.map +1 -1
- package/dist/field/index.js +75 -48
- package/dist/field/index.js.map +1 -1
- package/dist/overlay/index.js +24 -0
- package/dist/overlay/index.js.map +1 -0
- package/dist/styles/scheme.js +19 -0
- package/dist/styles/scheme.js.map +1 -0
- package/dist/styles.css +86 -26
- package/dist/theme-scope.d.ts +5 -2
- package/dist/theme-scope.js +2 -1
- package/dist/theme-scope.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ import { mergeStatefulStyles, mergeStyles } from "../../styles/merge.js";
|
|
|
5
5
|
import { overlay } from "../../styles/overlay.js";
|
|
6
6
|
import { useHoldBottomEdge } from "../../hooks/useBottomEdge.js";
|
|
7
7
|
import { useScrollable } from "../../hooks/useScrollable.js";
|
|
8
|
+
import { OverlayScope } from "../../overlay/index.js";
|
|
8
9
|
import { c } from "react/compiler-runtime";
|
|
9
10
|
import { useRef } from "react";
|
|
10
11
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -67,7 +68,7 @@ function Sheet(t0) {
|
|
|
67
68
|
}
|
|
68
69
|
function SheetBody(t0) {
|
|
69
70
|
const $ = c(7);
|
|
70
|
-
const { ref: callerRef, ...props$
|
|
71
|
+
const { ref: callerRef, ...props$1 } = t0;
|
|
71
72
|
const ref = useRef(null);
|
|
72
73
|
const scrollable = useScrollable(ref);
|
|
73
74
|
const t1 = callerRef ?? void 0;
|
|
@@ -79,17 +80,17 @@ function SheetBody(t0) {
|
|
|
79
80
|
} else t2 = $[1];
|
|
80
81
|
const merged = t2;
|
|
81
82
|
const t3 = scrollable ? 0 : void 0;
|
|
82
|
-
const t4 = mergeStyles(props(styles.body, overlay.modalBodyRing), props$
|
|
83
|
+
const t4 = mergeStyles(props(styles.body, overlay.modalBodyRing), props$1);
|
|
83
84
|
let t5;
|
|
84
|
-
if ($[2] !== merged || $[3] !== props$
|
|
85
|
+
if ($[2] !== merged || $[3] !== props$1 || $[4] !== t3 || $[5] !== t4) {
|
|
85
86
|
t5 = /* @__PURE__ */ jsx("div", {
|
|
86
87
|
tabIndex: t3,
|
|
87
|
-
...props$
|
|
88
|
+
...props$1,
|
|
88
89
|
ref: merged,
|
|
89
90
|
...t4
|
|
90
91
|
});
|
|
91
92
|
$[2] = merged;
|
|
92
|
-
$[3] = props$
|
|
93
|
+
$[3] = props$1;
|
|
93
94
|
$[4] = t3;
|
|
94
95
|
$[5] = t4;
|
|
95
96
|
$[6] = t5;
|
|
@@ -124,12 +125,12 @@ function SheetContent(t0) {
|
|
|
124
125
|
let isKeyboardDismissDisabled;
|
|
125
126
|
let isOpen;
|
|
126
127
|
let onOpenChange;
|
|
127
|
-
let props$
|
|
128
|
+
let props$2;
|
|
128
129
|
let ref;
|
|
129
130
|
let style;
|
|
130
131
|
let t1;
|
|
131
132
|
if ($[0] !== t0) {
|
|
132
|
-
({children, className, container, defaultOpen, isDismissable: t1, isKeyboardDismissDisabled, isOpen, onOpenChange, ref, style, ...props$
|
|
133
|
+
({children, className, container, defaultOpen, isDismissable: t1, isKeyboardDismissDisabled, isOpen, onOpenChange, ref, style, ...props$2} = t0);
|
|
133
134
|
$[0] = t0;
|
|
134
135
|
$[1] = children;
|
|
135
136
|
$[2] = className;
|
|
@@ -138,7 +139,7 @@ function SheetContent(t0) {
|
|
|
138
139
|
$[5] = isKeyboardDismissDisabled;
|
|
139
140
|
$[6] = isOpen;
|
|
140
141
|
$[7] = onOpenChange;
|
|
141
|
-
$[8] = props$
|
|
142
|
+
$[8] = props$2;
|
|
142
143
|
$[9] = ref;
|
|
143
144
|
$[10] = style;
|
|
144
145
|
$[11] = t1;
|
|
@@ -150,7 +151,7 @@ function SheetContent(t0) {
|
|
|
150
151
|
isKeyboardDismissDisabled = $[5];
|
|
151
152
|
isOpen = $[6];
|
|
152
153
|
onOpenChange = $[7];
|
|
153
|
-
props$
|
|
154
|
+
props$2 = $[8];
|
|
154
155
|
ref = $[9];
|
|
155
156
|
style = $[10];
|
|
156
157
|
t1 = $[11];
|
|
@@ -177,14 +178,14 @@ function SheetContent(t0) {
|
|
|
177
178
|
$[16] = t4;
|
|
178
179
|
} else t4 = $[16];
|
|
179
180
|
let t5;
|
|
180
|
-
if ($[17] !== children || $[18] !== props$
|
|
181
|
+
if ($[17] !== children || $[18] !== props$2) {
|
|
181
182
|
t5 = /* @__PURE__ */ jsx(Dialog, {
|
|
182
|
-
...props$
|
|
183
|
+
...props$2,
|
|
183
184
|
...t4,
|
|
184
185
|
children
|
|
185
186
|
});
|
|
186
187
|
$[17] = children;
|
|
187
|
-
$[18] = props$
|
|
188
|
+
$[18] = props$2;
|
|
188
189
|
$[19] = t5;
|
|
189
190
|
} else t5 = $[19];
|
|
190
191
|
let t6;
|
|
@@ -201,7 +202,7 @@ function SheetContent(t0) {
|
|
|
201
202
|
} else t6 = $[23];
|
|
202
203
|
let t7;
|
|
203
204
|
if ($[24] !== container || $[25] !== defaultOpen || $[26] !== isDismissable || $[27] !== isKeyboardDismissDisabled || $[28] !== isOpen || $[29] !== onOpenChange || $[30] !== t6) {
|
|
204
|
-
t7 = /* @__PURE__ */ jsx(ModalOverlay, {
|
|
205
|
+
t7 = /* @__PURE__ */ jsx(OverlayScope, { children: /* @__PURE__ */ jsx(ModalOverlay, {
|
|
205
206
|
defaultOpen,
|
|
206
207
|
isDismissable,
|
|
207
208
|
isKeyboardDismissDisabled,
|
|
@@ -210,7 +211,7 @@ function SheetContent(t0) {
|
|
|
210
211
|
UNSTABLE_portalContainer: container,
|
|
211
212
|
...t2,
|
|
212
213
|
children: t6
|
|
213
|
-
});
|
|
214
|
+
}) });
|
|
214
215
|
$[24] = container;
|
|
215
216
|
$[25] = defaultOpen;
|
|
216
217
|
$[26] = isDismissable;
|
|
@@ -242,7 +243,7 @@ function SheetFooter(t0) {
|
|
|
242
243
|
$[1] = t2;
|
|
243
244
|
} else t2 = $[1];
|
|
244
245
|
const merged = t2;
|
|
245
|
-
const t3 = mergeStyles({ className: "x12smttz x13fuv20 x178xt8z x9f619 x78zum5 x2lah0s x126z3so x1nhvcw1 x1qafhyn x8i8c5o x1clyivc xg0ps1x" }, props);
|
|
246
|
+
const t3 = mergeStyles({ className: "x12smttz x13fuv20 x178xt8z x9f619 x78zum5 x2lah0s x1a02dak x126z3so x1nhvcw1 x1qafhyn x8i8c5o x1clyivc xg0ps1x" }, props);
|
|
246
247
|
let t4;
|
|
247
248
|
if ($[2] !== merged || $[3] !== props || $[4] !== t3) {
|
|
248
249
|
t4 = /* @__PURE__ */ jsx("div", {
|
|
@@ -326,7 +327,7 @@ function SheetTitle(props) {
|
|
|
326
327
|
const $ = c(5);
|
|
327
328
|
let t0;
|
|
328
329
|
if ($[0] !== props) {
|
|
329
|
-
t0 = mergeStyles({ className: "x9f619 x1w5n3ug xdy5w5q xete2z3 x14ijtet xug9e1u x2divse x1ghz6dp" }, props);
|
|
330
|
+
t0 = mergeStyles({ className: "x9f619 x1w5n3ug xdy5w5q xete2z3 x14ijtet xug9e1u x2divse x1ghz6dp xeuugli xj0a0fe" }, props);
|
|
330
331
|
$[0] = props;
|
|
331
332
|
$[1] = t0;
|
|
332
333
|
} else t0 = $[1];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["c","_c","HTMLAttributes","ReactNode","RefAttributes","ClassNameOrFunction","DialogProps","DialogTriggerProps","HeadingProps","ModalOverlayProps","ModalRenderProps","StyleOrFunction","stylex","useMemo","useRef","Dialog","DialogTrigger","Heading","Modal","ModalOverlay","useHoldBottomEdge","useScrollable","mergeRefs","mergeStatefulStyles","mergeStyles","overlay","colors","media","motion","radii","shadows","spacing","typography","FORCED_COLORS","slideInFromEnd","slideInFromStart","slideInFromBottom","styles","body","kB7OPa","k1xSpc","kXwgrk","kzQI83","kOIVth","kORKVm","k8WAf4","kg3NbH","$$css","SheetProps","Omit","children","Sheet","t0","$","props","t1","SheetBody","ref","callerRef","scrollable","undefined","t2","merged","t3","t4","modalBodyRing","t5","SheetContent","className","container","defaultOpen","isKeyboardDismissDisabled","isOpen","onOpenChange","style","isDismissable","Symbol","for","scrim","modalDialog","t6","t7","SheetFooter","SheetHandle","SheetHeader","SheetTitle","Body","Content","Footer","Handle","Header","Title","SheetContentProps","Pick","Element","SheetTitleProps","_c","props","stylex.props"],"sources":["../../../src/components/sheet/index.tsx"],"sourcesContent":["'use client';\n\nimport type { HTMLAttributes, ReactNode, RefAttributes } from 'react';\nimport type { ClassNameOrFunction, DialogProps, DialogTriggerProps, HeadingProps, ModalOverlayProps, ModalRenderProps, StyleOrFunction } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { useMemo, useRef } from 'react';\nimport { Dialog, DialogTrigger, Heading, Modal, ModalOverlay } from 'react-aria-components';\nimport { useHoldBottomEdge } from '../../hooks/useBottomEdge';\nimport { useScrollable } from '../../hooks/useScrollable';\nimport { mergeRefs } from '../../render/ref';\nimport { mergeStatefulStyles, mergeStyles } from '../../styles/merge';\nimport { overlay } from '../../styles/overlay';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, media, motion, radii, shadows, spacing, typography } from '../../tokens/design.tokens.stylex';\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\n\n// One component, two presentations. Above the medium breakpoint it is a side\n// sheet pinned to the inline end of the viewport; below it, the same panel\n// becomes a bottom sheet. That is the pairing the Material Design pages draw\n// rather than two components: a sheet that stayed on the right at 375px would\n// be a drawer covering the whole screen.\n//\n// The two differ in five things and no more: which edges they are pinned to,\n// which two corners are rounded, which axis they arrive along, how much of\n// the viewport they may take, and the drag handle, which is the bottom\n// sheets page's element alone. Everything inside the panel — the 24 of start\n// and end padding, the 12 between the header's elements, the actions area —\n// comes from the side sheets page and is drawn the same in both.\n\n// The side sheet arrives along the inline axis, and it takes two keyframes to\n// do that rather than one. Which edge the panel rests against is logical —\n// `insetInlineEnd` puts it on the right under a left-to-right document and on\n// the left under a right-to-left one — but `translateX` is physical and flips\n// with nothing. One keyframe would therefore have the panel arrive from the\n// far side of where it comes to rest under one of the two.\nconst slideInFromEnd = \"x17cjob-B\";\nconst slideInFromStart = \"x18x3npg-B\";\nconst slideInFromBottom = \"x15b941j-B\";\n\n// Entry only, so there is no exit animation to wait for and closing is\n// immediate: React Aria keeps a closing panel mounted only while an animation\n// is running on it, and finds none. See the comment on `SheetContent` for why\n// that is a design call rather than a limit of StyleX.\n//\n// React Aria's overlay is three nested elements — the scrim, the panel, and\n// the dialog inside it — so the styles are split the same way: the overlay\n// module's scrim on the first, `content` on the panel, its modal dialog style\n// on the element that carries the role. The scrim and that dialog style are\n// shared with every modal overlay; the panel is the sheet's own, since which\n// edge it is pinned to is what makes it a sheet.\nconst styles = {\n body: {\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n kzQI83: \"x1iyjqo2\",\n kOIVth: \"xxj4525\",\n kORKVm: \"x1odjw0f\",\n k8WAf4: \"xp6hjv6\",\n kg3NbH: \"xg0ps1x\",\n $$css: true\n }\n};\ntype SheetProps = Omit<DialogTriggerProps, 'children'> & {\n children?: ReactNode;\n};\n\n/**\n * A modal panel that arrives from the edge of the screen — a side sheet on a\n * wide viewport, a bottom sheet on a narrow one. Open state is React Aria's:\n * pass `isOpen` with `onOpenChange` to control it, or `defaultOpen` to let it\n * keep its own.\n *\n * Composed rather than configured by props, because a sheet's header, body,\n * and footer all take arbitrary content — the parts are `Sheet.Content`,\n * `Sheet.Header`, `Sheet.Title`, `Sheet.Body`, and `Sheet.Footer`. A\n * `Button` or `IconButton` placed directly inside `Sheet` opens it, and one\n * given `slot=\"close\"` anywhere inside the content closes it; neither needs\n * a part of its own.\n *\n * `Sheet` is the trigger's half, so a sheet nothing on the page opens — one\n * a route shows, or a menu item raises — leaves it out and passes `isOpen`\n * and `onOpenChange` to `Sheet.Content` instead. Wrapped in `Sheet` with no\n * button inside it, React Aria warns that its press responder found nothing\n * to press.\n */\nfunction Sheet({\n children,\n ...props\n}: SheetProps) {\n return <DialogTrigger {...props}>{children}</DialogTrigger>;\n}\nfunction SheetBody({\n ref: callerRef,\n ...props\n}: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>) {\n const ref = useRef<HTMLDivElement>(null);\n // A body its content runs past is a tab stop, so a keyboard can scroll it\n // when nothing inside it takes focus; a call site's own tabIndex still\n // wins. See useScrollable.\n const scrollable = useScrollable(ref);\n // The body measures itself through its own ref, and the call site's lands\n // on the same element.\n const merged = useMemo(() => mergeRefs(ref, callerRef ?? undefined), [callerRef]);\n return <div\n // oxlint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- a scroll container with nothing focusable inside is otherwise out of a keyboard's reach, which axe's scrollable-region-focusable reports\n tabIndex={scrollable ? 0 : undefined} {...props} ref={merged} {...mergeStyles(stylex.props(styles.body, overlay.modalBodyRing), props)} />;\n}\n\n/**\n * The panel itself, and the scrim behind it. Everything the sheet shows goes\n * in here; the trigger stays outside it, since the trigger lives in the page\n * while this is portalled out to the end of the body.\n *\n * A press on the scrim closes the sheet unless `isDismissable` says\n * otherwise — React Aria's own default is the reverse, and a sheet that\n * ignores a tap outside it reads as stuck.\n *\n * Inside `Sheet`, the open state is the trigger's. On its own, with no\n * trigger, it is this part's: `isOpen` with `onOpenChange` controls it, and\n * a `slot=\"close\"` button, Escape and the scrim all report through\n * `onOpenChange`, as they would to `Sheet`.\n *\n * The scrim draws at `z-index: 900`, over any page content layered below\n * that, such as a sticky header, and the panel draws inside it. A\n * `Snackbar` draws at 1000, so a toast raised from inside the sheet is read\n * over it, and React Aria's popovers and menus draw above both.\n */\nfunction SheetContent({\n children,\n className,\n container,\n defaultOpen,\n isDismissable = true,\n isKeyboardDismissDisabled,\n isOpen,\n onOpenChange,\n ref,\n style,\n ...props\n}: RefAttributes<HTMLDivElement> & SheetContentProps) {\n return <ModalOverlay defaultOpen={defaultOpen} isDismissable={isDismissable} isKeyboardDismissDisabled={isKeyboardDismissDisabled} isOpen={isOpen} onOpenChange={onOpenChange}\n // oxlint-disable-next-line typescript/no-deprecated -- its replacement, UNSAFE_PortalProvider, is not exported by react-aria-components\n UNSTABLE_portalContainer={container} {...stylex.props(overlay.scrim)}>\n <Modal\n // The panel, where the call site's class and style land, rather than\n // the dialog inside it, which takes the rest of the props.\n ref={ref} {...mergeStatefulStyles({\n className: \"x1n1nwrg x1u6grsq x1ioi8j8 xu2fq7p x18ihq2d x16dv9tl x1vnz5z6 x19dwuzr xuz63mn x1lym3mf xkducg2 xrzall9 xb0nsol xjslfuv x1gbqego x1cfajip xjg5lhu x1a37zkv xys6ro8 x6xk272 x9t1vth x19efjv6 x9f619 x139gbkf x78zum5 xdt5ytf x1l2rt3b xwvxfow x1ey2m1c x13vifvy xmpip4z xtijo5x xhi6v0a x1upgybz x7ab17h x11ijow0 xb3r6kr x1a148e8 x1mrd0q x5ubeis x1lodr2j x1uhho1l x19b5e0v xg4bq00 xg4jtgg xsds98l xixxii4\"\n }, {\n className,\n style\n })}>\n <Dialog {...props} {...stylex.props(overlay.modalDialog)}>\n {children}\n </Dialog>\n </Modal>\n </ModalOverlay>;\n}\n\n/**\n * The sheet's actions. The panel is pinned to the window's bottom edge in\n * both presentations, so they sit on that edge, and a toast rises clear of\n * them while the sheet is open rather than lying over its buttons. A side\n * sheet's are included: the toast is centred in the window, and on any\n * window narrower than about 1376px its 576 reach into the sheet's 400.\n */\nfunction SheetFooter({\n ref: callerRef,\n ...props\n}: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>) {\n const ref = useRef<HTMLDivElement>(null);\n useHoldBottomEdge(ref, true);\n // The footer measures itself through its own ref, and the call site's\n // lands on the same element.\n const merged = useMemo(() => mergeRefs(ref, callerRef ?? undefined), [callerRef]);\n return <div {...props} ref={merged} {...mergeStyles({\n className: \"x12smttz x13fuv20 x178xt8z x9f619 x78zum5 x2lah0s x126z3so x1nhvcw1 x1qafhyn x8i8c5o x1clyivc xg0ps1x\"\n }, props)} />;\n}\n\n/**\n * The bottom sheets page's drag handle: a short bar above the sheet's\n * content, saying the panel is a bottom sheet. Place it first inside\n * `Sheet.Content`; above the medium breakpoint the panel is a side sheet and\n * this draws nothing.\n *\n * It is decoration rather than a control, and hidden from assistive\n * technology. Material's own handle drags a sheet between a collapsed and an\n * expanded height and dismisses it from the collapsed one; this panel has\n * one height and cannot be dragged, so a control that only looked draggable\n * would promise what it cannot do. Closing is already the scrim, Escape, and\n * any button given `slot=\"close\"`.\n */\nfunction SheetHandle(props: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>) {\n return <div aria-hidden=\"true\" {...props} {...mergeStyles({\n className: \"x6s0dn4 x9f619 x1s85apg x37i4ze x2lah0s xl56j7k x1xg6qyv\"\n }, props)}>\n <span className=\"x1ccu2yh xwvh9j7 xqu0tyb x1dkaolv x9f619 x1g12otp x1td3qas\" />\n </div>;\n}\nfunction SheetHeader(props: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>) {\n return <div {...props} {...mergeStyles({\n className: \"x6s0dn4 x1j6faob x1q0q8m5 xso031l x9f619 x78zum5 x2lah0s x1gka490 x1qughib x1cmllll xg0ps1x\"\n }, props)} />;\n}\n\n/**\n * Names the sheet. Rendered through React Aria's title slot, which is what\n * points the dialog's `aria-labelledby` at it — a sheet without one announces\n * itself as an unnamed dialog.\n */\nfunction SheetTitle(props: RefAttributes<HTMLHeadingElement> & SheetTitleProps) {\n return <Heading slot=\"title\" {...props} {...mergeStyles({\n className: \"x9f619 x1w5n3ug xdy5w5q xete2z3 x14ijtet xug9e1u x2divse x1ghz6dp\"\n }, props)} />;\n}\nSheet.Body = SheetBody;\nSheet.Content = SheetContent;\nSheet.Footer = SheetFooter;\nSheet.Handle = SheetHandle;\nSheet.Header = SheetHeader;\nSheet.Title = SheetTitle;\n\n// The dialog's own props, plus the scrim's open state and dismissal settings\n// and the panel's styling. A call site has no reason to know there are three\n// elements: `className` and `style` reach the panel, which is the one worth\n// restyling and positioning, the open state and the dismissal settings reach\n// the scrim, and everything else lands on the dialog.\n//\n// `isDismissable` is declared here rather than picked with its siblings,\n// since the picked one carries React Aria's documentation, whose default is\n// the reverse of this component's.\ntype SheetContentProps = Omit<DialogProps, 'className' | 'style'> & Pick<ModalOverlayProps, 'defaultOpen' | 'isKeyboardDismissDisabled' | 'isOpen' | 'onOpenChange'> & {\n /** A function may compute the class from the panel's render state. */\n className?: ClassNameOrFunction<ModalRenderProps>;\n /**\n * Where to portal the panel and scrim. Defaults to the container of the\n * `ThemeScope` around it, which keeps the sheet on that scope's tokens, or\n * to the end of `<body>` where there is none. A subtree themed through the\n * `themeScope` class has no container of its own, so point this inside it,\n * or the sheet renders outside and keeps the page's tokens.\n */\n container?: Element;\n /**\n * Whether a press on the scrim, outside the panel, closes the sheet.\n * `true` here where React Aria's own default is `false`, since a sheet\n * that ignores a tap outside it reads as stuck. Escape is\n * `isKeyboardDismissDisabled`'s, and this says nothing about it.\n * @default true\n */\n isDismissable?: boolean;\n /** A function may compute the style from the panel's render state. */\n style?: StyleOrFunction<ModalRenderProps>;\n};\ntype SheetTitleProps = HeadingProps;\nexport type { SheetContentProps, SheetProps, SheetTitleProps };\nexport { SheetBody, SheetContent, SheetFooter, SheetHandle, SheetHeader, SheetTitle };\nexport default Sheet;"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["c","_c","HTMLAttributes","ReactNode","RefAttributes","ClassNameOrFunction","DialogProps","DialogTriggerProps","HeadingProps","ModalOverlayProps","ModalRenderProps","StyleOrFunction","stylex","useMemo","useRef","Dialog","DialogTrigger","Heading","Modal","ModalOverlay","useHoldBottomEdge","useScrollable","OverlayScope","mergeRefs","mergeStatefulStyles","mergeStyles","overlay","colors","media","motion","radii","shadows","spacing","typography","FORCED_COLORS","slideInFromEnd","slideInFromStart","slideInFromBottom","styles","body","kB7OPa","k1xSpc","kXwgrk","kzQI83","kOIVth","kORKVm","k8WAf4","kg3NbH","$$css","SheetProps","Omit","children","Sheet","t0","$","props","t1","SheetBody","ref","callerRef","scrollable","undefined","t2","merged","t3","t4","modalBodyRing","t5","SheetContent","className","container","defaultOpen","isKeyboardDismissDisabled","isOpen","onOpenChange","style","isDismissable","Symbol","for","scrim","modalDialog","t6","t7","SheetFooter","SheetHandle","SheetHeader","SheetTitle","Body","Content","Footer","Handle","Header","Title","SheetContentProps","Pick","Element","SheetTitleProps","_c","props","stylex.props"],"sources":["../../../src/components/sheet/index.tsx"],"sourcesContent":["'use client';\n\nimport type { HTMLAttributes, ReactNode, RefAttributes } from 'react';\nimport type { ClassNameOrFunction, DialogProps, DialogTriggerProps, HeadingProps, ModalOverlayProps, ModalRenderProps, StyleOrFunction } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { useMemo, useRef } from 'react';\nimport { Dialog, DialogTrigger, Heading, Modal, ModalOverlay } from 'react-aria-components';\nimport { useHoldBottomEdge } from '../../hooks/useBottomEdge';\nimport { useScrollable } from '../../hooks/useScrollable';\nimport { OverlayScope } from '../../overlay';\nimport { mergeRefs } from '../../render/ref';\nimport { mergeStatefulStyles, mergeStyles } from '../../styles/merge';\nimport { overlay } from '../../styles/overlay';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, media, motion, radii, shadows, spacing, typography } from '../../tokens/design.tokens.stylex';\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\n\n// One component, two presentations. Above the medium breakpoint it is a side\n// sheet pinned to the inline end of the viewport; below it, the same panel\n// becomes a bottom sheet. That is the pairing the Material Design pages draw\n// rather than two components: a sheet that stayed on the right at 375px would\n// be a drawer covering the whole screen.\n//\n// The two differ in five things and no more: which edges they are pinned to,\n// which two corners are rounded, which axis they arrive along, how much of\n// the viewport they may take, and the drag handle, which is the bottom\n// sheets page's element alone. Everything inside the panel — the 24 of start\n// and end padding, the 12 between the header's elements, the actions area —\n// comes from the side sheets page and is drawn the same in both.\n\n// The side sheet arrives along the inline axis, and it takes two keyframes to\n// do that rather than one. Which edge the panel rests against is logical —\n// `insetInlineEnd` puts it on the right under a left-to-right document and on\n// the left under a right-to-left one — but `translateX` is physical and flips\n// with nothing. One keyframe would therefore have the panel arrive from the\n// far side of where it comes to rest under one of the two.\nconst slideInFromEnd = \"x17cjob-B\";\nconst slideInFromStart = \"x18x3npg-B\";\nconst slideInFromBottom = \"x15b941j-B\";\n\n// Entry only, so there is no exit animation to wait for and closing is\n// immediate: React Aria keeps a closing panel mounted only while an animation\n// is running on it, and finds none. See the comment on `SheetContent` for why\n// that is a design call rather than a limit of StyleX.\n//\n// React Aria's overlay is three nested elements — the scrim, the panel, and\n// the dialog inside it — so the styles are split the same way: the overlay\n// module's scrim on the first, `content` on the panel, its modal dialog style\n// on the element that carries the role. The scrim and that dialog style are\n// shared with every modal overlay; the panel is the sheet's own, since which\n// edge it is pinned to is what makes it a sheet.\nconst styles = {\n body: {\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n kzQI83: \"x1iyjqo2\",\n kOIVth: \"xxj4525\",\n kORKVm: \"x1odjw0f\",\n k8WAf4: \"xp6hjv6\",\n kg3NbH: \"xg0ps1x\",\n $$css: true\n }\n};\ntype SheetProps = Omit<DialogTriggerProps, 'children'> & {\n children?: ReactNode;\n};\n\n/**\n * A modal panel that arrives from the edge of the screen — a side sheet on a\n * wide viewport, a bottom sheet on a narrow one. Open state is React Aria's:\n * pass `isOpen` with `onOpenChange` to control it, or `defaultOpen` to let it\n * keep its own.\n *\n * Composed rather than configured by props, because a sheet's header, body,\n * and footer all take arbitrary content — the parts are `Sheet.Content`,\n * `Sheet.Header`, `Sheet.Title`, `Sheet.Body`, and `Sheet.Footer`. A\n * `Button` or `IconButton` placed directly inside `Sheet` opens it, and one\n * given `slot=\"close\"` anywhere inside the content closes it; neither needs\n * a part of its own.\n *\n * `Sheet` is the trigger's half, so a sheet nothing on the page opens — one\n * a route shows, or a menu item raises — leaves it out and passes `isOpen`\n * and `onOpenChange` to `Sheet.Content` instead. Wrapped in `Sheet` with no\n * button inside it, React Aria warns that its press responder found nothing\n * to press.\n */\nfunction Sheet({\n children,\n ...props\n}: SheetProps) {\n return <DialogTrigger {...props}>{children}</DialogTrigger>;\n}\nfunction SheetBody({\n ref: callerRef,\n ...props\n}: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>) {\n const ref = useRef<HTMLDivElement>(null);\n // A body its content runs past is a tab stop, so a keyboard can scroll it\n // when nothing inside it takes focus; a call site's own tabIndex still\n // wins. See useScrollable.\n const scrollable = useScrollable(ref);\n // The body measures itself through its own ref, and the call site's lands\n // on the same element.\n const merged = useMemo(() => mergeRefs(ref, callerRef ?? undefined), [callerRef]);\n return <div\n // oxlint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- a scroll container with nothing focusable inside is otherwise out of a keyboard's reach, which axe's scrollable-region-focusable reports\n tabIndex={scrollable ? 0 : undefined} {...props} ref={merged} {...mergeStyles(stylex.props(styles.body, overlay.modalBodyRing), props)} />;\n}\n\n/**\n * The panel itself, and the scrim behind it. Everything the sheet shows goes\n * in here; the trigger stays outside it, since the trigger lives in the page\n * while this is portalled out to the end of the body.\n *\n * A press on the scrim closes the sheet unless `isDismissable` says\n * otherwise — React Aria's own default is the reverse, and a sheet that\n * ignores a tap outside it reads as stuck.\n *\n * Inside `Sheet`, the open state is the trigger's. On its own, with no\n * trigger, it is this part's: `isOpen` with `onOpenChange` controls it, and\n * a `slot=\"close\"` button, Escape and the scrim all report through\n * `onOpenChange`, as they would to `Sheet`.\n *\n * The scrim draws at `z-index: 900`, over any page content layered below\n * that, such as a sticky header, and the panel draws inside it. A\n * `Snackbar` draws at 1000, so a toast raised from inside the sheet is read\n * over it, and React Aria's popovers and menus draw above both.\n */\nfunction SheetContent({\n children,\n className,\n container,\n defaultOpen,\n isDismissable = true,\n isKeyboardDismissDisabled,\n isOpen,\n onOpenChange,\n ref,\n style,\n ...props\n}: RefAttributes<HTMLDivElement> & SheetContentProps) {\n return <OverlayScope>\n <ModalOverlay defaultOpen={defaultOpen} isDismissable={isDismissable} isKeyboardDismissDisabled={isKeyboardDismissDisabled} isOpen={isOpen} onOpenChange={onOpenChange}\n // oxlint-disable-next-line typescript/no-deprecated -- its replacement, UNSAFE_PortalProvider, is not exported by react-aria-components\n UNSTABLE_portalContainer={container} {...stylex.props(overlay.scrim)}>\n <Modal\n // The panel, where the call site's class and style land, rather than\n // the dialog inside it, which takes the rest of the props.\n ref={ref} {...mergeStatefulStyles({\n className: \"x1n1nwrg x1u6grsq x1ioi8j8 xu2fq7p x18ihq2d x16dv9tl x1vnz5z6 x19dwuzr xuz63mn x1lym3mf xkducg2 xrzall9 xb0nsol xjslfuv x1gbqego x1cfajip xjg5lhu x1a37zkv xys6ro8 x6xk272 x9t1vth x19efjv6 x9f619 x139gbkf x78zum5 xdt5ytf x1l2rt3b xwvxfow x1ey2m1c x13vifvy xmpip4z xtijo5x xhi6v0a x1upgybz x7ab17h x11ijow0 xb3r6kr x1a148e8 x1mrd0q x5ubeis x1lodr2j x1uhho1l x19b5e0v xg4bq00 xg4jtgg xsds98l xixxii4\"\n }, {\n className,\n style\n })}>\n <Dialog {...props} {...stylex.props(overlay.modalDialog)}>\n {children}\n </Dialog>\n </Modal>\n </ModalOverlay>\n </OverlayScope>;\n}\n\n/**\n * The sheet's actions. The panel is pinned to the window's bottom edge in\n * both presentations, so they sit on that edge, and a toast rises clear of\n * them while the sheet is open rather than lying over its buttons. A side\n * sheet's are included: the toast is centred in the window, and on any\n * window narrower than about 1376px its 576 reach into the sheet's 400.\n */\nfunction SheetFooter({\n ref: callerRef,\n ...props\n}: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>) {\n const ref = useRef<HTMLDivElement>(null);\n useHoldBottomEdge(ref, true);\n // The footer measures itself through its own ref, and the call site's\n // lands on the same element.\n const merged = useMemo(() => mergeRefs(ref, callerRef ?? undefined), [callerRef]);\n return <div {...props} ref={merged} {...mergeStyles({\n className: \"x12smttz x13fuv20 x178xt8z x9f619 x78zum5 x2lah0s x1a02dak x126z3so x1nhvcw1 x1qafhyn x8i8c5o x1clyivc xg0ps1x\"\n }, props)} />;\n}\n\n/**\n * The bottom sheets page's drag handle: a short bar above the sheet's\n * content, saying the panel is a bottom sheet. Place it first inside\n * `Sheet.Content`; above the medium breakpoint the panel is a side sheet and\n * this draws nothing.\n *\n * It is decoration rather than a control, and hidden from assistive\n * technology. Material's own handle drags a sheet between a collapsed and an\n * expanded height and dismisses it from the collapsed one; this panel has\n * one height and cannot be dragged, so a control that only looked draggable\n * would promise what it cannot do. Closing is already the scrim, Escape, and\n * any button given `slot=\"close\"`.\n */\nfunction SheetHandle(props: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>) {\n return <div aria-hidden=\"true\" {...props} {...mergeStyles({\n className: \"x6s0dn4 x9f619 x1s85apg x37i4ze x2lah0s xl56j7k x1xg6qyv\"\n }, props)}>\n <span className=\"x1ccu2yh xwvh9j7 xqu0tyb x1dkaolv x9f619 x1g12otp x1td3qas\" />\n </div>;\n}\nfunction SheetHeader(props: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>) {\n return <div {...props} {...mergeStyles({\n className: \"x6s0dn4 x1j6faob x1q0q8m5 xso031l x9f619 x78zum5 x2lah0s x1gka490 x1qughib x1cmllll xg0ps1x\"\n }, props)} />;\n}\n\n/**\n * Names the sheet. Rendered through React Aria's title slot, which is what\n * points the dialog's `aria-labelledby` at it — a sheet without one announces\n * itself as an unnamed dialog.\n */\nfunction SheetTitle(props: RefAttributes<HTMLHeadingElement> & SheetTitleProps) {\n return <Heading slot=\"title\" {...props} {...mergeStyles({\n className: \"x9f619 x1w5n3ug xdy5w5q xete2z3 x14ijtet xug9e1u x2divse x1ghz6dp xeuugli xj0a0fe\"\n }, props)} />;\n}\nSheet.Body = SheetBody;\nSheet.Content = SheetContent;\nSheet.Footer = SheetFooter;\nSheet.Handle = SheetHandle;\nSheet.Header = SheetHeader;\nSheet.Title = SheetTitle;\n\n// The dialog's own props, plus the scrim's open state and dismissal settings\n// and the panel's styling. A call site has no reason to know there are three\n// elements: `className` and `style` reach the panel, which is the one worth\n// restyling and positioning, the open state and the dismissal settings reach\n// the scrim, and everything else lands on the dialog.\n//\n// `isDismissable` is declared here rather than picked with its siblings,\n// since the picked one carries React Aria's documentation, whose default is\n// the reverse of this component's.\ntype SheetContentProps = Omit<DialogProps, 'className' | 'style'> & Pick<ModalOverlayProps, 'defaultOpen' | 'isKeyboardDismissDisabled' | 'isOpen' | 'onOpenChange'> & {\n /** A function may compute the class from the panel's render state. */\n className?: ClassNameOrFunction<ModalRenderProps>;\n /**\n * Where to portal the panel and scrim. Defaults to the container of the\n * `ThemeScope` around it, which keeps the sheet on that scope's tokens, or\n * to the end of `<body>` where there is none. A subtree themed through the\n * `themeScope` class has no container of its own, so point this inside it,\n * or the sheet renders outside and keeps the page's tokens.\n */\n container?: Element;\n /**\n * Whether a press on the scrim, outside the panel, closes the sheet.\n * `true` here where React Aria's own default is `false`, since a sheet\n * that ignores a tap outside it reads as stuck. Escape is\n * `isKeyboardDismissDisabled`'s, and this says nothing about it.\n * @default true\n */\n isDismissable?: boolean;\n /** A function may compute the style from the panel's render state. */\n style?: StyleOrFunction<ModalRenderProps>;\n};\ntype SheetTitleProps = HeadingProps;\nexport type { SheetContentProps, SheetProps, SheetTitleProps };\nexport { SheetBody, SheetContent, SheetFooter, SheetHandle, SheetHeader, SheetTitle };\nexport default Sheet;"],"mappings":"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"}
|
|
@@ -19,7 +19,11 @@ type SnackbarOptions = {
|
|
|
19
19
|
* closes the snackbar, which is what the page draws.
|
|
20
20
|
*/
|
|
21
21
|
action?: SnackbarAction;
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Run when the snackbar closes, however it was closed: by its timer, its
|
|
24
|
+
* action or close button, `close`, `clear`, or a newer message added in its
|
|
25
|
+
* place.
|
|
26
|
+
*/
|
|
23
27
|
onClose?: () => void;
|
|
24
28
|
/**
|
|
25
29
|
* Whether a close button is shown at the end. The page draws one for a
|
|
@@ -82,6 +86,7 @@ type SnackbarProps = {
|
|
|
82
86
|
* keeps that API's `UNSTABLE_` name out of a consumer's code.
|
|
83
87
|
*/
|
|
84
88
|
declare class SnackbarQueue {
|
|
89
|
+
#private;
|
|
85
90
|
/**
|
|
86
91
|
* React Aria's queue, which `Snackbar` subscribes to. Not part of the
|
|
87
92
|
* package's API — read it and an upstream release may break the call site.
|
|
@@ -89,10 +94,12 @@ declare class SnackbarQueue {
|
|
|
89
94
|
readonly rac: UNSTABLE_ToastQueue<SnackbarMessage>;
|
|
90
95
|
constructor();
|
|
91
96
|
/**
|
|
92
|
-
* Shows a message, and returns the key that
|
|
97
|
+
* Shows a message in place of the one on screen, and returns the key that
|
|
98
|
+
* closes it. The message it replaces is closed, so its `onClose` runs, and
|
|
99
|
+
* it does not come back.
|
|
93
100
|
*/
|
|
94
101
|
add(message: ReactNode, options?: SnackbarOptions): string;
|
|
95
|
-
/** Closes
|
|
102
|
+
/** Closes the snackbar on screen, running its `onClose`. */
|
|
96
103
|
clear(): void;
|
|
97
104
|
/** Closes one snackbar, by the key `add` returned. */
|
|
98
105
|
close(key: string): void;
|
|
@@ -5,7 +5,7 @@ import { CloseGlyph } from "../../glyphs/index.js";
|
|
|
5
5
|
import { useRipple } from "../../hooks/useRipple.js";
|
|
6
6
|
import { useBottomEdgeClearance } from "../../hooks/useBottomEdge.js";
|
|
7
7
|
import { c } from "react/compiler-runtime";
|
|
8
|
-
import {
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
import { Button, Text, UNSTABLE_Toast, UNSTABLE_ToastContent, UNSTABLE_ToastQueue, UNSTABLE_ToastRegion } from "react-aria-components";
|
|
10
10
|
//#region src/components/snackbar/index.tsx
|
|
11
11
|
const MESSAGE_MS = 5e3;
|
|
@@ -17,12 +17,17 @@ const _temp = {
|
|
|
17
17
|
};
|
|
18
18
|
const styles = {
|
|
19
19
|
action: {
|
|
20
|
+
kgeoSG: "x1cpjm7i",
|
|
21
|
+
kGOzcv: "xun2zgk",
|
|
22
|
+
kpsdNU: "xm4btww",
|
|
23
|
+
kEoFBp: "x1hmns74",
|
|
20
24
|
kMwMTN: "x16bex6i",
|
|
21
25
|
kMv6JI: "xkknnkr",
|
|
22
26
|
kGuDYH: "x14zspaw",
|
|
23
27
|
k63SB2: "x1v9cpvo",
|
|
24
28
|
kb6lSQ: "x155f00i",
|
|
25
29
|
kLWn49: "x1lz68p4",
|
|
30
|
+
kAzted: "x1cio8j0",
|
|
26
31
|
k8WAf4: "x1cmllll",
|
|
27
32
|
kg3NbH: "x18fpw6u",
|
|
28
33
|
$$css: true
|
|
@@ -45,10 +50,9 @@ const styles = {
|
|
|
45
50
|
kmuXW: "x2lah0s",
|
|
46
51
|
kjj79g: "xl56j7k",
|
|
47
52
|
kjBf7l: "x14ytart",
|
|
48
|
-
kInvED: "
|
|
53
|
+
kInvED: "xr2mjdv",
|
|
49
54
|
k3XXqK: "x9v5kkp x1t137rt",
|
|
50
55
|
kMeerF: "x1de99jn",
|
|
51
|
-
kVQacm: "xb3r6kr",
|
|
52
56
|
kVAEAm: "x1n2onr6",
|
|
53
57
|
$$css: true
|
|
54
58
|
},
|
|
@@ -103,26 +107,35 @@ var SnackbarQueue = class {
|
|
|
103
107
|
* package's API — read it and an upstream release may break the call site.
|
|
104
108
|
*/
|
|
105
109
|
rac;
|
|
110
|
+
#open = /* @__PURE__ */ new Set();
|
|
106
111
|
constructor() {
|
|
107
112
|
this.rac = new UNSTABLE_ToastQueue({ maxVisibleToasts: 1 });
|
|
108
113
|
}
|
|
109
114
|
/**
|
|
110
|
-
* Shows a message, and returns the key that
|
|
115
|
+
* Shows a message in place of the one on screen, and returns the key that
|
|
116
|
+
* closes it. The message it replaces is closed, so its `onClose` runs, and
|
|
117
|
+
* it does not come back.
|
|
111
118
|
*/
|
|
112
119
|
add(message, options = {}) {
|
|
113
120
|
const { action, onClose, showCloseButton = false, timeout } = options;
|
|
114
|
-
|
|
121
|
+
this.clear();
|
|
122
|
+
const key = this.rac.add({
|
|
115
123
|
action,
|
|
116
124
|
message,
|
|
117
125
|
showCloseButton
|
|
118
126
|
}, {
|
|
119
|
-
onClose
|
|
127
|
+
onClose: () => {
|
|
128
|
+
this.#open.delete(key);
|
|
129
|
+
onClose?.();
|
|
130
|
+
},
|
|
120
131
|
timeout: timeout ?? (action === void 0 ? MESSAGE_MS : UNTIL_CLOSED)
|
|
121
132
|
});
|
|
133
|
+
this.#open.add(key);
|
|
134
|
+
return key;
|
|
122
135
|
}
|
|
123
|
-
/** Closes
|
|
136
|
+
/** Closes the snackbar on screen, running its `onClose`. */
|
|
124
137
|
clear() {
|
|
125
|
-
this.rac.
|
|
138
|
+
for (const key of this.#open) this.rac.close(key);
|
|
126
139
|
}
|
|
127
140
|
/** Closes one snackbar, by the key `add` returned. */
|
|
128
141
|
close(key) {
|
|
@@ -250,10 +263,14 @@ function snackbarContent(queue, closeLabel) {
|
|
|
250
263
|
toast
|
|
251
264
|
});
|
|
252
265
|
}
|
|
253
|
-
/**
|
|
266
|
+
/**
|
|
267
|
+
* The action, the close button, or nothing, after the message — together, so
|
|
268
|
+
* they move beneath it together.
|
|
269
|
+
*/
|
|
254
270
|
function SnackbarControls(t0) {
|
|
255
271
|
const $ = c(9);
|
|
256
272
|
const { action, close, closeLabel, showCloseButton } = t0;
|
|
273
|
+
if (action === void 0 && !showCloseButton) return null;
|
|
257
274
|
let t1;
|
|
258
275
|
if ($[0] !== action || $[1] !== close) {
|
|
259
276
|
t1 = action === void 0 ? null : /* @__PURE__ */ jsx(SnackbarButton, {
|
|
@@ -279,7 +296,10 @@ function SnackbarControls(t0) {
|
|
|
279
296
|
} else t2 = $[5];
|
|
280
297
|
let t3;
|
|
281
298
|
if ($[6] !== t1 || $[7] !== t2) {
|
|
282
|
-
t3 = /* @__PURE__ */ jsxs(
|
|
299
|
+
t3 = /* @__PURE__ */ jsxs("div", {
|
|
300
|
+
className: "x6s0dn4 x9f619 x78zum5 x2lah0s xvc5jky",
|
|
301
|
+
children: [t1, t2]
|
|
302
|
+
});
|
|
283
303
|
$[6] = t1;
|
|
284
304
|
$[7] = t2;
|
|
285
305
|
$[8] = t3;
|
|
@@ -294,7 +314,7 @@ function SnackbarToast(t0) {
|
|
|
294
314
|
let t1;
|
|
295
315
|
if ($[0] !== message) {
|
|
296
316
|
t1 = /* @__PURE__ */ jsx(UNSTABLE_ToastContent, {
|
|
297
|
-
className: "x9f619 x1girmi0 x1iyjqo2 xpo2rfv x193rfdd x1hews6w xn43zvd xv61bfh xz158ff xeuugli xxlmvz2",
|
|
317
|
+
className: "x9f619 x1girmi0 x4pfjvb x1iyjqo2 xpo2rfv x193rfdd x1hews6w xkjl1po xn43zvd xv61bfh xz158ff xeuugli xj0a0fe xxlmvz2",
|
|
298
318
|
children: /* @__PURE__ */ jsx(Text, {
|
|
299
319
|
slot: "title",
|
|
300
320
|
children: message
|
|
@@ -321,7 +341,7 @@ function SnackbarToast(t0) {
|
|
|
321
341
|
if ($[7] !== t1 || $[8] !== t2 || $[9] !== toast) {
|
|
322
342
|
t3 = /* @__PURE__ */ jsxs(UNSTABLE_Toast, {
|
|
323
343
|
toast,
|
|
324
|
-
className: "x6s0dn4 x1n1nwrg x1u6grsq x1dwmuk9 x16dv9tl x1c5gpgi x1w1tqly x1tfhd1 xx61lck x13rsnn2 x1udv5rz x9f619 x78zum5 xh8yej3 x1x1rfll xlx31pv x1dry9sr xeuugli xuq8xha x1ulcdur
|
|
344
|
+
className: "x6s0dn4 x1n1nwrg x1u6grsq x1dwmuk9 x16dv9tl x1c5gpgi x1w1tqly x1tfhd1 xx61lck x13rsnn2 x1udv5rz x9f619 x78zum5 x1a02dak xh8yej3 x1x1rfll xlx31pv x1dry9sr xeuugli xuq8xha x1ulcdur xr2mjdv x9v5kkp x1t137rt x1de99jn xt970qd xn60lsn x67bb7w",
|
|
325
345
|
children: [t1, t2]
|
|
326
346
|
});
|
|
327
347
|
$[7] = t1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["c","_c","ReactNode","RefAttributes","FocusableElement","ToastRegionProps","RACToastRegionProps","ToastRegionRenderProps","stylex","Button","RACButton","UNSTABLE_Toast","RACToast","UNSTABLE_ToastContent","RACToastContent","UNSTABLE_ToastQueue","RACToastQueue","UNSTABLE_ToastRegion","RACToastRegion","Text","CloseGlyph","useBottomEdgeClearance","useRipple","layers","mergeStatefulStyles","colors","motion","radii","shadows","sizing","spacing","stateLayerOpacity","typography","MESSAGE_MS","UNTIL_CLOSED","WIDE","rise","FORCED_COLORS","_temp","krVfgx","kGO01o","styles","action","kMwMTN","kMv6JI","kGuDYH","k63SB2","kb6lSQ","kLWn49","k8WAf4","kg3NbH","$$css","close","kZKoxP","kzqmXN","kmVPX3","control","kGNEyG","kWkggS","kaIpWk","kMzoRj","kB7OPa","kkrTdU","k1xSpc","kmuXW","kjj79g","kjBf7l","kInvED","k3XXqK","kMeerF","kVQacm","kVAEAm","controlFocused","controlHovered","controlPressed","region","kXwgrk","kOIVth","kkqhue","kLKAdn","kE3dHu","kpe85a","kfzvcC","kY2c9j","risen","clearance","val","undefined","SnackbarAction","label","onPress","SnackbarMessage","message","showCloseButton","SnackbarOptions","onClose","timeout","SnackbarProps","className","closeLabel","queue","SnackbarQueue","style","Omit","SnackbarToastItem","rac","constructor","maxVisibleToasts","add","options","clear","key","actionPress","closeToast","controlClassName","StyleXStyles","state","isFocusVisible","isHovered","isPressed","props","Snackbar","t0","$","T0","t1","t2","t3","snackbarContent","t4","SnackbarButton","children","ripple","handlers","surface","toast","SnackbarControls","SnackbarToast","content","Queue","SnackbarRegionRenderProps","RACToastQueue","stylex.props","_c","props","RACToastRegion","RACButton","RACToastContent","RACToast"],"sources":["../../../src/components/snackbar/index.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode, RefAttributes } from 'react';\nimport type { FocusableElement, ToastRegionProps as RACToastRegionProps, ToastRegionRenderProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { Button as RACButton, UNSTABLE_Toast as RACToast, UNSTABLE_ToastContent as RACToastContent, UNSTABLE_ToastQueue as RACToastQueue, UNSTABLE_ToastRegion as RACToastRegion, Text } from 'react-aria-components';\nimport { CloseGlyph } from '../../glyphs';\nimport { useBottomEdgeClearance } from '../../hooks/useBottomEdge';\nimport { useRipple } from '../../hooks/useRipple';\nimport '../../styles/layers.stylex';\nimport { layers } from '../../styles/layers.stylex';\nimport { mergeStatefulStyles } from '../../styles/merge';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, motion, radii, shadows, sizing, spacing, stateLayerOpacity, typography } from '../../tokens/design.tokens.stylex';\n\n// The snackbar page's brief message at the bottom of the screen, with an\n// optional action beside it and an optional close button after that. The\n// page's container is the inverse surface at a 4dp corner and elevation 3,\n// its supporting text is body-medium in inverse on surface, its action label\n// is inverse primary, and its close icon takes the supporting text's colour.\n// The measurements are the page's too: 8dp of margin from the edges of the\n// screen, 8dp of padding inside the container with another 8dp either side\n// of the message, 14dp above and below on a single line, and between 320 and\n// 576dp wide above the page's 600dp breakpoint — full width below it.\n//\n// One at a time. The page shows a single snackbar and replaces it rather\n// than stacking, which is `maxVisibleToasts: 1` on the queue.\n//\n// React Aria's toast is the behaviour: the region is a landmark that holds\n// the message, moves focus into it for a keyboard, and pauses every timer\n// while it is hovered or focused, so a message never expires while it is\n// being read or acted on.\n//\n// Three things are decided here rather than taken from React Aria or from\n// the page.\n//\n// **The queue is ours, not React Aria's.** React Aria's toast is still\n// `UNSTABLE_`, and `SnackbarQueue` is what keeps that name out of a\n// consumer's code — an upstream rename is this file rather than every call\n// site. It wraps their queue, defaults it to one visible message, and takes\n// the message and its options as one call.\n//\n// **The action and the close button are drawn here rather than through\n// Button and IconButton.** The page colours them inverse primary and inverse\n// on surface, which no variant of either carries, and a colour pushed in\n// from outside through `className` is the merge hazard AGENTS.md describes:\n// StyleX decides between two atomic classes by their order in the compiled\n// stylesheet, not by the order they are applied. Both are React Aria's\n// `Button` with the same ripple and the same state layers, over\n// `currentColor` so each takes the colour the snackbar gives it.\n//\n// **There is no `container` prop.** Every other overlay here takes one,\n// because React Aria's `Modal` and `Popover` accept a portal container, and\n// `src/components/portal-container.test.tsx` is what keeps that true.\n// Its toast region does not: it reads a portal provider that\n// `react-aria-components` does not export, so the region always lands at the\n// end of `<body>`. An app that scopes its StyleX theme to a subtree has to\n// put the theme on `:root` for the snackbar to be drawn in it.\n\n// How long a message is shown when the call site names no `timeout`. The\n// specs page gives no duration, so these come from the snackbar's guidelines\n// and accessibility pages.\n//\n// A message alone leaves after five seconds. The pages allow four to ten, and\n// React Aria's toast docs set five as the least a reader should be given.\n//\n// A message with an action stays until the action is taken or something\n// closes it, as the pages ask of every actionable snackbar. No timer can know\n// how long a reader needs to act: a screen reader user hears the message\n// first and has to reach the region before the action is any use, and the\n// pause while the region is hovered or focused only starts once they have.\n// Android's snackbar can keep shorter defaults because the platform lengthens\n// them from each user's accessibility settings, and the web has no such\n// setting to read.\nconst MESSAGE_MS = 5000;\nconst UNTIL_CLOSED = 0;\n\n// Below the page's 600dp breakpoint the snackbar runs the width of the\n// screen; above it, it takes between 320 and 576.\nconst WIDE = '@media (min-width: 600px)';\n\n// The page's own is a fade. It rises a little as it arrives too, which is\n// what the page draws and what says the message came from the edge of the\n// screen rather than appearing over it.\nconst rise = \"x15b941j-B\";\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\nconst _temp = {\n krVfgx: \"xiicpxy\",\n kGO01o: \"xqf7pud\",\n \"$$css\": true\n};\nconst styles = {\n action: {\n kMwMTN: \"x16bex6i\",\n kMv6JI: \"xkknnkr\",\n kGuDYH: \"x14zspaw\",\n k63SB2: \"x1v9cpvo\",\n kb6lSQ: \"x155f00i\",\n kLWn49: \"x1lz68p4\",\n k8WAf4: \"x1cmllll\",\n kg3NbH: \"x18fpw6u\",\n $$css: true\n },\n close: {\n kZKoxP: \"xbg5kjn\",\n kMwMTN: \"x1girmi0\",\n kzqmXN: \"xoqf9c6\",\n kmVPX3: \"x1717udv\",\n $$css: true\n },\n control: {\n kGNEyG: \"x6s0dn4\",\n kWkggS: \"xjbqb8w\",\n kaIpWk: \"x1dkaolv\",\n kMzoRj: \"xc342km\",\n kB7OPa: \"x9f619\",\n kkrTdU: \"x1ypdohk\",\n k1xSpc: \"x3nfvp2\",\n kmuXW: \"x2lah0s\",\n kjj79g: \"xl56j7k\",\n kjBf7l: \"x14ytart\",\n kInvED: \"x1hl8ikr\",\n k3XXqK: \"x9v5kkp x1t137rt\",\n kMeerF: \"x1de99jn\",\n kVQacm: \"xb3r6kr\",\n kVAEAm: \"x1n2onr6\",\n $$css: true\n },\n controlFocused: {\n kWkggS: \"x1mbb5iu\",\n $$css: true\n },\n controlHovered: {\n kWkggS: \"x930l3l\",\n $$css: true\n },\n controlPressed: {\n kWkggS: \"xsykwg8\",\n $$css: true\n },\n region: {\n kGNEyG: \"x6s0dn4\",\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n kOIVth: \"x126z3so\",\n krVfgx: \"x1ey2m1c\",\n kkqhue: \"x17y0mx6\",\n k3XXqK: \"x1t137rt\",\n kGO01o: \"x1u7mh7p\",\n kLKAdn: \"xi7mcox\",\n kE3dHu: \"xbpsoft\",\n kpe85a: \"xq5vm52\",\n kfzvcC: \"x47corl\",\n kVAEAm: \"xixxii4\",\n kY2c9j: \"x1bk8fjm\",\n $$css: true\n },\n risen: (clearance: string) => [_temp, {\n \"--x-insetBlockEnd\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(clearance)\n }]\n};\ntype SnackbarAction = {\n /** What the action says. The page gives it a single word where it can. */\n label: string;\n /** Run when the action is pressed, just before the snackbar closes. */\n onPress: () => void;\n};\n\n/** What a snackbar carries: its message, and what may sit beside it. */\ntype SnackbarMessage = {\n action: SnackbarAction | undefined;\n message: ReactNode;\n showCloseButton: boolean;\n};\ntype SnackbarOptions = {\n /**\n * A single action shown after the message. Pressing it runs `onPress` and\n * closes the snackbar, which is what the page draws.\n */\n action?: SnackbarAction;\n /** Run when the snackbar closes, however it was closed. */\n onClose?: () => void;\n /**\n * Whether a close button is shown at the end. The page draws one for a\n * message a reader may want out of the way before it expires.\n *\n * Named for what it draws rather than `isDismissable`, which on `Sheet`,\n * `Dialog` and React Aria's modals is whether a press outside them closes\n * them — a snackbar has no outside to press.\n * @default false\n */\n showCloseButton?: boolean;\n /**\n * How long the snackbar is shown, in milliseconds. Defaults to five seconds\n * for a message alone. A message with an action defaults to `0` and stays\n * until the action is taken or something closes it, as Material Design asks\n * of an actionable snackbar, since a reader may need longer to reach the\n * action than any timer allows. The timer is paused while the region is\n * hovered or focused, so a message never expires while it is being read.\n *\n * `0` is the page's indefinite length: the snackbar stays until something\n * closes it. Give one of those an action or `showCloseButton`, or there is no\n * way to be rid of it.\n */\n timeout?: number;\n};\ntype SnackbarProps = {\n /**\n * What a screen reader calls the region holding the snackbar. Left out,\n * React Aria names the region itself: a count of the messages it holds, in\n * the reader's own locale — \"1 notification.\" in English, and one of some\n * thirty languages otherwise. Pass a name only to replace that, and pass a\n * translated one, since whatever is passed is read as written.\n */\n 'aria-label'?: string;\n /** A function may compute the class from the region's render state. */\n className?: RACToastRegionProps<SnackbarMessage>['className'];\n /**\n * What a screen reader calls the button that dismisses a snackbar. It sits\n * here rather than on a message's own options because it does not vary by\n * message, so putting it there would make every `add` call repeat it. Left\n * out, React Aria names it in the reader's locale — \"Close\" in English.\n */\n closeLabel?: string;\n /** The queue the region shows messages from. */\n queue: SnackbarQueue;\n /** A function may compute the style from the region's render state. */\n style?: RACToastRegionProps<SnackbarMessage>['style'];\n} & Omit<RACToastRegionProps<SnackbarMessage>, 'children' | 'className' | 'queue' | 'style'>;\n\n// One entry of the queue, as React Aria hands it to the region's render\n// function. Taken from its render state rather than imported from\n// `react-stately`, which this package does not depend on.\ntype SnackbarToastItem = ToastRegionRenderProps<SnackbarMessage>['visibleToasts'][number];\n\n/**\n * The queue a snackbar is shown from. Make one where the app can reach it —\n * a module of its own is the usual place — mount `Snackbar` once with it,\n * and call `add` from anywhere.\n *\n * ```ts\n * const messages = new Snackbar.Queue()\n * messages.add('Label', { action: { label: 'Undo', onPress: undo } })\n * ```\n *\n * It wraps React Aria's toast queue rather than exposing it, which is what\n * keeps that API's `UNSTABLE_` name out of a consumer's code.\n */\nclass SnackbarQueue {\n /**\n * React Aria's queue, which `Snackbar` subscribes to. Not part of the\n * package's API — read it and an upstream release may break the call site.\n */\n readonly rac: RACToastQueue<SnackbarMessage>;\n constructor() {\n // One at a time, which is what the page shows: a second message replaces\n // the first rather than stacking under it.\n this.rac = new RACToastQueue<SnackbarMessage>({\n maxVisibleToasts: 1\n });\n }\n\n /**\n * Shows a message, and returns the key that closes it.\n */\n add(message: ReactNode, options: SnackbarOptions = {}) {\n const {\n action,\n onClose,\n showCloseButton = false,\n timeout\n } = options;\n return this.rac.add({\n action,\n message,\n showCloseButton\n }, {\n onClose,\n timeout: timeout ?? (action === undefined ? MESSAGE_MS : UNTIL_CLOSED)\n });\n }\n\n /** Closes every snackbar, shown or waiting. */\n clear() {\n this.rac.clear();\n }\n\n /** Closes one snackbar, by the key `add` returned. */\n close(key: string) {\n this.rac.close(key);\n }\n}\n\n// The three handlers the snackbar hands to something below it, each built by\n// a call rather than written inline at the prop, which is what react-perf's\n// no-new-function-as-prop is after; the React Compiler memoises the result on\n// its inputs.\nfunction actionPress(action: SnackbarAction, close: () => void) {\n return () => {\n action.onPress();\n close();\n };\n}\nfunction closeToast(queue: SnackbarQueue, key: string) {\n return () => {\n queue.close(key);\n };\n}\n\n// A control's classes, from its own render state — see `controlFocused`.\nfunction controlClassName(style: stylex.StyleXStyles) {\n return (state: {\n isFocusVisible: boolean;\n isHovered: boolean;\n isPressed: boolean;\n }) => stylex.props(styles.control, style, state.isHovered && styles.controlHovered, state.isFocusVisible && styles.controlFocused, state.isPressed && styles.controlPressed).className ?? '';\n}\n\n/**\n * A brief message at the bottom of the screen, with an optional action. Mount\n * one of these with a `Snackbar.Queue`, and call the queue's `add` to show a\n * message from anywhere.\n *\n * ```tsx\n * const messages = new Snackbar.Queue()\n *\n * <Snackbar queue={messages} />\n * ```\n *\n * The region is portalled to the end of `<body>` and renders nothing while\n * the queue is empty. It is one region rather than one per message, so mount\n * it once, near the root.\n *\n * The call site's `className` and `style` land on that region, which is the\n * element a layout positions.\n *\n * While a full-screen `Dialog` or a `Sheet` with a footer is open, the region\n * rises to sit above those actions rather than over them, since they share\n * the bottom edge of the window and the snackbar is drawn above both.\n */\nfunction Snackbar({\n closeLabel,\n queue,\n ...props\n}: RefAttributes<HTMLDivElement> & SnackbarProps) {\n const clearance = useBottomEdgeClearance();\n return <RACToastRegion<SnackbarMessage> queue={queue.rac} {...props} {...mergeStatefulStyles(stylex.props(styles.region, clearance > 0 && styles.risen(`${clearance}px`)), props)}>\n {snackbarContent(queue, closeLabel)}\n </RACToastRegion>;\n}\n\n/**\n * One of the snackbar's two controls. React Aria's `Button` rather than the\n * library's, for the colour reason in the comment at the top of this file;\n * the ripple and the state layers are the same ones every other control\n * here draws, over `currentColor`.\n */\nfunction SnackbarButton({\n children,\n style,\n ...props\n}: {\n 'aria-label'?: string;\n children: ReactNode;\n onPress?: () => void;\n slot?: string;\n style: stylex.StyleXStyles;\n}) {\n const ripple = useRipple<FocusableElement>();\n return <RACButton {...ripple.handlers} {...props} className={controlClassName(style)}>\n {children}\n {ripple.surface}\n </RACButton>;\n}\nfunction snackbarContent(queue: SnackbarQueue, closeLabel: string | undefined) {\n return ({\n toast\n }: {\n toast: SnackbarToastItem;\n }) => <SnackbarToast close={closeToast(queue, toast.key)} closeLabel={closeLabel} toast={toast} />;\n}\n\n/** The action, the close button, or nothing, after the message. */\nfunction SnackbarControls({\n action,\n close,\n closeLabel,\n showCloseButton\n}: {\n action: SnackbarAction | undefined;\n close: () => void;\n closeLabel: string | undefined;\n showCloseButton: boolean;\n}) {\n return <>\n {action === undefined ? null : <SnackbarButton onPress={actionPress(action, close)} style={styles.action}>\n {action.label}\n </SnackbarButton>}\n {showCloseButton ? <SnackbarButton aria-label={closeLabel} slot=\"close\" style={styles.close}>\n <CloseGlyph className=\"xxk0z11 xvy4d1p\" />\n </SnackbarButton> : null}\n </>;\n}\n\n/** One snackbar: its message, then whatever sits after it. */\nfunction SnackbarToast({\n close,\n closeLabel,\n toast\n}: {\n close: () => void;\n closeLabel: string | undefined;\n toast: SnackbarToastItem;\n}) {\n const {\n action,\n message,\n showCloseButton\n } = toast.content;\n return <RACToast toast={toast} className=\"x6s0dn4 x1n1nwrg x1u6grsq x1dwmuk9 x16dv9tl x1c5gpgi x1w1tqly x1tfhd1 xx61lck x13rsnn2 x1udv5rz x9f619 x78zum5 xh8yej3 x1x1rfll xlx31pv x1dry9sr xeuugli xuq8xha x1ulcdur x1hl8ikr x9v5kkp x1t137rt x1de99jn xt970qd xn60lsn x67bb7w\">\n <RACToastContent className=\"x9f619 x1girmi0 x1iyjqo2 xpo2rfv x193rfdd x1hews6w xn43zvd xv61bfh xz158ff xeuugli xxlmvz2\">\n <Text slot=\"title\">{message}</Text>\n </RACToastContent>\n <SnackbarControls action={action} close={close} closeLabel={closeLabel} showCloseButton={showCloseButton} />\n </RACToast>;\n}\nSnackbar.Queue = SnackbarQueue;\n\n// The queue is reached as `Snackbar.Queue` rather than exported beside the\n// component: this file would otherwise export something that is not a\n// component, which is what turns fast refresh off for it.\nexport type { SnackbarAction, SnackbarMessage, SnackbarOptions, SnackbarProps, SnackbarQueue, ToastRegionRenderProps as SnackbarRegionRenderProps };\nexport default Snackbar;"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["c","_c","ReactNode","RefAttributes","FocusableElement","ToastRegionProps","RACToastRegionProps","ToastRegionRenderProps","stylex","Button","RACButton","UNSTABLE_Toast","RACToast","UNSTABLE_ToastContent","RACToastContent","UNSTABLE_ToastQueue","RACToastQueue","UNSTABLE_ToastRegion","RACToastRegion","Text","CloseGlyph","useBottomEdgeClearance","useRipple","layers","mergeStatefulStyles","colors","motion","radii","shadows","sizing","spacing","stateLayerOpacity","typography","MESSAGE_MS","UNTIL_CLOSED","WIDE","rise","FORCED_COLORS","TARGET_SIZE","_temp","krVfgx","kGO01o","styles","action","kgeoSG","kGOzcv","kpsdNU","kEoFBp","kMwMTN","kMv6JI","kGuDYH","k63SB2","kb6lSQ","kLWn49","kAzted","k8WAf4","kg3NbH","$$css","close","kZKoxP","kzqmXN","kmVPX3","control","kGNEyG","kWkggS","kaIpWk","kMzoRj","kB7OPa","kkrTdU","k1xSpc","kmuXW","kjj79g","kjBf7l","kInvED","k3XXqK","kMeerF","kVAEAm","controlFocused","controlHovered","controlPressed","region","kXwgrk","kOIVth","kkqhue","kLKAdn","kE3dHu","kpe85a","kfzvcC","kY2c9j","risen","clearance","val","undefined","SnackbarAction","label","onPress","SnackbarMessage","message","showCloseButton","SnackbarOptions","onClose","timeout","SnackbarProps","className","closeLabel","queue","SnackbarQueue","style","Omit","SnackbarToastItem","rac","open","Set","constructor","maxVisibleToasts","add","options","clear","key","delete","actionPress","closeToast","controlClassName","StyleXStyles","state","isFocusVisible","isHovered","isPressed","props","Snackbar","t0","$","T0","t1","t2","t3","snackbarContent","t4","SnackbarButton","children","ripple","handlers","surface","toast","SnackbarControls","SnackbarToast","content","Queue","SnackbarRegionRenderProps","RACToastQueue","stylex.props","_c","props","RACToastRegion","RACButton","RACToastContent","RACToast"],"sources":["../../../src/components/snackbar/index.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode, RefAttributes } from 'react';\nimport type { FocusableElement, ToastRegionProps as RACToastRegionProps, ToastRegionRenderProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { Button as RACButton, UNSTABLE_Toast as RACToast, UNSTABLE_ToastContent as RACToastContent, UNSTABLE_ToastQueue as RACToastQueue, UNSTABLE_ToastRegion as RACToastRegion, Text } from 'react-aria-components';\nimport { CloseGlyph } from '../../glyphs';\nimport { useBottomEdgeClearance } from '../../hooks/useBottomEdge';\nimport { useRipple } from '../../hooks/useRipple';\nimport '../../styles/layers.stylex';\nimport { layers } from '../../styles/layers.stylex';\nimport { mergeStatefulStyles } from '../../styles/merge';\nimport '../../tokens/design.tokens.stylex';\nimport { colors, motion, radii, shadows, sizing, spacing, stateLayerOpacity, typography } from '../../tokens/design.tokens.stylex';\n\n// The snackbar page's brief message at the bottom of the screen, with an\n// optional action beside it and an optional close button after that. The\n// page's container is the inverse surface at a 4dp corner and elevation 3,\n// its supporting text is body-medium in inverse on surface, its action label\n// is inverse primary, and its close icon takes the supporting text's colour.\n// The measurements are the page's too: 8dp of margin from the edges of the\n// screen, 8dp of padding inside the container with another 8dp either side\n// of the message, 14dp above and below on a single line, and between 320 and\n// 576dp wide above the page's 600dp breakpoint — full width below it.\n//\n// One at a time. The page shows a single snackbar and replaces it rather\n// than stacking, so a message added while another is up closes that one —\n// its `onClose` runs — and takes its place. Nothing waits behind it: React\n// Aria's queue, left to itself, kept every message and showed the one it had\n// replaced again once the newer closed, so an Undo could come back long after\n// the thing it undid.\n//\n// React Aria's toast is the behaviour: the region is a landmark that holds\n// the message, moves focus into it for a keyboard, and pauses every timer\n// while it is hovered or focused, so a message never expires while it is\n// being read or acted on.\n//\n// Three things are decided here rather than taken from React Aria or from\n// the page.\n//\n// **The queue is ours, not React Aria's.** React Aria's toast is still\n// `UNSTABLE_`, and `SnackbarQueue` is what keeps that name out of a\n// consumer's code — an upstream rename is this file rather than every call\n// site. It wraps their queue, defaults it to one visible message, and takes\n// the message and its options as one call.\n//\n// **The action and the close button are drawn here rather than through\n// Button and IconButton.** The page colours them inverse primary and inverse\n// on surface, which no variant of either carries, and a colour pushed in\n// from outside through `className` is the merge hazard AGENTS.md describes:\n// StyleX decides between two atomic classes by their order in the compiled\n// stylesheet, not by the order they are applied. Both are React Aria's\n// `Button` with the same ripple and the same state layers, over\n// `currentColor` so each takes the colour the snackbar gives it.\n//\n// **There is no `container` prop.** Every other overlay here takes one,\n// because React Aria's `Modal` and `Popover` accept a portal container, and\n// `src/components/portal-container.test.tsx` is what keeps that true.\n// Its toast region does not: it reads a portal provider that\n// `react-aria-components` does not export, so the region always lands at the\n// end of `<body>`. An app that scopes its StyleX theme to a subtree has to\n// put the theme on `:root` for the snackbar to be drawn in it.\n\n// How long a message is shown when the call site names no `timeout`. The\n// specs page gives no duration, so these come from the snackbar's guidelines\n// and accessibility pages.\n//\n// A message alone leaves after five seconds. The pages allow four to ten, and\n// React Aria's toast docs set five as the least a reader should be given.\n//\n// A message with an action stays until the action is taken or something\n// closes it, as the pages ask of every actionable snackbar. No timer can know\n// how long a reader needs to act: a screen reader user hears the message\n// first and has to reach the region before the action is any use, and the\n// pause while the region is hovered or focused only starts once they have.\n// Android's snackbar can keep shorter defaults because the platform lengthens\n// them from each user's accessibility settings, and the web has no such\n// setting to read.\nconst MESSAGE_MS = 5000;\nconst UNTIL_CLOSED = 0;\n\n// Below the page's 600dp breakpoint the snackbar runs the width of the\n// screen; above it, it takes between 320 and 576.\nconst WIDE = '@media (min-width: 600px)';\n\n// The page's own is a fade. It rises a little as it arrives too, which is\n// what the page draws and what says the message came from the edge of the\n// screen rather than appearing over it.\nconst rise = \"x15b941j-B\";\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\n\n// The least press area the action keeps, as Button's medium size does. A\n// literal rather than a token, for the reason Button's `TARGET_SIZE` gives: a\n// consumer resizing their controls should not shrink a floor the page states.\nconst TARGET_SIZE = '48px';\nconst _temp = {\n krVfgx: \"xiicpxy\",\n kGO01o: \"xqf7pud\",\n \"$$css\": true\n};\nconst styles = {\n action: {\n kgeoSG: \"x1cpjm7i\",\n kGOzcv: \"xun2zgk\",\n kpsdNU: \"xm4btww\",\n kEoFBp: \"x1hmns74\",\n kMwMTN: \"x16bex6i\",\n kMv6JI: \"xkknnkr\",\n kGuDYH: \"x14zspaw\",\n k63SB2: \"x1v9cpvo\",\n kb6lSQ: \"x155f00i\",\n kLWn49: \"x1lz68p4\",\n kAzted: \"x1cio8j0\",\n k8WAf4: \"x1cmllll\",\n kg3NbH: \"x18fpw6u\",\n $$css: true\n },\n close: {\n kZKoxP: \"xbg5kjn\",\n kMwMTN: \"x1girmi0\",\n kzqmXN: \"xoqf9c6\",\n kmVPX3: \"x1717udv\",\n $$css: true\n },\n control: {\n kGNEyG: \"x6s0dn4\",\n kWkggS: \"xjbqb8w\",\n kaIpWk: \"x1dkaolv\",\n kMzoRj: \"xc342km\",\n kB7OPa: \"x9f619\",\n kkrTdU: \"x1ypdohk\",\n k1xSpc: \"x3nfvp2\",\n kmuXW: \"x2lah0s\",\n kjj79g: \"xl56j7k\",\n kjBf7l: \"x14ytart\",\n kInvED: \"xr2mjdv\",\n k3XXqK: \"x9v5kkp x1t137rt\",\n kMeerF: \"x1de99jn\",\n kVAEAm: \"x1n2onr6\",\n $$css: true\n },\n controlFocused: {\n kWkggS: \"x1mbb5iu\",\n $$css: true\n },\n controlHovered: {\n kWkggS: \"x930l3l\",\n $$css: true\n },\n controlPressed: {\n kWkggS: \"xsykwg8\",\n $$css: true\n },\n region: {\n kGNEyG: \"x6s0dn4\",\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n kOIVth: \"x126z3so\",\n krVfgx: \"x1ey2m1c\",\n kkqhue: \"x17y0mx6\",\n k3XXqK: \"x1t137rt\",\n kGO01o: \"x1u7mh7p\",\n kLKAdn: \"xi7mcox\",\n kE3dHu: \"xbpsoft\",\n kpe85a: \"xq5vm52\",\n kfzvcC: \"x47corl\",\n kVAEAm: \"xixxii4\",\n kY2c9j: \"x1bk8fjm\",\n $$css: true\n },\n risen: (clearance: string) => [_temp, {\n \"--x-insetBlockEnd\": (val => typeof val === \"number\" ? val + \"px\" : val != null ? val : undefined)(clearance)\n }]\n};\ntype SnackbarAction = {\n /** What the action says. The page gives it a single word where it can. */\n label: string;\n /** Run when the action is pressed, just before the snackbar closes. */\n onPress: () => void;\n};\n\n/** What a snackbar carries: its message, and what may sit beside it. */\ntype SnackbarMessage = {\n action: SnackbarAction | undefined;\n message: ReactNode;\n showCloseButton: boolean;\n};\ntype SnackbarOptions = {\n /**\n * A single action shown after the message. Pressing it runs `onPress` and\n * closes the snackbar, which is what the page draws.\n */\n action?: SnackbarAction;\n /**\n * Run when the snackbar closes, however it was closed: by its timer, its\n * action or close button, `close`, `clear`, or a newer message added in its\n * place.\n */\n onClose?: () => void;\n /**\n * Whether a close button is shown at the end. The page draws one for a\n * message a reader may want out of the way before it expires.\n *\n * Named for what it draws rather than `isDismissable`, which on `Sheet`,\n * `Dialog` and React Aria's modals is whether a press outside them closes\n * them — a snackbar has no outside to press.\n * @default false\n */\n showCloseButton?: boolean;\n /**\n * How long the snackbar is shown, in milliseconds. Defaults to five seconds\n * for a message alone. A message with an action defaults to `0` and stays\n * until the action is taken or something closes it, as Material Design asks\n * of an actionable snackbar, since a reader may need longer to reach the\n * action than any timer allows. The timer is paused while the region is\n * hovered or focused, so a message never expires while it is being read.\n *\n * `0` is the page's indefinite length: the snackbar stays until something\n * closes it. Give one of those an action or `showCloseButton`, or there is no\n * way to be rid of it.\n */\n timeout?: number;\n};\ntype SnackbarProps = {\n /**\n * What a screen reader calls the region holding the snackbar. Left out,\n * React Aria names the region itself: a count of the messages it holds, in\n * the reader's own locale — \"1 notification.\" in English, and one of some\n * thirty languages otherwise. Pass a name only to replace that, and pass a\n * translated one, since whatever is passed is read as written.\n */\n 'aria-label'?: string;\n /** A function may compute the class from the region's render state. */\n className?: RACToastRegionProps<SnackbarMessage>['className'];\n /**\n * What a screen reader calls the button that dismisses a snackbar. It sits\n * here rather than on a message's own options because it does not vary by\n * message, so putting it there would make every `add` call repeat it. Left\n * out, React Aria names it in the reader's locale — \"Close\" in English.\n */\n closeLabel?: string;\n /** The queue the region shows messages from. */\n queue: SnackbarQueue;\n /** A function may compute the style from the region's render state. */\n style?: RACToastRegionProps<SnackbarMessage>['style'];\n} & Omit<RACToastRegionProps<SnackbarMessage>, 'children' | 'className' | 'queue' | 'style'>;\n\n// One entry of the queue, as React Aria hands it to the region's render\n// function. Taken from its render state rather than imported from\n// `react-stately`, which this package does not depend on.\ntype SnackbarToastItem = ToastRegionRenderProps<SnackbarMessage>['visibleToasts'][number];\n\n/**\n * The queue a snackbar is shown from. Make one where the app can reach it —\n * a module of its own is the usual place — mount `Snackbar` once with it,\n * and call `add` from anywhere.\n *\n * ```ts\n * const messages = new Snackbar.Queue()\n * messages.add('Label', { action: { label: 'Undo', onPress: undo } })\n * ```\n *\n * It wraps React Aria's toast queue rather than exposing it, which is what\n * keeps that API's `UNSTABLE_` name out of a consumer's code.\n */\nclass SnackbarQueue {\n /**\n * React Aria's queue, which `Snackbar` subscribes to. Not part of the\n * package's API — read it and an upstream release may break the call site.\n */\n readonly rac: RACToastQueue<SnackbarMessage>;\n\n // The keys of the snackbars not yet closed, which `add` and `clear` close.\n // Kept here because React Aria keeps its own list private, and its own\n // `clear` empties that list without running a single `onClose`.\n readonly #open = new Set<string>();\n constructor() {\n // One at a time, which is what the page shows. `add` closes whatever is\n // up before it adds, so nothing is ever left waiting for this to hold\n // back; it says the same thing to React Aria in its own terms.\n this.rac = new RACToastQueue<SnackbarMessage>({\n maxVisibleToasts: 1\n });\n }\n\n /**\n * Shows a message in place of the one on screen, and returns the key that\n * closes it. The message it replaces is closed, so its `onClose` runs, and\n * it does not come back.\n */\n add(message: ReactNode, options: SnackbarOptions = {}) {\n const {\n action,\n onClose,\n showCloseButton = false,\n timeout\n } = options;\n this.clear();\n const key = this.rac.add({\n action,\n message,\n showCloseButton\n }, {\n // However it closes — its timer runs inside React Aria's queue,\n // past this one — it leaves the open set on the way out.\n onClose: () => {\n this.#open.delete(key);\n onClose?.();\n },\n timeout: timeout ?? (action === undefined ? MESSAGE_MS : UNTIL_CLOSED)\n });\n this.#open.add(key);\n return key;\n }\n\n /** Closes the snackbar on screen, running its `onClose`. */\n clear() {\n // Each close runs that message's `onClose`, which deletes its own key\n // from the set — the entry being visited, which a Set allows.\n for (const key of this.#open) {\n this.rac.close(key);\n }\n }\n\n /** Closes one snackbar, by the key `add` returned. */\n close(key: string) {\n this.rac.close(key);\n }\n}\n\n// The three handlers the snackbar hands to something below it, each built by\n// a call rather than written inline at the prop, which is what react-perf's\n// no-new-function-as-prop is after; the React Compiler memoises the result on\n// its inputs.\nfunction actionPress(action: SnackbarAction, close: () => void) {\n return () => {\n action.onPress();\n close();\n };\n}\nfunction closeToast(queue: SnackbarQueue, key: string) {\n return () => {\n queue.close(key);\n };\n}\n\n// A control's classes, from its own render state — see `controlFocused`.\nfunction controlClassName(style: stylex.StyleXStyles) {\n return (state: {\n isFocusVisible: boolean;\n isHovered: boolean;\n isPressed: boolean;\n }) => stylex.props(styles.control, style, state.isHovered && styles.controlHovered, state.isFocusVisible && styles.controlFocused, state.isPressed && styles.controlPressed).className ?? '';\n}\n\n/**\n * A brief message at the bottom of the screen, with an optional action. Mount\n * one of these with a `Snackbar.Queue`, and call the queue's `add` to show a\n * message from anywhere.\n *\n * ```tsx\n * const messages = new Snackbar.Queue()\n *\n * <Snackbar queue={messages} />\n * ```\n *\n * The region is portalled to the end of `<body>` and renders nothing while\n * the queue is empty. It is one region rather than one per message, so mount\n * it once, near the root.\n *\n * The call site's `className` and `style` land on that region, which is the\n * element a layout positions.\n *\n * While a full-screen `Dialog` or a `Sheet` with a footer is open, the region\n * rises to sit above those actions rather than over them, since they share\n * the bottom edge of the window and the snackbar is drawn above both.\n */\nfunction Snackbar({\n closeLabel,\n queue,\n ...props\n}: RefAttributes<HTMLDivElement> & SnackbarProps) {\n const clearance = useBottomEdgeClearance();\n return <RACToastRegion<SnackbarMessage> queue={queue.rac} {...props} {...mergeStatefulStyles(stylex.props(styles.region, clearance > 0 && styles.risen(`${clearance}px`)), props)}>\n {snackbarContent(queue, closeLabel)}\n </RACToastRegion>;\n}\n\n/**\n * One of the snackbar's two controls. React Aria's `Button` rather than the\n * library's, for the colour reason in the comment at the top of this file;\n * the ripple and the state layers are the same ones every other control\n * here draws, over `currentColor`.\n */\nfunction SnackbarButton({\n children,\n style,\n ...props\n}: {\n 'aria-label'?: string;\n children: ReactNode;\n onPress?: () => void;\n slot?: string;\n style: stylex.StyleXStyles;\n}) {\n const ripple = useRipple<FocusableElement>();\n return <RACButton {...ripple.handlers} {...props} className={controlClassName(style)}>\n {children}\n {ripple.surface}\n </RACButton>;\n}\nfunction snackbarContent(queue: SnackbarQueue, closeLabel: string | undefined) {\n return ({\n toast\n }: {\n toast: SnackbarToastItem;\n }) => <SnackbarToast close={closeToast(queue, toast.key)} closeLabel={closeLabel} toast={toast} />;\n}\n\n/**\n * The action, the close button, or nothing, after the message — together, so\n * they move beneath it together.\n */\nfunction SnackbarControls({\n action,\n close,\n closeLabel,\n showCloseButton\n}: {\n action: SnackbarAction | undefined;\n close: () => void;\n closeLabel: string | undefined;\n showCloseButton: boolean;\n}) {\n if (action === undefined && !showCloseButton) {\n return null;\n }\n return <div className=\"x6s0dn4 x9f619 x78zum5 x2lah0s xvc5jky\">\n {action === undefined ? null : <SnackbarButton onPress={actionPress(action, close)} style={styles.action}>\n {action.label}\n </SnackbarButton>}\n {showCloseButton ? <SnackbarButton aria-label={closeLabel} slot=\"close\" style={styles.close}>\n <CloseGlyph className=\"xxk0z11 xvy4d1p\" />\n </SnackbarButton> : null}\n </div>;\n}\n\n/** One snackbar: its message, then whatever sits after it. */\nfunction SnackbarToast({\n close,\n closeLabel,\n toast\n}: {\n close: () => void;\n closeLabel: string | undefined;\n toast: SnackbarToastItem;\n}) {\n const {\n action,\n message,\n showCloseButton\n } = toast.content;\n return <RACToast toast={toast} className=\"x6s0dn4 x1n1nwrg x1u6grsq x1dwmuk9 x16dv9tl x1c5gpgi x1w1tqly x1tfhd1 xx61lck x13rsnn2 x1udv5rz x9f619 x78zum5 x1a02dak xh8yej3 x1x1rfll xlx31pv x1dry9sr xeuugli xuq8xha x1ulcdur xr2mjdv x9v5kkp x1t137rt x1de99jn xt970qd xn60lsn x67bb7w\">\n <RACToastContent className=\"x9f619 x1girmi0 x4pfjvb x1iyjqo2 xpo2rfv x193rfdd x1hews6w xkjl1po xn43zvd xv61bfh xz158ff xeuugli xj0a0fe xxlmvz2\">\n <Text slot=\"title\">{message}</Text>\n </RACToastContent>\n <SnackbarControls action={action} close={close} closeLabel={closeLabel} showCloseButton={showCloseButton} />\n </RACToast>;\n}\nSnackbar.Queue = SnackbarQueue;\n\n// The queue is reached as `Snackbar.Queue` rather than exported beside the\n// component: this file would otherwise export something that is not a\n// component, which is what turns fast refresh off for it.\nexport type { SnackbarAction, SnackbarMessage, SnackbarOptions, SnackbarProps, SnackbarQueue, ToastRegionRenderProps as SnackbarRegionRenderProps };\nexport default Snackbar;"],"mappings":"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"}
|
|
@@ -185,7 +185,8 @@ const pressedLayers = {
|
|
|
185
185
|
}
|
|
186
186
|
};
|
|
187
187
|
const TRAVEL = 20;
|
|
188
|
-
const
|
|
188
|
+
const MOUSE_SLOP = TRAVEL / 4;
|
|
189
|
+
const TOUCH_SLOP = TRAVEL / 2;
|
|
189
190
|
function buttonContent(children, icon, ripple, drag) {
|
|
190
191
|
return (state) => {
|
|
191
192
|
const interactive = !state.isDisabled && !state.isReadOnly;
|
|
@@ -316,6 +317,9 @@ function Switch(t0) {
|
|
|
316
317
|
* A press that moves no further than the slop is left alone entirely, so a
|
|
317
318
|
* tap flips the switch however still the pointer was — a drag starts only
|
|
318
319
|
* once the pointer passes it, and from then on the handle follows every move.
|
|
320
|
+
* The slop is the pointer's own: a finger and a pen drift further on a tap
|
|
321
|
+
* than a mouse does. A mouse or pen drag then focuses the input, as a tap
|
|
322
|
+
* does.
|
|
319
323
|
*
|
|
320
324
|
* The guard for the click after a drag is cleared by the next press, not by
|
|
321
325
|
* that click, since the click may never come: a touch dragged past the
|
|
@@ -355,7 +359,7 @@ function useHandleDrag() {
|
|
|
355
359
|
const from = origin.current;
|
|
356
360
|
if (from === null) return;
|
|
357
361
|
const along = from.rtl ? from.x - event_0.clientX : event_0.clientX - from.x;
|
|
358
|
-
if (settled.current === null && Math.abs(along) <=
|
|
362
|
+
if (settled.current === null && Math.abs(along) <= from.slop) return;
|
|
359
363
|
const next = Math.min(TRAVEL, Math.max(0, from.base + along));
|
|
360
364
|
settled.current = next;
|
|
361
365
|
setOffset(next);
|
|
@@ -379,8 +383,10 @@ function useHandleDrag() {
|
|
|
379
383
|
pointerType: event_1.pointerType
|
|
380
384
|
}));
|
|
381
385
|
cancelClick.current = true;
|
|
386
|
+
const input = seat.closest("label")?.querySelector("input");
|
|
387
|
+
if (from_0.focuses) input?.focus({ preventScroll: true });
|
|
382
388
|
if (stopped > TRAVEL / 2 === from_0.on) return;
|
|
383
|
-
|
|
389
|
+
input?.click();
|
|
384
390
|
};
|
|
385
391
|
$[3] = t3;
|
|
386
392
|
} else t3 = $[3];
|
|
@@ -393,10 +399,13 @@ function useHandleDrag() {
|
|
|
393
399
|
onPointerDown: (event_2) => {
|
|
394
400
|
cancelClick.current = false;
|
|
395
401
|
if (event_2.pointerType === "mouse" && event_2.button !== 0) return;
|
|
402
|
+
const touch = event_2.pointerType === "touch";
|
|
396
403
|
origin.current = {
|
|
397
404
|
base: on ? TRAVEL : 0,
|
|
405
|
+
focuses: !touch,
|
|
398
406
|
on,
|
|
399
407
|
rtl: getComputedStyle(event_2.currentTarget).direction === "rtl",
|
|
408
|
+
slop: touch || event_2.pointerType === "pen" ? TOUCH_SLOP : MOUSE_SLOP,
|
|
400
409
|
x: event_2.clientX
|
|
401
410
|
};
|
|
402
411
|
settled.current = null;
|