@fluix-ui/vue 0.0.2

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,722 @@
1
+ import { Toaster as Toaster$1, TOAST_DEFAULTS } from '@fluix-ui/core';
2
+ export { fluix } from '@fluix-ui/core';
3
+ import { defineComponent, ref, computed, watch, watchEffect, onMounted, nextTick, onUnmounted, isVNode, h, Fragment, shallowRef } from 'vue';
4
+
5
+ // src/index.ts
6
+ var WIDTH = 350;
7
+ var HEIGHT = 40;
8
+ var PILL_CONTENT_PADDING = 16;
9
+ var HEADER_HORIZONTAL_PADDING_PX = 12;
10
+ var MIN_EXPAND_RATIO = 2.25;
11
+ var BODY_MERGE_OVERLAP = 6;
12
+ var DISMISS_STAGE_DELAY_MS = 260;
13
+ function resolveOffsetValue(value) {
14
+ return typeof value === "number" ? `${value}px` : value;
15
+ }
16
+ function getViewportOffsetStyle(offset, position) {
17
+ if (offset == null) return {};
18
+ let top;
19
+ let right;
20
+ let bottom;
21
+ let left;
22
+ if (typeof offset === "number" || typeof offset === "string") {
23
+ const resolved = resolveOffsetValue(offset);
24
+ top = resolved;
25
+ right = resolved;
26
+ bottom = resolved;
27
+ left = resolved;
28
+ } else {
29
+ if (offset.top != null) top = resolveOffsetValue(offset.top);
30
+ if (offset.right != null) right = resolveOffsetValue(offset.right);
31
+ if (offset.bottom != null) bottom = resolveOffsetValue(offset.bottom);
32
+ if (offset.left != null) left = resolveOffsetValue(offset.left);
33
+ }
34
+ const style = {};
35
+ if (position.startsWith("top") && top) style.top = top;
36
+ if (position.startsWith("bottom") && bottom) style.bottom = bottom;
37
+ if (position.endsWith("right") && right) style.right = right;
38
+ if (position.endsWith("left") && left) style.left = left;
39
+ if (position.endsWith("center")) {
40
+ if (left) style.paddingLeft = left;
41
+ if (right) style.paddingRight = right;
42
+ }
43
+ return style;
44
+ }
45
+ function getPillAlign(position) {
46
+ if (position.includes("right")) return "right";
47
+ if (position.includes("center")) return "center";
48
+ return "left";
49
+ }
50
+ function renderIcon(icon, state) {
51
+ if (icon != null) {
52
+ if (isVNode(icon)) return icon;
53
+ return h("span", { "aria-hidden": "true" }, String(icon));
54
+ }
55
+ switch (state) {
56
+ case "success":
57
+ return h(
58
+ "svg",
59
+ {
60
+ width: "14",
61
+ height: "14",
62
+ viewBox: "0 0 24 24",
63
+ fill: "none",
64
+ stroke: "currentColor",
65
+ "stroke-width": "2.5",
66
+ "stroke-linecap": "round",
67
+ "stroke-linejoin": "round",
68
+ "aria-hidden": "true"
69
+ },
70
+ [h("polyline", { points: "20 6 9 17 4 12" })]
71
+ );
72
+ case "error":
73
+ return h(
74
+ "svg",
75
+ {
76
+ width: "14",
77
+ height: "14",
78
+ viewBox: "0 0 24 24",
79
+ fill: "none",
80
+ stroke: "currentColor",
81
+ "stroke-width": "2.5",
82
+ "stroke-linecap": "round",
83
+ "stroke-linejoin": "round",
84
+ "aria-hidden": "true"
85
+ },
86
+ [
87
+ h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
88
+ h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
89
+ ]
90
+ );
91
+ case "warning":
92
+ return h(
93
+ "svg",
94
+ {
95
+ width: "14",
96
+ height: "14",
97
+ viewBox: "0 0 24 24",
98
+ fill: "none",
99
+ stroke: "currentColor",
100
+ "stroke-width": "2.5",
101
+ "stroke-linecap": "round",
102
+ "stroke-linejoin": "round",
103
+ "aria-hidden": "true"
104
+ },
105
+ [
106
+ h("path", {
107
+ d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
108
+ }),
109
+ h("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
110
+ h("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
111
+ ]
112
+ );
113
+ case "info":
114
+ return h(
115
+ "svg",
116
+ {
117
+ width: "14",
118
+ height: "14",
119
+ viewBox: "0 0 24 24",
120
+ fill: "none",
121
+ stroke: "currentColor",
122
+ "stroke-width": "2.5",
123
+ "stroke-linecap": "round",
124
+ "stroke-linejoin": "round",
125
+ "aria-hidden": "true"
126
+ },
127
+ [
128
+ h("circle", { cx: "12", cy: "12", r: "10" }),
129
+ h("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
130
+ h("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
131
+ ]
132
+ );
133
+ case "loading":
134
+ return h(
135
+ "svg",
136
+ {
137
+ width: "14",
138
+ height: "14",
139
+ viewBox: "0 0 24 24",
140
+ fill: "none",
141
+ stroke: "currentColor",
142
+ "stroke-width": "2.5",
143
+ "stroke-linecap": "round",
144
+ "stroke-linejoin": "round",
145
+ "aria-hidden": "true",
146
+ "data-fluix-icon": "spin"
147
+ },
148
+ [
149
+ h("line", { x1: "12", y1: "2", x2: "12", y2: "6" }),
150
+ h("line", { x1: "12", y1: "18", x2: "12", y2: "22" }),
151
+ h("line", { x1: "4.93", y1: "4.93", x2: "7.76", y2: "7.76" }),
152
+ h("line", { x1: "16.24", y1: "16.24", x2: "19.07", y2: "19.07" }),
153
+ h("line", { x1: "2", y1: "12", x2: "6", y2: "12" }),
154
+ h("line", { x1: "18", y1: "12", x2: "22", y2: "12" }),
155
+ h("line", { x1: "4.93", y1: "19.07", x2: "7.76", y2: "16.24" }),
156
+ h("line", { x1: "16.24", y1: "7.76", x2: "19.07", y2: "4.93" })
157
+ ]
158
+ );
159
+ case "action":
160
+ return h(
161
+ "svg",
162
+ {
163
+ width: "14",
164
+ height: "14",
165
+ viewBox: "0 0 24 24",
166
+ fill: "none",
167
+ stroke: "currentColor",
168
+ "stroke-width": "2.5",
169
+ "stroke-linecap": "round",
170
+ "stroke-linejoin": "round",
171
+ "aria-hidden": "true"
172
+ },
173
+ [
174
+ h("circle", { cx: "12", cy: "12", r: "10" }),
175
+ h("polygon", {
176
+ points: "10 8 16 12 10 16 10 8",
177
+ fill: "currentColor",
178
+ stroke: "none"
179
+ })
180
+ ]
181
+ );
182
+ default:
183
+ return null;
184
+ }
185
+ }
186
+ var ToastItem = defineComponent({
187
+ name: "FluixToastItem",
188
+ props: {
189
+ item: {
190
+ type: Object,
191
+ required: true
192
+ },
193
+ machine: {
194
+ type: Object,
195
+ required: true
196
+ },
197
+ localState: {
198
+ type: Object,
199
+ required: true
200
+ }
201
+ },
202
+ emits: {
203
+ localStateChange: (_patch) => true
204
+ },
205
+ setup(props, { emit }) {
206
+ const rootRef = ref(null);
207
+ const headerRef = ref(null);
208
+ const headerInnerRef = ref(null);
209
+ const contentRef = ref(null);
210
+ const pillWidth = ref(HEIGHT);
211
+ const contentHeight = ref(0);
212
+ const hovering = ref(false);
213
+ const pendingDismiss = ref(false);
214
+ const dismissRequested = ref(false);
215
+ const dismissTimer = ref(null);
216
+ const attrs = computed(() => Toaster$1.getAttrs(props.item, props.localState));
217
+ const hasDescription = computed(
218
+ () => Boolean(props.item.description) || Boolean(props.item.button)
219
+ );
220
+ const isLoading = computed(() => props.item.state === "loading");
221
+ const open = computed(
222
+ () => hasDescription.value && props.localState.expanded && !isLoading.value
223
+ );
224
+ const edge = computed(() => props.item.position.startsWith("top") ? "bottom" : "top");
225
+ const pillAlign = computed(() => getPillAlign(props.item.position));
226
+ const filterId = computed(() => `fluix-gooey-${props.item.id.replace(/[^a-z0-9-]/gi, "-")}`);
227
+ const roundness = computed(() => props.item.roundness ?? TOAST_DEFAULTS.roundness);
228
+ const blur = computed(() => Math.min(10, Math.max(6, roundness.value * 0.45)));
229
+ const minExpanded = HEIGHT * MIN_EXPAND_RATIO;
230
+ const frozenExpanded = ref(minExpanded);
231
+ const rawExpanded = computed(
232
+ () => hasDescription.value ? Math.max(minExpanded, HEIGHT + contentHeight.value) : minExpanded
233
+ );
234
+ watch(
235
+ () => open.value,
236
+ (isOpen) => {
237
+ if (isOpen) frozenExpanded.value = rawExpanded.value;
238
+ },
239
+ { immediate: true }
240
+ );
241
+ watch(rawExpanded, (val) => {
242
+ if (open.value) frozenExpanded.value = val;
243
+ });
244
+ const expanded = computed(() => open.value ? rawExpanded.value : frozenExpanded.value);
245
+ const expandedContent = computed(() => Math.max(0, expanded.value - HEIGHT));
246
+ const expandedHeight = computed(
247
+ () => hasDescription.value ? Math.max(expanded.value, minExpanded) : HEIGHT
248
+ );
249
+ const resolvedPillWidth = computed(() => Math.max(HEIGHT, pillWidth.value));
250
+ const pillX = computed(() => {
251
+ if (pillAlign.value === "right") return WIDTH - resolvedPillWidth.value;
252
+ if (pillAlign.value === "center") return (WIDTH - resolvedPillWidth.value) / 2;
253
+ return 0;
254
+ });
255
+ const rootStyle = computed(() => ({
256
+ "--_h": `${open.value ? expanded.value : HEIGHT}px`,
257
+ "--_pw": `${resolvedPillWidth.value}px`,
258
+ "--_px": `${pillX.value}px`,
259
+ "--_ht": `translateY(${open.value ? edge.value === "bottom" ? 3 : -3 : 0}px) scale(${open.value ? 0.9 : 1})`,
260
+ "--_co": `${open.value ? 1 : 0}`,
261
+ "--_cy": `${open.value ? 0 : -14}px`,
262
+ "--_cm": `${open.value ? expandedContent.value : 0}px`,
263
+ "--_by": `${open.value ? HEIGHT - BODY_MERGE_OVERLAP : HEIGHT}px`,
264
+ "--_bh": `${open.value ? expandedContent.value : 0}px`,
265
+ "--_bo": `${open.value ? 1 : 0}`
266
+ }));
267
+ const clearDismissTimer = () => {
268
+ if (dismissTimer.value) {
269
+ clearTimeout(dismissTimer.value);
270
+ dismissTimer.value = null;
271
+ }
272
+ };
273
+ const measureContentHeight = () => {
274
+ const element = contentRef.value;
275
+ if (!element) return;
276
+ contentHeight.value = element.scrollHeight;
277
+ };
278
+ const requestDismiss = () => {
279
+ if (dismissRequested.value) return;
280
+ dismissRequested.value = true;
281
+ hovering.value = false;
282
+ pendingDismiss.value = false;
283
+ emit("localStateChange", { expanded: false });
284
+ clearDismissTimer();
285
+ dismissTimer.value = setTimeout(
286
+ () => {
287
+ props.machine.dismiss(props.item.id);
288
+ dismissTimer.value = null;
289
+ },
290
+ hasDescription.value ? DISMISS_STAGE_DELAY_MS : 0
291
+ );
292
+ };
293
+ watchEffect((onCleanup) => {
294
+ const headerElement = headerRef.value;
295
+ const headerInner = headerInnerRef.value;
296
+ if (!headerElement || !headerInner) return;
297
+ let frame = 0;
298
+ const measure = () => {
299
+ const cs = getComputedStyle(headerElement);
300
+ const horizontalPadding = Number.parseFloat(cs.paddingLeft || "0") + Number.parseFloat(cs.paddingRight || "0");
301
+ const intrinsicWidth = headerInner.getBoundingClientRect().width;
302
+ pillWidth.value = intrinsicWidth + horizontalPadding + PILL_CONTENT_PADDING;
303
+ };
304
+ frame = requestAnimationFrame(measure);
305
+ const observer = new ResizeObserver(measure);
306
+ observer.observe(headerInner);
307
+ onCleanup(() => {
308
+ cancelAnimationFrame(frame);
309
+ observer.disconnect();
310
+ });
311
+ });
312
+ onMounted(() => {
313
+ const readyTimer = setTimeout(() => {
314
+ emit("localStateChange", { ready: true });
315
+ }, 32);
316
+ return () => clearTimeout(readyTimer);
317
+ });
318
+ watchEffect(
319
+ (onCleanup) => {
320
+ if (!hasDescription.value) {
321
+ contentHeight.value = 0;
322
+ return;
323
+ }
324
+ const element = contentRef.value;
325
+ if (!element) return;
326
+ measureContentHeight();
327
+ let rafId = 0;
328
+ const observer = new ResizeObserver(() => {
329
+ cancelAnimationFrame(rafId);
330
+ rafId = requestAnimationFrame(measureContentHeight);
331
+ });
332
+ observer.observe(element);
333
+ onCleanup(() => {
334
+ cancelAnimationFrame(rafId);
335
+ observer.disconnect();
336
+ });
337
+ },
338
+ { flush: "post" }
339
+ );
340
+ watch(
341
+ () => [
342
+ props.item.instanceId,
343
+ props.item.description,
344
+ props.item.button?.title,
345
+ props.localState.expanded
346
+ ],
347
+ () => {
348
+ void nextTick(() => {
349
+ requestAnimationFrame(() => {
350
+ measureContentHeight();
351
+ });
352
+ });
353
+ },
354
+ { immediate: true }
355
+ );
356
+ watch(
357
+ () => [props.item.id, props.item.instanceId, props.item.duration],
358
+ (_next, _prev, onCleanup) => {
359
+ if (props.item.duration == null || props.item.duration <= 0) return;
360
+ const timer = setTimeout(() => {
361
+ if (hovering.value) {
362
+ pendingDismiss.value = true;
363
+ return;
364
+ }
365
+ pendingDismiss.value = false;
366
+ requestDismiss();
367
+ }, props.item.duration);
368
+ onCleanup(() => clearTimeout(timer));
369
+ },
370
+ { immediate: true }
371
+ );
372
+ watch(
373
+ () => [
374
+ props.item.id,
375
+ props.item.instanceId,
376
+ props.item.autoExpandDelayMs,
377
+ props.item.autoCollapseDelayMs,
378
+ props.localState.ready
379
+ ],
380
+ (_next, _prev, onCleanup) => {
381
+ if (!props.localState.ready) return;
382
+ const timers = [];
383
+ if (props.item.autoExpandDelayMs != null && props.item.autoExpandDelayMs > 0) {
384
+ timers.push(
385
+ setTimeout(() => {
386
+ if (dismissRequested.value) return;
387
+ if (!hovering.value) emit("localStateChange", { expanded: true });
388
+ }, props.item.autoExpandDelayMs)
389
+ );
390
+ }
391
+ if (props.item.autoCollapseDelayMs != null && props.item.autoCollapseDelayMs > 0) {
392
+ timers.push(
393
+ setTimeout(() => {
394
+ if (dismissRequested.value) return;
395
+ if (!hovering.value) emit("localStateChange", { expanded: false });
396
+ }, props.item.autoCollapseDelayMs)
397
+ );
398
+ }
399
+ onCleanup(() => {
400
+ for (const timer of timers) clearTimeout(timer);
401
+ });
402
+ },
403
+ { immediate: true }
404
+ );
405
+ watch(
406
+ () => props.item.instanceId,
407
+ () => {
408
+ hovering.value = false;
409
+ pendingDismiss.value = false;
410
+ dismissRequested.value = false;
411
+ clearDismissTimer();
412
+ },
413
+ { immediate: true }
414
+ );
415
+ onUnmounted(() => {
416
+ clearDismissTimer();
417
+ });
418
+ watchEffect((onCleanup) => {
419
+ const element = rootRef.value;
420
+ if (!element) return;
421
+ const callbacks = {
422
+ onExpand: () => {
423
+ if (props.item.exiting || dismissRequested.value) return;
424
+ emit("localStateChange", { expanded: true });
425
+ },
426
+ onCollapse: () => {
427
+ if (props.item.exiting || dismissRequested.value) return;
428
+ if (props.item.autopilot !== false) return;
429
+ emit("localStateChange", { expanded: false });
430
+ },
431
+ onDismiss: () => {
432
+ requestDismiss();
433
+ },
434
+ onHoverStart: () => {
435
+ hovering.value = true;
436
+ },
437
+ onHoverEnd: () => {
438
+ hovering.value = false;
439
+ if (pendingDismiss.value && !dismissRequested.value) {
440
+ pendingDismiss.value = false;
441
+ requestDismiss();
442
+ }
443
+ }
444
+ };
445
+ const { destroy } = Toaster$1.connect(element, callbacks, props.item);
446
+ onCleanup(() => destroy());
447
+ });
448
+ return () => {
449
+ const item = props.item;
450
+ const toastAttrs = attrs.value;
451
+ const descriptionChildren = [];
452
+ if (typeof item.description === "string" || typeof item.description === "number") {
453
+ descriptionChildren.push(String(item.description));
454
+ } else if (isVNode(item.description)) {
455
+ descriptionChildren.push(item.description);
456
+ }
457
+ if (item.button) {
458
+ descriptionChildren.push(
459
+ h(
460
+ "button",
461
+ {
462
+ ...toastAttrs.button,
463
+ type: "button",
464
+ class: item.styles?.button,
465
+ onClick: (event) => {
466
+ event.stopPropagation();
467
+ item.button?.onClick();
468
+ }
469
+ },
470
+ item.button.title
471
+ )
472
+ );
473
+ }
474
+ const children = [
475
+ h("div", toastAttrs.canvas, [
476
+ h(
477
+ "svg",
478
+ {
479
+ xmlns: "http://www.w3.org/2000/svg",
480
+ "data-fluix-svg": "",
481
+ width: WIDTH,
482
+ height: expandedHeight.value,
483
+ viewBox: `0 0 ${WIDTH} ${expandedHeight.value}`,
484
+ style: {
485
+ position: "absolute",
486
+ left: "0px",
487
+ top: "0px",
488
+ overflow: "visible"
489
+ },
490
+ "aria-hidden": "true"
491
+ },
492
+ [
493
+ h("defs", [
494
+ h(
495
+ "filter",
496
+ {
497
+ id: filterId.value,
498
+ x: "-20%",
499
+ y: "-20%",
500
+ width: "140%",
501
+ height: "140%",
502
+ colorInterpolationFilters: "sRGB"
503
+ },
504
+ [
505
+ h("feGaussianBlur", {
506
+ in: "SourceGraphic",
507
+ stdDeviation: blur.value,
508
+ result: "blur"
509
+ }),
510
+ h("feColorMatrix", {
511
+ in: "blur",
512
+ type: "matrix",
513
+ values: "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10",
514
+ result: "goo"
515
+ }),
516
+ h("feComposite", {
517
+ in: "SourceGraphic",
518
+ in2: "goo",
519
+ operator: "atop"
520
+ })
521
+ ]
522
+ )
523
+ ]),
524
+ h("g", { filter: `url(#${filterId.value})` }, [
525
+ h("rect", {
526
+ "data-fluix-pill": "",
527
+ x: pillX.value,
528
+ y: 0,
529
+ width: resolvedPillWidth.value,
530
+ height: HEIGHT,
531
+ rx: roundness.value,
532
+ ry: roundness.value,
533
+ fill: item.fill ?? "#FFFFFF"
534
+ }),
535
+ h("rect", {
536
+ "data-fluix-body": "",
537
+ x: 0,
538
+ y: HEIGHT,
539
+ width: WIDTH,
540
+ height: 0,
541
+ rx: 0,
542
+ ry: 0,
543
+ fill: item.fill ?? "#FFFFFF",
544
+ opacity: 0
545
+ })
546
+ ])
547
+ ]
548
+ )
549
+ ]),
550
+ h(
551
+ "div",
552
+ {
553
+ ref: headerRef,
554
+ ...toastAttrs.header,
555
+ style: {
556
+ paddingLeft: `${HEADER_HORIZONTAL_PADDING_PX}px`,
557
+ paddingRight: `${HEADER_HORIZONTAL_PADDING_PX}px`
558
+ }
559
+ },
560
+ [
561
+ h("div", { "data-fluix-header-stack": "" }, [
562
+ h(
563
+ "div",
564
+ {
565
+ ref: headerInnerRef,
566
+ "data-fluix-header-inner": "",
567
+ "data-layer": "current"
568
+ },
569
+ [
570
+ h(
571
+ "div",
572
+ {
573
+ ...toastAttrs.badge,
574
+ class: item.styles?.badge
575
+ },
576
+ [renderIcon(item.icon, item.state)]
577
+ ),
578
+ h(
579
+ "span",
580
+ {
581
+ ...toastAttrs.title,
582
+ class: item.styles?.title
583
+ },
584
+ item.title ?? item.state
585
+ )
586
+ ]
587
+ )
588
+ ])
589
+ ]
590
+ )
591
+ ];
592
+ if (hasDescription.value) {
593
+ children.push(
594
+ h("div", toastAttrs.content, [
595
+ h(
596
+ "div",
597
+ {
598
+ ref: contentRef,
599
+ ...toastAttrs.description,
600
+ class: item.styles?.description
601
+ },
602
+ descriptionChildren
603
+ )
604
+ ])
605
+ );
606
+ }
607
+ return h(
608
+ "button",
609
+ {
610
+ ref: rootRef,
611
+ type: "button",
612
+ ...toastAttrs.root,
613
+ style: rootStyle.value
614
+ },
615
+ children
616
+ );
617
+ };
618
+ }
619
+ });
620
+ function useFluixToasts() {
621
+ const machine = Toaster$1.getMachine();
622
+ const snapshot = shallowRef(machine.store.getSnapshot());
623
+ onMounted(() => {
624
+ const unsubscribe = machine.store.subscribe(() => {
625
+ snapshot.value = machine.store.getSnapshot();
626
+ });
627
+ onUnmounted(() => unsubscribe());
628
+ });
629
+ const toasts = computed(() => snapshot.value.toasts);
630
+ const config = computed(() => snapshot.value.config);
631
+ return {
632
+ machine,
633
+ snapshot,
634
+ toasts,
635
+ config
636
+ };
637
+ }
638
+ var Toaster = defineComponent({
639
+ name: "FluixToaster",
640
+ props: {
641
+ config: {
642
+ type: Object,
643
+ required: false
644
+ }
645
+ },
646
+ setup(props) {
647
+ const { machine, snapshot } = useFluixToasts();
648
+ const localState = ref({});
649
+ watch(
650
+ () => props.config,
651
+ (nextConfig) => {
652
+ if (nextConfig) machine.configure(nextConfig);
653
+ },
654
+ { deep: true, immediate: true }
655
+ );
656
+ watch(
657
+ () => snapshot.value.toasts,
658
+ (toasts) => {
659
+ const ids = new Set(toasts.map((toast) => toast.id));
660
+ const next = {};
661
+ for (const id of ids) {
662
+ next[id] = localState.value[id] ?? { ready: false, expanded: false };
663
+ }
664
+ localState.value = next;
665
+ },
666
+ { immediate: true }
667
+ );
668
+ const byPosition = computed(() => {
669
+ const grouped = /* @__PURE__ */ new Map();
670
+ for (const toast of snapshot.value.toasts) {
671
+ const current = grouped.get(toast.position) ?? [];
672
+ current.push(toast);
673
+ grouped.set(toast.position, current);
674
+ }
675
+ return grouped;
676
+ });
677
+ const resolvedOffset = computed(() => snapshot.value.config?.offset ?? props.config?.offset);
678
+ const resolvedLayout = computed(
679
+ () => snapshot.value.config?.layout ?? props.config?.layout ?? "stack"
680
+ );
681
+ const setToastLocal = (id, patch) => {
682
+ localState.value = {
683
+ ...localState.value,
684
+ [id]: {
685
+ ready: localState.value[id]?.ready ?? false,
686
+ expanded: localState.value[id]?.expanded ?? false,
687
+ ...patch
688
+ }
689
+ };
690
+ };
691
+ return () => h(
692
+ Fragment,
693
+ null,
694
+ Array.from(byPosition.value.entries()).map(
695
+ ([position, toasts]) => h(
696
+ "section",
697
+ {
698
+ key: position,
699
+ ...Toaster$1.getViewportAttrs(position, resolvedLayout.value),
700
+ style: getViewportOffsetStyle(resolvedOffset.value, position)
701
+ },
702
+ toasts.map(
703
+ (item) => h(ToastItem, {
704
+ key: item.instanceId,
705
+ item,
706
+ machine,
707
+ localState: localState.value[item.id] ?? {
708
+ ready: false,
709
+ expanded: false
710
+ },
711
+ onLocalStateChange: (patch) => setToastLocal(item.id, patch)
712
+ })
713
+ )
714
+ )
715
+ )
716
+ );
717
+ }
718
+ });
719
+
720
+ export { Toaster, useFluixToasts };
721
+ //# sourceMappingURL=index.js.map
722
+ //# sourceMappingURL=index.js.map