@stackone/malachite 2.68.1 → 2.69.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/COMPONENTS.md CHANGED
@@ -44,6 +44,7 @@ The catalog of components exported from `@stackone/malachite`. **Reach for one o
44
44
  - **`UsageCard`** — A small metered card: a title (optionally a link via `titleLink`, drawn with a trailing arrow), a right-aligned `detail` such as "700/1,000", and a body, usually a `Progress`. Used by `Sidebar.Usage`, and fine on its own, e.g. on a billing page. _Key props:_ `title`, `titleLink`, `detail`, `children`, `aria-label` (required; names the group), `busy` (sets `aria-busy` only).
45
45
  - **`Progress`** — Progress bar.
46
46
  - **`LoadingBar`** — Indeterminate full-width loading line; the variant colour sweeps across a pale track for work of unknown duration. Toggle `active` rather than unmounting, so the reserved height prevents layout shift. _Key props:_ `active`, `LoadingBarVariant` (`default` | `warning` | `error`), `LoadingBarSize` (`small` | `medium` | `large`), `aria-label`, `aria-labelledby`, `className`, `style`.
47
+ - **`ToastProvider`** — Transient top-centre toasts for the outcome of an action. Wrap the app once in `ToastProvider` and call `useToast().show({ message, variant })` anywhere beneath it. Each toast auto-dismisses, pauses while hovered and dismisses on click; at most three show at once. Toasts are announced through always-mounted live regions (`status` for success, `alert` for error), and the pills themselves are hidden from assistive tech and never take focus, so they cannot fight a dialog's focus trap. The host mounts on the first toast and joins the top layer, so toasts paint above elevated side panels. _Key props:_ `ToastProvider`: `children`, `duration` (ms, default 3000). `useToast()` → `show({ message, variant })`, `ToastVariant` (`success` | `error`, default `success`).
47
48
  - **`Spinner`** — Loading spinner.
48
49
  - **`Skeleton`** — Loading placeholders. Includes `Skeleton.Avatar` and `Skeleton.Input`. The shimmer stops under `prefers-reduced-motion`, leaving the plain placeholder.
49
50
  - **`Tooltip`** — Hover/focus tooltip; also works on disabled controls (see CLAUDE.md). It describes its trigger once shown, so `describesTrigger={false}` where the same sentence is already on screen and referenced — otherwise a screen reader reads it twice. _Key props:_ `text`, `placement`, `delay`, `maxWidth`, `shouldShow`, `triggerAs`, `describesTrigger`, `isShrinkable`, `fill`, `wrapChildren`, `suppressed` (holds the tooltip back, e.g. while the popup its trigger opens is up), `showOnFocus` (false where script can move focus onto the trigger, e.g. an option a panel focuses on open), `focusableTrigger` (makes a trigger that cannot take focus — text, a static `Tag` — a tab stop, so the tooltip is not mouse-only; not for focusable children).
