sileo-solid 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,827 @@
1
+ function __insertCSS(code) {
2
+ if (!code || typeof document == 'undefined') return
3
+ let head = document.head || document.getElementsByTagName('head')[0]
4
+ let style = document.createElement('style')
5
+ style.type = 'text/css'
6
+ head.appendChild(style)
7
+ ;style.styleSheet ? (style.styleSheet.cssText = code) : style.appendChild(document.createTextNode(code))
8
+ }
9
+
10
+ Object.defineProperty(exports, '__esModule', { value: true });
11
+
12
+ var solidJs = require('solid-js');
13
+ require('motion');
14
+
15
+ __insertCSS(":root{--sileo-spring-easing:linear(\r\n\t\t0,\r\n\t\t0.002 0.6%,\r\n\t\t0.007 1.2%,\r\n\t\t0.015 1.8%,\r\n\t\t0.026 2.4%,\r\n\t\t0.041 3.1%,\r\n\t\t0.06 3.8%,\r\n\t\t0.108 5.3%,\r\n\t\t0.157 6.6%,\r\n\t\t0.214 8%,\r\n\t\t0.467 13.7%,\r\n\t\t0.577 16.3%,\r\n\t\t0.631 17.7%,\r\n\t\t0.682 19.1%,\r\n\t\t0.73 20.5%,\r\n\t\t0.771 21.8%,\r\n\t\t0.808 23.1%,\r\n\t\t0.844 24.5%,\r\n\t\t0.874 25.8%,\r\n\t\t0.903 27.2%,\r\n\t\t0.928 28.6%,\r\n\t\t0.952 30.1%,\r\n\t\t0.972 31.6%,\r\n\t\t0.988 33.1%,\r\n\t\t1.01 35.7%,\r\n\t\t1.025 38.5%,\r\n\t\t1.034 41.6%,\r\n\t\t1.038 45%,\r\n\t\t1.035 50.1%,\r\n\t\t1.012 64.2%,\r\n\t\t1.003 73%,\r\n\t\t0.999 83.7%,\r\n\t\t1\r\n\t);--sileo-duration:600ms;--sileo-height:40px;--sileo-width:350px;--sileo-state-success:oklch(0.723 0.219 142.136);--sileo-state-loading:oklch(0.556 0 0);--sileo-state-error:oklch(0.637 0.237 25.331);--sileo-state-warning:oklch(0.795 0.184 86.047);--sileo-state-info:oklch(0.685 0.169 237.323);--sileo-state-action:oklch(0.623 0.214 259.815)}[data-sileo-toast]{position:relative;cursor:pointer;pointer-events:auto;touch-action:none;border:0;background:0 0;padding:0;width:var(--sileo-width);height:var(--_h,var(--sileo-height));opacity:0;transform:translateZ(0) scale(.95);transform-origin:center;contain:layout style;overflow:visible}[data-sileo-toast][data-state=loading]{cursor:default}[data-sileo-toast][data-ready=true]{opacity:1;transform:translateZ(0) scale(1);transition:transform calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),opacity calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),margin-bottom calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),margin-top calc(var(--sileo-duration) * .66) var(--sileo-spring-easing),height var(--sileo-duration) var(--sileo-spring-easing)}[data-sileo-viewport][data-position^=top] [data-sileo-toast]:not([data-ready=true]){transform:translateY(-6px) scale(.95)}[data-sileo-viewport][data-position^=bottom] [data-sileo-toast]:not([data-ready=true]){transform:translateY(6px) scale(.95)}[data-sileo-toast][data-ready=true][data-exiting=true]{opacity:0;pointer-events:none}[data-sileo-viewport][data-position^=top] [data-sileo-toast][data-ready=true][data-exiting=true]{transform:translateY(-6px) scale(.95)}[data-sileo-viewport][data-position^=bottom] [data-sileo-toast][data-ready=true][data-exiting=true]{transform:translateY(6px) scale(.95)}[data-sileo-canvas]{position:absolute;left:0;right:0;pointer-events:none;transform:translateZ(0);contain:layout style;overflow:visible}[data-sileo-canvas][data-edge=top]{bottom:0;transform:scaleY(-1) translateZ(0)}[data-sileo-canvas][data-edge=bottom]{top:0}[data-sileo-svg]{overflow:visible}[data-sileo-header]{position:absolute;z-index:20;display:flex;align-items:center;padding:.5rem;height:var(--sileo-height);overflow:hidden;left:var(--_px,0);transform:var(--_ht);max-width:var(--_pw)}[data-sileo-toast][data-ready=true] [data-sileo-header]{transition:transform var(--sileo-duration) var(--sileo-spring-easing),left var(--sileo-duration) var(--sileo-spring-easing),max-width var(--sileo-duration) var(--sileo-spring-easing)}[data-sileo-header][data-edge=top]{bottom:0}[data-sileo-header][data-edge=bottom]{top:0}[data-sileo-header-stack]{position:relative;display:inline-flex;align-items:center;height:100%}[data-sileo-header-inner]{display:flex;align-items:center;gap:.5rem;white-space:nowrap;opacity:1;filter:blur(0px);transform:translateZ(0)}[data-sileo-header-inner][data-layer=current]{position:relative;z-index:1;animation:sileo-header-enter var(--sileo-duration) var(--sileo-spring-easing) both}[data-sileo-header-inner][data-exiting=true],[data-sileo-header-inner][data-layer=current]:not(:only-child){will-change:opacity,filter}[data-sileo-header-inner][data-layer=prev]{position:absolute;left:0;top:0;z-index:0;pointer-events:none}[data-sileo-header-inner][data-exiting=true]{animation:sileo-header-exit calc(var(--sileo-duration) * .7) ease forwards}[data-sileo-badge]{display:flex;height:24px;width:24px;flex-shrink:0;align-items:center;justify-content:center;padding:2px;box-sizing:border-box;border-radius:9999px;color:var(--sileo-tone,currentColor);background-color:var(--sileo-tone-bg,transparent)}[data-sileo-title]{font-size:.825rem;line-height:1rem;font-weight:500;text-transform:capitalize;color:var(--sileo-tone,currentColor)}:is([data-sileo-badge],[data-sileo-title],[data-sileo-button])[data-state]{--_c:var(--sileo-state-success)}:is(\r[data-sileo-badge],[data-sileo-title],[data-sileo-button]\r)[data-state=loading]{--_c:var(--sileo-state-loading)}:is(\r[data-sileo-badge],[data-sileo-title],[data-sileo-button]\r)[data-state=error]{--_c:var(--sileo-state-error)}:is(\r[data-sileo-badge],[data-sileo-title],[data-sileo-button]\r)[data-state=warning]{--_c:var(--sileo-state-warning)}:is(\r[data-sileo-badge],[data-sileo-title],[data-sileo-button]\r)[data-state=info]{--_c:var(--sileo-state-info)}:is(\r[data-sileo-badge],[data-sileo-title],[data-sileo-button]\r)[data-state=action]{--_c:var(--sileo-state-action)}:is([data-sileo-badge],[data-sileo-title])[data-state]{--sileo-tone:var(--_c);--sileo-tone-bg:color-mix(in oklch, var(--_c) 20%, transparent)}[data-sileo-content]{position:absolute;left:0;z-index:10;width:100%;pointer-events:none;opacity:var(--_co, 0)}[data-sileo-content]:not([data-visible=true]){content-visibility:hidden}[data-sileo-toast][data-ready=true] [data-sileo-content]{transition:opacity calc(var(--sileo-duration) * .08) ease calc(var(--sileo-duration) * .04)}[data-sileo-content][data-edge=top]{top:0}[data-sileo-content][data-edge=bottom]{top:var(--sileo-height)}[data-sileo-content][data-visible=true]{pointer-events:auto}[data-sileo-toast][data-ready=true] [data-sileo-content][data-visible=true]{transition:opacity calc(var(--sileo-duration) * .6) ease calc(var(--sileo-duration) * .3)}[data-sileo-description]{width:100%;text-align:left;padding:1rem;font-size:.875rem;line-height:1.25rem;contain:layout style paint;content-visibility:auto;color:rgba(0,0,0,.7)}[data-sileo-button]{display:flex;align-items:center;justify-content:center;height:1.75rem;padding:0 .625rem;margin-top:.75rem;border-radius:9999px;border:0;font-size:.75rem;font-weight:500;cursor:pointer;color:var(--sileo-btn-color,currentColor);background-color:var(--sileo-btn-bg,transparent);transition:background-color 150ms ease}[data-sileo-button]:hover{background-color:var(--sileo-btn-bg-hover,transparent)}[data-sileo-button][data-state]{--sileo-btn-color:var(--_c);--sileo-btn-bg:color-mix(in oklch, var(--_c) 15%, transparent);--sileo-btn-bg-hover:color-mix(in oklch, var(--_c) 25%, transparent)}[data-sileo-icon=spin]{animation:sileo-spin 1s linear infinite}@keyframes sileo-spin{to{transform:rotate(360deg)}}@keyframes sileo-header-enter{from{opacity:0;filter:blur(6px)}to{opacity:1;filter:blur(0px)}}@keyframes sileo-header-exit{from{opacity:1;filter:blur(0px)}to{opacity:0;filter:blur(6px)}}[data-sileo-viewport]{position:fixed;z-index:50;display:flex;gap:.75rem;padding:.75rem;pointer-events:none;max-width:calc(100vw - 1.5rem);contain:layout style}[data-sileo-viewport][data-position^=top] [data-sileo-toast]:not([data-ready=true]){margin-bottom:calc(-1 * (var(--sileo-height) + .75rem))}[data-sileo-viewport][data-position^=bottom] [data-sileo-toast]:not([data-ready=true]){margin-top:calc(-1 * (var(--sileo-height) + .75rem))}[data-sileo-viewport][data-position^=top]{top:0;flex-direction:column-reverse}[data-sileo-viewport][data-position^=bottom]{bottom:0;flex-direction:column}[data-sileo-viewport][data-position$=left]{left:0;align-items:flex-start}[data-sileo-viewport][data-position$=right]{right:0;align-items:flex-end}[data-sileo-viewport][data-position$=center]{left:50%;transform:translateX(-50%);align-items:center}@media (prefers-reduced-motion:no-preference){[data-sileo-toast][data-ready=true]:hover,[data-sileo-toast][data-ready=true][data-exiting=true]{will-change:transform,opacity,height}}@media (prefers-reduced-motion:reduce){[data-sileo-viewport],[data-sileo-viewport] *,[data-sileo-viewport] ::after,[data-sileo-viewport] ::before{animation-duration:0s;animation-iteration-count:1;transition-duration:0s}}[data-sileo-viewport][data-theme=dark] [data-sileo-description]{color:rgba(0,0,0,.7)}[data-sileo-viewport][data-theme=light] [data-sileo-description]{color:rgba(255,255,255,.5)}");
16
+
17
+ /* --------------------------------- Layout --------------------------------- */ const HEIGHT = 40;
18
+ const WIDTH = 350;
19
+ const DEFAULT_ROUNDNESS = 16;
20
+ /* --------------------------------- Timing --------------------------------- */ const DURATION_MS = 600;
21
+ const DEFAULT_TOAST_DURATION = 6000;
22
+ const EXIT_DURATION = DEFAULT_TOAST_DURATION * 0.1;
23
+ const AUTO_EXPAND_DELAY = DEFAULT_TOAST_DURATION * 0.025;
24
+ const AUTO_COLLAPSE_DELAY = DEFAULT_TOAST_DURATION - 2000;
25
+ /* --------------------------------- Render --------------------------------- */ const BLUR_RATIO = 0.5;
26
+ const MIN_EXPAND_RATIO = 2.25;
27
+ const SWAP_COLLAPSE_MS = 200;
28
+ const HEADER_EXIT_MS = DURATION_MS * 0.7;
29
+
30
+ const Icon = (props)=>{
31
+ const { title, children, ...rest } = props;
32
+ return /*#__PURE__*/ React.createElement("svg", {
33
+ ...rest,
34
+ xmlns: "http://www.w3.org/2000/svg",
35
+ width: "16",
36
+ height: "16",
37
+ viewBox: "0 0 24 24",
38
+ fill: "none",
39
+ stroke: "currentColor",
40
+ "stroke-width": "2",
41
+ "stroke-linecap": "round",
42
+ "stroke-linejoin": "round"
43
+ }, /*#__PURE__*/ React.createElement("title", null, title), children);
44
+ };
45
+ const ArrowRight = ()=>/*#__PURE__*/ React.createElement(Icon, {
46
+ title: "Arrow Right"
47
+ }, /*#__PURE__*/ React.createElement("path", {
48
+ d: "M5 12h14"
49
+ }), /*#__PURE__*/ React.createElement("path", {
50
+ d: "m12 5 7 7-7 7"
51
+ }));
52
+ const LifeBuoy = ()=>/*#__PURE__*/ React.createElement(Icon, {
53
+ title: "Life Buoy"
54
+ }, /*#__PURE__*/ React.createElement("circle", {
55
+ cx: "12",
56
+ cy: "12",
57
+ r: "10"
58
+ }), /*#__PURE__*/ React.createElement("path", {
59
+ d: "m4.93 4.93 4.24 4.24"
60
+ }), /*#__PURE__*/ React.createElement("path", {
61
+ d: "m14.83 9.17 4.24-4.24"
62
+ }), /*#__PURE__*/ React.createElement("path", {
63
+ d: "m14.83 14.83 4.24 4.24"
64
+ }), /*#__PURE__*/ React.createElement("path", {
65
+ d: "m9.17 14.83-4.24 4.24"
66
+ }), /*#__PURE__*/ React.createElement("circle", {
67
+ cx: "12",
68
+ cy: "12",
69
+ r: "4"
70
+ }));
71
+ const LoaderCircle = (props)=>/*#__PURE__*/ React.createElement(Icon, {
72
+ title: "Loader Circle",
73
+ ...props
74
+ }, /*#__PURE__*/ React.createElement("path", {
75
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
76
+ }));
77
+ const X = ()=>/*#__PURE__*/ React.createElement(Icon, {
78
+ title: "X"
79
+ }, /*#__PURE__*/ React.createElement("path", {
80
+ d: "M18 6 6 18"
81
+ }), /*#__PURE__*/ React.createElement("path", {
82
+ d: "m6 6 12 12"
83
+ }));
84
+ const CircleAlert = ()=>/*#__PURE__*/ React.createElement(Icon, {
85
+ title: "Circle Alert"
86
+ }, /*#__PURE__*/ React.createElement("circle", {
87
+ cx: "12",
88
+ cy: "12",
89
+ r: "10"
90
+ }), /*#__PURE__*/ React.createElement("line", {
91
+ x1: "12",
92
+ x2: "12",
93
+ y1: "8",
94
+ y2: "12"
95
+ }), /*#__PURE__*/ React.createElement("line", {
96
+ x1: "12",
97
+ x2: "12.01",
98
+ y1: "16",
99
+ y2: "16"
100
+ }));
101
+ const Check = ()=>/*#__PURE__*/ React.createElement(Icon, {
102
+ title: "Check"
103
+ }, /*#__PURE__*/ React.createElement("path", {
104
+ d: "M20 6 9 17l-5-5"
105
+ }));
106
+
107
+ const STATE_ICON = {
108
+ success: /*#__PURE__*/ React.createElement(Check, null),
109
+ loading: /*#__PURE__*/ React.createElement(LoaderCircle, {
110
+ "data-sileo-icon": "spin",
111
+ "aria-hidden": "true"
112
+ }),
113
+ error: /*#__PURE__*/ React.createElement(X, null),
114
+ warning: /*#__PURE__*/ React.createElement(CircleAlert, null),
115
+ info: /*#__PURE__*/ React.createElement(LifeBuoy, null),
116
+ action: /*#__PURE__*/ React.createElement(ArrowRight, null)
117
+ };
118
+ function GooeyDefs(props) {
119
+ return /*#__PURE__*/ React.createElement("defs", null, /*#__PURE__*/ React.createElement("filter", {
120
+ id: props.filterId,
121
+ x: "-20%",
122
+ y: "-20%",
123
+ width: "140%",
124
+ height: "140%",
125
+ "color-interpolation-filters": "sRGB"
126
+ }, /*#__PURE__*/ React.createElement("feGaussianBlur", {
127
+ in: "SourceGraphic",
128
+ stdDeviation: props.blur,
129
+ result: "blur"
130
+ }), /*#__PURE__*/ React.createElement("feColorMatrix", {
131
+ in: "blur",
132
+ type: "matrix",
133
+ values: "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10",
134
+ result: "goo"
135
+ }), /*#__PURE__*/ React.createElement("feComposite", {
136
+ in: "SourceGraphic",
137
+ in2: "goo",
138
+ operator: "atop"
139
+ })));
140
+ }
141
+ function Sileo(props) {
142
+ const state = ()=>props.state ?? "success";
143
+ const fill = ()=>props.fill ?? "#FFFFFF";
144
+ const next = solidJs.createMemo(()=>({
145
+ title: props.title,
146
+ description: props.description,
147
+ state: state(),
148
+ icon: props.icon,
149
+ styles: props.styles,
150
+ button: props.button,
151
+ fill: fill()
152
+ }));
153
+ const [view, setView] = solidJs.createSignal(next());
154
+ const [applied, setApplied] = solidJs.createSignal(props.refreshKey);
155
+ const [isExpanded, setIsExpanded] = solidJs.createSignal(false);
156
+ const [ready, setReady] = solidJs.createSignal(false);
157
+ const [pillWidth, setPillWidth] = solidJs.createSignal(0);
158
+ const [contentHeight, setContentHeight] = solidJs.createSignal(0);
159
+ const hasDesc = solidJs.createMemo(()=>Boolean(view().description) || Boolean(view().button));
160
+ const isLoading = solidJs.createMemo(()=>view().state === "loading");
161
+ const open = solidJs.createMemo(()=>hasDesc() && isExpanded() && !isLoading());
162
+ const allowExpand = solidJs.createMemo(()=>isLoading() ? false : props.canExpand ?? (!props.interruptKey || props.interruptKey === props.id));
163
+ const headerKey = solidJs.createMemo(()=>`${view().state}-${view().title}`);
164
+ const filterId = `sileo-gooey-${props.id}`;
165
+ const resolvedRoundness = solidJs.createMemo(()=>Math.max(0, props.roundness ?? DEFAULT_ROUNDNESS));
166
+ const blur = solidJs.createMemo(()=>resolvedRoundness() * BLUR_RATIO);
167
+ let contentRef;
168
+ const headerExitRef = {
169
+ current: null
170
+ };
171
+ const autoExpandRef = {
172
+ current: null
173
+ };
174
+ const autoCollapseRef = {
175
+ current: null
176
+ };
177
+ const swapTimerRef = {
178
+ current: null
179
+ };
180
+ const lastRefreshKeyRef = {
181
+ current: props.refreshKey
182
+ };
183
+ const pendingRef = {
184
+ current: null
185
+ };
186
+ const [headerCurrentKey, setHeaderCurrentKey] = solidJs.createSignal(headerKey());
187
+ const [headerCurrentView, setHeaderCurrentView] = solidJs.createSignal(view());
188
+ const [headerPrevKey, setHeaderPrevKey] = solidJs.createSignal(null);
189
+ const [headerPrevView, setHeaderPrevView] = solidJs.createSignal(null);
190
+ let innerRef;
191
+ let headerEl;
192
+ let pillRaf = 0;
193
+ solidJs.createEffect(()=>{
194
+ headerKey();
195
+ return;
196
+ });
197
+ solidJs.onCleanup(()=>{
198
+ cancelAnimationFrame(pillRaf);
199
+ });
200
+ solidJs.createEffect(()=>{
201
+ if (!hasDesc()) {
202
+ setContentHeight(0);
203
+ return;
204
+ }
205
+ return;
206
+ });
207
+ solidJs.onMount(()=>{
208
+ const raf = requestAnimationFrame(()=>setReady(true));
209
+ return ()=>cancelAnimationFrame(raf);
210
+ });
211
+ solidJs.createEffect(()=>{
212
+ const hk = headerKey();
213
+ const v = view();
214
+ if (headerCurrentKey() === hk) {
215
+ if (headerCurrentView() === v) return;
216
+ setHeaderCurrentView(v);
217
+ } else {
218
+ setHeaderPrevKey(headerCurrentKey());
219
+ setHeaderPrevView(headerCurrentView());
220
+ setHeaderCurrentKey(hk);
221
+ setHeaderCurrentView(v);
222
+ }
223
+ });
224
+ solidJs.createEffect(()=>{
225
+ if (!headerPrevKey()) return;
226
+ if (headerExitRef.current) clearTimeout(headerExitRef.current);
227
+ headerExitRef.current = window.setTimeout(()=>{
228
+ headerExitRef.current = null;
229
+ setHeaderPrevKey(null);
230
+ setHeaderPrevView(null);
231
+ }, HEADER_EXIT_MS);
232
+ return ()=>{
233
+ if (headerExitRef.current) {
234
+ clearTimeout(headerExitRef.current);
235
+ headerExitRef.current = null;
236
+ }
237
+ };
238
+ });
239
+ solidJs.createEffect(()=>{
240
+ const f = props.fill;
241
+ if (f !== undefined && view().fill !== f) {
242
+ setView((prev)=>({
243
+ ...prev,
244
+ fill: f
245
+ }));
246
+ }
247
+ });
248
+ solidJs.createEffect(()=>{
249
+ const rk = props.refreshKey;
250
+ const n = next();
251
+ if (rk === undefined) {
252
+ setView(n);
253
+ setApplied(undefined);
254
+ pendingRef.current = null;
255
+ lastRefreshKeyRef.current = rk;
256
+ return;
257
+ }
258
+ if (lastRefreshKeyRef.current === rk) return;
259
+ lastRefreshKeyRef.current = rk;
260
+ if (swapTimerRef.current) {
261
+ clearTimeout(swapTimerRef.current);
262
+ swapTimerRef.current = null;
263
+ }
264
+ if (open()) {
265
+ pendingRef.current = {
266
+ key: rk,
267
+ payload: n
268
+ };
269
+ setIsExpanded(false);
270
+ swapTimerRef.current = window.setTimeout(()=>{
271
+ swapTimerRef.current = null;
272
+ const pending = pendingRef.current;
273
+ if (!pending) return;
274
+ setView(pending.payload);
275
+ setApplied(pending.key);
276
+ pendingRef.current = null;
277
+ }, SWAP_COLLAPSE_MS);
278
+ } else {
279
+ pendingRef.current = null;
280
+ setView(n);
281
+ setApplied(rk);
282
+ }
283
+ });
284
+ solidJs.createEffect(()=>{
285
+ const hd = hasDesc();
286
+ if (!hd) return;
287
+ if (autoExpandRef.current) clearTimeout(autoExpandRef.current);
288
+ if (autoCollapseRef.current) clearTimeout(autoCollapseRef.current);
289
+ if (props.exiting || !allowExpand()) {
290
+ setIsExpanded(false);
291
+ return;
292
+ }
293
+ if (props.autoExpandDelayMs == null && props.autoCollapseDelayMs == null) return;
294
+ const expandDelay = props.autoExpandDelayMs ?? 0;
295
+ const collapseDelay = props.autoCollapseDelayMs ?? 0;
296
+ if (expandDelay > 0) {
297
+ autoExpandRef.current = window.setTimeout(()=>setIsExpanded(true), expandDelay);
298
+ } else {
299
+ setIsExpanded(true);
300
+ }
301
+ if (collapseDelay > 0) {
302
+ autoCollapseRef.current = window.setTimeout(()=>setIsExpanded(false), collapseDelay);
303
+ }
304
+ return ()=>{
305
+ if (autoExpandRef.current) clearTimeout(autoExpandRef.current);
306
+ if (autoCollapseRef.current) clearTimeout(autoCollapseRef.current);
307
+ };
308
+ });
309
+ const minExpanded = HEIGHT * MIN_EXPAND_RATIO;
310
+ const rawExpanded = solidJs.createMemo(()=>hasDesc() ? Math.max(minExpanded, HEIGHT + contentHeight()) : minExpanded);
311
+ const frozenExpandedRef = {
312
+ current: minExpanded
313
+ };
314
+ solidJs.createEffect(()=>{
315
+ if (open()) {
316
+ frozenExpandedRef.current = rawExpanded();
317
+ }
318
+ });
319
+ const expanded = open() ? rawExpanded() : frozenExpandedRef.current;
320
+ const svgHeight = hasDesc() ? Math.max(expanded, minExpanded) : HEIGHT;
321
+ const resolvedPillWidth = solidJs.createMemo(()=>Math.max(pillWidth() || HEIGHT, HEIGHT));
322
+ HEIGHT + blur() * 3;
323
+ const pillX = solidJs.createMemo(()=>props.position === "right" ? WIDTH - resolvedPillWidth() : props.position === "center" ? (WIDTH - resolvedPillWidth()) / 2 : 0);
324
+ const viewBox = `0 0 ${WIDTH} ${svgHeight}`;
325
+ const canvasStyle = solidJs.createMemo(()=>({
326
+ filter: `url(#${filterId})`
327
+ }));
328
+ const rootStyle = solidJs.createMemo(()=>({
329
+ "--_h": `${open() ? expanded : HEIGHT}px`,
330
+ "--_pw": `${resolvedPillWidth()}px`,
331
+ "--_px": `${pillX()}px`,
332
+ "--_ht": `translateY(${open() ? props.expand === "bottom" ? 3 : -3 : 0}px) scale(${open() ? 0.9 : 1})`,
333
+ "--_co": `${open() ? 1 : 0}`
334
+ }));
335
+ const handleEnter = (e)=>{
336
+ props.onMouseEnter?.(e);
337
+ if (hasDesc()) setIsExpanded(true);
338
+ };
339
+ const handleLeave = (e)=>{
340
+ props.onMouseLeave?.(e);
341
+ setIsExpanded(false);
342
+ };
343
+ const handleTransitionEnd = (e)=>{
344
+ if (e.propertyName !== "height" && e.propertyName !== "transform") return;
345
+ if (open()) return;
346
+ const pending = pendingRef.current;
347
+ if (!pending) return;
348
+ if (swapTimerRef.current) {
349
+ clearTimeout(swapTimerRef.current);
350
+ swapTimerRef.current = null;
351
+ }
352
+ setView(pending.payload);
353
+ setApplied(pending.key);
354
+ pendingRef.current = null;
355
+ };
356
+ let buttonRef;
357
+ ({
358
+ current: props.onDismiss
359
+ });
360
+ props.onDismiss;
361
+ const handleButtonClick = (e)=>{
362
+ e.preventDefault();
363
+ e.stopPropagation();
364
+ view().button?.onClick();
365
+ };
366
+ const handlePointerDown = (e)=>{
367
+ if (props.exiting || !props.onDismiss) return;
368
+ const target = e.target;
369
+ if (target.closest("[data-sileo-button]")) return;
370
+ e.clientY;
371
+ e.currentTarget.setPointerCapture(e.pointerId);
372
+ };
373
+ let pillRef;
374
+ let bodyRef;
375
+ solidJs.createEffect(()=>{
376
+ return;
377
+ });
378
+ solidJs.createEffect(()=>{
379
+ return;
380
+ });
381
+ const curView = headerCurrentView();
382
+ const prevView = headerPrevView();
383
+ return /*#__PURE__*/ React.createElement("button", {
384
+ ref: buttonRef,
385
+ type: "button",
386
+ "data-sileo-toast": true,
387
+ "data-ready": ready(),
388
+ "data-expanded": open(),
389
+ "data-exiting": props.exiting,
390
+ "data-edge": props.expand,
391
+ "data-position": props.position,
392
+ "data-state": view().state,
393
+ class: props.class,
394
+ style: rootStyle(),
395
+ onMouseEnter: handleEnter,
396
+ onMouseLeave: handleLeave,
397
+ onTransitionEnd: handleTransitionEnd,
398
+ onPointerDown: handlePointerDown
399
+ }, /*#__PURE__*/ React.createElement("div", {
400
+ "data-sileo-canvas": true,
401
+ "data-edge": props.expand,
402
+ style: canvasStyle()
403
+ }, /*#__PURE__*/ React.createElement("svg", {
404
+ "data-sileo-svg": true,
405
+ width: WIDTH,
406
+ height: svgHeight,
407
+ viewBox: viewBox
408
+ }, /*#__PURE__*/ React.createElement("title", null, "Sileo Notification"), /*#__PURE__*/ React.createElement(GooeyDefs, {
409
+ filterId: filterId,
410
+ blur: blur()
411
+ }), /*#__PURE__*/ React.createElement("rect", {
412
+ ref: pillRef,
413
+ "data-sileo-pill": true,
414
+ rx: resolvedRoundness(),
415
+ ry: resolvedRoundness(),
416
+ fill: view().fill
417
+ }), /*#__PURE__*/ React.createElement("rect", {
418
+ ref: bodyRef,
419
+ "data-sileo-body": true,
420
+ y: HEIGHT,
421
+ width: WIDTH,
422
+ rx: resolvedRoundness(),
423
+ ry: resolvedRoundness(),
424
+ fill: view().fill
425
+ }))), /*#__PURE__*/ React.createElement("div", {
426
+ ref: headerEl,
427
+ "data-sileo-header": true,
428
+ "data-edge": props.expand
429
+ }, /*#__PURE__*/ React.createElement("div", {
430
+ "data-sileo-header-stack": true
431
+ }, /*#__PURE__*/ React.createElement("div", {
432
+ ref: innerRef,
433
+ "data-sileo-header-inner": true,
434
+ "data-layer": "current"
435
+ }, /*#__PURE__*/ React.createElement("div", {
436
+ "data-sileo-badge": true,
437
+ "data-state": curView.state,
438
+ class: curView.styles?.badge
439
+ }, curView.icon ?? STATE_ICON[curView.state]), /*#__PURE__*/ React.createElement("span", {
440
+ "data-sileo-title": true,
441
+ "data-state": curView.state,
442
+ class: curView.styles?.title
443
+ }, curView.title)), /*#__PURE__*/ React.createElement(solidJs.Show, {
444
+ when: prevView
445
+ }, (pv)=>/*#__PURE__*/ React.createElement("div", {
446
+ "data-sileo-header-inner": true,
447
+ "data-layer": "prev",
448
+ "data-exiting": "true"
449
+ }, /*#__PURE__*/ React.createElement("div", {
450
+ "data-sileo-badge": true,
451
+ "data-state": pv().state,
452
+ class: pv().styles?.badge
453
+ }, pv().icon ?? STATE_ICON[pv().state]), /*#__PURE__*/ React.createElement("span", {
454
+ "data-sileo-title": true,
455
+ "data-state": pv().state,
456
+ class: pv().styles?.title
457
+ }, pv().title))))), hasDesc() && /*#__PURE__*/ React.createElement("div", {
458
+ "data-sileo-content": true,
459
+ "data-edge": props.expand,
460
+ "data-visible": open()
461
+ }, /*#__PURE__*/ React.createElement("div", {
462
+ ref: contentRef,
463
+ "data-sileo-description": true,
464
+ class: view().styles?.description
465
+ }, view().description, view().button && /*#__PURE__*/ React.createElement("a", {
466
+ href: "#",
467
+ type: "button",
468
+ "data-sileo-button": true,
469
+ "data-state": view().state,
470
+ class: view().styles?.button,
471
+ onClick: handleButtonClick
472
+ }, view().button?.title))));
473
+ }
474
+
475
+ const pillAlign = (pos)=>pos.includes("right") ? "right" : pos.includes("center") ? "center" : "left";
476
+ const expandDir = (pos)=>pos.startsWith("top") ? "bottom" : "top";
477
+ const store = {
478
+ toasts: [],
479
+ listeners: new Set(),
480
+ position: "top-right",
481
+ options: undefined,
482
+ emit () {
483
+ for (const fn of this.listeners)fn(this.toasts);
484
+ },
485
+ update (fn) {
486
+ this.toasts = fn(this.toasts);
487
+ this.emit();
488
+ }
489
+ };
490
+ let idCounter = 0;
491
+ const generateId = ()=>`${++idCounter}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
492
+ const timeoutKey = (t)=>`${t.id}:${t.instanceId}`;
493
+ /* ------------------------------- Toast API -------------------------------- */ const dismissToast = (id)=>{
494
+ const item = store.toasts.find((t)=>t.id === id);
495
+ if (!item || item.exiting) return;
496
+ store.update((prev)=>prev.map((t)=>t.id === id ? {
497
+ ...t,
498
+ exiting: true
499
+ } : t));
500
+ setTimeout(()=>store.update((prev)=>prev.filter((t)=>t.id !== id)), EXIT_DURATION);
501
+ };
502
+ const resolveAutopilot = (opts, duration)=>{
503
+ if (opts.autopilot === false || !duration || duration <= 0) return {};
504
+ const cfg = typeof opts.autopilot === "object" ? opts.autopilot : undefined;
505
+ const clamp = (v)=>Math.min(duration, Math.max(0, v));
506
+ return {
507
+ expandDelayMs: clamp(cfg?.expand ?? AUTO_EXPAND_DELAY),
508
+ collapseDelayMs: clamp(cfg?.collapse ?? AUTO_COLLAPSE_DELAY)
509
+ };
510
+ };
511
+ const mergeOptions = (options)=>({
512
+ ...store.options,
513
+ ...options,
514
+ styles: {
515
+ ...store.options?.styles,
516
+ ...options.styles
517
+ }
518
+ });
519
+ const buildSileoItem = (merged, id, fallbackPosition)=>{
520
+ const duration = merged.duration ?? DEFAULT_TOAST_DURATION;
521
+ const auto = resolveAutopilot(merged, duration);
522
+ return {
523
+ ...merged,
524
+ id,
525
+ instanceId: generateId(),
526
+ position: merged.position ?? fallbackPosition ?? store.position,
527
+ autoExpandDelayMs: auto.expandDelayMs,
528
+ autoCollapseDelayMs: auto.collapseDelayMs
529
+ };
530
+ };
531
+ const createToast = (options)=>{
532
+ const live = store.toasts.filter((t)=>!t.exiting);
533
+ const merged = mergeOptions(options);
534
+ const id = merged.id ?? "sileo-default";
535
+ const prev = live.find((t)=>t.id === id);
536
+ const item = buildSileoItem(merged, id, prev?.position);
537
+ if (prev) {
538
+ store.update((p)=>p.map((t)=>t.id === id ? item : t));
539
+ } else {
540
+ store.update((p)=>[
541
+ ...p.filter((t)=>t.id !== id),
542
+ item
543
+ ]);
544
+ }
545
+ return {
546
+ id,
547
+ duration: merged.duration ?? DEFAULT_TOAST_DURATION
548
+ };
549
+ };
550
+ const updateToast = (id, options)=>{
551
+ const existing = store.toasts.find((t)=>t.id === id);
552
+ if (!existing) return;
553
+ const item = buildSileoItem(mergeOptions(options), id, existing.position);
554
+ store.update((prev)=>prev.map((t)=>t.id === id ? item : t));
555
+ };
556
+ const sileo = {
557
+ show: (opts)=>createToast({
558
+ ...opts,
559
+ state: opts.type
560
+ }).id,
561
+ success: (opts)=>createToast({
562
+ ...opts,
563
+ state: "success"
564
+ }).id,
565
+ error: (opts)=>createToast({
566
+ ...opts,
567
+ state: "error"
568
+ }).id,
569
+ warning: (opts)=>createToast({
570
+ ...opts,
571
+ state: "warning"
572
+ }).id,
573
+ info: (opts)=>createToast({
574
+ ...opts,
575
+ state: "info"
576
+ }).id,
577
+ action: (opts)=>createToast({
578
+ ...opts,
579
+ state: "action"
580
+ }).id,
581
+ promise: (promise, opts)=>{
582
+ const { id } = createToast({
583
+ ...opts.loading,
584
+ state: "loading",
585
+ duration: null,
586
+ position: opts.position
587
+ });
588
+ const p = typeof promise === "function" ? promise() : promise;
589
+ p.then((data)=>{
590
+ if (opts.action) {
591
+ const actionOpts = typeof opts.action === "function" ? opts.action(data) : opts.action;
592
+ updateToast(id, {
593
+ ...actionOpts,
594
+ state: "action",
595
+ id
596
+ });
597
+ } else {
598
+ const successOpts = typeof opts.success === "function" ? opts.success(data) : opts.success;
599
+ updateToast(id, {
600
+ ...successOpts,
601
+ state: "success",
602
+ id
603
+ });
604
+ }
605
+ }).catch((err)=>{
606
+ const errorOpts = typeof opts.error === "function" ? opts.error(err) : opts.error;
607
+ updateToast(id, {
608
+ ...errorOpts,
609
+ state: "error",
610
+ id
611
+ });
612
+ });
613
+ return p;
614
+ },
615
+ dismiss: dismissToast,
616
+ clear: (position)=>store.update((prev)=>position ? prev.filter((t)=>t.position !== position) : [])
617
+ };
618
+ /* ------------------------------ Toaster Component ------------------------- */ const THEME_FILLS = {
619
+ light: "#1a1a1a",
620
+ dark: "#f2f2f2"
621
+ };
622
+ function useResolvedTheme(theme) {
623
+ const getInitialTheme = ()=>{
624
+ if (theme === "light" || theme === "dark") return theme;
625
+ if (typeof window === "undefined") return "light";
626
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
627
+ };
628
+ const [resolved, setResolved] = solidJs.createSignal(getInitialTheme());
629
+ solidJs.createEffect(()=>{
630
+ const t = theme;
631
+ if (t === "light" || t === "dark") {
632
+ setResolved(t);
633
+ return;
634
+ }
635
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
636
+ const handler = (e)=>setResolved(e.matches ? "dark" : "light");
637
+ setResolved(mq.matches ? "dark" : "light");
638
+ mq.addEventListener("change", handler);
639
+ return ()=>mq.removeEventListener("change", handler);
640
+ });
641
+ return resolved;
642
+ }
643
+ function Toaster(props) {
644
+ const resolvedTheme = useResolvedTheme(props.theme);
645
+ const [toasts, setToasts] = solidJs.createSignal(store.toasts);
646
+ const [activeId, setActiveId] = solidJs.createSignal();
647
+ const hoverRef = {
648
+ current: false
649
+ };
650
+ const timersRef = {
651
+ current: new Map()
652
+ };
653
+ const listRef = {
654
+ current: store.toasts
655
+ };
656
+ const latestRef = {
657
+ current: undefined
658
+ };
659
+ const handlersCache = {
660
+ current: new Map()
661
+ };
662
+ solidJs.createEffect(()=>{
663
+ store.position = props.position ?? "top-right";
664
+ store.options = props.options;
665
+ });
666
+ const clearAllTimers = ()=>{
667
+ for (const t of timersRef.current.values())clearTimeout(t);
668
+ timersRef.current.clear();
669
+ };
670
+ const schedule = (items)=>{
671
+ if (hoverRef.current) return;
672
+ for (const item of items){
673
+ if (item.exiting) continue;
674
+ const key = timeoutKey(item);
675
+ if (timersRef.current.has(key)) continue;
676
+ if (item.duration === null) continue;
677
+ const dur = item.duration ?? DEFAULT_TOAST_DURATION;
678
+ if (dur <= 0) continue;
679
+ timersRef.current.set(key, window.setTimeout(()=>dismissToast(item.id), dur));
680
+ }
681
+ };
682
+ solidJs.createEffect(()=>{
683
+ const listener = (next)=>setToasts(next);
684
+ store.listeners.add(listener);
685
+ return ()=>{
686
+ store.listeners.delete(listener);
687
+ clearAllTimers();
688
+ };
689
+ });
690
+ solidJs.createEffect(()=>{
691
+ const items = toasts();
692
+ listRef.current = items;
693
+ const toastKeys = new Set(items.map(timeoutKey));
694
+ const toastIds = new Set(items.map((t)=>t.id));
695
+ for (const [key, timer] of timersRef.current){
696
+ if (!toastKeys.has(key)) {
697
+ clearTimeout(timer);
698
+ timersRef.current.delete(key);
699
+ }
700
+ }
701
+ for (const id of handlersCache.current.keys()){
702
+ if (!toastIds.has(id)) handlersCache.current.delete(id);
703
+ }
704
+ schedule(items);
705
+ });
706
+ const handleMouseEnterRef = {
707
+ current: null
708
+ };
709
+ const handleMouseLeaveRef = {
710
+ current: null
711
+ };
712
+ handleMouseEnterRef.current = ()=>{
713
+ if (hoverRef.current) return;
714
+ hoverRef.current = true;
715
+ clearAllTimers();
716
+ };
717
+ handleMouseLeaveRef.current = ()=>{
718
+ if (!hoverRef.current) return;
719
+ hoverRef.current = false;
720
+ schedule(listRef.current);
721
+ };
722
+ const latest = solidJs.createMemo(()=>{
723
+ const items = toasts();
724
+ for(let i = items.length - 1; i >= 0; i--){
725
+ if (!items[i].exiting) return items[i].id;
726
+ }
727
+ return undefined;
728
+ });
729
+ solidJs.createEffect(()=>{
730
+ latestRef.current = latest();
731
+ setActiveId(latest());
732
+ });
733
+ const getHandlers = (toastId)=>{
734
+ let cached = handlersCache.current.get(toastId);
735
+ if (cached) return cached;
736
+ cached = {
737
+ enter: (e)=>{
738
+ setActiveId((prev)=>prev === toastId ? prev : toastId);
739
+ handleMouseEnterRef.current?.(e);
740
+ },
741
+ leave: (e)=>{
742
+ setActiveId((prev)=>prev === latestRef.current ? prev : latestRef.current);
743
+ handleMouseLeaveRef.current?.(e);
744
+ },
745
+ dismiss: ()=>dismissToast(toastId)
746
+ };
747
+ handlersCache.current.set(toastId, cached);
748
+ return cached;
749
+ };
750
+ const getViewportStyle = (pos)=>{
751
+ if (props.offset === undefined) return undefined;
752
+ const o = typeof props.offset === "object" ? props.offset : {
753
+ top: props.offset,
754
+ right: props.offset,
755
+ bottom: props.offset,
756
+ left: props.offset
757
+ };
758
+ const s = {};
759
+ const px = (v)=>typeof v === "number" ? `${v}px` : v;
760
+ if (pos.startsWith("top") && o.top) s.top = px(o.top);
761
+ if (pos.startsWith("bottom") && o.bottom) s.bottom = px(o.bottom);
762
+ if (pos.endsWith("left") && o.left) s.left = px(o.left);
763
+ if (pos.endsWith("right") && o.right) s.right = px(o.right);
764
+ return s;
765
+ };
766
+ const activePositionsList = solidJs.createMemo(()=>{
767
+ const map = new Map();
768
+ const items = toasts();
769
+ const pos = props.position ?? "top-right";
770
+ for (const t of items){
771
+ const tPos = t.position ?? pos;
772
+ const arr = map.get(tPos);
773
+ if (arr) {
774
+ arr.push(t);
775
+ } else {
776
+ map.set(tPos, [
777
+ t
778
+ ]);
779
+ }
780
+ }
781
+ return Array.from(map, ([p, its])=>({
782
+ pos: p,
783
+ items: its
784
+ }));
785
+ });
786
+ return /*#__PURE__*/ React.createElement(React.Fragment, null, props.children, /*#__PURE__*/ React.createElement(solidJs.For, {
787
+ each: activePositionsList()
788
+ }, ({ pos, items })=>{
789
+ const pill = pillAlign(pos);
790
+ const expand = expandDir(pos);
791
+ return /*#__PURE__*/ React.createElement("section", {
792
+ "data-sileo-viewport": true,
793
+ "data-position": pos,
794
+ "data-theme": props.theme ? resolvedTheme() : undefined,
795
+ "aria-live": "polite",
796
+ style: getViewportStyle(pos)
797
+ }, /*#__PURE__*/ React.createElement(solidJs.For, {
798
+ each: items
799
+ }, (item)=>{
800
+ const h = getHandlers(item.id);
801
+ return /*#__PURE__*/ React.createElement(Sileo, {
802
+ id: item.id,
803
+ state: item.state,
804
+ title: item.title,
805
+ description: item.description,
806
+ position: pill,
807
+ expand: expand,
808
+ icon: item.icon,
809
+ fill: item.fill ?? (props.theme ? THEME_FILLS[resolvedTheme()] : undefined),
810
+ styles: item.styles,
811
+ button: item.button,
812
+ roundness: item.roundness,
813
+ exiting: item.exiting,
814
+ autoExpandDelayMs: item.autoExpandDelayMs,
815
+ autoCollapseDelayMs: item.autoCollapseDelayMs,
816
+ refreshKey: item.instanceId,
817
+ canExpand: activeId() === undefined || activeId() === item.id,
818
+ onMouseEnter: h.enter,
819
+ onMouseLeave: h.leave,
820
+ onDismiss: h.dismiss
821
+ });
822
+ }));
823
+ }));
824
+ }
825
+
826
+ exports.Toaster = Toaster;
827
+ exports.sileo = sileo;