premium-ds 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-NKGMQL6I.js → chunk-NIZLUYLW.js} +53 -26
- package/dist/chunk-NIZLUYLW.js.map +1 -0
- package/dist/{chunk-PUPZ4HME.js → chunk-YTMZEJ7M.js} +36 -7
- package/dist/chunk-YTMZEJ7M.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/toast-store.d.ts +13 -2
- package/dist/toast-store.js +1 -1
- package/dist/toast.d.ts +7 -2
- package/dist/toast.js +2 -2
- package/llms.txt +4 -2
- package/package.json +1 -1
- package/src/components/button/button.css +1 -1
- package/src/components/toast/Toast.tsx +71 -27
- package/src/components/toast/toast-store.ts +55 -5
- package/src/components/toast/toast.css +30 -6
- package/src/tokens/elevation.css +5 -2
- package/src/tokens/semantic.css +1 -15
- package/dist/chunk-NKGMQL6I.js.map +0 -1
- package/dist/chunk-PUPZ4HME.js.map +0 -1
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
'use client';import { UIToast } from './chunk-
|
|
1
|
+
'use client';import { DEFAULT_TOASTER_CONFIG, UIToast } from './chunk-YTMZEJ7M.js';
|
|
2
2
|
import { Icon } from './chunk-KBWNUUWM.js';
|
|
3
3
|
import { UIMotion } from './chunk-37O2ZXD6.js';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
|
-
import { createRoot } from 'react-dom/client';
|
|
7
6
|
import { AnimatePresence, useMotionValue, motion, animate } from 'motion/react';
|
|
8
7
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
8
|
|
|
10
9
|
var SM = UIMotion;
|
|
11
10
|
var store = UIToast;
|
|
12
11
|
var { useRef, useEffect, useLayoutEffect, useState, useSyncExternalStore } = React;
|
|
13
|
-
var VISIBLE = 3;
|
|
14
12
|
var COLLAPSE_GRACE = 140;
|
|
15
13
|
var SWIPE_X = 64;
|
|
16
14
|
var SWIPE_V = 480;
|
|
@@ -60,6 +58,7 @@ function ToastItem({
|
|
|
60
58
|
hidden,
|
|
61
59
|
behind,
|
|
62
60
|
frameHeight,
|
|
61
|
+
isTop,
|
|
63
62
|
onHeight
|
|
64
63
|
}) {
|
|
65
64
|
const ref = useRef(null);
|
|
@@ -86,10 +85,10 @@ function ToastItem({
|
|
|
86
85
|
role: t.tone === "error" ? "alert" : "status",
|
|
87
86
|
"aria-atomic": "true",
|
|
88
87
|
style: { x },
|
|
89
|
-
initial: { opacity: 0, y: 24, scale: 0.97 },
|
|
88
|
+
initial: { opacity: 0, y: isTop ? -24 : 24, scale: 0.97 },
|
|
90
89
|
animate: {
|
|
91
90
|
opacity: hidden ? 0 : 1,
|
|
92
|
-
y: -offset,
|
|
91
|
+
y: isTop ? offset : -offset,
|
|
93
92
|
scale: 1 - depth * 0.05,
|
|
94
93
|
/* behind-cards adopt the front card's frame height (content faded) so a short card never drowns behind a tall one */
|
|
95
94
|
height: frameHeight || "auto",
|
|
@@ -201,11 +200,22 @@ function ToastBody({ t }) {
|
|
|
201
200
|
)
|
|
202
201
|
] });
|
|
203
202
|
}
|
|
204
|
-
function ToastHost() {
|
|
205
|
-
const {
|
|
203
|
+
function ToastHost({ config }) {
|
|
204
|
+
const {
|
|
205
|
+
toasts,
|
|
206
|
+
paused,
|
|
207
|
+
expanded: hoverExpanded
|
|
208
|
+
} = useSyncExternalStore(
|
|
209
|
+
store.subscribe,
|
|
210
|
+
store.get,
|
|
211
|
+
store.get
|
|
212
|
+
// server snapshot - the host renders nothing until mounted anyway
|
|
213
|
+
);
|
|
206
214
|
const [heights, setHeights] = useState({});
|
|
215
|
+
const [ready, setReady] = useState(false);
|
|
207
216
|
const collapseTimer = useRef(0);
|
|
208
217
|
const hovering = useRef(false);
|
|
218
|
+
useEffect(() => setReady(true), []);
|
|
209
219
|
const onHeight = (id, h) => setHeights((prev) => prev[id] === h ? prev : { ...prev, [id]: h });
|
|
210
220
|
const onHold = () => {
|
|
211
221
|
hovering.current = true;
|
|
@@ -240,15 +250,22 @@ function ToastHost() {
|
|
|
240
250
|
store.resume();
|
|
241
251
|
}
|
|
242
252
|
}, [toasts.length]);
|
|
243
|
-
|
|
253
|
+
if (!ready) return null;
|
|
254
|
+
const isTop = config.position.startsWith("top");
|
|
255
|
+
const visible = config.visibleToasts;
|
|
256
|
+
const rendered = visible * 2;
|
|
257
|
+
const gap = config.gap || stackGap();
|
|
258
|
+
const expanded = config.expand || hoverExpanded;
|
|
259
|
+
const slice = toasts.slice(-rendered);
|
|
244
260
|
const n = slice.length;
|
|
245
261
|
const frontH = n ? heights[slice[n - 1].id] || 0 : 0;
|
|
246
|
-
const gap = stackGap();
|
|
247
262
|
return createPortal(
|
|
248
263
|
/* @__PURE__ */ jsx(
|
|
249
264
|
"ol",
|
|
250
265
|
{
|
|
251
266
|
className: "toast-viewport" + (paused ? " is-paused" : ""),
|
|
267
|
+
"data-position": config.position,
|
|
268
|
+
style: config.offset ? { "--toast-offset": `${config.offset}px` } : void 0,
|
|
252
269
|
"aria-label": "Notifications",
|
|
253
270
|
onPointerOver: (e) => {
|
|
254
271
|
if (e.pointerType !== "touch") onHold();
|
|
@@ -274,9 +291,10 @@ function ToastHost() {
|
|
|
274
291
|
t,
|
|
275
292
|
depth: expanded ? 0 : depth,
|
|
276
293
|
offset,
|
|
277
|
-
hidden: !expanded && depth >=
|
|
294
|
+
hidden: !expanded && depth >= visible,
|
|
278
295
|
behind: !expanded && depth > 0,
|
|
279
296
|
frameHeight: !expanded && depth > 0 && frontH ? frontH : null,
|
|
297
|
+
isTop,
|
|
280
298
|
onHeight
|
|
281
299
|
},
|
|
282
300
|
t.id
|
|
@@ -287,24 +305,33 @@ function ToastHost() {
|
|
|
287
305
|
document.body
|
|
288
306
|
);
|
|
289
307
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
document.body.appendChild(el);
|
|
297
|
-
createRoot(el).render(/* @__PURE__ */ jsx(ToastHost, {}));
|
|
308
|
+
function stripUndefined(o) {
|
|
309
|
+
const out = {};
|
|
310
|
+
Object.keys(o).forEach((k) => {
|
|
311
|
+
if (o[k] !== void 0) out[k] = o[k];
|
|
312
|
+
});
|
|
313
|
+
return out;
|
|
298
314
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
function Toaster() {
|
|
315
|
+
function Toaster(props) {
|
|
316
|
+
const config = { ...DEFAULT_TOASTER_CONFIG, ...stripUndefined(props) };
|
|
302
317
|
useEffect(() => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
318
|
+
store.config = config;
|
|
319
|
+
store.mounted = true;
|
|
320
|
+
if (config.expand) store.setExpanded(true);
|
|
321
|
+
return () => {
|
|
322
|
+
store.mounted = false;
|
|
323
|
+
};
|
|
324
|
+
}, [
|
|
325
|
+
config.position,
|
|
326
|
+
config.duration,
|
|
327
|
+
config.visibleToasts,
|
|
328
|
+
config.gap,
|
|
329
|
+
config.offset,
|
|
330
|
+
config.expand
|
|
331
|
+
]);
|
|
332
|
+
return /* @__PURE__ */ jsx(ToastHost, { config });
|
|
306
333
|
}
|
|
307
334
|
|
|
308
335
|
export { Toaster };
|
|
309
|
-
//# sourceMappingURL=chunk-
|
|
310
|
-
//# sourceMappingURL=chunk-
|
|
336
|
+
//# sourceMappingURL=chunk-NIZLUYLW.js.map
|
|
337
|
+
//# sourceMappingURL=chunk-NIZLUYLW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/toast/Toast.tsx"],"names":[],"mappings":";;;;;;;;AAgBA,IAAM,EAAA,GAAK,QAAA;AACX,IAAM,KAAA,GAAQ,OAAA;AACd,IAAM,EAAE,MAAA,EAAQ,SAAA,EAAW,eAAA,EAAiB,QAAA,EAAU,sBAAqB,GAAI,KAAA;AAE/E,IAAM,cAAA,GAAiB,GAAA;AACvB,IAAM,OAAA,GAAU,EAAA;AAChB,IAAM,OAAA,GAAU,GAAA;AAGhB,IAAI,GAAA,GAAM,CAAA;AACV,SAAS,QAAA,GAAW;AAClB,EAAA,IAAI,KAAK,OAAO,GAAA;AAChB,EAAA,MAAM,EAAA,GAAK,gBAAA,CAAiB,QAAA,CAAS,eAAe,CAAA;AACpD,EAAA,MAAM,GAAA,GAAM,EAAA,CAAG,gBAAA,CAAiB,WAAW,EAAE,IAAA,EAAK;AAClD,EAAA,MAAM,CAAA,GAAI,UAAA,CAAW,GAAG,CAAA,IAAK,CAAA;AAC7B,EAAA,GAAA,GAAA,CAAO,GAAA,CAAI,QAAA,CAAS,KAAK,CAAA,GAAI,CAAA,IAAK,WAAW,EAAA,CAAG,QAAQ,CAAA,IAAK,EAAA,CAAA,GAAM,CAAA,KAAM,EAAA;AACzE,EAAA,OAAO,GAAA;AACT;AAEA,IAAM,SAAA,GAAsC;AAAA,EAC1C,OAAA,EAAS,cAAA;AAAA,EACT,KAAA,EAAO,gBAAA;AAAA,EACP,OAAA,EAAS,SAAA;AAAA,EACT,IAAA,EAAM;AACR,CAAA;AAGA,SAAS,cAAA,CACP,IAAA,EACA,GAAA,EACA,CAAA,EACA;AACA,EAAA,MAAM,QAAA,GAAW,OAAyB,IAAI,CAAA;AAC9C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,OAAO,QAAA,CAAS,OAAA;AACtB,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,IAAA,IAAI,SAAS,IAAA,EAAM;AACnB,IAAA,IAAI,SAAS,SAAA,EAAW;AACtB,MAAA,MAAM,KAAK,GAAA,CAAI,OAAA;AACf,MAAA,EAAA,CAAG,SAAA,CAAU,OAAO,aAAa,CAAA;AACjC,MAAA,KAAK,EAAA,CAAG,WAAA;AACR,MAAA,EAAA,CAAG,SAAA,CAAU,IAAI,aAAa,CAAA;AAC9B,MAAA,MAAM,EAAA,GAAK,UAAA,CAAW,MAAM,EAAA,CAAG,SAAA,CAAU,MAAA,CAAO,aAAa,CAAA,EAAG,EAAA,CAAG,GAAA,CAAI,IAAA,GAAO,GAAA,GAAO,EAAE,CAAA;AACvF,MAAA,OAAO,MAAM,aAAa,EAAE,CAAA;AAAA,IAC9B;AACA,IAAA,IAAI,SAAS,OAAA,EAAS;AACpB,MAAA,MAAM,IAAA,GAAO,QAAQ,CAAA,EAAG,CAAC,GAAG,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,CAAC,CAAA,EAAG;AAAA,QACzC,QAAA,EAAU,GAAG,GAAA,CAAI,IAAA;AAAA,QACjB,IAAA,EAAM,GAAG,IAAA,CAAK,QAAA;AAAA,QACd,KAAA,EAAO,GAAG,GAAA,CAAI;AAAA,OACf,CAAA;AACD,MAAA,OAAO,MAAM,KAAK,IAAA,EAAK;AAAA,IACzB;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AACX;AAEA,SAAS,SAAA,CAAU;AAAA,EACjB,CAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EASG;AACD,EAAA,MAAM,GAAA,GAAM,OAAsB,IAAI,CAAA;AACtC,EAAA,MAAM,CAAA,GAAI,eAAe,CAAC,CAAA;AAC1B,EAAA,cAAA,CAAe,CAAA,CAAE,IAAA,EAAM,GAAA,EAAK,CAAC,CAAA;AAG7B,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,IAAI,GAAA,CAAI,OAAA,IAAW,GAAA,CAAI,OAAA,CAAQ,iBAAA;AAC7B,MAAA,QAAA,CAAS,CAAA,CAAE,EAAA,EAAK,GAAA,CAAI,OAAA,CAAQ,kBAAkC,YAAY,CAAA;AAAA,EAC9E,CAAC,CAAA;AAED,EAAA,MAAM,KAAA,GAAQ,CAAC,EAAA,EAA4C,IAAA,KAAkB;AAC3E,IAAA,IAAI,KAAK,MAAA,CAAO,CAAA,GAAI,WAAW,IAAA,CAAK,QAAA,CAAS,IAAI,OAAA,EAAS;AAExD,MAAA,OAAA,CAAQ,CAAA,EAAG,GAAA,EAAK,EAAE,QAAA,EAAU,EAAA,CAAG,GAAA,CAAI,IAAA,EAAM,IAAA,EAAM,EAAA,CAAG,IAAA,CAAK,IAAA,EAAM,CAAA,CAAE,IAAA;AAAA,QAAK,MAClE,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,EAAE;AAAA,OACpB;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,MAAA,CAAO,EAAA;AAAA,IAAP;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAU,aAAA;AAAA,MACV,aAAW,CAAA,CAAE,IAAA;AAAA,MACb,aAAA,EAAa,SAAS,EAAA,GAAK,MAAA;AAAA,MAC3B,IAAA,EAAM,CAAA,CAAE,IAAA,KAAS,OAAA,GAAU,OAAA,GAAU,QAAA;AAAA,MACrC,aAAA,EAAY,MAAA;AAAA,MACZ,KAAA,EAAO,EAAE,CAAA,EAAE;AAAA,MACX,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAG,GAAG,KAAA,GAAQ,GAAA,GAAM,EAAA,EAAI,KAAA,EAAO,IAAA,EAAK;AAAA,MACxD,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,SAAS,CAAA,GAAI,CAAA;AAAA,QACtB,CAAA,EAAG,KAAA,GAAQ,MAAA,GAAS,CAAC,MAAA;AAAA,QACrB,KAAA,EAAO,IAAI,KAAA,GAAQ,IAAA;AAAA;AAAA,QAEnB,QAAQ,WAAA,IAAe,MAAA;AAAA,QACvB,aAAA,EAAe,SAAS,MAAA,GAAS;AAAA,OACnC;AAAA,MACA,MAAM,EAAE,OAAA,EAAS,CAAA,EAAG,KAAA,EAAO,MAAM,UAAA,EAAY,EAAE,QAAA,EAAU,EAAA,CAAG,IAAI,IAAA,EAAM,IAAA,EAAM,EAAA,CAAG,IAAA,CAAK,MAAK,EAAE;AAAA,MAC3F,YAAY,EAAE,CAAA,EAAG,EAAA,CAAG,CAAA,CAAE,QAAQ,KAAA,EAAO,EAAA,CAAG,CAAA,CAAE,MAAA,EAAQ,QAAQ,EAAA,CAAG,CAAA,CAAE,QAAQ,OAAA,EAAS,EAAA,CAAG,EAAE,KAAA,EAAM;AAAA,MAC3F,IAAA,EAAM,CAAA,CAAE,WAAA,GAAc,GAAA,GAAM,KAAA;AAAA,MAC5B,eAAA,EAAiB,EAAE,IAAA,EAAM,CAAA,EAAG,OAAO,CAAA,EAAE;AAAA,MACrC,WAAA,EAAa,EAAE,IAAA,EAAM,IAAA,EAAM,OAAO,GAAA,EAAI;AAAA,MACtC,YAAA,EAAc,KAAA;AAAA,MACd,SAAA,EAAW,KAAA;AAAA,MACX,SAAA,EAAW,CAAC,CAAA,KAAM;AAChB,QAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,IAAY,CAAA,CAAE,aAAa,KAAA,CAAM,OAAA,CAAQ,EAAE,EAAE,CAAA;AAAA,MAC7D,CAAA;AAAA,MAEC,QAAA,EAAA,CAAA,CAAE,IAAA,mBACD,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eAAA,EAAiB,QAAA,EAAA,CAAA,CAAE,IAAA,EAAwB,CAAA,mBAE1D,GAAA,CAAC,SAAA,EAAA,EAAU,CAAA,EAAM;AAAA;AAAA,GAErB;AAEJ;AAEA,SAAS,SAAA,CAAU,EAAE,CAAA,EAAE,EAAuB;AAC5C,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,cAAA,EACX,QAAA,EAAA;AAAA,IAAA,CAAA,CAAA,CAAE,IAAA,KAAS,aAAa,QAAA,CAAS,CAAA,CAAE,QAAQ,CAAA,qBAC3C,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,aAAA,EACb,QAAA,EAAA;AAAA,MAAA,CAAA,CAAE,IAAA,KAAS,SAAA;AAAA,sBAEV,GAAA;AAAA,QAAC,MAAA,CAAO,IAAA;AAAA,QAAP;AAAA,UAEC,SAAA,EAAU,mBAAA;AAAA,UACV,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAK,SAAS,CAAA,EAAE;AAAA,UAClC,OAAA,EAAS,EAAE,KAAA,EAAO,CAAA,EAAG,SAAS,CAAA,EAAE;AAAA,UAChC,UAAA,EAAY,EAAE,KAAA,EAAO,EAAA,CAAG,EAAE,MAAA,EAAQ,OAAA,EAAS,EAAA,CAAG,CAAA,CAAE,KAAA,EAAM;AAAA,UAErD,YAAE,IAAA,KAAS,SAAA,uBACT,MAAA,EAAA,EAAK,SAAA,EAAU,kBAAiB,aAAA,EAAY,MAAA,EAAO,CAAA,mBAEpD,GAAA,CAAC,QAAK,IAAA,EAAM,SAAA,CAAU,EAAE,IAAI,CAAA,EAAG,QAAO,MAAA,EAAO;AAAA,SAAA;AAAA,QAT1C,CAAA,CAAE;AAAA,OAWT;AAAA,MAED,QAAA,CAAS,EAAE,QAAQ,CAAA;AAAA,sBAElB,IAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EAAU,aAAA;AAAA,UACV,OAAA,EAAQ,WAAA;AAAA,UACR,aAAA,EAAY,MAAA;AAAA,UAEZ,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,QAAA,EAAA,EAAO,WAAU,mBAAA,EAAoB,EAAA,EAAG,MAAK,EAAA,EAAG,IAAA,EAAK,GAAE,MAAA,EAAO,CAAA;AAAA,4BAC/D,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAU,iBAAA;AAAA,gBACV,EAAA,EAAG,IAAA;AAAA,gBACH,EAAA,EAAG,IAAA;AAAA,gBACH,CAAA,EAAE,MAAA;AAAA,gBACF,UAAA,EAAY,CAAA;AAAA,gBACZ,KAAA,EAAO,EAAE,iBAAA,EAAmB,CAAA,CAAE,WAAW,IAAA;AAAK;AAAA;AAC/C;AAAA,SAAA;AAAA,QAbI,UAAU,CAAA,CAAE;AAAA;AAcnB,KAAA,EAEJ,CAAA;AAAA,oBAEF,IAAA;AAAA,MAAC,MAAA,CAAO,GAAA;AAAA,MAAP;AAAA,QAEC,SAAA,EAAU,aAAA;AAAA,QACV,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAE;AAAA,QACtB,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAE;AAAA,QACtB,UAAA,EAAY,GAAG,CAAA,CAAE,KAAA;AAAA,QAEjB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gBAAA,EAAkB,QAAA,EAAA,CAAA,CAAE,OAAA,EAAQ,CAAA;AAAA,UACxC,CAAA,CAAE,eAAe,IAAA,oBAAQ,GAAA,CAAC,OAAE,SAAA,EAAU,aAAA,EAAe,YAAE,WAAA,EAAY;AAAA;AAAA,OAAA;AAAA,MAP/D,OAAO,CAAA,CAAE,OAAO,IAAI,GAAA,GAAM,MAAA,CAAO,EAAE,WAAW;AAAA,KAQrD;AAAA,IACC,CAAA,CAAE,QAAQ,CAAA,oBACT,IAAA;AAAA,MAAC,MAAA,CAAO,IAAA;AAAA,MAAP;AAAA,QAEC,SAAA,EAAU,cAAA;AAAA,QACV,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAI;AAAA,QACtB,OAAA,EAAS,EAAE,KAAA,EAAO,CAAA,EAAE;AAAA,QACpB,UAAA,EAAY,GAAG,CAAA,CAAE,MAAA;AAAA,QAClB,QAAA,EAAA;AAAA,UAAA,MAAA;AAAA,UACG,CAAA,CAAE;AAAA;AAAA,OAAA;AAAA,MANC,CAAA,CAAE;AAAA,KAOT;AAAA,IAED,EAAE,MAAA,oBACD,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,SAAA,EAAU,0CAAA;AAAA,QACV,SAAS,MAAM;AACb,UAAA,IAAI,CAAA,CAAE,MAAA,CAAO,OAAA,EAAS,CAAA,CAAE,OAAO,OAAA,EAAQ;AACvC,UAAA,KAAA,CAAM,OAAA,CAAQ,EAAE,EAAE,CAAA;AAAA,QACpB,CAAA;AAAA,QAEC,YAAE,MAAA,CAAO;AAAA;AAAA,KACZ;AAAA,IAED,EAAE,WAAA,oBACD,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,SAAA,EAAU,cAAA;AAAA,QACV,YAAA,EAAW,SAAA;AAAA,QACX,OAAA,EAAS,MAAM,KAAA,CAAM,OAAA,CAAQ,EAAE,EAAE,CAAA;AAAA,QAEjC,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,MAAK,IAAA,EAAK;AAAA;AAAA;AAC/B,GAAA,EAEJ,CAAA;AAEJ;AAEA,SAAS,SAAA,CAAU,EAAE,MAAA,EAAO,EAA8B;AACxD,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA,EAAU;AAAA,GACZ,GAAI,oBAAA;AAAA,IACF,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,GAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AACA,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA,CAAiC,EAAE,CAAA;AACjE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,KAAK,CAAA;AACxC,EAAA,MAAM,aAAA,GAAgB,OAA0C,CAAC,CAAA;AACjE,EAAA,MAAM,QAAA,GAAW,OAAO,KAAK,CAAA;AAG7B,EAAA,SAAA,CAAU,MAAM,QAAA,CAAS,IAAI,CAAA,EAAG,EAAE,CAAA;AAElC,EAAA,MAAM,WAAW,CAAC,EAAA,EAAY,MAC5B,UAAA,CAAW,CAAC,SAAU,IAAA,CAAK,EAAE,MAAM,CAAA,GAAI,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,CAAC,EAAE,GAAG,GAAI,CAAA;AAGrE,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,IAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,IAAA,KAAA,CAAM,YAAY,IAAI,CAAA;AACtB,IAAA,KAAA,CAAM,KAAA,EAAM;AAAA,EACd,CAAA;AACA,EAAA,MAAM,SAAA,GAAY,CAAC,MAAA,KAAoB;AACrC,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,IAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,IAAA,aAAA,CAAc,OAAA,GAAU,UAAA;AAAA,MACtB,MAAM;AACJ,QAAA,KAAA,CAAM,YAAY,KAAK,CAAA;AACvB,QAAA,KAAA,CAAM,MAAA,EAAO;AAAA,MACf,CAAA;AAAA,MACA,SAAS,cAAA,GAAiB;AAAA,KAC5B;AAAA,EACF,CAAA;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,IAAI,QAAA,CAAS,MAAA,EAAQ,KAAA,CAAM,KAAA,EAAM;AAAA,WAAA,IACxB,CAAC,QAAA,CAAS,OAAA,EAAS,KAAA,CAAM,MAAA,EAAO;AAAA,IAC3C,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,oBAAoB,KAAK,CAAA;AACnD,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,kBAAA,EAAoB,KAAK,CAAA;AAAA,EACrE,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,MAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,MAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,MAAA,KAAA,CAAM,YAAY,KAAK,CAAA;AACvB,MAAA,KAAA,CAAM,MAAA,EAAO;AAAA,IACf;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,CAAO,MAAM,CAAC,CAAA;AAElB,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AAEnB,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,QAAA,CAAS,UAAA,CAAW,KAAK,CAAA;AAC9C,EAAA,MAAM,UAAU,MAAA,CAAO,aAAA;AACvB,EAAA,MAAM,WAAW,OAAA,GAAU,CAAA;AAC3B,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,IAAO,QAAA,EAAS;AACnC,EAAA,MAAM,QAAA,GAAW,OAAO,MAAA,IAAU,aAAA;AAElC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,CAAC,QAAQ,CAAA;AACpC,EAAA,MAAM,IAAI,KAAA,CAAM,MAAA;AAChB,EAAA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAC,CAAA,CAAE,EAAE,CAAA,IAAK,CAAA,GAAI,CAAA;AAEnD,EAAA,OAAO,YAAA;AAAA,oBACL,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,gBAAA,IAAoB,MAAA,GAAS,YAAA,GAAe,EAAA,CAAA;AAAA,QACvD,iBAAe,MAAA,CAAO,QAAA;AAAA,QACtB,KAAA,EACE,OAAO,MAAA,GACF,EAAE,kBAAkB,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,EAAA,CAAA,EAAK,GAC1C,MAAA;AAAA,QAEN,YAAA,EAAW,eAAA;AAAA,QACX,aAAA,EAAe,CAAC,CAAA,KAAM;AACpB,UAAA,IAAI,CAAA,CAAE,WAAA,KAAgB,OAAA,EAAS,MAAA,EAAO;AAAA,QACxC,CAAA;AAAA,QACA,YAAA,EAAc,CAAC,CAAA,KAAM;AACnB,UAAA,IAAI,CAAC,CAAA,CAAE,aAAA,IAAiB,CAAC,CAAA,CAAE,aAAA,CAAc,QAAA,CAAS,CAAA,CAAE,aAAqB,CAAA,EAAG,SAAA,CAAU,IAAI,CAAA;AAAA,QAC5F,CAAA;AAAA,QACA,OAAA,EAAS,MAAA;AAAA,QACT,MAAA,EAAQ,CAAC,CAAA,KAAM;AACb,UAAA,IAAI,CAAC,EAAE,aAAA,IAAiB,CAAC,EAAE,aAAA,CAAc,QAAA,CAAS,EAAE,aAAqB,CAAA;AACvE,YAAA,SAAA,CAAU,KAAK,CAAA;AAAA,QACnB,CAAA;AAAA,QAEA,8BAAC,eAAA,EAAA,EACE,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AACnB,UAAA,MAAM,KAAA,GAAQ,IAAI,CAAA,GAAI,CAAA;AACtB,UAAA,IAAI,SAAS,KAAA,GAAQ,GAAA;AACrB,UAAA,IAAI,QAAA,EAAU;AAEZ,YAAA,MAAA,GAAS,CAAA;AACT,YAAA,KAAA,IAAS,CAAA,GAAI,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK,MAAA,IAAA,CAAW,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,CAAE,EAAE,KAAK,CAAA,IAAK,GAAA;AAAA,UAC1E;AACA,UAAA,uBACE,GAAA;AAAA,YAAC,SAAA;AAAA,YAAA;AAAA,cAEC,CAAA;AAAA,cACA,KAAA,EAAO,WAAW,CAAA,GAAI,KAAA;AAAA,cACtB,MAAA;AAAA,cACA,MAAA,EAAQ,CAAC,QAAA,IAAY,KAAA,IAAS,OAAA;AAAA,cAC9B,MAAA,EAAQ,CAAC,QAAA,IAAY,KAAA,GAAQ,CAAA;AAAA,cAC7B,aAAa,CAAC,QAAA,IAAY,KAAA,GAAQ,CAAA,IAAK,SAAS,MAAA,GAAS,IAAA;AAAA,cACzD,KAAA;AAAA,cACA;AAAA,aAAA;AAAA,YARK,CAAA,CAAE;AAAA,WAST;AAAA,QAEJ,CAAC,CAAA,EACH;AAAA;AAAA,KACF;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AACF;AAEA,SAAS,eAAiC,CAAA,EAAkB;AAC1D,EAAA,MAAM,MAAkB,EAAC;AACzB,EAAC,OAAO,IAAA,CAAK,CAAC,CAAA,CAAkB,OAAA,CAAQ,CAAC,CAAA,KAAM;AAC7C,IAAA,IAAI,CAAA,CAAE,CAAC,CAAA,KAAM,MAAA,MAAe,CAAC,CAAA,GAAI,EAAE,CAAC,CAAA;AAAA,EACtC,CAAC,CAAA;AACD,EAAA,OAAO,GAAA;AACT;AAMO,SAAS,QAAQ,KAAA,EAAyC;AAC/D,EAAA,MAAM,SAAwB,EAAE,GAAG,wBAAwB,GAAG,cAAA,CAAe,KAAK,CAAA,EAAE;AAEpF,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,KAAA,CAAM,MAAA,GAAS,MAAA;AACf,IAAA,KAAA,CAAM,OAAA,GAAU,IAAA;AAChB,IAAA,IAAI,MAAA,CAAO,MAAA,EAAQ,KAAA,CAAM,WAAA,CAAY,IAAI,CAAA;AACzC,IAAA,OAAO,MAAM;AACX,MAAA,KAAA,CAAM,OAAA,GAAU,KAAA;AAAA,IAClB,CAAA;AAAA,EACF,CAAA,EAAG;AAAA,IACD,MAAA,CAAO,QAAA;AAAA,IACP,MAAA,CAAO,QAAA;AAAA,IACP,MAAA,CAAO,aAAA;AAAA,IACP,MAAA,CAAO,GAAA;AAAA,IACP,MAAA,CAAO,MAAA;AAAA,IACP,MAAA,CAAO;AAAA,GACR,CAAA;AAED,EAAA,uBAAO,GAAA,CAAC,aAAU,MAAA,EAAgB,CAAA;AACpC","file":"chunk-NIZLUYLW.js","sourcesContent":["'use client';\n\n/* Toast - the React render layer (queue + clocks live in toast-store.ts). */\nimport * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { motion, AnimatePresence, animate, useMotionValue, type PanInfo } from 'motion/react';\nimport { UIMotion } from '../../tokens/motion-tokens';\nimport { Icon, type IconName } from '../icon/Icon';\nimport {\n UIToast,\n DEFAULT_TOASTER_CONFIG,\n type ToastRecord,\n type ToastTone,\n type ToasterConfig,\n} from './toast-store';\n\nconst SM = UIMotion;\nconst store = UIToast;\nconst { useRef, useEffect, useLayoutEffect, useState, useSyncExternalStore } = React;\n\nconst COLLAPSE_GRACE = 140;\nconst SWIPE_X = 64;\nconst SWIPE_V = 480;\n\n// expanded gap AND collapsed peek - read lazily (post-stylesheet), once\nlet GAP = 0;\nfunction stackGap() {\n if (GAP) return GAP;\n const cs = getComputedStyle(document.documentElement);\n const raw = cs.getPropertyValue('--space-3').trim();\n const n = parseFloat(raw) || 0;\n GAP = (raw.endsWith('rem') ? n * (parseFloat(cs.fontSize) || 16) : n) || 12;\n return GAP;\n}\n\nconst TONE_ICON: Record<string, IconName> = {\n success: 'check-circle',\n error: 'warning-circle',\n warning: 'warning',\n info: 'info',\n};\n\n/* useToneGesture - success glint, error headshake; the glint class is toggled with a reflow (remove - offsetWidth - add) to restart the one-shot. */\nfunction useToneGesture(\n tone: ToastTone,\n ref: React.RefObject<HTMLElement>,\n x: ReturnType<typeof useMotionValue<number>>,\n) {\n const prevTone = useRef<ToastTone | null>(null);\n useEffect(() => {\n const prev = prevTone.current;\n prevTone.current = tone;\n if (tone === prev) return;\n if (tone === 'success') {\n const el = ref.current;\n el.classList.remove('glass-glint');\n void el.offsetWidth;\n el.classList.add('glass-glint');\n const id = setTimeout(() => el.classList.remove('glass-glint'), SM.dur.slow * 1000 + 80);\n return () => clearTimeout(id);\n }\n if (tone === 'error') {\n const fall = animate(x, [0, -7, 5, -2, 0], {\n duration: SM.dur.slow,\n ease: SM.ease.standard,\n delay: SM.dur.base,\n });\n return () => fall.stop();\n }\n }, [tone]);\n}\n\nfunction ToastItem({\n t,\n depth,\n offset,\n hidden,\n behind,\n frameHeight,\n isTop,\n onHeight,\n}: {\n t: ToastRecord;\n depth: number;\n offset: number;\n hidden: boolean;\n behind: boolean;\n frameHeight: number | null;\n isTop: boolean;\n onHeight: (id: string, h: number) => void;\n}) {\n const ref = useRef<HTMLLIElement>(null);\n const x = useMotionValue(0); // swipe travel - ours, so dismissal can finish it\n useToneGesture(t.tone, ref, x);\n\n // report the CONTENT height (firstChild - the li's own height is animated, so it'd read mid-tween)\n useLayoutEffect(() => {\n if (ref.current && ref.current.firstElementChild)\n onHeight(t.id, (ref.current.firstElementChild as HTMLElement).offsetHeight);\n });\n\n const swipe = (_e: PointerEvent | MouseEvent | TouchEvent, info: PanInfo) => {\n if (info.offset.x > SWIPE_X || info.velocity.x > SWIPE_V) {\n // fling out the right edge, THEN remove - the exit fade plays where it landed, no snap-back\n animate(x, 420, { duration: SM.dur.fast, ease: SM.ease.exit }).then(() =>\n store.dismiss(t.id),\n );\n }\n };\n\n return (\n <motion.li\n ref={ref}\n className=\"toast glass\"\n data-tone={t.tone}\n data-behind={behind ? '' : undefined}\n role={t.tone === 'error' ? 'alert' : 'status'}\n aria-atomic=\"true\"\n style={{ x }}\n initial={{ opacity: 0, y: isTop ? -24 : 24, scale: 0.97 }}\n animate={{\n opacity: hidden ? 0 : 1,\n y: isTop ? offset : -offset,\n scale: 1 - depth * 0.05,\n /* behind-cards adopt the front card's frame height (content faded) so a short card never drowns behind a tall one */\n height: frameHeight || 'auto',\n pointerEvents: hidden ? 'none' : 'auto',\n }}\n exit={{ opacity: 0, scale: 0.96, transition: { duration: SM.dur.fast, ease: SM.ease.exit } }}\n transition={{ y: SM.t.settle, scale: SM.t.settle, height: SM.t.settle, opacity: SM.t.enter }}\n drag={t.dismissible ? 'x' : false}\n dragConstraints={{ left: 0, right: 0 }}\n dragElastic={{ left: 0.04, right: 0.9 }}\n dragMomentum={false}\n onDragEnd={swipe}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && t.dismissible) store.dismiss(t.id);\n }}\n >\n {t.node ? (\n <div className=\"toast__custom\">{t.node as React.ReactNode}</div>\n ) : (\n <ToastBody t={t} />\n )}\n </motion.li>\n );\n}\n\nfunction ToastBody({ t }: { t: ToastRecord }) {\n return (\n <div className=\"toast__inner\">\n {(t.tone !== 'default' || isFinite(t.duration)) && (\n <span className=\"toast__icon\">\n {t.tone !== 'default' && (\n /* keyed remount (not nested AnimatePresence): old glyph cuts, new springs in */\n <motion.span\n key={t.tone}\n className=\"toast__icon-glyph\"\n initial={{ scale: 0.5, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{ scale: SM.t.settle, opacity: SM.t.enter }}\n >\n {t.tone === 'loading' ? (\n <span className=\"toast__spinner\" aria-hidden=\"true\"></span>\n ) : (\n <Icon name={TONE_ICON[t.tone]} weight=\"fill\" />\n )}\n </motion.span>\n )}\n {isFinite(t.duration) && (\n /* the ring - keyed to the timer so a restart re-fills it; pathLength=1 makes dashoffset a fraction */\n <svg\n key={'ring-' + t.timerKey}\n className=\"toast__ring\"\n viewBox=\"0 0 36 36\"\n aria-hidden=\"true\"\n >\n <circle className=\"toast__ring-track\" cx=\"18\" cy=\"18\" r=\"16.5\"></circle>\n <circle\n className=\"toast__ring-arc\"\n cx=\"18\"\n cy=\"18\"\n r=\"16.5\"\n pathLength={1}\n style={{ animationDuration: t.duration + 'ms' }}\n ></circle>\n </svg>\n )}\n </span>\n )}\n <motion.div\n key={String(t.message) + '-' + String(t.description)}\n className=\"toast__text\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={SM.t.enter}\n >\n <p className=\"toast__message\">{t.message}</p>\n {t.description != null && <p className=\"toast__desc\">{t.description}</p>}\n </motion.div>\n {t.count > 1 && (\n <motion.span\n key={t.count}\n className=\"toast__count\"\n initial={{ scale: 0.6 }}\n animate={{ scale: 1 }}\n transition={SM.t.settle}\n >\n ×{t.count}\n </motion.span>\n )}\n {t.action && (\n <button\n type=\"button\"\n className=\"btn btn--secondary btn--sm toast__action\"\n onClick={() => {\n if (t.action.onClick) t.action.onClick();\n store.dismiss(t.id);\n }}\n >\n {t.action.label}\n </button>\n )}\n {t.dismissible && (\n <button\n type=\"button\"\n className=\"toast__close\"\n aria-label=\"Dismiss\"\n onClick={() => store.dismiss(t.id)}\n >\n <Icon name=\"close\" size=\"sm\" />\n </button>\n )}\n </div>\n );\n}\n\nfunction ToastHost({ config }: { config: ToasterConfig }) {\n const {\n toasts,\n paused,\n expanded: hoverExpanded,\n } = useSyncExternalStore(\n store.subscribe,\n store.get,\n store.get, // server snapshot - the host renders nothing until mounted anyway\n );\n const [heights, setHeights] = useState<Record<string, number>>({});\n const [ready, setReady] = useState(false);\n const collapseTimer = useRef<ReturnType<typeof setTimeout> | 0>(0);\n const hovering = useRef(false);\n\n // Portals into document.body, so render nothing until mounted (SSR-safe, no hydration mismatch).\n useEffect(() => setReady(true), []);\n\n const onHeight = (id: string, h: number) =>\n setHeights((prev) => (prev[id] === h ? prev : { ...prev, [id]: h }));\n\n // hold = fan open + freeze clocks; release = graced fold + resume\n const onHold = () => {\n hovering.current = true;\n clearTimeout(collapseTimer.current);\n store.setExpanded(true);\n store.pause();\n };\n const onRelease = (graced: boolean) => {\n hovering.current = false;\n clearTimeout(collapseTimer.current);\n collapseTimer.current = setTimeout(\n () => {\n store.setExpanded(false);\n store.resume();\n },\n graced ? COLLAPSE_GRACE : 0,\n );\n };\n\n // tab hidden - freeze clocks, visible - resume (visibility, not window focus: an embedded preview blurs on outside clicks).\n useEffect(() => {\n const onVis = () => {\n if (document.hidden) store.pause();\n else if (!hovering.current) store.resume();\n };\n document.addEventListener('visibilitychange', onVis);\n return () => document.removeEventListener('visibilitychange', onVis);\n }, []);\n\n // safety net: last card removed under the cursor fires no pointerout, so release here\n useEffect(() => {\n if (toasts.length === 0) {\n hovering.current = false;\n clearTimeout(collapseTimer.current);\n store.setExpanded(false);\n store.resume();\n }\n }, [toasts.length]);\n\n if (!ready) return null;\n\n const isTop = config.position.startsWith('top');\n const visible = config.visibleToasts;\n const rendered = visible * 2;\n const gap = config.gap || stackGap();\n const expanded = config.expand || hoverExpanded;\n\n const slice = toasts.slice(-rendered);\n const n = slice.length;\n const frontH = n ? heights[slice[n - 1].id] || 0 : 0;\n\n return createPortal(\n <ol\n className={'toast-viewport' + (paused ? ' is-paused' : '')}\n data-position={config.position}\n style={\n config.offset\n ? ({ '--toast-offset': `${config.offset}px` } as React.CSSProperties)\n : undefined\n }\n aria-label=\"Notifications\"\n onPointerOver={(e) => {\n if (e.pointerType !== 'touch') onHold();\n }}\n onPointerOut={(e) => {\n if (!e.relatedTarget || !e.currentTarget.contains(e.relatedTarget as Node)) onRelease(true);\n }}\n onFocus={onHold}\n onBlur={(e) => {\n if (!e.relatedTarget || !e.currentTarget.contains(e.relatedTarget as Node))\n onRelease(false);\n }}\n >\n <AnimatePresence>\n {slice.map((t, i) => {\n const depth = n - 1 - i; // newest = 0, at the front\n let offset = depth * gap; // collapsed: peek per depth\n if (expanded) {\n // expanded: real heights\n offset = 0;\n for (let j = i + 1; j < n; j++) offset += (heights[slice[j].id] || 0) + gap;\n }\n return (\n <ToastItem\n key={t.id}\n t={t}\n depth={expanded ? 0 : depth}\n offset={offset}\n hidden={!expanded && depth >= visible}\n behind={!expanded && depth > 0}\n frameHeight={!expanded && depth > 0 && frontH ? frontH : null}\n isTop={isTop}\n onHeight={onHeight}\n />\n );\n })}\n </AnimatePresence>\n </ol>,\n document.body,\n );\n}\n\nfunction stripUndefined<T extends object>(o: T): Partial<T> {\n const out: Partial<T> = {};\n (Object.keys(o) as (keyof T)[]).forEach((k) => {\n if (o[k] !== undefined) out[k] = o[k];\n });\n return out;\n}\n\nexport interface ToasterProps extends Partial<ToasterConfig> {}\n\n/* Toaster - mount once near the app root. It owns the toast viewport and registers the queue;\n without it, toast() renders nothing (and warns once in the browser). */\nexport function Toaster(props: ToasterProps): React.ReactElement {\n const config: ToasterConfig = { ...DEFAULT_TOASTER_CONFIG, ...stripUndefined(props) };\n\n useEffect(() => {\n store.config = config;\n store.mounted = true;\n if (config.expand) store.setExpanded(true);\n return () => {\n store.mounted = false;\n };\n }, [\n config.position,\n config.duration,\n config.visibleToasts,\n config.gap,\n config.offset,\n config.expand,\n ]);\n\n return <ToastHost config={config} />;\n}\n"]}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
// src/components/toast/toast-store.ts
|
|
2
|
+
var DEFAULT_TOASTER_CONFIG = {
|
|
3
|
+
position: "bottom-right",
|
|
4
|
+
duration: 0,
|
|
5
|
+
visibleToasts: 3,
|
|
6
|
+
gap: 0,
|
|
7
|
+
offset: 0,
|
|
8
|
+
expand: false
|
|
9
|
+
};
|
|
2
10
|
var DURATION = {
|
|
3
11
|
default: 5e3,
|
|
4
12
|
success: 5e3,
|
|
@@ -14,7 +22,8 @@ var store = {
|
|
|
14
22
|
toasts: [],
|
|
15
23
|
paused: false,
|
|
16
24
|
expanded: false,
|
|
17
|
-
|
|
25
|
+
mounted: false,
|
|
26
|
+
config: { ...DEFAULT_TOASTER_CONFIG },
|
|
18
27
|
snap: { toasts: [], paused: false, expanded: false },
|
|
19
28
|
listeners: /* @__PURE__ */ new Set(),
|
|
20
29
|
subscribe(l) {
|
|
@@ -92,10 +101,30 @@ var store = {
|
|
|
92
101
|
store.emit();
|
|
93
102
|
}
|
|
94
103
|
};
|
|
104
|
+
var warned = false;
|
|
105
|
+
var warnScheduled = false;
|
|
106
|
+
function warnIfDetached() {
|
|
107
|
+
if (store.mounted || warned || warnScheduled || typeof window === "undefined") return;
|
|
108
|
+
warnScheduled = true;
|
|
109
|
+
setTimeout(() => {
|
|
110
|
+
warnScheduled = false;
|
|
111
|
+
if (store.mounted || warned) return;
|
|
112
|
+
warned = true;
|
|
113
|
+
console.warn(
|
|
114
|
+
"premium-ds: a toast was triggered but no <Toaster /> is mounted, so nothing will render. Mount <Toaster /> once near your app root."
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function resolveDuration(tone, opt) {
|
|
119
|
+
if (opt != null) return opt;
|
|
120
|
+
const toneDefault = DURATION[tone];
|
|
121
|
+
if (toneDefault === Infinity || store.config.duration <= 0) return toneDefault;
|
|
122
|
+
return store.config.duration;
|
|
123
|
+
}
|
|
95
124
|
function make(tone, message, opts = {}) {
|
|
96
|
-
|
|
125
|
+
warnIfDetached();
|
|
97
126
|
const id = opts.id != null ? String(opts.id) : "toast-" + ++uid;
|
|
98
|
-
const duration =
|
|
127
|
+
const duration = resolveDuration(tone, opts.duration);
|
|
99
128
|
if (store.toasts.some((t) => t.id === id)) {
|
|
100
129
|
return store.update(id, {
|
|
101
130
|
tone,
|
|
@@ -140,7 +169,7 @@ toast.promise = function(promise, msgs = {}) {
|
|
|
140
169
|
return promise;
|
|
141
170
|
};
|
|
142
171
|
toast.custom = (node, opts = {}) => {
|
|
143
|
-
|
|
172
|
+
warnIfDetached();
|
|
144
173
|
const id = opts.id != null ? String(opts.id) : "toast-" + ++uid;
|
|
145
174
|
const duration = opts.duration != null ? opts.duration : Infinity;
|
|
146
175
|
if (store.toasts.some((t) => t.id === id)) return store.update(id, { node });
|
|
@@ -160,6 +189,6 @@ toast.custom = (node, opts = {}) => {
|
|
|
160
189
|
};
|
|
161
190
|
var UIToast = store;
|
|
162
191
|
|
|
163
|
-
export { UIToast, toast };
|
|
164
|
-
//# sourceMappingURL=chunk-
|
|
165
|
-
//# sourceMappingURL=chunk-
|
|
192
|
+
export { DEFAULT_TOASTER_CONFIG, UIToast, toast };
|
|
193
|
+
//# sourceMappingURL=chunk-YTMZEJ7M.js.map
|
|
194
|
+
//# sourceMappingURL=chunk-YTMZEJ7M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/toast/toast-store.ts"],"names":[],"mappings":"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","file":"chunk-YTMZEJ7M.js","sourcesContent":["// toast-store - the Toast machinery: queue, clocks, coalescing, imperative API (zero React).\n\nexport type ToastTone = 'default' | 'success' | 'error' | 'warning' | 'info' | 'loading' | 'custom';\n\nexport interface ToastAction {\n label: string;\n onClick: () => void;\n}\n\nexport interface ToastOptions {\n id?: string | number;\n duration?: number;\n description?: string | null;\n action?: ToastAction | null;\n}\n\nexport interface ToastRecord {\n id: string;\n tone: ToastTone;\n message: string | null;\n description: string | null;\n action: ToastAction | null;\n duration: number;\n remaining: number;\n count: number;\n timerKey: number;\n node: unknown; // a React node, kept opaque so this module stays React-free\n dismissible: boolean;\n expiresAt?: number;\n}\n\nexport interface ToastSnapshot {\n toasts: ToastRecord[];\n paused: boolean;\n expanded: boolean;\n}\n\nexport type ToastPosition =\n 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n\n/* Root-level options - set once on <Toaster /> and read by the queue + host. */\nexport interface ToasterConfig {\n position: ToastPosition;\n duration: number; // default auto-dismiss ms for timed tones; 0 keeps the per-tone defaults\n visibleToasts: number; // cards shown before the rest recede behind\n gap: number; // px between cards; 0 reads --space-3 from the stylesheet\n offset: number; // px inset from the viewport edge; 0 reads --space-6\n expand: boolean; // start the stack fanned open instead of collapsed\n}\n\nexport const DEFAULT_TOASTER_CONFIG: ToasterConfig = {\n position: 'bottom-right',\n duration: 0,\n visibleToasts: 3,\n gap: 0,\n offset: 0,\n expand: false,\n};\n\nconst DURATION: Record<string, number> = {\n default: 5000,\n success: 5000,\n info: 5000,\n warning: 8000,\n error: 8000,\n loading: Infinity, // sticky until updated/dismissed\n};\n\nlet uid = 0;\nconst timers = new Map<string, ReturnType<typeof setTimeout>>();\n\ninterface ToastStore {\n toasts: ToastRecord[];\n paused: boolean;\n expanded: boolean;\n mounted: boolean; // a <Toaster /> is live; toasts no-op until it is\n config: ToasterConfig;\n snap: ToastSnapshot;\n listeners: Set<() => void>;\n subscribe(l: () => void): () => void;\n get(): ToastSnapshot;\n emit(): void;\n add(t: ToastRecord): string;\n update(id: string, patch: Partial<ToastRecord>): string;\n dismiss(id?: string | null): void;\n schedule(t: ToastRecord): void;\n pause(): void;\n resume(): void;\n setExpanded(v: boolean): void;\n}\n\n/* Store - the queue; the API writes, the host renders. */\nconst store: ToastStore = {\n toasts: [],\n paused: false,\n expanded: false,\n mounted: false,\n config: { ...DEFAULT_TOASTER_CONFIG },\n snap: { toasts: [], paused: false, expanded: false },\n listeners: new Set(),\n subscribe(l) {\n store.listeners.add(l);\n return () => store.listeners.delete(l);\n },\n get: () => store.snap,\n emit() {\n store.snap = { toasts: store.toasts.slice(), paused: store.paused, expanded: store.expanded };\n store.listeners.forEach((l) => l());\n },\n\n add(t) {\n // coalesce: an identical visible toast becomes a xN counter instead of a duplicate\n const twin = store.toasts.find(\n (x) =>\n !x.node &&\n !t.node &&\n x.tone === t.tone &&\n x.message === t.message &&\n x.description === t.description,\n );\n if (twin) return store.update(twin.id, { count: twin.count + 1 });\n store.toasts.push(t);\n store.schedule(t);\n store.emit();\n return t.id;\n },\n\n update(id, patch) {\n const t = store.toasts.find((x) => x.id === id);\n if (!t) return id;\n Object.assign(t, patch);\n if ('tone' in patch || 'duration' in patch || 'count' in patch) {\n t.remaining = t.duration;\n t.timerKey++; // re-key the ring so it re-fills\n store.schedule(t);\n }\n store.emit();\n return id;\n },\n\n dismiss(id) {\n const gone = id == null ? store.toasts : store.toasts.filter((t) => t.id === id);\n gone.forEach((t) => {\n clearTimeout(timers.get(t.id));\n timers.delete(t.id);\n });\n store.toasts = id == null ? [] : store.toasts.filter((t) => t.id !== id);\n store.emit();\n },\n\n schedule(t) {\n clearTimeout(timers.get(t.id));\n timers.delete(t.id);\n if (!isFinite(t.duration)) return;\n if (store.paused) return; // resume() picks it up with t.remaining\n t.expiresAt = performance.now() + t.remaining;\n timers.set(\n t.id,\n setTimeout(() => store.dismiss(t.id), t.remaining),\n );\n },\n\n pause() {\n // freeze every clock, remember what's left\n if (store.paused) return;\n store.paused = true;\n store.toasts.forEach((t) => {\n if (timers.has(t.id)) {\n clearTimeout(timers.get(t.id));\n timers.delete(t.id);\n t.remaining = Math.max(0, (t.expiresAt ?? performance.now()) - performance.now());\n }\n });\n store.emit();\n },\n\n resume() {\n if (!store.paused) return;\n store.paused = false;\n store.toasts.forEach((t) => store.schedule(t));\n store.emit();\n },\n\n setExpanded(v) {\n if (v === store.expanded) return;\n store.expanded = v;\n store.emit();\n },\n};\n\nlet warned = false;\nlet warnScheduled = false;\n\n/* A toast with no <Toaster /> mounted renders nothing. Warn once, deferred a tick so a\n toast fired during the same render that mounts <Toaster /> is not a false positive. */\nfunction warnIfDetached(): void {\n if (store.mounted || warned || warnScheduled || typeof window === 'undefined') return;\n warnScheduled = true;\n setTimeout(() => {\n warnScheduled = false;\n if (store.mounted || warned) return;\n warned = true;\n console.warn(\n 'premium-ds: a toast was triggered but no <Toaster /> is mounted, so nothing will render. Mount <Toaster /> once near your app root.',\n );\n });\n}\n\n/* Per-tone default unless the root sets a global duration; loading stays sticky (Infinity). */\nfunction resolveDuration(tone: ToastTone, opt?: number): number {\n if (opt != null) return opt;\n const toneDefault = DURATION[tone];\n if (toneDefault === Infinity || store.config.duration <= 0) return toneDefault;\n return store.config.duration;\n}\n\nfunction make(tone: ToastTone, message: string | null, opts: ToastOptions = {}): string {\n warnIfDetached();\n const id = opts.id != null ? String(opts.id) : 'toast-' + ++uid;\n const duration = resolveDuration(tone, opts.duration);\n if (store.toasts.some((t) => t.id === id)) {\n return store.update(id, {\n tone,\n message,\n duration,\n description: opts.description != null ? opts.description : null,\n action: opts.action != null ? opts.action : null,\n });\n }\n return store.add({\n id,\n tone,\n message,\n description: opts.description != null ? opts.description : null,\n action: opts.action != null ? opts.action : null,\n duration,\n remaining: duration,\n count: 1,\n timerKey: 0,\n node: null,\n dismissible: true,\n });\n}\n\ntype PromiseMsg<V> = string | ((v: V) => string);\nexport interface ToastPromiseMsgs<T> {\n loading?: string;\n success?: PromiseMsg<T>;\n error?: PromiseMsg<unknown>;\n}\n\nexport interface ToastApi {\n (message: string, opts?: ToastOptions): string;\n success(m: string, o?: ToastOptions): string;\n error(m: string, o?: ToastOptions): string;\n warning(m: string, o?: ToastOptions): string;\n info(m: string, o?: ToastOptions): string;\n loading(m: string, o?: ToastOptions): string;\n dismiss(id?: string | null): void;\n update(id: string, patch?: Partial<ToastRecord>): string;\n promise<T>(promise: Promise<T>, msgs?: ToastPromiseMsgs<T>): Promise<T>;\n custom(\n node: unknown,\n opts?: { id?: string | number; duration?: number; dismissible?: boolean },\n ): string;\n}\n\nconst toast = ((message: string, opts?: ToastOptions) =>\n make('default', message, opts)) as ToastApi;\ntoast.success = (m, o) => make('success', m, o);\ntoast.error = (m, o) => make('error', m, o);\ntoast.warning = (m, o) => make('warning', m, o);\ntoast.info = (m, o) => make('info', m, o);\ntoast.loading = (m, o) => make('loading', m, o);\ntoast.dismiss = (id) => store.dismiss(id);\n\ntoast.update = (id, patch = {}) => {\n // a tone change without an explicit duration adopts that tone's clock\n if (patch.tone && patch.duration == null) patch = { ...patch, duration: DURATION[patch.tone] };\n return store.update(id, patch);\n};\n\ntoast.promise = function <T>(promise: Promise<T>, msgs: ToastPromiseMsgs<T> = {}): Promise<T> {\n const id = make('loading', msgs.loading != null ? msgs.loading : 'Working...');\n const text = <V>(m: PromiseMsg<V> | undefined, fallback: string, v: V): string =>\n typeof m === 'function' ? (m as (x: V) => string)(v) : m != null ? m : fallback;\n promise.then(\n (v) => toast.update(id, { tone: 'success', message: text(msgs.success, 'Done', v) }),\n (e) =>\n toast.update(id, { tone: 'error', message: text(msgs.error, 'Something went wrong', e) }),\n );\n return promise;\n};\n\ntoast.custom = (node, opts = {}) => {\n warnIfDetached();\n const id = opts.id != null ? String(opts.id) : 'toast-' + ++uid;\n const duration = opts.duration != null ? opts.duration : Infinity;\n if (store.toasts.some((t) => t.id === id)) return store.update(id, { node });\n return store.add({\n id,\n tone: 'custom',\n node,\n message: null,\n description: null,\n action: null,\n duration,\n remaining: duration,\n count: 1,\n timerKey: 0,\n dismissible: opts.dismissible === true,\n });\n};\n\nexport { toast };\nexport const UIToast = store;\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -28,8 +28,8 @@ export { Overlay, OverlayProps } from './overlay.js';
|
|
|
28
28
|
export { Dialog, DialogProps } from './dialog.js';
|
|
29
29
|
export { Tooltip, TooltipHost, TooltipProps } from './tooltip.js';
|
|
30
30
|
export { Alert, AlertAction, AlertProps, AlertTone } from './alert.js';
|
|
31
|
-
export { Toaster } from './toast.js';
|
|
32
|
-
export { ToastAction, ToastApi, ToastOptions, ToastPromiseMsgs, ToastRecord, ToastSnapshot, ToastTone, UIToast, toast } from './toast-store.js';
|
|
31
|
+
export { Toaster, ToasterProps } from './toast.js';
|
|
32
|
+
export { DEFAULT_TOASTER_CONFIG, ToastAction, ToastApi, ToastOptions, ToastPosition, ToastPromiseMsgs, ToastRecord, ToastSnapshot, ToastTone, ToasterConfig, UIToast, toast } from './toast-store.js';
|
|
33
33
|
export { Bezier, MotionTokens, UIMotion } from './motion-tokens.js';
|
|
34
34
|
import 'react';
|
|
35
35
|
import 'motion/react';
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@ export { TabPanel, Tabs } from './chunk-EZ2CWTBE.js';
|
|
|
3
3
|
export { Dialog } from './chunk-FPP2XLKX.js';
|
|
4
4
|
export { Tooltip, TooltipHost } from './chunk-BXXS7YRC.js';
|
|
5
5
|
export { Alert } from './chunk-H6KWJNOE.js';
|
|
6
|
-
export { Toaster } from './chunk-
|
|
7
|
-
export { UIToast, toast } from './chunk-
|
|
6
|
+
export { Toaster } from './chunk-NIZLUYLW.js';
|
|
7
|
+
export { DEFAULT_TOASTER_CONFIG, UIToast, toast } from './chunk-YTMZEJ7M.js';
|
|
8
8
|
export { Checkbox } from './chunk-XA3T5KWA.js';
|
|
9
9
|
export { Toggle } from './chunk-5PQMQBQC.js';
|
|
10
10
|
export { RadioGroup } from './chunk-KN7JFAZ6.js';
|
package/dist/toast-store.d.ts
CHANGED
|
@@ -28,11 +28,22 @@ interface ToastSnapshot {
|
|
|
28
28
|
paused: boolean;
|
|
29
29
|
expanded: boolean;
|
|
30
30
|
}
|
|
31
|
+
type ToastPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
32
|
+
interface ToasterConfig {
|
|
33
|
+
position: ToastPosition;
|
|
34
|
+
duration: number;
|
|
35
|
+
visibleToasts: number;
|
|
36
|
+
gap: number;
|
|
37
|
+
offset: number;
|
|
38
|
+
expand: boolean;
|
|
39
|
+
}
|
|
40
|
+
declare const DEFAULT_TOASTER_CONFIG: ToasterConfig;
|
|
31
41
|
interface ToastStore {
|
|
32
42
|
toasts: ToastRecord[];
|
|
33
43
|
paused: boolean;
|
|
34
44
|
expanded: boolean;
|
|
35
|
-
|
|
45
|
+
mounted: boolean;
|
|
46
|
+
config: ToasterConfig;
|
|
36
47
|
snap: ToastSnapshot;
|
|
37
48
|
listeners: Set<() => void>;
|
|
38
49
|
subscribe(l: () => void): () => void;
|
|
@@ -72,4 +83,4 @@ declare const toast: ToastApi;
|
|
|
72
83
|
|
|
73
84
|
declare const UIToast: ToastStore;
|
|
74
85
|
|
|
75
|
-
export { type ToastAction, type ToastApi, type ToastOptions, type ToastPromiseMsgs, type ToastRecord, type ToastSnapshot, type ToastTone, UIToast, toast };
|
|
86
|
+
export { DEFAULT_TOASTER_CONFIG, type ToastAction, type ToastApi, type ToastOptions, type ToastPosition, type ToastPromiseMsgs, type ToastRecord, type ToastSnapshot, type ToastTone, type ToasterConfig, UIToast, toast };
|
package/dist/toast-store.js
CHANGED
package/dist/toast.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ToasterConfig } from './toast-store.js';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
interface ToasterProps extends Partial<ToasterConfig> {
|
|
5
|
+
}
|
|
6
|
+
declare function Toaster(props: ToasterProps): React.ReactElement;
|
|
7
|
+
|
|
8
|
+
export { Toaster, type ToasterProps };
|
package/dist/toast.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
'use client';export { Toaster } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
'use client';export { Toaster } from './chunk-NIZLUYLW.js';
|
|
2
|
+
import './chunk-YTMZEJ7M.js';
|
|
3
3
|
import './chunk-KBWNUUWM.js';
|
|
4
4
|
import './chunk-37O2ZXD6.js';
|
|
5
5
|
//# sourceMappingURL=toast.js.map
|
package/llms.txt
CHANGED
|
@@ -139,9 +139,11 @@ Alert - premium-ds/alert
|
|
|
139
139
|
Persistent, in-flow status. tone, title, children (body), action { label, onClick }, dismissible, banner, open/onDismiss (controlled).
|
|
140
140
|
<Alert tone="warning" title="Your trial ends in 5 days" action={{ label: 'Upgrade', onClick: fn }}>Add a plan...</Alert>
|
|
141
141
|
|
|
142
|
-
Toast - premium-ds/toast (imperative; the
|
|
142
|
+
Toast - premium-ds/toast (imperative; mount <Toaster /> once at the app root, then call toast() from anywhere)
|
|
143
|
+
<Toaster /> props: position ('bottom-right' default), duration, visibleToasts, gap, offset, expand. Without it, toast() no-ops.
|
|
143
144
|
toast(msg) - toast.success/error/warning/info(msg, { description, action }) - toast.promise(p, { loading, success, error }) - toast.loading - toast.dismiss().
|
|
144
|
-
import { toast } from 'premium-ds';
|
|
145
|
+
import { Toaster, toast } from 'premium-ds';
|
|
146
|
+
// once at the root: <Toaster position="bottom-right" />
|
|
145
147
|
toast.success('Changes saved', { description: 'Synced to the cloud' });
|
|
146
148
|
toast.promise(save(), { loading: 'Saving...', success: (v) => `Saved - ${v.count}`, error: (e) => `Failed - ${e.message}` });
|
|
147
149
|
|
package/package.json
CHANGED
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
--btn-shadow: inset 0 1px 0 0 rgb(255 255 255 / 0.16), var(--shadow-sm);
|
|
86
86
|
}
|
|
87
87
|
.btn--primary:hover:not(:disabled):not(.is-loading) {
|
|
88
|
-
background: linear-gradient(180deg, var(--
|
|
88
|
+
background: linear-gradient(180deg, var(--accent-lift), var(--accent));
|
|
89
89
|
--btn-shadow: inset 0 1px 0 0 rgb(255 255 255 / 0.22), var(--shadow-md);
|
|
90
90
|
}
|
|
91
91
|
.btn--primary:active:not(:disabled):not(.is-loading) {
|
|
@@ -3,18 +3,21 @@
|
|
|
3
3
|
/* Toast - the React render layer (queue + clocks live in toast-store.ts). */
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
|
-
import { createRoot } from 'react-dom/client';
|
|
7
6
|
import { motion, AnimatePresence, animate, useMotionValue, type PanInfo } from 'motion/react';
|
|
8
7
|
import { UIMotion } from '../../tokens/motion-tokens';
|
|
9
8
|
import { Icon, type IconName } from '../icon/Icon';
|
|
10
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
UIToast,
|
|
11
|
+
DEFAULT_TOASTER_CONFIG,
|
|
12
|
+
type ToastRecord,
|
|
13
|
+
type ToastTone,
|
|
14
|
+
type ToasterConfig,
|
|
15
|
+
} from './toast-store';
|
|
11
16
|
|
|
12
17
|
const SM = UIMotion;
|
|
13
18
|
const store = UIToast;
|
|
14
19
|
const { useRef, useEffect, useLayoutEffect, useState, useSyncExternalStore } = React;
|
|
15
20
|
|
|
16
|
-
const VISIBLE = 3;
|
|
17
|
-
const RENDERED = 6;
|
|
18
21
|
const COLLAPSE_GRACE = 140;
|
|
19
22
|
const SWIPE_X = 64;
|
|
20
23
|
const SWIPE_V = 480;
|
|
@@ -74,6 +77,7 @@ function ToastItem({
|
|
|
74
77
|
hidden,
|
|
75
78
|
behind,
|
|
76
79
|
frameHeight,
|
|
80
|
+
isTop,
|
|
77
81
|
onHeight,
|
|
78
82
|
}: {
|
|
79
83
|
t: ToastRecord;
|
|
@@ -82,6 +86,7 @@ function ToastItem({
|
|
|
82
86
|
hidden: boolean;
|
|
83
87
|
behind: boolean;
|
|
84
88
|
frameHeight: number | null;
|
|
89
|
+
isTop: boolean;
|
|
85
90
|
onHeight: (id: string, h: number) => void;
|
|
86
91
|
}) {
|
|
87
92
|
const ref = useRef<HTMLLIElement>(null);
|
|
@@ -112,10 +117,10 @@ function ToastItem({
|
|
|
112
117
|
role={t.tone === 'error' ? 'alert' : 'status'}
|
|
113
118
|
aria-atomic="true"
|
|
114
119
|
style={{ x }}
|
|
115
|
-
initial={{ opacity: 0, y: 24, scale: 0.97 }}
|
|
120
|
+
initial={{ opacity: 0, y: isTop ? -24 : 24, scale: 0.97 }}
|
|
116
121
|
animate={{
|
|
117
122
|
opacity: hidden ? 0 : 1,
|
|
118
|
-
y: -offset,
|
|
123
|
+
y: isTop ? offset : -offset,
|
|
119
124
|
scale: 1 - depth * 0.05,
|
|
120
125
|
/* behind-cards adopt the front card's frame height (content faded) so a short card never drowns behind a tall one */
|
|
121
126
|
height: frameHeight || 'auto',
|
|
@@ -230,12 +235,24 @@ function ToastBody({ t }: { t: ToastRecord }) {
|
|
|
230
235
|
);
|
|
231
236
|
}
|
|
232
237
|
|
|
233
|
-
function ToastHost() {
|
|
234
|
-
const {
|
|
238
|
+
function ToastHost({ config }: { config: ToasterConfig }) {
|
|
239
|
+
const {
|
|
240
|
+
toasts,
|
|
241
|
+
paused,
|
|
242
|
+
expanded: hoverExpanded,
|
|
243
|
+
} = useSyncExternalStore(
|
|
244
|
+
store.subscribe,
|
|
245
|
+
store.get,
|
|
246
|
+
store.get, // server snapshot - the host renders nothing until mounted anyway
|
|
247
|
+
);
|
|
235
248
|
const [heights, setHeights] = useState<Record<string, number>>({});
|
|
249
|
+
const [ready, setReady] = useState(false);
|
|
236
250
|
const collapseTimer = useRef<ReturnType<typeof setTimeout> | 0>(0);
|
|
237
251
|
const hovering = useRef(false);
|
|
238
252
|
|
|
253
|
+
// Portals into document.body, so render nothing until mounted (SSR-safe, no hydration mismatch).
|
|
254
|
+
useEffect(() => setReady(true), []);
|
|
255
|
+
|
|
239
256
|
const onHeight = (id: string, h: number) =>
|
|
240
257
|
setHeights((prev) => (prev[id] === h ? prev : { ...prev, [id]: h }));
|
|
241
258
|
|
|
@@ -278,14 +295,27 @@ function ToastHost() {
|
|
|
278
295
|
}
|
|
279
296
|
}, [toasts.length]);
|
|
280
297
|
|
|
281
|
-
|
|
298
|
+
if (!ready) return null;
|
|
299
|
+
|
|
300
|
+
const isTop = config.position.startsWith('top');
|
|
301
|
+
const visible = config.visibleToasts;
|
|
302
|
+
const rendered = visible * 2;
|
|
303
|
+
const gap = config.gap || stackGap();
|
|
304
|
+
const expanded = config.expand || hoverExpanded;
|
|
305
|
+
|
|
306
|
+
const slice = toasts.slice(-rendered);
|
|
282
307
|
const n = slice.length;
|
|
283
308
|
const frontH = n ? heights[slice[n - 1].id] || 0 : 0;
|
|
284
|
-
const gap = stackGap();
|
|
285
309
|
|
|
286
310
|
return createPortal(
|
|
287
311
|
<ol
|
|
288
312
|
className={'toast-viewport' + (paused ? ' is-paused' : '')}
|
|
313
|
+
data-position={config.position}
|
|
314
|
+
style={
|
|
315
|
+
config.offset
|
|
316
|
+
? ({ '--toast-offset': `${config.offset}px` } as React.CSSProperties)
|
|
317
|
+
: undefined
|
|
318
|
+
}
|
|
289
319
|
aria-label="Notifications"
|
|
290
320
|
onPointerOver={(e) => {
|
|
291
321
|
if (e.pointerType !== 'touch') onHold();
|
|
@@ -299,7 +329,6 @@ function ToastHost() {
|
|
|
299
329
|
onRelease(false);
|
|
300
330
|
}}
|
|
301
331
|
>
|
|
302
|
-
{/* initial stays true - the host mounts with the first toast, so initial={false} would skip its entrance */}
|
|
303
332
|
<AnimatePresence>
|
|
304
333
|
{slice.map((t, i) => {
|
|
305
334
|
const depth = n - 1 - i; // newest = 0, at the front
|
|
@@ -315,9 +344,10 @@ function ToastHost() {
|
|
|
315
344
|
t={t}
|
|
316
345
|
depth={expanded ? 0 : depth}
|
|
317
346
|
offset={offset}
|
|
318
|
-
hidden={!expanded && depth >=
|
|
347
|
+
hidden={!expanded && depth >= visible}
|
|
319
348
|
behind={!expanded && depth > 0}
|
|
320
349
|
frameHeight={!expanded && depth > 0 && frontH ? frontH : null}
|
|
350
|
+
isTop={isTop}
|
|
321
351
|
onHeight={onHeight}
|
|
322
352
|
/>
|
|
323
353
|
);
|
|
@@ -328,22 +358,36 @@ function ToastHost() {
|
|
|
328
358
|
);
|
|
329
359
|
}
|
|
330
360
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
document.body.appendChild(el);
|
|
338
|
-
createRoot(el).render(<ToastHost />);
|
|
361
|
+
function stripUndefined<T extends object>(o: T): Partial<T> {
|
|
362
|
+
const out: Partial<T> = {};
|
|
363
|
+
(Object.keys(o) as (keyof T)[]).forEach((k) => {
|
|
364
|
+
if (o[k] !== undefined) out[k] = o[k];
|
|
365
|
+
});
|
|
366
|
+
return out;
|
|
339
367
|
}
|
|
340
|
-
store.host = ensureToastHost;
|
|
341
|
-
if (store.toasts.length) ensureToastHost(); // toasts fired before we loaded
|
|
342
368
|
|
|
343
|
-
|
|
344
|
-
|
|
369
|
+
export interface ToasterProps extends Partial<ToasterConfig> {}
|
|
370
|
+
|
|
371
|
+
/* Toaster - mount once near the app root. It owns the toast viewport and registers the queue;
|
|
372
|
+
without it, toast() renders nothing (and warns once in the browser). */
|
|
373
|
+
export function Toaster(props: ToasterProps): React.ReactElement {
|
|
374
|
+
const config: ToasterConfig = { ...DEFAULT_TOASTER_CONFIG, ...stripUndefined(props) };
|
|
375
|
+
|
|
345
376
|
useEffect(() => {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
377
|
+
store.config = config;
|
|
378
|
+
store.mounted = true;
|
|
379
|
+
if (config.expand) store.setExpanded(true);
|
|
380
|
+
return () => {
|
|
381
|
+
store.mounted = false;
|
|
382
|
+
};
|
|
383
|
+
}, [
|
|
384
|
+
config.position,
|
|
385
|
+
config.duration,
|
|
386
|
+
config.visibleToasts,
|
|
387
|
+
config.gap,
|
|
388
|
+
config.offset,
|
|
389
|
+
config.expand,
|
|
390
|
+
]);
|
|
391
|
+
|
|
392
|
+
return <ToastHost config={config} />;
|
|
349
393
|
}
|
|
@@ -35,6 +35,28 @@ export interface ToastSnapshot {
|
|
|
35
35
|
expanded: boolean;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
export type ToastPosition =
|
|
39
|
+
'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
40
|
+
|
|
41
|
+
/* Root-level options - set once on <Toaster /> and read by the queue + host. */
|
|
42
|
+
export interface ToasterConfig {
|
|
43
|
+
position: ToastPosition;
|
|
44
|
+
duration: number; // default auto-dismiss ms for timed tones; 0 keeps the per-tone defaults
|
|
45
|
+
visibleToasts: number; // cards shown before the rest recede behind
|
|
46
|
+
gap: number; // px between cards; 0 reads --space-3 from the stylesheet
|
|
47
|
+
offset: number; // px inset from the viewport edge; 0 reads --space-6
|
|
48
|
+
expand: boolean; // start the stack fanned open instead of collapsed
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const DEFAULT_TOASTER_CONFIG: ToasterConfig = {
|
|
52
|
+
position: 'bottom-right',
|
|
53
|
+
duration: 0,
|
|
54
|
+
visibleToasts: 3,
|
|
55
|
+
gap: 0,
|
|
56
|
+
offset: 0,
|
|
57
|
+
expand: false,
|
|
58
|
+
};
|
|
59
|
+
|
|
38
60
|
const DURATION: Record<string, number> = {
|
|
39
61
|
default: 5000,
|
|
40
62
|
success: 5000,
|
|
@@ -51,7 +73,8 @@ interface ToastStore {
|
|
|
51
73
|
toasts: ToastRecord[];
|
|
52
74
|
paused: boolean;
|
|
53
75
|
expanded: boolean;
|
|
54
|
-
|
|
76
|
+
mounted: boolean; // a <Toaster /> is live; toasts no-op until it is
|
|
77
|
+
config: ToasterConfig;
|
|
55
78
|
snap: ToastSnapshot;
|
|
56
79
|
listeners: Set<() => void>;
|
|
57
80
|
subscribe(l: () => void): () => void;
|
|
@@ -71,7 +94,8 @@ const store: ToastStore = {
|
|
|
71
94
|
toasts: [],
|
|
72
95
|
paused: false,
|
|
73
96
|
expanded: false,
|
|
74
|
-
|
|
97
|
+
mounted: false,
|
|
98
|
+
config: { ...DEFAULT_TOASTER_CONFIG },
|
|
75
99
|
snap: { toasts: [], paused: false, expanded: false },
|
|
76
100
|
listeners: new Set(),
|
|
77
101
|
subscribe(l) {
|
|
@@ -164,10 +188,36 @@ const store: ToastStore = {
|
|
|
164
188
|
},
|
|
165
189
|
};
|
|
166
190
|
|
|
191
|
+
let warned = false;
|
|
192
|
+
let warnScheduled = false;
|
|
193
|
+
|
|
194
|
+
/* A toast with no <Toaster /> mounted renders nothing. Warn once, deferred a tick so a
|
|
195
|
+
toast fired during the same render that mounts <Toaster /> is not a false positive. */
|
|
196
|
+
function warnIfDetached(): void {
|
|
197
|
+
if (store.mounted || warned || warnScheduled || typeof window === 'undefined') return;
|
|
198
|
+
warnScheduled = true;
|
|
199
|
+
setTimeout(() => {
|
|
200
|
+
warnScheduled = false;
|
|
201
|
+
if (store.mounted || warned) return;
|
|
202
|
+
warned = true;
|
|
203
|
+
console.warn(
|
|
204
|
+
'premium-ds: a toast was triggered but no <Toaster /> is mounted, so nothing will render. Mount <Toaster /> once near your app root.',
|
|
205
|
+
);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* Per-tone default unless the root sets a global duration; loading stays sticky (Infinity). */
|
|
210
|
+
function resolveDuration(tone: ToastTone, opt?: number): number {
|
|
211
|
+
if (opt != null) return opt;
|
|
212
|
+
const toneDefault = DURATION[tone];
|
|
213
|
+
if (toneDefault === Infinity || store.config.duration <= 0) return toneDefault;
|
|
214
|
+
return store.config.duration;
|
|
215
|
+
}
|
|
216
|
+
|
|
167
217
|
function make(tone: ToastTone, message: string | null, opts: ToastOptions = {}): string {
|
|
168
|
-
|
|
218
|
+
warnIfDetached();
|
|
169
219
|
const id = opts.id != null ? String(opts.id) : 'toast-' + ++uid;
|
|
170
|
-
const duration =
|
|
220
|
+
const duration = resolveDuration(tone, opts.duration);
|
|
171
221
|
if (store.toasts.some((t) => t.id === id)) {
|
|
172
222
|
return store.update(id, {
|
|
173
223
|
tone,
|
|
@@ -243,7 +293,7 @@ toast.promise = function <T>(promise: Promise<T>, msgs: ToastPromiseMsgs<T> = {}
|
|
|
243
293
|
};
|
|
244
294
|
|
|
245
295
|
toast.custom = (node, opts = {}) => {
|
|
246
|
-
|
|
296
|
+
warnIfDetached();
|
|
247
297
|
const id = opts.id != null ? String(opts.id) : 'toast-' + ++uid;
|
|
248
298
|
const duration = opts.duration != null ? opts.duration : Infinity;
|
|
249
299
|
if (store.toasts.some((t) => t.id === id)) return store.update(id, { node });
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
.toast-viewport {
|
|
4
4
|
position: fixed;
|
|
5
|
-
|
|
6
|
-
right: var(--space-6);
|
|
7
|
-
width: min(22.5rem, calc(100vw - 2 * var(--space-6)));
|
|
5
|
+
width: min(22.5rem, calc(100vw - 2 * var(--toast-offset, var(--space-6))));
|
|
8
6
|
z-index: var(--layer-toast);
|
|
9
7
|
margin: 0;
|
|
10
8
|
padding: 0;
|
|
@@ -12,6 +10,24 @@
|
|
|
12
10
|
pointer-events: none; /* only the cards themselves are live */
|
|
13
11
|
}
|
|
14
12
|
|
|
13
|
+
/* Anchored by [data-position]; --toast-offset (set by <Toaster offset>) overrides the edge inset. */
|
|
14
|
+
.toast-viewport[data-position^='top'] {
|
|
15
|
+
top: var(--toast-offset, var(--space-6));
|
|
16
|
+
}
|
|
17
|
+
.toast-viewport[data-position^='bottom'] {
|
|
18
|
+
bottom: var(--toast-offset, var(--space-6));
|
|
19
|
+
}
|
|
20
|
+
.toast-viewport[data-position$='right'] {
|
|
21
|
+
right: var(--toast-offset, var(--space-6));
|
|
22
|
+
}
|
|
23
|
+
.toast-viewport[data-position$='left'] {
|
|
24
|
+
left: var(--toast-offset, var(--space-6));
|
|
25
|
+
}
|
|
26
|
+
.toast-viewport[data-position$='center'] {
|
|
27
|
+
left: 50%;
|
|
28
|
+
transform: translateX(-50%);
|
|
29
|
+
}
|
|
30
|
+
|
|
15
31
|
/* The card - a glass consumer (.glass is set in JSX). */
|
|
16
32
|
.toast {
|
|
17
33
|
/* tone hooks - set by [data-tone] below */
|
|
@@ -21,13 +37,11 @@
|
|
|
21
37
|
--glass-sheen-rest: 0.45;
|
|
22
38
|
|
|
23
39
|
position: absolute;
|
|
24
|
-
|
|
25
|
-
right: 0;
|
|
40
|
+
left: 0;
|
|
26
41
|
width: 100%;
|
|
27
42
|
box-sizing: border-box;
|
|
28
43
|
overflow: hidden; /* custom content stays in the pane */
|
|
29
44
|
pointer-events: auto;
|
|
30
|
-
transform-origin: center bottom; /* the stack recedes upward */
|
|
31
45
|
border-radius: var(--radius-lg);
|
|
32
46
|
|
|
33
47
|
/* Motion owns transform - keep only the color/shadow transitions (never smooth Motion's writes) */
|
|
@@ -36,6 +50,16 @@
|
|
|
36
50
|
box-shadow var(--duration-base) var(--ease-standard);
|
|
37
51
|
}
|
|
38
52
|
|
|
53
|
+
/* Cards pin to the stack's edge; Motion offsets each one away from it (up from bottom, down from top). */
|
|
54
|
+
.toast-viewport[data-position^='bottom'] .toast {
|
|
55
|
+
bottom: 0;
|
|
56
|
+
transform-origin: center bottom;
|
|
57
|
+
}
|
|
58
|
+
.toast-viewport[data-position^='top'] .toast {
|
|
59
|
+
top: 0;
|
|
60
|
+
transform-origin: center top;
|
|
61
|
+
}
|
|
62
|
+
|
|
39
63
|
/* rich panes for genuine status, diluted to stay glass; neutral otherwise */
|
|
40
64
|
.toast[data-tone='success'] {
|
|
41
65
|
--toast-hue: var(--success);
|
package/src/tokens/elevation.css
CHANGED
|
@@ -12,9 +12,12 @@
|
|
|
12
12
|
--border-emphasis: 1.5px;
|
|
13
13
|
|
|
14
14
|
/* Focus & selection rings - box-shadows (not outlines) so they follow border-radius. */
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
/* Derive from --accent so the ring tracks the active accent and theme, never a fixed hue. */
|
|
17
|
+
--ring-accent: 0 0 0 3px color-mix(in oklab, var(--accent) 32%, transparent);
|
|
16
18
|
--ring-danger: 0 0 0 3px oklch(0.602 0.196 27 / 0.3);
|
|
17
19
|
--ring-warning: 0 0 0 3px color-mix(in oklab, var(--warning) 30%, transparent);
|
|
18
20
|
--ring-success: 0 0 0 3px color-mix(in oklab, var(--success) 30%, transparent);
|
|
19
|
-
--ring-offset:
|
|
21
|
+
--ring-offset:
|
|
22
|
+
0 0 0 2px var(--bg-surface), 0 0 0 4px color-mix(in oklab, var(--accent) 40%, transparent);
|
|
20
23
|
}
|
package/src/tokens/semantic.css
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
--border-default: var(--gray-200);
|
|
23
23
|
--border-strong: var(--gray-300);
|
|
24
24
|
|
|
25
|
+
--accent-lift: var(--teal-400);
|
|
25
26
|
--accent: var(--teal-500);
|
|
26
27
|
--accent-hover: var(--teal-600);
|
|
27
28
|
--accent-active: var(--teal-700);
|
|
@@ -58,18 +59,3 @@
|
|
|
58
59
|
|
|
59
60
|
--focus-ring: var(--ring-accent);
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
/* -- Dark theme - scaffold (light-first; build this next pass) --------------
|
|
63
|
-
[data-theme="dark"] {
|
|
64
|
-
--bg-app: var(--gray-950);
|
|
65
|
-
--bg-surface: var(--gray-900);
|
|
66
|
-
--bg-subtle: var(--gray-800);
|
|
67
|
-
--text-strong: var(--gray-25);
|
|
68
|
-
--text-body: var(--gray-200);
|
|
69
|
-
--text-muted: var(--gray-400);
|
|
70
|
-
--border-default: var(--gray-800);
|
|
71
|
-
--accent: var(--teal-400);
|
|
72
|
-
--text-accent: var(--teal-300);
|
|
73
|
-
...
|
|
74
|
-
}
|
|
75
|
-
*/
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/toast/Toast.tsx"],"names":[],"mappings":";;;;;;;;;AAWA,IAAM,EAAA,GAAK,QAAA;AACX,IAAM,KAAA,GAAQ,OAAA;AACd,IAAM,EAAE,MAAA,EAAQ,SAAA,EAAW,eAAA,EAAiB,QAAA,EAAU,sBAAqB,GAAI,KAAA;AAE/E,IAAM,OAAA,GAAU,CAAA;AAEhB,IAAM,cAAA,GAAiB,GAAA;AACvB,IAAM,OAAA,GAAU,EAAA;AAChB,IAAM,OAAA,GAAU,GAAA;AAGhB,IAAI,GAAA,GAAM,CAAA;AACV,SAAS,QAAA,GAAW;AAClB,EAAA,IAAI,KAAK,OAAO,GAAA;AAChB,EAAA,MAAM,EAAA,GAAK,gBAAA,CAAiB,QAAA,CAAS,eAAe,CAAA;AACpD,EAAA,MAAM,GAAA,GAAM,EAAA,CAAG,gBAAA,CAAiB,WAAW,EAAE,IAAA,EAAK;AAClD,EAAA,MAAM,CAAA,GAAI,UAAA,CAAW,GAAG,CAAA,IAAK,CAAA;AAC7B,EAAA,GAAA,GAAA,CAAO,GAAA,CAAI,QAAA,CAAS,KAAK,CAAA,GAAI,CAAA,IAAK,WAAW,EAAA,CAAG,QAAQ,CAAA,IAAK,EAAA,CAAA,GAAM,CAAA,KAAM,EAAA;AACzE,EAAA,OAAO,GAAA;AACT;AAEA,IAAM,SAAA,GAAsC;AAAA,EAC1C,OAAA,EAAS,cAAA;AAAA,EACT,KAAA,EAAO,gBAAA;AAAA,EACP,OAAA,EAAS,SAAA;AAAA,EACT,IAAA,EAAM;AACR,CAAA;AAGA,SAAS,cAAA,CACP,IAAA,EACA,GAAA,EACA,CAAA,EACA;AACA,EAAA,MAAM,QAAA,GAAW,OAAyB,IAAI,CAAA;AAC9C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,OAAO,QAAA,CAAS,OAAA;AACtB,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,IAAA,IAAI,SAAS,IAAA,EAAM;AACnB,IAAA,IAAI,SAAS,SAAA,EAAW;AACtB,MAAA,MAAM,KAAK,GAAA,CAAI,OAAA;AACf,MAAA,EAAA,CAAG,SAAA,CAAU,OAAO,aAAa,CAAA;AACjC,MAAA,KAAK,EAAA,CAAG,WAAA;AACR,MAAA,EAAA,CAAG,SAAA,CAAU,IAAI,aAAa,CAAA;AAC9B,MAAA,MAAM,EAAA,GAAK,UAAA,CAAW,MAAM,EAAA,CAAG,SAAA,CAAU,MAAA,CAAO,aAAa,CAAA,EAAG,EAAA,CAAG,GAAA,CAAI,IAAA,GAAO,GAAA,GAAO,EAAE,CAAA;AACvF,MAAA,OAAO,MAAM,aAAa,EAAE,CAAA;AAAA,IAC9B;AACA,IAAA,IAAI,SAAS,OAAA,EAAS;AACpB,MAAA,MAAM,IAAA,GAAO,QAAQ,CAAA,EAAG,CAAC,GAAG,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,CAAC,CAAA,EAAG;AAAA,QACzC,QAAA,EAAU,GAAG,GAAA,CAAI,IAAA;AAAA,QACjB,IAAA,EAAM,GAAG,IAAA,CAAK,QAAA;AAAA,QACd,KAAA,EAAO,GAAG,GAAA,CAAI;AAAA,OACf,CAAA;AACD,MAAA,OAAO,MAAM,KAAK,IAAA,EAAK;AAAA,IACzB;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AACX;AAEA,SAAS,SAAA,CAAU;AAAA,EACjB,CAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA,EAQG;AACD,EAAA,MAAM,GAAA,GAAM,OAAsB,IAAI,CAAA;AACtC,EAAA,MAAM,CAAA,GAAI,eAAe,CAAC,CAAA;AAC1B,EAAA,cAAA,CAAe,CAAA,CAAE,IAAA,EAAM,GAAA,EAAK,CAAC,CAAA;AAG7B,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,IAAI,GAAA,CAAI,OAAA,IAAW,GAAA,CAAI,OAAA,CAAQ,iBAAA;AAC7B,MAAA,QAAA,CAAS,CAAA,CAAE,EAAA,EAAK,GAAA,CAAI,OAAA,CAAQ,kBAAkC,YAAY,CAAA;AAAA,EAC9E,CAAC,CAAA;AAED,EAAA,MAAM,KAAA,GAAQ,CAAC,EAAA,EAA4C,IAAA,KAAkB;AAC3E,IAAA,IAAI,KAAK,MAAA,CAAO,CAAA,GAAI,WAAW,IAAA,CAAK,QAAA,CAAS,IAAI,OAAA,EAAS;AAExD,MAAA,OAAA,CAAQ,CAAA,EAAG,GAAA,EAAK,EAAE,QAAA,EAAU,EAAA,CAAG,GAAA,CAAI,IAAA,EAAM,IAAA,EAAM,EAAA,CAAG,IAAA,CAAK,IAAA,EAAM,CAAA,CAAE,IAAA;AAAA,QAAK,MAClE,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,EAAE;AAAA,OACpB;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,MAAA,CAAO,EAAA;AAAA,IAAP;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAU,aAAA;AAAA,MACV,aAAW,CAAA,CAAE,IAAA;AAAA,MACb,aAAA,EAAa,SAAS,EAAA,GAAK,MAAA;AAAA,MAC3B,IAAA,EAAM,CAAA,CAAE,IAAA,KAAS,OAAA,GAAU,OAAA,GAAU,QAAA;AAAA,MACrC,aAAA,EAAY,MAAA;AAAA,MACZ,KAAA,EAAO,EAAE,CAAA,EAAE;AAAA,MACX,SAAS,EAAE,OAAA,EAAS,GAAG,CAAA,EAAG,EAAA,EAAI,OAAO,IAAA,EAAK;AAAA,MAC1C,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,SAAS,CAAA,GAAI,CAAA;AAAA,QACtB,GAAG,CAAC,MAAA;AAAA,QACJ,KAAA,EAAO,IAAI,KAAA,GAAQ,IAAA;AAAA;AAAA,QAEnB,QAAQ,WAAA,IAAe,MAAA;AAAA,QACvB,aAAA,EAAe,SAAS,MAAA,GAAS;AAAA,OACnC;AAAA,MACA,MAAM,EAAE,OAAA,EAAS,CAAA,EAAG,KAAA,EAAO,MAAM,UAAA,EAAY,EAAE,QAAA,EAAU,EAAA,CAAG,IAAI,IAAA,EAAM,IAAA,EAAM,EAAA,CAAG,IAAA,CAAK,MAAK,EAAE;AAAA,MAC3F,YAAY,EAAE,CAAA,EAAG,EAAA,CAAG,CAAA,CAAE,QAAQ,KAAA,EAAO,EAAA,CAAG,CAAA,CAAE,MAAA,EAAQ,QAAQ,EAAA,CAAG,CAAA,CAAE,QAAQ,OAAA,EAAS,EAAA,CAAG,EAAE,KAAA,EAAM;AAAA,MAC3F,IAAA,EAAM,CAAA,CAAE,WAAA,GAAc,GAAA,GAAM,KAAA;AAAA,MAC5B,eAAA,EAAiB,EAAE,IAAA,EAAM,CAAA,EAAG,OAAO,CAAA,EAAE;AAAA,MACrC,WAAA,EAAa,EAAE,IAAA,EAAM,IAAA,EAAM,OAAO,GAAA,EAAI;AAAA,MACtC,YAAA,EAAc,KAAA;AAAA,MACd,SAAA,EAAW,KAAA;AAAA,MACX,SAAA,EAAW,CAAC,CAAA,KAAM;AAChB,QAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,IAAY,CAAA,CAAE,aAAa,KAAA,CAAM,OAAA,CAAQ,EAAE,EAAE,CAAA;AAAA,MAC7D,CAAA;AAAA,MAEC,QAAA,EAAA,CAAA,CAAE,IAAA,mBACD,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eAAA,EAAiB,QAAA,EAAA,CAAA,CAAE,IAAA,EAAwB,CAAA,mBAE1D,GAAA,CAAC,SAAA,EAAA,EAAU,CAAA,EAAM;AAAA;AAAA,GAErB;AAEJ;AAEA,SAAS,SAAA,CAAU,EAAE,CAAA,EAAE,EAAuB;AAC5C,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,cAAA,EACX,QAAA,EAAA;AAAA,IAAA,CAAA,CAAA,CAAE,IAAA,KAAS,aAAa,QAAA,CAAS,CAAA,CAAE,QAAQ,CAAA,qBAC3C,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,aAAA,EACb,QAAA,EAAA;AAAA,MAAA,CAAA,CAAE,IAAA,KAAS,SAAA;AAAA,sBAEV,GAAA;AAAA,QAAC,MAAA,CAAO,IAAA;AAAA,QAAP;AAAA,UAEC,SAAA,EAAU,mBAAA;AAAA,UACV,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAK,SAAS,CAAA,EAAE;AAAA,UAClC,OAAA,EAAS,EAAE,KAAA,EAAO,CAAA,EAAG,SAAS,CAAA,EAAE;AAAA,UAChC,UAAA,EAAY,EAAE,KAAA,EAAO,EAAA,CAAG,EAAE,MAAA,EAAQ,OAAA,EAAS,EAAA,CAAG,CAAA,CAAE,KAAA,EAAM;AAAA,UAErD,YAAE,IAAA,KAAS,SAAA,uBACT,MAAA,EAAA,EAAK,SAAA,EAAU,kBAAiB,aAAA,EAAY,MAAA,EAAO,CAAA,mBAEpD,GAAA,CAAC,QAAK,IAAA,EAAM,SAAA,CAAU,EAAE,IAAI,CAAA,EAAG,QAAO,MAAA,EAAO;AAAA,SAAA;AAAA,QAT1C,CAAA,CAAE;AAAA,OAWT;AAAA,MAED,QAAA,CAAS,EAAE,QAAQ,CAAA;AAAA,sBAElB,IAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EAAU,aAAA;AAAA,UACV,OAAA,EAAQ,WAAA;AAAA,UACR,aAAA,EAAY,MAAA;AAAA,UAEZ,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,QAAA,EAAA,EAAO,WAAU,mBAAA,EAAoB,EAAA,EAAG,MAAK,EAAA,EAAG,IAAA,EAAK,GAAE,MAAA,EAAO,CAAA;AAAA,4BAC/D,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAU,iBAAA;AAAA,gBACV,EAAA,EAAG,IAAA;AAAA,gBACH,EAAA,EAAG,IAAA;AAAA,gBACH,CAAA,EAAE,MAAA;AAAA,gBACF,UAAA,EAAY,CAAA;AAAA,gBACZ,KAAA,EAAO,EAAE,iBAAA,EAAmB,CAAA,CAAE,WAAW,IAAA;AAAK;AAAA;AAC/C;AAAA,SAAA;AAAA,QAbI,UAAU,CAAA,CAAE;AAAA;AAcnB,KAAA,EAEJ,CAAA;AAAA,oBAEF,IAAA;AAAA,MAAC,MAAA,CAAO,GAAA;AAAA,MAAP;AAAA,QAEC,SAAA,EAAU,aAAA;AAAA,QACV,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAE;AAAA,QACtB,OAAA,EAAS,EAAE,OAAA,EAAS,CAAA,EAAE;AAAA,QACtB,UAAA,EAAY,GAAG,CAAA,CAAE,KAAA;AAAA,QAEjB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gBAAA,EAAkB,QAAA,EAAA,CAAA,CAAE,OAAA,EAAQ,CAAA;AAAA,UACxC,CAAA,CAAE,eAAe,IAAA,oBAAQ,GAAA,CAAC,OAAE,SAAA,EAAU,aAAA,EAAe,YAAE,WAAA,EAAY;AAAA;AAAA,OAAA;AAAA,MAP/D,OAAO,CAAA,CAAE,OAAO,IAAI,GAAA,GAAM,MAAA,CAAO,EAAE,WAAW;AAAA,KAQrD;AAAA,IACC,CAAA,CAAE,QAAQ,CAAA,oBACT,IAAA;AAAA,MAAC,MAAA,CAAO,IAAA;AAAA,MAAP;AAAA,QAEC,SAAA,EAAU,cAAA;AAAA,QACV,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAI;AAAA,QACtB,OAAA,EAAS,EAAE,KAAA,EAAO,CAAA,EAAE;AAAA,QACpB,UAAA,EAAY,GAAG,CAAA,CAAE,MAAA;AAAA,QAClB,QAAA,EAAA;AAAA,UAAA,MAAA;AAAA,UACG,CAAA,CAAE;AAAA;AAAA,OAAA;AAAA,MANC,CAAA,CAAE;AAAA,KAOT;AAAA,IAED,EAAE,MAAA,oBACD,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,SAAA,EAAU,0CAAA;AAAA,QACV,SAAS,MAAM;AACb,UAAA,IAAI,CAAA,CAAE,MAAA,CAAO,OAAA,EAAS,CAAA,CAAE,OAAO,OAAA,EAAQ;AACvC,UAAA,KAAA,CAAM,OAAA,CAAQ,EAAE,EAAE,CAAA;AAAA,QACpB,CAAA;AAAA,QAEC,YAAE,MAAA,CAAO;AAAA;AAAA,KACZ;AAAA,IAED,EAAE,WAAA,oBACD,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,SAAA,EAAU,cAAA;AAAA,QACV,YAAA,EAAW,SAAA;AAAA,QACX,OAAA,EAAS,MAAM,KAAA,CAAM,OAAA,CAAQ,EAAE,EAAE,CAAA;AAAA,QAEjC,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,MAAK,IAAA,EAAK;AAAA;AAAA;AAC/B,GAAA,EAEJ,CAAA;AAEJ;AAEA,SAAS,SAAA,GAAY;AACnB,EAAA,MAAM,EAAE,QAAQ,MAAA,EAAQ,QAAA,KAAa,oBAAA,CAAqB,KAAA,CAAM,SAAA,EAAW,KAAA,CAAM,GAAG,CAAA;AACpF,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA,CAAiC,EAAE,CAAA;AACjE,EAAA,MAAM,aAAA,GAAgB,OAA0C,CAAC,CAAA;AACjE,EAAA,MAAM,QAAA,GAAW,OAAO,KAAK,CAAA;AAE7B,EAAA,MAAM,WAAW,CAAC,EAAA,EAAY,MAC5B,UAAA,CAAW,CAAC,SAAU,IAAA,CAAK,EAAE,MAAM,CAAA,GAAI,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,CAAC,EAAE,GAAG,GAAI,CAAA;AAGrE,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,IAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,IAAA,KAAA,CAAM,YAAY,IAAI,CAAA;AACtB,IAAA,KAAA,CAAM,KAAA,EAAM;AAAA,EACd,CAAA;AACA,EAAA,MAAM,SAAA,GAAY,CAAC,MAAA,KAAoB;AACrC,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,IAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,IAAA,aAAA,CAAc,OAAA,GAAU,UAAA;AAAA,MACtB,MAAM;AACJ,QAAA,KAAA,CAAM,YAAY,KAAK,CAAA;AACvB,QAAA,KAAA,CAAM,MAAA,EAAO;AAAA,MACf,CAAA;AAAA,MACA,SAAS,cAAA,GAAiB;AAAA,KAC5B;AAAA,EACF,CAAA;AAGA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,IAAI,QAAA,CAAS,MAAA,EAAQ,KAAA,CAAM,KAAA,EAAM;AAAA,WAAA,IACxB,CAAC,QAAA,CAAS,OAAA,EAAS,KAAA,CAAM,MAAA,EAAO;AAAA,IAC3C,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,oBAAoB,KAAK,CAAA;AACnD,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,kBAAA,EAAoB,KAAK,CAAA;AAAA,EACrE,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,MAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,MAAA,YAAA,CAAa,cAAc,OAAO,CAAA;AAClC,MAAA,KAAA,CAAM,YAAY,KAAK,CAAA;AACvB,MAAA,KAAA,CAAM,MAAA,EAAO;AAAA,IACf;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,CAAO,MAAM,CAAC,CAAA;AAElB,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,EAAS,CAAA;AACpC,EAAA,MAAM,IAAI,KAAA,CAAM,MAAA;AAChB,EAAA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAC,CAAA,CAAE,EAAE,CAAA,IAAK,CAAA,GAAI,CAAA;AACnD,EAAA,MAAM,MAAM,QAAA,EAAS;AAErB,EAAA,OAAO,YAAA;AAAA,oBACL,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,gBAAA,IAAoB,MAAA,GAAS,YAAA,GAAe,EAAA,CAAA;AAAA,QACvD,YAAA,EAAW,eAAA;AAAA,QACX,aAAA,EAAe,CAAC,CAAA,KAAM;AACpB,UAAA,IAAI,CAAA,CAAE,WAAA,KAAgB,OAAA,EAAS,MAAA,EAAO;AAAA,QACxC,CAAA;AAAA,QACA,YAAA,EAAc,CAAC,CAAA,KAAM;AACnB,UAAA,IAAI,CAAC,CAAA,CAAE,aAAA,IAAiB,CAAC,CAAA,CAAE,aAAA,CAAc,QAAA,CAAS,CAAA,CAAE,aAAqB,CAAA,EAAG,SAAA,CAAU,IAAI,CAAA;AAAA,QAC5F,CAAA;AAAA,QACA,OAAA,EAAS,MAAA;AAAA,QACT,MAAA,EAAQ,CAAC,CAAA,KAAM;AACb,UAAA,IAAI,CAAC,EAAE,aAAA,IAAiB,CAAC,EAAE,aAAA,CAAc,QAAA,CAAS,EAAE,aAAqB,CAAA;AACvE,YAAA,SAAA,CAAU,KAAK,CAAA;AAAA,QACnB,CAAA;AAAA,QAGA,8BAAC,eAAA,EAAA,EACE,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AACnB,UAAA,MAAM,KAAA,GAAQ,IAAI,CAAA,GAAI,CAAA;AACtB,UAAA,IAAI,SAAS,KAAA,GAAQ,GAAA;AACrB,UAAA,IAAI,QAAA,EAAU;AAEZ,YAAA,MAAA,GAAS,CAAA;AACT,YAAA,KAAA,IAAS,CAAA,GAAI,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK,MAAA,IAAA,CAAW,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA,CAAE,EAAE,KAAK,CAAA,IAAK,GAAA;AAAA,UAC1E;AACA,UAAA,uBACE,GAAA;AAAA,YAAC,SAAA;AAAA,YAAA;AAAA,cAEC,CAAA;AAAA,cACA,KAAA,EAAO,WAAW,CAAA,GAAI,KAAA;AAAA,cACtB,MAAA;AAAA,cACA,MAAA,EAAQ,CAAC,QAAA,IAAY,KAAA,IAAS,OAAA;AAAA,cAC9B,MAAA,EAAQ,CAAC,QAAA,IAAY,KAAA,GAAQ,CAAA;AAAA,cAC7B,aAAa,CAAC,QAAA,IAAY,KAAA,GAAQ,CAAA,IAAK,SAAS,MAAA,GAAS,IAAA;AAAA,cACzD;AAAA,aAAA;AAAA,YAPK,CAAA,CAAE;AAAA,WAQT;AAAA,QAEJ,CAAC,CAAA,EACH;AAAA;AAAA,KACF;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AACF;AAEA,IAAI,WAAA,GAAc,KAAA;AAClB,SAAS,eAAA,GAAkB;AACzB,EAAA,IAAI,WAAA,EAAa;AACjB,EAAA,WAAA,GAAc,IAAA;AACd,EAAA,MAAM,EAAA,GAAK,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AACvC,EAAA,EAAA,CAAG,YAAA,CAAa,mBAAmB,EAAE,CAAA;AACrC,EAAA,QAAA,CAAS,IAAA,CAAK,YAAY,EAAE,CAAA;AAC5B,EAAA,UAAA,CAAW,EAAE,CAAA,CAAE,MAAA,iBAAO,GAAA,CAAC,aAAU,CAAE,CAAA;AACrC;AACA,KAAA,CAAM,IAAA,GAAO,eAAA;AACb,IAAI,KAAA,CAAM,MAAA,CAAO,MAAA,EAAQ,eAAA,EAAgB;AAGlC,SAAS,OAAA,GAAgB;AAC9B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,eAAA,EAAgB;AAAA,EAClB,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,OAAO,IAAA;AACT","file":"chunk-NKGMQL6I.js","sourcesContent":["'use client';\n\n/* Toast - the React render layer (queue + clocks live in toast-store.ts). */\nimport * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { createRoot } from 'react-dom/client';\nimport { motion, AnimatePresence, animate, useMotionValue, type PanInfo } from 'motion/react';\nimport { UIMotion } from '../../tokens/motion-tokens';\nimport { Icon, type IconName } from '../icon/Icon';\nimport { UIToast, type ToastRecord, type ToastTone } from './toast-store';\n\nconst SM = UIMotion;\nconst store = UIToast;\nconst { useRef, useEffect, useLayoutEffect, useState, useSyncExternalStore } = React;\n\nconst VISIBLE = 3;\nconst RENDERED = 6;\nconst COLLAPSE_GRACE = 140;\nconst SWIPE_X = 64;\nconst SWIPE_V = 480;\n\n// expanded gap AND collapsed peek - read lazily (post-stylesheet), once\nlet GAP = 0;\nfunction stackGap() {\n if (GAP) return GAP;\n const cs = getComputedStyle(document.documentElement);\n const raw = cs.getPropertyValue('--space-3').trim();\n const n = parseFloat(raw) || 0;\n GAP = (raw.endsWith('rem') ? n * (parseFloat(cs.fontSize) || 16) : n) || 12;\n return GAP;\n}\n\nconst TONE_ICON: Record<string, IconName> = {\n success: 'check-circle',\n error: 'warning-circle',\n warning: 'warning',\n info: 'info',\n};\n\n/* useToneGesture - success glint, error headshake; the glint class is toggled with a reflow (remove - offsetWidth - add) to restart the one-shot. */\nfunction useToneGesture(\n tone: ToastTone,\n ref: React.RefObject<HTMLElement>,\n x: ReturnType<typeof useMotionValue<number>>,\n) {\n const prevTone = useRef<ToastTone | null>(null);\n useEffect(() => {\n const prev = prevTone.current;\n prevTone.current = tone;\n if (tone === prev) return;\n if (tone === 'success') {\n const el = ref.current;\n el.classList.remove('glass-glint');\n void el.offsetWidth;\n el.classList.add('glass-glint');\n const id = setTimeout(() => el.classList.remove('glass-glint'), SM.dur.slow * 1000 + 80);\n return () => clearTimeout(id);\n }\n if (tone === 'error') {\n const fall = animate(x, [0, -7, 5, -2, 0], {\n duration: SM.dur.slow,\n ease: SM.ease.standard,\n delay: SM.dur.base,\n });\n return () => fall.stop();\n }\n }, [tone]);\n}\n\nfunction ToastItem({\n t,\n depth,\n offset,\n hidden,\n behind,\n frameHeight,\n onHeight,\n}: {\n t: ToastRecord;\n depth: number;\n offset: number;\n hidden: boolean;\n behind: boolean;\n frameHeight: number | null;\n onHeight: (id: string, h: number) => void;\n}) {\n const ref = useRef<HTMLLIElement>(null);\n const x = useMotionValue(0); // swipe travel - ours, so dismissal can finish it\n useToneGesture(t.tone, ref, x);\n\n // report the CONTENT height (firstChild - the li's own height is animated, so it'd read mid-tween)\n useLayoutEffect(() => {\n if (ref.current && ref.current.firstElementChild)\n onHeight(t.id, (ref.current.firstElementChild as HTMLElement).offsetHeight);\n });\n\n const swipe = (_e: PointerEvent | MouseEvent | TouchEvent, info: PanInfo) => {\n if (info.offset.x > SWIPE_X || info.velocity.x > SWIPE_V) {\n // fling out the right edge, THEN remove - the exit fade plays where it landed, no snap-back\n animate(x, 420, { duration: SM.dur.fast, ease: SM.ease.exit }).then(() =>\n store.dismiss(t.id),\n );\n }\n };\n\n return (\n <motion.li\n ref={ref}\n className=\"toast glass\"\n data-tone={t.tone}\n data-behind={behind ? '' : undefined}\n role={t.tone === 'error' ? 'alert' : 'status'}\n aria-atomic=\"true\"\n style={{ x }}\n initial={{ opacity: 0, y: 24, scale: 0.97 }}\n animate={{\n opacity: hidden ? 0 : 1,\n y: -offset,\n scale: 1 - depth * 0.05,\n /* behind-cards adopt the front card's frame height (content faded) so a short card never drowns behind a tall one */\n height: frameHeight || 'auto',\n pointerEvents: hidden ? 'none' : 'auto',\n }}\n exit={{ opacity: 0, scale: 0.96, transition: { duration: SM.dur.fast, ease: SM.ease.exit } }}\n transition={{ y: SM.t.settle, scale: SM.t.settle, height: SM.t.settle, opacity: SM.t.enter }}\n drag={t.dismissible ? 'x' : false}\n dragConstraints={{ left: 0, right: 0 }}\n dragElastic={{ left: 0.04, right: 0.9 }}\n dragMomentum={false}\n onDragEnd={swipe}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && t.dismissible) store.dismiss(t.id);\n }}\n >\n {t.node ? (\n <div className=\"toast__custom\">{t.node as React.ReactNode}</div>\n ) : (\n <ToastBody t={t} />\n )}\n </motion.li>\n );\n}\n\nfunction ToastBody({ t }: { t: ToastRecord }) {\n return (\n <div className=\"toast__inner\">\n {(t.tone !== 'default' || isFinite(t.duration)) && (\n <span className=\"toast__icon\">\n {t.tone !== 'default' && (\n /* keyed remount (not nested AnimatePresence): old glyph cuts, new springs in */\n <motion.span\n key={t.tone}\n className=\"toast__icon-glyph\"\n initial={{ scale: 0.5, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{ scale: SM.t.settle, opacity: SM.t.enter }}\n >\n {t.tone === 'loading' ? (\n <span className=\"toast__spinner\" aria-hidden=\"true\"></span>\n ) : (\n <Icon name={TONE_ICON[t.tone]} weight=\"fill\" />\n )}\n </motion.span>\n )}\n {isFinite(t.duration) && (\n /* the ring - keyed to the timer so a restart re-fills it; pathLength=1 makes dashoffset a fraction */\n <svg\n key={'ring-' + t.timerKey}\n className=\"toast__ring\"\n viewBox=\"0 0 36 36\"\n aria-hidden=\"true\"\n >\n <circle className=\"toast__ring-track\" cx=\"18\" cy=\"18\" r=\"16.5\"></circle>\n <circle\n className=\"toast__ring-arc\"\n cx=\"18\"\n cy=\"18\"\n r=\"16.5\"\n pathLength={1}\n style={{ animationDuration: t.duration + 'ms' }}\n ></circle>\n </svg>\n )}\n </span>\n )}\n <motion.div\n key={String(t.message) + '-' + String(t.description)}\n className=\"toast__text\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={SM.t.enter}\n >\n <p className=\"toast__message\">{t.message}</p>\n {t.description != null && <p className=\"toast__desc\">{t.description}</p>}\n </motion.div>\n {t.count > 1 && (\n <motion.span\n key={t.count}\n className=\"toast__count\"\n initial={{ scale: 0.6 }}\n animate={{ scale: 1 }}\n transition={SM.t.settle}\n >\n ×{t.count}\n </motion.span>\n )}\n {t.action && (\n <button\n type=\"button\"\n className=\"btn btn--secondary btn--sm toast__action\"\n onClick={() => {\n if (t.action.onClick) t.action.onClick();\n store.dismiss(t.id);\n }}\n >\n {t.action.label}\n </button>\n )}\n {t.dismissible && (\n <button\n type=\"button\"\n className=\"toast__close\"\n aria-label=\"Dismiss\"\n onClick={() => store.dismiss(t.id)}\n >\n <Icon name=\"close\" size=\"sm\" />\n </button>\n )}\n </div>\n );\n}\n\nfunction ToastHost() {\n const { toasts, paused, expanded } = useSyncExternalStore(store.subscribe, store.get);\n const [heights, setHeights] = useState<Record<string, number>>({});\n const collapseTimer = useRef<ReturnType<typeof setTimeout> | 0>(0);\n const hovering = useRef(false);\n\n const onHeight = (id: string, h: number) =>\n setHeights((prev) => (prev[id] === h ? prev : { ...prev, [id]: h }));\n\n // hold = fan open + freeze clocks; release = graced fold + resume\n const onHold = () => {\n hovering.current = true;\n clearTimeout(collapseTimer.current);\n store.setExpanded(true);\n store.pause();\n };\n const onRelease = (graced: boolean) => {\n hovering.current = false;\n clearTimeout(collapseTimer.current);\n collapseTimer.current = setTimeout(\n () => {\n store.setExpanded(false);\n store.resume();\n },\n graced ? COLLAPSE_GRACE : 0,\n );\n };\n\n // tab hidden - freeze clocks, visible - resume (visibility, not window focus: an embedded preview blurs on outside clicks).\n useEffect(() => {\n const onVis = () => {\n if (document.hidden) store.pause();\n else if (!hovering.current) store.resume();\n };\n document.addEventListener('visibilitychange', onVis);\n return () => document.removeEventListener('visibilitychange', onVis);\n }, []);\n\n // safety net: last card removed under the cursor fires no pointerout, so release here\n useEffect(() => {\n if (toasts.length === 0) {\n hovering.current = false;\n clearTimeout(collapseTimer.current);\n store.setExpanded(false);\n store.resume();\n }\n }, [toasts.length]);\n\n const slice = toasts.slice(-RENDERED);\n const n = slice.length;\n const frontH = n ? heights[slice[n - 1].id] || 0 : 0;\n const gap = stackGap();\n\n return createPortal(\n <ol\n className={'toast-viewport' + (paused ? ' is-paused' : '')}\n aria-label=\"Notifications\"\n onPointerOver={(e) => {\n if (e.pointerType !== 'touch') onHold();\n }}\n onPointerOut={(e) => {\n if (!e.relatedTarget || !e.currentTarget.contains(e.relatedTarget as Node)) onRelease(true);\n }}\n onFocus={onHold}\n onBlur={(e) => {\n if (!e.relatedTarget || !e.currentTarget.contains(e.relatedTarget as Node))\n onRelease(false);\n }}\n >\n {/* initial stays true - the host mounts with the first toast, so initial={false} would skip its entrance */}\n <AnimatePresence>\n {slice.map((t, i) => {\n const depth = n - 1 - i; // newest = 0, at the front\n let offset = depth * gap; // collapsed: peek per depth\n if (expanded) {\n // expanded: real heights\n offset = 0;\n for (let j = i + 1; j < n; j++) offset += (heights[slice[j].id] || 0) + gap;\n }\n return (\n <ToastItem\n key={t.id}\n t={t}\n depth={expanded ? 0 : depth}\n offset={offset}\n hidden={!expanded && depth >= VISIBLE}\n behind={!expanded && depth > 0}\n frameHeight={!expanded && depth > 0 && frontH ? frontH : null}\n onHeight={onHeight}\n />\n );\n })}\n </AnimatePresence>\n </ol>,\n document.body,\n );\n}\n\nlet hostMounted = false;\nfunction ensureToastHost() {\n if (hostMounted) return;\n hostMounted = true;\n const el = document.createElement('div');\n el.setAttribute('data-toast-host', '');\n document.body.appendChild(el);\n createRoot(el).render(<ToastHost />);\n}\nstore.host = ensureToastHost;\nif (store.toasts.length) ensureToastHost(); // toasts fired before we loaded\n\n/* Toaster - mount once near the app root so this module loads client-side and the lazy host is registered (toast() also auto-mounts). */\nexport function Toaster(): null {\n useEffect(() => {\n ensureToastHost();\n }, []);\n return null;\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/toast/toast-store.ts"],"names":[],"mappings":"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","file":"chunk-PUPZ4HME.js","sourcesContent":["// toast-store - the Toast machinery: queue, clocks, coalescing, imperative API (zero React).\n\nexport type ToastTone = 'default' | 'success' | 'error' | 'warning' | 'info' | 'loading' | 'custom';\n\nexport interface ToastAction {\n label: string;\n onClick: () => void;\n}\n\nexport interface ToastOptions {\n id?: string | number;\n duration?: number;\n description?: string | null;\n action?: ToastAction | null;\n}\n\nexport interface ToastRecord {\n id: string;\n tone: ToastTone;\n message: string | null;\n description: string | null;\n action: ToastAction | null;\n duration: number;\n remaining: number;\n count: number;\n timerKey: number;\n node: unknown; // a React node, kept opaque so this module stays React-free\n dismissible: boolean;\n expiresAt?: number;\n}\n\nexport interface ToastSnapshot {\n toasts: ToastRecord[];\n paused: boolean;\n expanded: boolean;\n}\n\nconst DURATION: Record<string, number> = {\n default: 5000,\n success: 5000,\n info: 5000,\n warning: 8000,\n error: 8000,\n loading: Infinity, // sticky until updated/dismissed\n};\n\nlet uid = 0;\nconst timers = new Map<string, ReturnType<typeof setTimeout>>();\n\ninterface ToastStore {\n toasts: ToastRecord[];\n paused: boolean;\n expanded: boolean;\n host: null | (() => void);\n snap: ToastSnapshot;\n listeners: Set<() => void>;\n subscribe(l: () => void): () => void;\n get(): ToastSnapshot;\n emit(): void;\n add(t: ToastRecord): string;\n update(id: string, patch: Partial<ToastRecord>): string;\n dismiss(id?: string | null): void;\n schedule(t: ToastRecord): void;\n pause(): void;\n resume(): void;\n setExpanded(v: boolean): void;\n}\n\n/* Store - the queue; the API writes, the host renders. */\nconst store: ToastStore = {\n toasts: [],\n paused: false,\n expanded: false,\n host: null,\n snap: { toasts: [], paused: false, expanded: false },\n listeners: new Set(),\n subscribe(l) {\n store.listeners.add(l);\n return () => store.listeners.delete(l);\n },\n get: () => store.snap,\n emit() {\n store.snap = { toasts: store.toasts.slice(), paused: store.paused, expanded: store.expanded };\n store.listeners.forEach((l) => l());\n },\n\n add(t) {\n // coalesce: an identical visible toast becomes a xN counter instead of a duplicate\n const twin = store.toasts.find(\n (x) =>\n !x.node &&\n !t.node &&\n x.tone === t.tone &&\n x.message === t.message &&\n x.description === t.description,\n );\n if (twin) return store.update(twin.id, { count: twin.count + 1 });\n store.toasts.push(t);\n store.schedule(t);\n store.emit();\n return t.id;\n },\n\n update(id, patch) {\n const t = store.toasts.find((x) => x.id === id);\n if (!t) return id;\n Object.assign(t, patch);\n if ('tone' in patch || 'duration' in patch || 'count' in patch) {\n t.remaining = t.duration;\n t.timerKey++; // re-key the ring so it re-fills\n store.schedule(t);\n }\n store.emit();\n return id;\n },\n\n dismiss(id) {\n const gone = id == null ? store.toasts : store.toasts.filter((t) => t.id === id);\n gone.forEach((t) => {\n clearTimeout(timers.get(t.id));\n timers.delete(t.id);\n });\n store.toasts = id == null ? [] : store.toasts.filter((t) => t.id !== id);\n store.emit();\n },\n\n schedule(t) {\n clearTimeout(timers.get(t.id));\n timers.delete(t.id);\n if (!isFinite(t.duration)) return;\n if (store.paused) return; // resume() picks it up with t.remaining\n t.expiresAt = performance.now() + t.remaining;\n timers.set(\n t.id,\n setTimeout(() => store.dismiss(t.id), t.remaining),\n );\n },\n\n pause() {\n // freeze every clock, remember what's left\n if (store.paused) return;\n store.paused = true;\n store.toasts.forEach((t) => {\n if (timers.has(t.id)) {\n clearTimeout(timers.get(t.id));\n timers.delete(t.id);\n t.remaining = Math.max(0, (t.expiresAt ?? performance.now()) - performance.now());\n }\n });\n store.emit();\n },\n\n resume() {\n if (!store.paused) return;\n store.paused = false;\n store.toasts.forEach((t) => store.schedule(t));\n store.emit();\n },\n\n setExpanded(v) {\n if (v === store.expanded) return;\n store.expanded = v;\n store.emit();\n },\n};\n\nfunction make(tone: ToastTone, message: string | null, opts: ToastOptions = {}): string {\n if (store.host) store.host();\n const id = opts.id != null ? String(opts.id) : 'toast-' + ++uid;\n const duration = opts.duration != null ? opts.duration : DURATION[tone];\n if (store.toasts.some((t) => t.id === id)) {\n return store.update(id, {\n tone,\n message,\n duration,\n description: opts.description != null ? opts.description : null,\n action: opts.action != null ? opts.action : null,\n });\n }\n return store.add({\n id,\n tone,\n message,\n description: opts.description != null ? opts.description : null,\n action: opts.action != null ? opts.action : null,\n duration,\n remaining: duration,\n count: 1,\n timerKey: 0,\n node: null,\n dismissible: true,\n });\n}\n\ntype PromiseMsg<V> = string | ((v: V) => string);\nexport interface ToastPromiseMsgs<T> {\n loading?: string;\n success?: PromiseMsg<T>;\n error?: PromiseMsg<unknown>;\n}\n\nexport interface ToastApi {\n (message: string, opts?: ToastOptions): string;\n success(m: string, o?: ToastOptions): string;\n error(m: string, o?: ToastOptions): string;\n warning(m: string, o?: ToastOptions): string;\n info(m: string, o?: ToastOptions): string;\n loading(m: string, o?: ToastOptions): string;\n dismiss(id?: string | null): void;\n update(id: string, patch?: Partial<ToastRecord>): string;\n promise<T>(promise: Promise<T>, msgs?: ToastPromiseMsgs<T>): Promise<T>;\n custom(\n node: unknown,\n opts?: { id?: string | number; duration?: number; dismissible?: boolean },\n ): string;\n}\n\nconst toast = ((message: string, opts?: ToastOptions) =>\n make('default', message, opts)) as ToastApi;\ntoast.success = (m, o) => make('success', m, o);\ntoast.error = (m, o) => make('error', m, o);\ntoast.warning = (m, o) => make('warning', m, o);\ntoast.info = (m, o) => make('info', m, o);\ntoast.loading = (m, o) => make('loading', m, o);\ntoast.dismiss = (id) => store.dismiss(id);\n\ntoast.update = (id, patch = {}) => {\n // a tone change without an explicit duration adopts that tone's clock\n if (patch.tone && patch.duration == null) patch = { ...patch, duration: DURATION[patch.tone] };\n return store.update(id, patch);\n};\n\ntoast.promise = function <T>(promise: Promise<T>, msgs: ToastPromiseMsgs<T> = {}): Promise<T> {\n const id = make('loading', msgs.loading != null ? msgs.loading : 'Working...');\n const text = <V>(m: PromiseMsg<V> | undefined, fallback: string, v: V): string =>\n typeof m === 'function' ? (m as (x: V) => string)(v) : m != null ? m : fallback;\n promise.then(\n (v) => toast.update(id, { tone: 'success', message: text(msgs.success, 'Done', v) }),\n (e) =>\n toast.update(id, { tone: 'error', message: text(msgs.error, 'Something went wrong', e) }),\n );\n return promise;\n};\n\ntoast.custom = (node, opts = {}) => {\n if (store.host) store.host();\n const id = opts.id != null ? String(opts.id) : 'toast-' + ++uid;\n const duration = opts.duration != null ? opts.duration : Infinity;\n if (store.toasts.some((t) => t.id === id)) return store.update(id, { node });\n return store.add({\n id,\n tone: 'custom',\n node,\n message: null,\n description: null,\n action: null,\n duration,\n remaining: duration,\n count: 1,\n timerKey: 0,\n dismissible: opts.dismissible === true,\n });\n};\n\nexport { toast };\nexport const UIToast = store;\n"]}
|