@@ -0,0 +1,59 @@
1
+ import { jsx as i } from "react/jsx-runtime";
2
+ import { useRef as a, useLayoutEffect as n } from "react";
3
+ import { createPortal as c } from "react-dom";
4
+ import { ShadowRootWrapper as l } from "../ShadowRootWrapper.js";
5
+ import d from "./ToastItem.js";
6
+ import { keepAboveOverlayStack as u } from "./overlayBehaviour.js";
7
+ import { ensureToastStyles as h, overlayIdentity as v } from "./portalOverlay.js";
8
+ import { leaveTopLayer as x, raiseToTopLayer as y } from "./topLayer.js";
9
+ const T = {
10
+ position: "fixed",
11
+ top: 0,
12
+ left: 0,
13
+ right: 0,
14
+ pointerEvents: "none"
15
+ }, w = ({ toasts: t, duration: m, onDismiss: f }) => {
16
+ var p;
17
+ const e = a(null), r = (p = t[t.length - 1]) == null ? void 0 : p.id;
18
+ n(() => {
19
+ h();
20
+ }, []), n(() => {
21
+ const o = e.current;
22
+ if (o) {
23
+ if (r === void 0) {
24
+ x(o);
25
+ return;
26
+ }
27
+ y(o);
28
+ }
29
+ }, [r]);
30
+ const s = r !== void 0;
31
+ return n(() => {
32
+ const o = e.current;
33
+ if (!(!o || !s))
34
+ return u(o);
35
+ }, [s]), c(
36
+ /* @__PURE__ */ i(
37
+ l,
38
+ {
39
+ hostRef: e,
40
+ hostStyle: T,
41
+ hostProps: v("toast"),
42
+ children: /* @__PURE__ */ i("div", { className: "flex flex-col items-center gap-[8px] px-[16px] pt-[24px]", children: t.map((o) => /* @__PURE__ */ i(
43
+ d,
44
+ {
45
+ toast: o,
46
+ duration: m,
47
+ onDismiss: f
48
+ },
49
+ o.id
50
+ )) })
51
+ }
52
+ ),
53
+ document.body
54
+ );
55
+ };
56
+ export {
57
+ w as default
58
+ };
59
+ //# sourceMappingURL=ToastHost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToastHost.js","sources":["../../src/components/ToastHost.tsx"],"sourcesContent":["import { useLayoutEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ShadowRootWrapper } from '../ShadowRootWrapper';\nimport ToastItem from './ToastItem';\nimport { keepAboveOverlayStack } from './overlayBehaviour';\nimport { ensureToastStyles, overlayIdentity } from './portalOverlay';\nimport type { QueuedToast } from './toastTypes';\nimport { leaveTopLayer, raiseToTopLayer } from './topLayer';\n\ninterface ToastHostProps {\n toasts: QueuedToast[];\n duration: number;\n onDismiss: (id: number) => void;\n}\n\nconst HOST_STYLE: React.CSSProperties = {\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n pointerEvents: 'none',\n};\n\nconst ToastHost: React.FC<ToastHostProps> = ({ toasts, duration, onDismiss }) => {\n const hostRef = useRef<HTMLDivElement | null>(null);\n const newestId = toasts[toasts.length - 1]?.id;\n\n useLayoutEffect(() => {\n ensureToastStyles();\n }, []);\n\n useLayoutEffect(() => {\n const host = hostRef.current;\n if (!host) {\n return;\n }\n if (newestId === undefined) {\n leaveTopLayer(host);\n return;\n }\n raiseToTopLayer(host);\n }, [newestId]);\n\n const visible = newestId !== undefined;\n useLayoutEffect(() => {\n const host = hostRef.current;\n if (!host || !visible) {\n return;\n }\n return keepAboveOverlayStack(host);\n }, [visible]);\n\n return createPortal(\n <ShadowRootWrapper\n hostRef={hostRef}\n hostStyle={HOST_STYLE}\n hostProps={overlayIdentity('toast')}\n >\n <div className=\"flex flex-col items-center gap-[8px] px-[16px] pt-[24px]\">\n {toasts.map((toast) => (\n <ToastItem\n key={toast.id}\n toast={toast}\n duration={duration}\n onDismiss={onDismiss}\n />\n ))}\n </div>\n </ShadowRootWrapper>,\n document.body,\n );\n};\n\nexport default ToastHost;\n"],"names":["HOST_STYLE","ToastHost","toasts","duration","onDismiss","hostRef","useRef","newestId","_a","useLayoutEffect","ensureToastStyles","host","leaveTopLayer","raiseToTopLayer","visible","keepAboveOverlayStack","createPortal","jsx","ShadowRootWrapper","overlayIdentity","toast","ToastItem"],"mappings":";;;;;;;;AAeA,MAAMA,IAAkC;AAAA,EACpC,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,eAAe;AACnB,GAEMC,IAAsC,CAAC,EAAE,QAAAC,GAAQ,UAAAC,GAAU,WAAAC,QAAgB;;AAC7E,QAAMC,IAAUC,EAA8B,IAAI,GAC5CC,KAAWC,IAAAN,EAAOA,EAAO,SAAS,CAAC,MAAxB,gBAAAM,EAA2B;AAE5C,EAAAC,EAAgB,MAAM;AAClB,IAAAC,EAAA;AAAA,EACJ,GAAG,CAAA,CAAE,GAELD,EAAgB,MAAM;AAClB,UAAME,IAAON,EAAQ;AACrB,QAAKM,GAGL;AAAA,UAAIJ,MAAa,QAAW;AACxB,QAAAK,EAAcD,CAAI;AAClB;AAAA,MACJ;AACA,MAAAE,EAAgBF,CAAI;AAAA;AAAA,EACxB,GAAG,CAACJ,CAAQ,CAAC;AAEb,QAAMO,IAAUP,MAAa;AAC7B,SAAAE,EAAgB,MAAM;AAClB,UAAME,IAAON,EAAQ;AACrB,QAAI,GAACM,KAAQ,CAACG;AAGd,aAAOC,EAAsBJ,CAAI;AAAA,EACrC,GAAG,CAACG,CAAO,CAAC,GAELE;AAAA,IACH,gBAAAC;AAAA,MAACC;AAAA,MAAA;AAAA,QACG,SAAAb;AAAA,QACA,WAAWL;AAAA,QACX,WAAWmB,EAAgB,OAAO;AAAA,QAElC,4BAAC,OAAA,EAAI,WAAU,4DACV,UAAAjB,EAAO,IAAI,CAACkB,MACT,gBAAAH;AAAA,UAACI;AAAA,UAAA;AAAA,YAEG,OAAAD;AAAA,YACA,UAAAjB;AAAA,YACA,WAAAC;AAAA,UAAA;AAAA,UAHKgB,EAAM;AAAA,QAAA,CAKlB,EAAA,CACL;AAAA,MAAA;AAAA,IAAA;AAAA,IAEJ,SAAS;AAAA,EAAA;AAEjB;"}
@@ -0,0 +1,51 @@
1
+ import { jsxs as x, jsx as l } from "react/jsx-runtime";
2
+ import { useState as v, useRef as m, useEffect as p } from "react";
3
+ import g from "./CustomIcons/CheckCircleFilled.js";
4
+ import h from "./CustomIcons/ErrorCircleFilled.js";
5
+ const f = {
6
+ success: "text-[var(--malachite-text-success,rgb(2,122,66))] supports-[color:color-mix(in_srgb,red,red)]:text-[color-mix(in_srgb,var(--malachite-text-success,rgb(2,122,66))_70%,var(--malachite-tooltip-foreground,rgb(255,255,255)))]",
7
+ error: "text-[var(--malachite-text-destructive,rgb(237,53,54))] supports-[color:color-mix(in_srgb,red,red)]:text-[color-mix(in_srgb,var(--malachite-text-destructive,rgb(237,53,54))_70%,var(--malachite-tooltip-foreground,rgb(255,255,255)))]"
8
+ }, E = ({ toast: r, duration: u, onDismiss: a }) => {
9
+ const [i, n] = v(!1), s = m(null), o = m(u);
10
+ p(() => {
11
+ const e = s.current;
12
+ if (!e)
13
+ return;
14
+ const t = () => n(!0), c = () => n(!1);
15
+ return e.addEventListener("pointerenter", t), e.addEventListener("pointerleave", c), () => {
16
+ e.removeEventListener("pointerenter", t), e.removeEventListener("pointerleave", c);
17
+ };
18
+ }, []), p(() => {
19
+ if (i)
20
+ return;
21
+ const e = Date.now(), t = setTimeout(() => a(r.id), o.current);
22
+ return () => {
23
+ clearTimeout(t), o.current = Math.max(0, o.current - (Date.now() - e));
24
+ };
25
+ }, [i, a, r.id]);
26
+ const d = r.variant === "error" ? h : g;
27
+ return (
28
+ // aria-hidden: the provider's live regions are the announced copy.
29
+ /* @__PURE__ */ x(
30
+ "div",
31
+ {
32
+ ref: s,
33
+ "aria-hidden": "true",
34
+ "data-toast": r.variant,
35
+ onClick: (e) => {
36
+ e.stopPropagation(), a(r.id);
37
+ },
38
+ className: "pointer-events-auto flex max-w-[480px] cursor-pointer items-start gap-[8px] rounded-[var(--malachite-radius-xxxl,16px)] bg-[var(--malachite-tooltip-background,rgb(59,59,59))] px-[12px] py-[8px] text-[length:var(--malachite-font-size-medium,14px)] leading-[20px] text-[var(--malachite-tooltip-foreground,rgb(255,255,255))] [box-shadow:var(--malachite-tooltip-shadow,0px_0px_10px_0px_rgba(0,0,0,0.2))] animate-[malachite-toast-in_150ms_ease-out] motion-reduce:animate-none",
39
+ style: { overflowWrap: "anywhere" },
40
+ children: [
41
+ /* @__PURE__ */ l(d, { size: 16, className: `mt-[2px] shrink-0 ${f[r.variant]}` }),
42
+ /* @__PURE__ */ l("span", { children: r.message })
43
+ ]
44
+ }
45
+ )
46
+ );
47
+ };
48
+ export {
49
+ E as default
50
+ };
51
+ //# sourceMappingURL=ToastItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToastItem.js","sources":["../../src/components/ToastItem.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport CheckCircleFilled from './CustomIcons/CheckCircleFilled';\nimport ErrorCircleFilled from './CustomIcons/ErrorCircleFilled';\nimport type { QueuedToast, ToastVariant } from './toastTypes';\n\n// The plain status tokens fall under 3:1 on the pill; the mix clears it in both themes.\nconst ICON_COLOR: Record<ToastVariant, string> = {\n success:\n 'text-[var(--malachite-text-success,rgb(2,122,66))] supports-[color:color-mix(in_srgb,red,red)]:text-[color-mix(in_srgb,var(--malachite-text-success,rgb(2,122,66))_70%,var(--malachite-tooltip-foreground,rgb(255,255,255)))]',\n error: 'text-[var(--malachite-text-destructive,rgb(237,53,54))] supports-[color:color-mix(in_srgb,red,red)]:text-[color-mix(in_srgb,var(--malachite-text-destructive,rgb(237,53,54))_70%,var(--malachite-tooltip-foreground,rgb(255,255,255)))]',\n};\n\ninterface ToastItemProps {\n toast: QueuedToast;\n duration: number;\n onDismiss: (id: number) => void;\n}\n\nconst ToastItem: React.FC<ToastItemProps> = ({ toast, duration, onDismiss }) => {\n const [paused, setPaused] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n const remaining = useRef(duration);\n\n // React's onPointerEnter never fires across this portal's shadow boundary.\n useEffect(() => {\n const el = ref.current;\n if (!el) {\n return;\n }\n const pause = () => setPaused(true);\n const resume = () => setPaused(false);\n el.addEventListener('pointerenter', pause);\n el.addEventListener('pointerleave', resume);\n return () => {\n el.removeEventListener('pointerenter', pause);\n el.removeEventListener('pointerleave', resume);\n };\n }, []);\n\n useEffect(() => {\n if (paused) {\n return;\n }\n const startedAt = Date.now();\n const timeout = setTimeout(() => onDismiss(toast.id), remaining.current);\n return () => {\n clearTimeout(timeout);\n remaining.current = Math.max(0, remaining.current - (Date.now() - startedAt));\n };\n }, [paused, onDismiss, toast.id]);\n\n const Icon = toast.variant === 'error' ? ErrorCircleFilled : CheckCircleFilled;\n\n return (\n // aria-hidden: the provider's live regions are the announced copy.\n <div\n ref={ref}\n aria-hidden=\"true\"\n data-toast={toast.variant}\n onClick={(event) => {\n // A portal bubbles through the React tree, to the provider's ancestors.\n event.stopPropagation();\n onDismiss(toast.id);\n }}\n className=\"pointer-events-auto flex max-w-[480px] cursor-pointer items-start gap-[8px] rounded-[var(--malachite-radius-xxxl,16px)] bg-[var(--malachite-tooltip-background,rgb(59,59,59))] px-[12px] py-[8px] text-[length:var(--malachite-font-size-medium,14px)] leading-[20px] text-[var(--malachite-tooltip-foreground,rgb(255,255,255))] [box-shadow:var(--malachite-tooltip-shadow,0px_0px_10px_0px_rgba(0,0,0,0.2))] animate-[malachite-toast-in_150ms_ease-out] motion-reduce:animate-none\"\n style={{ overflowWrap: 'anywhere' }}\n >\n <Icon size={16} className={`mt-[2px] shrink-0 ${ICON_COLOR[toast.variant]}`} />\n <span>{toast.message}</span>\n </div>\n );\n};\n\nexport default ToastItem;\n"],"names":["ICON_COLOR","ToastItem","toast","duration","onDismiss","paused","setPaused","useState","ref","useRef","remaining","useEffect","el","pause","resume","startedAt","timeout","Icon","ErrorCircleFilled","CheckCircleFilled","jsxs","event","jsx"],"mappings":";;;;AAMA,MAAMA,IAA2C;AAAA,EAC7C,SACI;AAAA,EACJ,OAAO;AACX,GAQMC,IAAsC,CAAC,EAAE,OAAAC,GAAO,UAAAC,GAAU,WAAAC,QAAgB;AAC5E,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAAS,EAAK,GACpCC,IAAMC,EAAuB,IAAI,GACjCC,IAAYD,EAAON,CAAQ;AAGjC,EAAAQ,EAAU,MAAM;AACZ,UAAMC,IAAKJ,EAAI;AACf,QAAI,CAACI;AACD;AAEJ,UAAMC,IAAQ,MAAMP,EAAU,EAAI,GAC5BQ,IAAS,MAAMR,EAAU,EAAK;AACpC,WAAAM,EAAG,iBAAiB,gBAAgBC,CAAK,GACzCD,EAAG,iBAAiB,gBAAgBE,CAAM,GACnC,MAAM;AACT,MAAAF,EAAG,oBAAoB,gBAAgBC,CAAK,GAC5CD,EAAG,oBAAoB,gBAAgBE,CAAM;AAAA,IACjD;AAAA,EACJ,GAAG,CAAA,CAAE,GAELH,EAAU,MAAM;AACZ,QAAIN;AACA;AAEJ,UAAMU,IAAY,KAAK,IAAA,GACjBC,IAAU,WAAW,MAAMZ,EAAUF,EAAM,EAAE,GAAGQ,EAAU,OAAO;AACvE,WAAO,MAAM;AACT,mBAAaM,CAAO,GACpBN,EAAU,UAAU,KAAK,IAAI,GAAGA,EAAU,WAAW,KAAK,IAAA,IAAQK,EAAU;AAAA,IAChF;AAAA,EACJ,GAAG,CAACV,GAAQD,GAAWF,EAAM,EAAE,CAAC;AAEhC,QAAMe,IAAOf,EAAM,YAAY,UAAUgB,IAAoBC;AAE7D;AAAA;AAAA,IAEI,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,KAAAZ;AAAA,QACA,eAAY;AAAA,QACZ,cAAYN,EAAM;AAAA,QAClB,SAAS,CAACmB,MAAU;AAEhB,UAAAA,EAAM,gBAAA,GACNjB,EAAUF,EAAM,EAAE;AAAA,QACtB;AAAA,QACA,WAAU;AAAA,QACV,OAAO,EAAE,cAAc,WAAA;AAAA,QAEvB,UAAA;AAAA,UAAA,gBAAAoB,EAACL,GAAA,EAAK,MAAM,IAAI,WAAW,qBAAqBjB,EAAWE,EAAM,OAAO,CAAC,GAAA,CAAI;AAAA,UAC7E,gBAAAoB,EAAC,QAAA,EAAM,UAAApB,EAAM,QAAA,CAAQ;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA;AAGjC;"}
@@ -0,0 +1,54 @@
1
+ import { jsxs as m, jsx as n } from "react/jsx-runtime";
2
+ import { useState as i, useRef as v, useCallback as u, useEffect as D, useMemo as E } from "react";
3
+ import _ from "./ToastHost.js";
4
+ import { ToastContext as x } from "./toastContext.js";
5
+ import { TOAST_ANNOUNCEMENT_LIFETIME_MS as I, TOAST_DEFAULT_DURATION_MS as M } from "./toastTypes.js";
6
+ const N = {
7
+ position: "absolute",
8
+ width: 1,
9
+ height: 1,
10
+ margin: -1,
11
+ padding: 0,
12
+ border: 0,
13
+ overflow: "hidden",
14
+ clip: "rect(0 0 0 0)",
15
+ clipPath: "inset(50%)",
16
+ whiteSpace: "nowrap"
17
+ }, C = ({
18
+ children: p,
19
+ duration: f = M
20
+ }) => {
21
+ const [h, r] = i([]), [a, c] = i(
22
+ []
23
+ ), [T, w] = i(!1), l = v(0), d = u(({ message: t, variant: s = "success" }) => {
24
+ l.current += 1;
25
+ const e = { id: l.current, message: t, variant: s };
26
+ r((o) => [...o, e].slice(-3)), c((o) => [...o, { ...e, announcedAt: Date.now() }]), w(!0);
27
+ }, []), A = u((t) => {
28
+ r((s) => s.filter((e) => e.id !== t));
29
+ }, []);
30
+ D(() => {
31
+ const t = a[0];
32
+ if (!t)
33
+ return;
34
+ const s = setTimeout(
35
+ () => c((e) => e.filter((o) => o.id !== t.id)),
36
+ Math.max(0, t.announcedAt + I - Date.now())
37
+ );
38
+ return () => clearTimeout(s);
39
+ }, [a]);
40
+ const S = E(() => ({ show: d }), [d]);
41
+ return /* @__PURE__ */ m(x.Provider, { value: S, children: [
42
+ p,
43
+ /* @__PURE__ */ m("div", { style: N, children: [
44
+ /* @__PURE__ */ n("span", { role: "status", "aria-atomic": "false", children: a.filter((t) => t.variant === "success").map((t) => /* @__PURE__ */ n("span", { children: t.message }, t.id)) }),
45
+ /* @__PURE__ */ n("span", { role: "alert", "aria-atomic": "false", children: a.filter((t) => t.variant === "error").map((t) => /* @__PURE__ */ n("span", { children: t.message }, t.id)) })
46
+ ] }),
47
+ T && /* @__PURE__ */ n(_, { toasts: h, duration: f, onDismiss: A })
48
+ ] });
49
+ };
50
+ export {
51
+ C as ToastProvider,
52
+ C as default
53
+ };
54
+ //# sourceMappingURL=ToastProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToastProvider.js","sources":["../../src/components/ToastProvider.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ToastHost from './ToastHost';\nimport { ToastContext } from './toastContext';\nimport {\n type QueuedToast,\n TOAST_ANNOUNCEMENT_LIFETIME_MS,\n TOAST_DEFAULT_DURATION_MS,\n TOAST_MAX_VISIBLE,\n type ToastOptions,\n} from './toastTypes';\n\n// Outside any shadow root, so Tailwind's sr-only is not available.\nconst VISUALLY_HIDDEN: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n padding: 0,\n border: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n};\n\nexport interface ToastProviderProps {\n children?: React.ReactNode;\n /** How long each toast stays, in ms. Defaults to 3000. */\n duration?: number;\n}\n\nconst ToastProvider: React.FC<ToastProviderProps> = ({\n children,\n duration = TOAST_DEFAULT_DURATION_MS,\n}) => {\n const [toasts, setToasts] = useState<QueuedToast[]>([]);\n const [announcements, setAnnouncements] = useState<(QueuedToast & { announcedAt: number })[]>(\n [],\n );\n const [hasShown, setHasShown] = useState(false);\n const nextId = useRef(0);\n\n const show = useCallback(({ message, variant = 'success' }: ToastOptions) => {\n nextId.current += 1;\n const toast: QueuedToast = { id: nextId.current, message, variant };\n setToasts((previous) => [...previous, toast].slice(-TOAST_MAX_VISIBLE));\n setAnnouncements((previous) => [...previous, { ...toast, announcedAt: Date.now() }]);\n setHasShown(true);\n }, []);\n\n const dismiss = useCallback((id: number) => {\n setToasts((previous) => previous.filter((toast) => toast.id !== id));\n }, []);\n\n useEffect(() => {\n const oldest = announcements[0];\n if (!oldest) {\n return;\n }\n const timeout = setTimeout(\n () =>\n setAnnouncements((previous) => previous.filter((entry) => entry.id !== oldest.id)),\n Math.max(0, oldest.announcedAt + TOAST_ANNOUNCEMENT_LIFETIME_MS - Date.now()),\n );\n return () => clearTimeout(timeout);\n }, [announcements]);\n\n const api = useMemo(() => ({ show }), [show]);\n\n return (\n <ToastContext.Provider value={api}>\n {children}\n {/* A region added with its text is not announced; status and alert default to atomic. */}\n <div style={VISUALLY_HIDDEN}>\n <span role=\"status\" aria-atomic=\"false\">\n {announcements\n .filter((entry) => entry.variant === 'success')\n .map((entry) => (\n <span key={entry.id}>{entry.message}</span>\n ))}\n </span>\n <span role=\"alert\" aria-atomic=\"false\">\n {announcements\n .filter((entry) => entry.variant === 'error')\n .map((entry) => (\n <span key={entry.id}>{entry.message}</span>\n ))}\n </span>\n </div>\n {hasShown && <ToastHost toasts={toasts} duration={duration} onDismiss={dismiss} />}\n </ToastContext.Provider>\n );\n};\n\nexport { ToastProvider };\nexport default ToastProvider;\n"],"names":["VISUALLY_HIDDEN","ToastProvider","children","duration","TOAST_DEFAULT_DURATION_MS","toasts","setToasts","useState","announcements","setAnnouncements","hasShown","setHasShown","nextId","useRef","show","useCallback","message","variant","toast","previous","dismiss","id","useEffect","oldest","timeout","entry","TOAST_ANNOUNCEMENT_LIFETIME_MS","api","useMemo","jsxs","ToastContext","jsx","ToastHost"],"mappings":";;;;;AAYA,MAAMA,IAAuC;AAAA,EACzC,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,MAAM;AAAA,EACN,UAAU;AAAA,EACV,YAAY;AAChB,GAQMC,IAA8C,CAAC;AAAA,EACjD,UAAAC;AAAA,EACA,UAAAC,IAAWC;AACf,MAAM;AACF,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAAwB,CAAA,CAAE,GAChD,CAACC,GAAeC,CAAgB,IAAIF;AAAA,IACtC,CAAA;AAAA,EAAC,GAEC,CAACG,GAAUC,CAAW,IAAIJ,EAAS,EAAK,GACxCK,IAASC,EAAO,CAAC,GAEjBC,IAAOC,EAAY,CAAC,EAAE,SAAAC,GAAS,SAAAC,IAAU,gBAA8B;AACzE,IAAAL,EAAO,WAAW;AAClB,UAAMM,IAAqB,EAAE,IAAIN,EAAO,SAAS,SAAAI,GAAS,SAAAC,EAAA;AAC1D,IAAAX,EAAU,CAACa,MAAa,CAAC,GAAGA,GAAUD,CAAK,EAAE,MAAM,EAAkB,CAAC,GACtET,EAAiB,CAACU,MAAa,CAAC,GAAGA,GAAU,EAAE,GAAGD,GAAO,aAAa,KAAK,IAAA,EAAI,CAAG,CAAC,GACnFP,EAAY,EAAI;AAAA,EACpB,GAAG,CAAA,CAAE,GAECS,IAAUL,EAAY,CAACM,MAAe;AACxC,IAAAf,EAAU,CAACa,MAAaA,EAAS,OAAO,CAACD,MAAUA,EAAM,OAAOG,CAAE,CAAC;AAAA,EACvE,GAAG,CAAA,CAAE;AAEL,EAAAC,EAAU,MAAM;AACZ,UAAMC,IAASf,EAAc,CAAC;AAC9B,QAAI,CAACe;AACD;AAEJ,UAAMC,IAAU;AAAA,MACZ,MACIf,EAAiB,CAACU,MAAaA,EAAS,OAAO,CAACM,MAAUA,EAAM,OAAOF,EAAO,EAAE,CAAC;AAAA,MACrF,KAAK,IAAI,GAAGA,EAAO,cAAcG,IAAiC,KAAK,KAAK;AAAA,IAAA;AAEhF,WAAO,MAAM,aAAaF,CAAO;AAAA,EACrC,GAAG,CAAChB,CAAa,CAAC;AAElB,QAAMmB,IAAMC,EAAQ,OAAO,EAAE,MAAAd,MAAS,CAACA,CAAI,CAAC;AAE5C,SACI,gBAAAe,EAACC,EAAa,UAAb,EAAsB,OAAOH,GACzB,UAAA;AAAA,IAAAzB;AAAA,IAED,gBAAA2B,EAAC,OAAA,EAAI,OAAO7B,GACR,UAAA;AAAA,MAAA,gBAAA+B,EAAC,QAAA,EAAK,MAAK,UAAS,eAAY,SAC3B,UAAAvB,EACI,OAAO,CAACiB,MAAUA,EAAM,YAAY,SAAS,EAC7C,IAAI,CAACA,MACF,gBAAAM,EAAC,QAAA,EAAqB,YAAM,QAAA,GAAjBN,EAAM,EAAmB,CACvC,EAAA,CACT;AAAA,MACA,gBAAAM,EAAC,QAAA,EAAK,MAAK,SAAQ,eAAY,SAC1B,UAAAvB,EACI,OAAO,CAACiB,MAAUA,EAAM,YAAY,OAAO,EAC3C,IAAI,CAACA,MACF,gBAAAM,EAAC,QAAA,EAAqB,YAAM,QAAA,GAAjBN,EAAM,EAAmB,CACvC,EAAA,CACT;AAAA,IAAA,GACJ;AAAA,IACCf,KAAY,gBAAAqB,EAACC,GAAA,EAAU,QAAA3B,GAAgB,UAAAF,GAAoB,WAAWiB,EAAA,CAAS;AAAA,EAAA,GACpF;AAER;"}
@@ -1,119 +1,123 @@
1
1
  import { useSyncExternalStore as b, useRef as f, useCallback as N, useEffect as E, useLayoutEffect as m } from "react";
2
- import { getDeepActiveElement as k, containsComposed as F } from "./activeElement.js";
3
- import { pushEscapeLayer as K } from "./escapeLayers.js";
4
- import { FOCUS_RING as W } from "./focusRing.js";
5
- import { nextLayerTicket as V, popupLayerHolding as Y } from "./overlayLayers.js";
6
- import { useOwnedByPopover as j } from "./popoverTree.js";
7
- import { OVERLAY_Z_BASE as R, ensureElevatedOverlayStyles as Z } from "./portalOverlay.js";
8
- import { lockBodyScroll as $ } from "./scrollLock.js";
9
- import { leaveTopLayer as U, raiseToTopLayer as q } from "./topLayer.js";
10
- const Ot = `flex shrink-0 cursor-pointer items-center justify-center rounded-md border-0 bg-transparent p-[4px] text-[var(--malachite-text-secondary)] hover:text-[var(--malachite-text-primary)] transition-colors ${W}`, J = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), summary, [tabindex]:not([tabindex="-1"])', Q = (t) => t.assignedSlot ?? t.parentElement ?? (t.parentNode instanceof ShadowRoot ? t.parentNode.host : null), X = (t) => Array.from(t.children).find((o) => o.tagName === "SUMMARY"), tt = () => {
11
- const t = /* @__PURE__ */ new Map(), o = (n) => {
12
- const e = t.get(n);
13
- if (e)
14
- return e;
15
- const { display: a, visibility: r, contentVisibility: s } = getComputedStyle(n), c = Q(n), d = c ? o(c) : null, h = c instanceof HTMLDetailsElement && !c.open && X(c) !== n, l = {
16
- hidden: n.hasAttribute("inert") || a === "none" || h || !!(d && (d.hidden || d.hidesContent)),
2
+ import { getDeepActiveElement as R, containsComposed as B } from "./activeElement.js";
3
+ import { pushEscapeLayer as V } from "./escapeLayers.js";
4
+ import { FOCUS_RING as Y } from "./focusRing.js";
5
+ import { nextLayerTicket as j, popupLayerHolding as Z } from "./overlayLayers.js";
6
+ import { useOwnedByPopover as $ } from "./popoverTree.js";
7
+ import { OVERLAY_Z_BASE as _, ensureElevatedOverlayStyles as q } from "./portalOverlay.js";
8
+ import { lockBodyScroll as J } from "./scrollLock.js";
9
+ import { leaveTopLayer as G, raiseToTopLayer as M } from "./topLayer.js";
10
+ const Tt = `flex shrink-0 cursor-pointer items-center justify-center rounded-md border-0 bg-transparent p-[4px] text-[var(--malachite-text-secondary)] hover:text-[var(--malachite-text-primary)] transition-colors ${Y}`, Q = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), summary, [tabindex]:not([tabindex="-1"])', X = (t) => t.assignedSlot ?? t.parentElement ?? (t.parentNode instanceof ShadowRoot ? t.parentNode.host : null), tt = (t) => Array.from(t.children).find((o) => o.tagName === "SUMMARY"), et = () => {
11
+ const t = /* @__PURE__ */ new Map(), o = (e) => {
12
+ const n = t.get(e);
13
+ if (n)
14
+ return n;
15
+ const { display: a, visibility: r, contentVisibility: s } = getComputedStyle(e), c = X(e), d = c ? o(c) : null, h = c instanceof HTMLDetailsElement && !c.open && tt(c) !== e, l = {
16
+ hidden: e.hasAttribute("inert") || a === "none" || h || !!(d && (d.hidden || d.hidesContent)),
17
17
  invisible: r === "hidden" || r === "collapse",
18
18
  hidesContent: s === "hidden"
19
19
  };
20
- return t.set(n, l), l;
20
+ return t.set(e, l), l;
21
21
  };
22
22
  return o;
23
23
  }, nt = (t, o) => {
24
24
  if (t.tabIndex < 0 || t.matches(":disabled"))
25
25
  return !1;
26
- const { hidden: n, invisible: e } = o(t);
27
- return !n && !e;
28
- }, _ = (t) => t instanceof HTMLInputElement && t.type === "radio" && t.name !== "", et = (t, o) => {
29
- if (!_(t))
26
+ const { hidden: e, invisible: n } = o(t);
27
+ return !e && !n;
28
+ }, v = (t) => t instanceof HTMLInputElement && t.type === "radio" && t.name !== "", ot = (t, o) => {
29
+ if (!v(t))
30
30
  return !1;
31
- const n = o.filter(
32
- (e) => _(e) && e.name === t.name && e.form === t.form
31
+ const e = o.filter(
32
+ (n) => v(n) && n.name === t.name && n.form === t.form
33
33
  );
34
- return (n.find((e) => e.checked) ?? n[0]) !== t;
35
- }, ot = (t, o) => t.map((n, e) => ({ element: n, index: e, tabIndex: o(n) })).sort((n, e) => n.tabIndex !== e.tabIndex ? n.tabIndex === 0 ? 1 : e.tabIndex === 0 ? -1 : n.tabIndex - e.tabIndex : n.index - e.index).map(({ element: n }) => n), x = (t) => t instanceof HTMLSlotElement && t.getRootNode() instanceof ShadowRoot, I = (t, o = []) => {
36
- for (const n of t)
37
- o.push(n), !n.shadowRoot && !x(n) && I(n.children, o);
34
+ return (e.find((n) => n.checked) ?? e[0]) !== t;
35
+ }, rt = (t, o) => t.map((e, n) => ({ element: e, index: n, tabIndex: o(e) })).sort((e, n) => e.tabIndex !== n.tabIndex ? e.tabIndex === 0 ? 1 : n.tabIndex === 0 ? -1 : e.tabIndex - n.tabIndex : e.index - n.index).map(({ element: e }) => e), x = (t) => t instanceof HTMLSlotElement && t.getRootNode() instanceof ShadowRoot, O = (t, o = []) => {
36
+ for (const e of t)
37
+ o.push(e), !e.shadowRoot && !x(e) && O(e.children, o);
38
38
  return o;
39
39
  }, L = (t, o) => {
40
- const n = t.filter(
41
- (r) => r instanceof HTMLElement && r.matches(J) && nt(r, o)
42
- ), e = new Set(
43
- n.filter((r) => !et(r, n))
40
+ const e = t.filter(
41
+ (r) => r instanceof HTMLElement && r.matches(Q) && nt(r, o)
42
+ ), n = new Set(
43
+ e.filter((r) => !ot(r, e))
44
44
  ), a = t.filter(
45
- (r) => e.has(r) || r.shadowRoot || x(r)
45
+ (r) => n.has(r) || r.shadowRoot || x(r)
46
46
  );
47
- return ot(
47
+ return rt(
48
48
  a,
49
- (r) => e.has(r) ? r.tabIndex : 0
49
+ (r) => n.has(r) ? r.tabIndex : 0
50
50
  ).flatMap((r) => {
51
51
  if (x(r))
52
- return L(I(r.assignedElements({ flatten: !0 })), o);
52
+ return L(O(r.assignedElements({ flatten: !0 })), o);
53
53
  const s = r.shadowRoot;
54
54
  if (s && Number.parseInt(r.getAttribute("tabindex") ?? "", 10) < 0)
55
55
  return [];
56
- const c = e.has(r) && !(s != null && s.delegatesFocus) ? [r] : [];
57
- return s ? [...c, ...L(I(s.children), o)] : c;
56
+ const c = n.has(r) && !(s != null && s.delegatesFocus) ? [r] : [];
57
+ return s ? [...c, ...L(O(s.children), o)] : c;
58
58
  });
59
- }, C = (t) => L(I(t.children), tt()), rt = (t, o) => {
60
- const n = (r) => {
59
+ }, C = (t) => L(O(t.children), et()), st = (t, o) => {
60
+ const e = (r) => {
61
61
  const s = [r];
62
62
  for (let c = r.getRootNode(); c instanceof ShadowRoot; c = c.host.getRootNode())
63
63
  s.push(c.host);
64
64
  return s;
65
- }, e = n(t), a = n(o);
66
- for (const r of e) {
65
+ }, n = e(t), a = e(o);
66
+ for (const r of n) {
67
67
  const s = a.find((c) => c.getRootNode() === r.getRootNode());
68
68
  if (s)
69
69
  return r !== s ? r.compareDocumentPosition(s) : r === t ? Node.DOCUMENT_POSITION_FOLLOWING : Node.DOCUMENT_POSITION_PRECEDING;
70
70
  }
71
71
  return Node.DOCUMENT_POSITION_DISCONNECTED;
72
- }, st = (t) => C(t)[0] ?? null, u = [], p = /* @__PURE__ */ new Set(), w = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Map(), D = /* @__PURE__ */ new Set(), ct = () => {
72
+ }, ct = (t) => C(t)[0] ?? null, u = [], p = /* @__PURE__ */ new Set(), k = /* @__PURE__ */ new Map(), w = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Set(), at = () => {
73
73
  };
74
74
  let y = [];
75
- const at = () => {
76
- const t = p.size ? u.map((n) => {
77
- var e;
78
- return (e = w.get(n)) == null ? void 0 : e();
79
- }).filter((n) => !!n) : [];
80
- if (t.length === y.length && t.every((n, e) => n === y[e]))
75
+ const D = /* @__PURE__ */ new Set(), it = () => {
76
+ const t = p.size ? u.map((e) => {
77
+ var n;
78
+ return (n = k.get(e)) == null ? void 0 : n();
79
+ }).filter((e) => !!e) : [];
80
+ if (t.length === y.length && t.every((e, n) => e === y[n]))
81
81
  return;
82
82
  const o = new Set(t);
83
- for (const n of y)
84
- o.has(n) || U(n);
85
- for (const n of t)
86
- q(n);
83
+ for (const e of y)
84
+ o.has(e) || G(e);
85
+ for (const e of t)
86
+ M(e);
87
87
  y = t;
88
- }, O = () => {
89
- for (const t of D)
90
- t();
91
- }, B = (t) => (D.add(t), () => {
88
+ for (const e of D)
89
+ M(e);
90
+ }, Nt = (t) => (D.add(t), () => {
92
91
  D.delete(t);
93
- }), M = (t, o, n, e) => {
94
- const a = e[0], r = e[e.length - 1], s = F(n, o);
95
- if (o && s && o !== n && !e.includes(o)) {
92
+ }), I = () => {
93
+ for (const t of g)
94
+ t();
95
+ }, P = (t) => (g.add(t), () => {
96
+ g.delete(t);
97
+ }), A = (t, o, e, n) => {
98
+ const a = n[0], r = n[n.length - 1], s = B(e, o);
99
+ if (o && s && o !== e && !n.includes(o)) {
96
100
  const c = t.shiftKey ? Node.DOCUMENT_POSITION_PRECEDING : Node.DOCUMENT_POSITION_FOLLOWING;
97
- e.some((d) => rt(o, d) & c) || (t.preventDefault(), (t.shiftKey ? r : a).focus());
101
+ n.some((d) => st(o, d) & c) || (t.preventDefault(), (t.shiftKey ? r : a).focus());
98
102
  return;
99
103
  }
100
- t.shiftKey ? (!s || o === a || o === n) && (t.preventDefault(), r.focus()) : (!s || o === r || o === n) && (t.preventDefault(), a.focus());
101
- }, v = (t) => {
104
+ t.shiftKey ? (!s || o === a || o === e) && (t.preventDefault(), r.focus()) : (!s || o === r || o === e) && (t.preventDefault(), a.focus());
105
+ }, F = (t) => {
102
106
  if (t.key !== "Tab" || t.defaultPrevented)
103
107
  return;
104
- let o = null, n = 0;
108
+ let o = null, e = 0;
105
109
  for (let s = u.length - 1; s >= 0 && !o; s -= 1)
106
- o = u[s](), o && (n = g.get(u[s]) ?? 0);
110
+ o = u[s](), o && (e = w.get(u[s]) ?? 0);
107
111
  if (!o)
108
112
  return;
109
- const e = k(), a = e ? Y(e) : null;
110
- if (e && a && a.ticket > n) {
113
+ const n = R(), a = n ? Z(n) : null;
114
+ if (n && a && a.ticket > e) {
111
115
  const s = a.popup.shadowRoot ?? a.popup, c = C(s);
112
116
  if (c.length === 0) {
113
117
  t.preventDefault();
114
118
  return;
115
119
  }
116
- M(t, e, s, c);
120
+ A(t, n, s, c);
117
121
  return;
118
122
  }
119
123
  const r = C(o);
@@ -121,35 +125,35 @@ const at = () => {
121
125
  t.preventDefault(), o.focus();
122
126
  return;
123
127
  }
124
- M(t, e, o, r);
125
- }, it = (t, o) => (u.length === 0 && document.addEventListener("keydown", v), u.push(t), w.set(t, o), g.set(t, V()), O(), () => {
126
- const n = u.lastIndexOf(t);
127
- n !== -1 && u.splice(n, 1), p.delete(t), w.delete(t), g.delete(t);
128
- const e = o();
129
- e && U(e), u.length === 0 && document.removeEventListener("keydown", v), O();
130
- }), Tt = () => b(
131
- B,
128
+ A(t, n, o, r);
129
+ }, ut = (t, o) => (u.length === 0 && document.addEventListener("keydown", F), u.push(t), k.set(t, o), w.set(t, j()), I(), () => {
130
+ const e = u.lastIndexOf(t);
131
+ e !== -1 && u.splice(e, 1), p.delete(t), k.delete(t), w.delete(t);
132
+ const n = o();
133
+ n && G(n), u.length === 0 && document.removeEventListener("keydown", F), I();
134
+ }), Et = () => b(
135
+ P,
132
136
  () => u.length > 0,
133
137
  () => !1
134
- ), A = (t, o) => {
138
+ ), U = (t, o) => {
135
139
  if (o === "content") {
136
- const n = k();
137
- if (F(t, n))
140
+ const e = R();
141
+ if (B(t, e))
138
142
  return;
139
- (st(t) ?? t).focus();
143
+ (ct(t) ?? t).focus();
140
144
  return;
141
145
  }
142
146
  t.focus();
143
- }, Nt = ({
147
+ }, mt = ({
144
148
  open: t,
145
149
  onClose: o,
146
- elevated: n = !1,
147
- hostRef: e,
150
+ elevated: e = !1,
151
+ hostRef: n,
148
152
  initialFocus: a = "panel"
149
153
  }) => {
150
154
  const r = f(null), s = f(() => r.current).current;
151
- j(
152
- N(() => (e == null ? void 0 : e.current) ?? r.current, [e]),
155
+ $(
156
+ N(() => (n == null ? void 0 : n.current) ?? r.current, [n]),
153
157
  t
154
158
  );
155
159
  const c = f(null), d = f(null), h = f(a), l = f(o);
@@ -157,7 +161,7 @@ const at = () => {
157
161
  l.current = o;
158
162
  }, [o]), E(() => {
159
163
  if (t)
160
- return c.current = k(), () => {
164
+ return c.current = R(), () => {
161
165
  const i = c.current;
162
166
  c.current = null, i != null && i.isConnected && i.focus();
163
167
  };
@@ -165,20 +169,20 @@ const at = () => {
165
169
  if (!t)
166
170
  return;
167
171
  d.current = s;
168
- const i = K(() => l.current()), H = $(), z = it(s, () => (e == null ? void 0 : e.current) ?? null);
169
- return r.current && A(r.current, h.current), () => {
170
- d.current = null, z(), i(), H();
172
+ const i = V(() => l.current()), K = J(), W = ut(s, () => (n == null ? void 0 : n.current) ?? null);
173
+ return r.current && U(r.current, h.current), () => {
174
+ d.current = null, W(), i(), K();
171
175
  };
172
- }, [t, e, s]), m(() => {
173
- if (!(!t || !n))
174
- return p.add(s), O(), () => {
175
- p.delete(s), O();
176
+ }, [t, n, s]), m(() => {
177
+ if (!(!t || !e))
178
+ return p.add(s), I(), () => {
179
+ p.delete(s), I();
176
180
  };
177
- }, [t, n, s]);
181
+ }, [t, e, s]);
178
182
  const T = N(
179
- (i) => t ? B(i) : ct,
183
+ (i) => t ? P(i) : at,
180
184
  [t]
181
- ), G = b(
185
+ ), H = b(
182
186
  T,
183
187
  // Gated on `open` so an overlay fading out stops claiming modal. Before it registers
184
188
  // it is the one about to go on top, or aria-modal would drop for a frame on open.
@@ -186,29 +190,30 @@ const at = () => {
186
190
  () => !0
187
191
  ), S = b(
188
192
  T,
189
- () => t && (n || p.size > 0),
193
+ () => t && (e || p.size > 0),
190
194
  () => !1
191
- ), P = b(
195
+ ), z = b(
192
196
  T,
193
197
  () => {
194
198
  const i = d.current;
195
- return R + (t && i ? Math.max(0, u.indexOf(i)) : 0);
199
+ return _ + (t && i ? Math.max(0, u.indexOf(i)) : 0);
196
200
  },
197
- () => R
201
+ () => _
198
202
  );
199
203
  return m(() => {
200
- S && Z();
204
+ S && q();
201
205
  }, [S]), m(() => {
202
- at();
206
+ it();
203
207
  }), { ref: N((i) => {
204
- r.current = i, i && A(i, h.current);
205
- }, []), isTopmost: G, zIndex: S ? void 0 : P, elevated: S };
208
+ r.current = i, i && U(i, h.current);
209
+ }, []), isTopmost: H, zIndex: S ? void 0 : z, elevated: S };
206
210
  };
207
211
  export {
208
- J as FOCUSABLE_SELECTOR,
209
- Ot as OVERLAY_ICON_BUTTON_CLASSES,
210
- st as firstTabStopIn,
211
- Tt as useHasOpenOverlay,
212
- Nt as useOverlayBehaviour
212
+ Q as FOCUSABLE_SELECTOR,
213
+ Tt as OVERLAY_ICON_BUTTON_CLASSES,
214
+ ct as firstTabStopIn,
215
+ Nt as keepAboveOverlayStack,
216
+ Et as useHasOpenOverlay,
217
+ mt as useOverlayBehaviour
213
218
  };
214
219
  //# sourceMappingURL=overlayBehaviour.js.map