@rozie-ui/toast-lit 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.cjs ADDED
@@ -0,0 +1,598 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ let lit = require("lit");
6
+ let lit_decorators_js = require("lit/decorators.js");
7
+ let _lit_labs_preact_signals = require("@lit-labs/preact-signals");
8
+ let _rozie_runtime_lit = require("@rozie/runtime-lit");
9
+ let lit_directives_repeat_js = require("lit/directives/repeat.js");
10
+ //#region \0@oxc-project+runtime@0.127.0/helpers/decorate.js
11
+ function __decorate(decorators, target, key, desc) {
12
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
13
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
14
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
15
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
16
+ }
17
+ //#endregion
18
+ //#region src/Toaster.ts
19
+ let Toaster = class Toaster extends (0, _lit_labs_preact_signals.SignalWatcher)(lit.LitElement) {
20
+ constructor(..._args) {
21
+ super(..._args);
22
+ this.position = "bottom-right";
23
+ this.duration = 4e3;
24
+ this.max = 0;
25
+ this.disablePauseOnHover = false;
26
+ this.ariaLabel = null;
27
+ this.disableSwipe = false;
28
+ this.stacked = false;
29
+ this._toasts = (0, _lit_labs_preact_signals.signal)([]);
30
+ this._seq = (0, _lit_labs_preact_signals.signal)(0);
31
+ this._swipe = (0, _lit_labs_preact_signals.signal)(null);
32
+ this._swipeGesture = (0, _lit_labs_preact_signals.signal)(null);
33
+ this._hasSlotToast = false;
34
+ this._disconnectCleanups = [];
35
+ this._rozieTornDown = false;
36
+ this.timers = {};
37
+ this.exitFailsafes = {};
38
+ this.unmounted = false;
39
+ this.seqLocal = 0;
40
+ this.paused = false;
41
+ this.startTimer = (toast) => {
42
+ if (!toast || !toast.duration || toast.duration <= 0) return;
43
+ if (typeof window === "undefined") return;
44
+ const existing = this.timers[toast.id];
45
+ if (existing && existing.handle != null) window.clearTimeout(existing.handle);
46
+ const remaining = toast.duration;
47
+ const handle = window.setTimeout(() => this.dismissBegin(toast.id, "timeout"), remaining);
48
+ this.timers[toast.id] = {
49
+ handle,
50
+ startedAt: Date.now(),
51
+ remaining
52
+ };
53
+ };
54
+ this.clearTimer = (id) => {
55
+ const entry = this.timers[id];
56
+ if (entry && entry.handle != null && typeof window !== "undefined") window.clearTimeout(entry.handle);
57
+ delete this.timers[id];
58
+ };
59
+ this.pauseTimers = () => {
60
+ this.paused = true;
61
+ if (typeof window === "undefined") return;
62
+ for (const id in this.timers) {
63
+ const entry = this.timers[id];
64
+ if (entry.handle == null) continue;
65
+ window.clearTimeout(entry.handle);
66
+ const elapsed = Date.now() - entry.startedAt;
67
+ const remaining = Math.max(0, entry.remaining - elapsed);
68
+ this.timers[id] = {
69
+ handle: null,
70
+ startedAt: entry.startedAt,
71
+ remaining
72
+ };
73
+ }
74
+ };
75
+ this.resumeTimers = () => {
76
+ this.paused = false;
77
+ if (typeof window === "undefined") return;
78
+ for (const id in this.timers) {
79
+ const entry = this.timers[id];
80
+ if (entry.handle != null) continue;
81
+ if (entry.remaining == null || entry.remaining <= 0) {
82
+ this.dismissBegin(id, "timeout");
83
+ continue;
84
+ }
85
+ const remaining = entry.remaining;
86
+ const handle = window.setTimeout(() => this.dismissBegin(id, "timeout"), remaining);
87
+ this.timers[id] = {
88
+ handle,
89
+ startedAt: Date.now(),
90
+ remaining
91
+ };
92
+ }
93
+ };
94
+ this.teardownTimers = () => {
95
+ if (typeof window !== "undefined") {
96
+ for (const id in this.timers) {
97
+ const entry = this.timers[id];
98
+ if (entry.handle != null) window.clearTimeout(entry.handle);
99
+ }
100
+ for (const id in this.exitFailsafes) if (this.exitFailsafes[id] != null) window.clearTimeout(this.exitFailsafes[id]);
101
+ }
102
+ this.timers = {};
103
+ this.exitFailsafes = {};
104
+ };
105
+ this.show = (input) => {
106
+ const t = input || {};
107
+ let id;
108
+ if (t.id != null) id = String(t.id);
109
+ else {
110
+ const s = Math.max(this._seq.value, this.seqLocal);
111
+ id = "t" + s;
112
+ this.seqLocal = s + 1;
113
+ this._seq.value = s + 1;
114
+ }
115
+ const toast = {
116
+ id,
117
+ message: t.message != null ? t.message : "",
118
+ type: t.type || "info",
119
+ duration: t.duration != null ? t.duration : this.duration
120
+ };
121
+ this._toasts.value = this._toasts.value.concat([toast]).slice(this.max > 0 ? Math.max(0, this._toasts.value.length + 1 - this.max) : 0);
122
+ this.startTimer(toast);
123
+ return id;
124
+ };
125
+ this.EXIT_FAILSAFE_MS = 350;
126
+ this.removeToast = (id) => {
127
+ if (typeof window !== "undefined" && this.exitFailsafes[id] != null) window.clearTimeout(this.exitFailsafes[id]);
128
+ delete this.exitFailsafes[id];
129
+ this._toasts.value = this._toasts.value.filter((t) => t.id !== id);
130
+ };
131
+ this.dismissBegin = (id, reason, extra) => {
132
+ const entry = this._toasts.value.find((t) => t.id === id);
133
+ if (!entry || entry.exiting) return;
134
+ this.clearTimer(id);
135
+ this.dispatchEvent(new CustomEvent("dismissed", {
136
+ detail: {
137
+ toast: entry,
138
+ reason
139
+ },
140
+ bubbles: true,
141
+ composed: true
142
+ }));
143
+ this._toasts.value = this._toasts.value.map((t) => t.id === id ? {
144
+ ...t,
145
+ exiting: true,
146
+ ...extra || {}
147
+ } : t);
148
+ if (typeof window === "undefined") this.removeToast(id);
149
+ else this.exitFailsafes[id] = window.setTimeout(() => this.removeToast(id), this.EXIT_FAILSAFE_MS);
150
+ };
151
+ this.dismiss = (id) => {
152
+ this.dismissBegin(id, "api");
153
+ };
154
+ this.clear = () => {
155
+ this.teardownTimers();
156
+ this._toasts.value = [];
157
+ };
158
+ this.patch = (id, changes) => {
159
+ const c = changes || {};
160
+ let existed = false;
161
+ const next = this._toasts.value.map((t) => {
162
+ if (t.id !== id) return t;
163
+ if (t.exiting) return t;
164
+ existed = true;
165
+ const merged = { ...t };
166
+ if (c.message !== void 0) merged.message = c.message;
167
+ if (c.type !== void 0) merged.type = c.type;
168
+ if (c.duration !== void 0) merged.duration = c.duration;
169
+ return merged;
170
+ });
171
+ if (!existed) return false;
172
+ this._toasts.value = next;
173
+ if (c.duration !== void 0) {
174
+ this.clearTimer(id);
175
+ const patched = next.find((t) => t.id === id);
176
+ if (this.paused) {
177
+ if (patched && patched.duration > 0 && typeof window !== "undefined") this.timers[id] = {
178
+ handle: null,
179
+ startedAt: Date.now(),
180
+ remaining: patched.duration
181
+ };
182
+ } else this.startTimer(patched);
183
+ }
184
+ return true;
185
+ };
186
+ this.settlePromise = (id, type, messageOrFn, value) => {
187
+ if (this.unmounted) return;
188
+ const entry = this._toasts.value.find((t) => t.id === id);
189
+ if (!entry || entry.exiting) return;
190
+ const message = typeof messageOrFn === "function" ? messageOrFn(value) : messageOrFn;
191
+ this.patch(id, {
192
+ type,
193
+ message,
194
+ duration: this.duration
195
+ });
196
+ };
197
+ this.promise = (p, opts) => {
198
+ const o = opts || {};
199
+ const id = this.show({
200
+ type: "loading",
201
+ duration: 0,
202
+ message: o.loading
203
+ });
204
+ if (p && typeof p.then === "function") p.then((value) => this.settlePromise(id, "success", o.success, value)).catch((err) => this.settlePromise(id, "error", o.error, err));
205
+ return id;
206
+ };
207
+ this.swipeAxisFor = (position) => position === "top-center" || position === "bottom-center" ? "y" : "x";
208
+ this.swipeSignFor = (position) => {
209
+ if (position === "top-right" || position === "bottom-right") return 1;
210
+ if (position === "top-left" || position === "bottom-left") return -1;
211
+ if (position === "bottom-center") return 1;
212
+ return -1;
213
+ };
214
+ this.onToastPointerDown = (t, event) => {
215
+ if (this.disableSwipe) return;
216
+ if (event.button != null && event.button !== 0) return;
217
+ if (event.target && event.target.closest ? event.target.closest("button, a") : null) return;
218
+ const axis = this.swipeAxisFor(this.position);
219
+ const sign = this.swipeSignFor(this.position);
220
+ const el = event.currentTarget;
221
+ const size = axis === "x" ? el.offsetWidth : el.offsetHeight;
222
+ this._swipeGesture.value = {
223
+ id: t.id,
224
+ axis,
225
+ sign,
226
+ size,
227
+ startX: event.clientX,
228
+ startY: event.clientY,
229
+ startTime: Date.now()
230
+ };
231
+ if (el && el.setPointerCapture) try {
232
+ el.setPointerCapture(event.pointerId);
233
+ } catch (e) {}
234
+ };
235
+ this.onToastPointerMove = (t, event) => {
236
+ if (this.disableSwipe) return;
237
+ const gesture = this._swipeGesture.value;
238
+ if (!gesture || gesture.id !== t.id) return;
239
+ const raw = gesture.axis === "x" ? event.clientX - gesture.startX : event.clientY - gesture.startY;
240
+ const d = raw * gesture.sign > 0 ? raw : raw * .15;
241
+ this._swipe.value = {
242
+ id: t.id,
243
+ d,
244
+ axis: gesture.axis,
245
+ sign: gesture.sign,
246
+ size: gesture.size
247
+ };
248
+ };
249
+ this.onToastPointerUp = (t, event) => {
250
+ if (this.disableSwipe) return;
251
+ const gesture = this._swipeGesture.value;
252
+ this._swipeGesture.value = null;
253
+ const dragState = this._swipe.value;
254
+ this._swipe.value = null;
255
+ if (!gesture || gesture.id !== t.id || !dragState) return;
256
+ const elapsed = Math.max(1, Date.now() - gesture.startTime);
257
+ const magnitude = dragState.d * gesture.sign;
258
+ const velocity = magnitude / elapsed;
259
+ if (magnitude > 0 && (magnitude > gesture.size * .45 || velocity > .11)) this.dismissBegin(t.id, "swipe", { swipeExitSign: gesture.sign });
260
+ };
261
+ this.onToastPointerCancel = (t) => {
262
+ if (this.disableSwipe) return;
263
+ if (this._swipeGesture.value && this._swipeGesture.value.id === t.id) this._swipeGesture.value = null;
264
+ if (this._swipe.value && this._swipe.value.id === t.id) this._swipe.value = null;
265
+ };
266
+ this.depth = (t) => {
267
+ const idx = this._toasts.value.findIndex((x) => x.id === t.id);
268
+ return idx === -1 ? 0 : this._toasts.value.length - 1 - idx;
269
+ };
270
+ this.toastStyle = (t) => {
271
+ const depthDecl = "--rozie-toast-depth: " + this.depth(t) + ";";
272
+ if (t.exiting) return t.swipeExitSign != null ? depthDecl + " --rozie-toast-swipe-exit: " + t.swipeExitSign + ";" : depthDecl;
273
+ const dragState = this._swipe.value;
274
+ if (!dragState || dragState.id !== t.id) return depthDecl;
275
+ const translate = dragState.axis === "x" ? "translateX(" + dragState.d + "px)" : "translateY(" + dragState.d + "px)";
276
+ const magnitude = dragState.d * dragState.sign;
277
+ const opacity = magnitude > 0 && dragState.size > 0 ? Math.max(.3, 1 - magnitude / dragState.size) : 1;
278
+ return depthDecl + " transform: " + translate + "; opacity: " + opacity + "; transition: none;";
279
+ };
280
+ this.onMouseEnter = () => {
281
+ if (this.disablePauseOnHover) return;
282
+ this.pauseTimers();
283
+ };
284
+ this.onMouseLeave = () => {
285
+ if (this.disablePauseOnHover) return;
286
+ this.resumeTimers();
287
+ };
288
+ this.regionLabel = () => this.ariaLabel != null ? this.ariaLabel : "Notifications";
289
+ this.liveFor = (type) => type === "error" || type === "warning" ? "assertive" : "polite";
290
+ }
291
+ static {
292
+ this.styles = lit.css`
293
+ :host{display:contents}
294
+ @media (prefers-reduced-motion: reduce) {
295
+ .rozie-toast[data-rozie-s-12d4265c] {
296
+ animation-name: rozie-toast-fade-in;
297
+ animation-duration: 1ms;
298
+ }
299
+ .rozie-toast--exiting[data-rozie-s-12d4265c] {
300
+ animation-name: rozie-toast-fade-out;
301
+ animation-duration: 1ms;
302
+ }
303
+ }
304
+ .rozie-toaster[data-rozie-s-12d4265c] {
305
+ position: fixed;
306
+ z-index: var(--rozie-toast-z, 9999);
307
+ display: flex;
308
+ flex-direction: column;
309
+ gap: var(--rozie-toast-gap, 0.5rem);
310
+ padding: var(--rozie-toast-region-padding, 1rem);
311
+ max-width: var(--rozie-toast-max-width, calc(100vw - 2rem));
312
+ pointer-events: none;
313
+ font: var(--rozie-toast-font, inherit);
314
+ }
315
+ .rozie-toaster[data-rozie-s-12d4265c] > *[data-rozie-s-12d4265c] {
316
+ pointer-events: auto;
317
+ }
318
+ .rozie-toaster--top-left[data-rozie-s-12d4265c] { top: 0; left: 0; align-items: flex-start; }
319
+ .rozie-toaster--top-right[data-rozie-s-12d4265c] { top: 0; right: 0; align-items: flex-end; }
320
+ .rozie-toaster--top-center[data-rozie-s-12d4265c] { top: 0; left: 50%; transform: translateX(-50%); align-items: center; }
321
+ .rozie-toaster--bottom-left[data-rozie-s-12d4265c] { bottom: 0; left: 0; align-items: flex-start; flex-direction: column-reverse; }
322
+ .rozie-toaster--bottom-right[data-rozie-s-12d4265c] { bottom: 0; right: 0; align-items: flex-end; flex-direction: column-reverse; }
323
+ .rozie-toaster--bottom-center[data-rozie-s-12d4265c] { bottom: 0; left: 50%; transform: translateX(-50%); align-items: center; flex-direction: column-reverse; }
324
+ .rozie-toaster--stacked[data-rozie-s-12d4265c] .rozie-toast[data-rozie-s-12d4265c] {
325
+ grid-area: 1 / 1;
326
+ z-index: calc(100 - var(--rozie-toast-depth, 0));
327
+ }
328
+ .rozie-toaster--stacked[data-rozie-s-12d4265c]:not([data-rozie-s-12d4265c]:hover):not([data-rozie-s-12d4265c]:focus-within) {
329
+ display: grid;
330
+ }
331
+ .rozie-toaster--stacked[data-rozie-s-12d4265c]:not([data-rozie-s-12d4265c]:hover):not([data-rozie-s-12d4265c]:focus-within) .rozie-toast[data-rozie-s-12d4265c] {
332
+ transform:
333
+ translateY(calc(var(--rozie-toast-depth, 0) * var(--rozie-toast-stack-offset, 8px)))
334
+ scale(calc(1 - var(--rozie-toast-depth, 0) * var(--rozie-toast-stack-scale-step, 0.05)));
335
+ opacity: calc(1 - min(1, max(0, var(--rozie-toast-depth, 0) - 2)));
336
+ }
337
+ .rozie-toaster--stacked.rozie-toaster--bottom-left[data-rozie-s-12d4265c]:not([data-rozie-s-12d4265c]:hover):not([data-rozie-s-12d4265c]:focus-within) .rozie-toast[data-rozie-s-12d4265c],
338
+ .rozie-toaster--stacked.rozie-toaster--bottom-right[data-rozie-s-12d4265c]:not([data-rozie-s-12d4265c]:hover):not([data-rozie-s-12d4265c]:focus-within) .rozie-toast[data-rozie-s-12d4265c],
339
+ .rozie-toaster--stacked.rozie-toaster--bottom-center[data-rozie-s-12d4265c]:not([data-rozie-s-12d4265c]:hover):not([data-rozie-s-12d4265c]:focus-within) .rozie-toast[data-rozie-s-12d4265c] {
340
+ transform:
341
+ translateY(calc(var(--rozie-toast-depth, 0) * var(--rozie-toast-stack-offset, 8px) * -1))
342
+ scale(calc(1 - var(--rozie-toast-depth, 0) * var(--rozie-toast-stack-scale-step, 0.05)));
343
+ }
344
+ .rozie-toast[data-rozie-s-12d4265c] {
345
+ display: flex;
346
+ align-items: center;
347
+ gap: var(--rozie-toast-content-gap, 0.75rem);
348
+ min-width: var(--rozie-toast-min-width, 16rem);
349
+ max-width: var(--rozie-toast-toast-max-width, 24rem);
350
+ padding: var(--rozie-toast-padding, 0.75rem 1rem);
351
+ color: var(--rozie-toast-color, #fff);
352
+ background: var(--rozie-toast-bg, #333);
353
+ border-radius: var(--rozie-toast-radius, 0.5rem);
354
+ box-shadow: var(--rozie-toast-shadow, 0 6px 20px rgba(0, 0, 0, 0.25));
355
+ /* Swipe: page scroll stays alive on touch along the axis the toast does
356
+ NOT move on. The transition here drives the spring-back (the active-drag
357
+ :style sets an inline \`transition: none\` to track the finger 1:1;
358
+ releasing it without a further gesture falls back to this transition). */
359
+ touch-action: pan-y;
360
+ transition: transform 200ms ease, opacity 200ms ease;
361
+ }
362
+ .rozie-toaster--top-center[data-rozie-s-12d4265c] .rozie-toast[data-rozie-s-12d4265c],
363
+ .rozie-toaster--bottom-center[data-rozie-s-12d4265c] .rozie-toast[data-rozie-s-12d4265c] {
364
+ touch-action: pan-x;
365
+ }
366
+ .rozie-toast--success[data-rozie-s-12d4265c] { background: var(--rozie-toast-success-bg, #16a34a); }
367
+ .rozie-toast--error[data-rozie-s-12d4265c] { background: var(--rozie-toast-error-bg, #dc2626); }
368
+ .rozie-toast--warning[data-rozie-s-12d4265c] { background: var(--rozie-toast-warning-bg, #ca8a04); }
369
+ .rozie-toast--info[data-rozie-s-12d4265c] { background: var(--rozie-toast-info-bg, var(--rozie-toast-bg, #333)); }
370
+ from[data-rozie-s-12d4265c] { opacity: 0; transform: translateY(-0.5rem); }
371
+ to[data-rozie-s-12d4265c] { opacity: 1; transform: translateY(0); }
372
+ from[data-rozie-s-12d4265c] { opacity: 0; transform: translateY(0.5rem); }
373
+ to[data-rozie-s-12d4265c] { opacity: 1; transform: translateY(0); }
374
+ from[data-rozie-s-12d4265c] { opacity: 1; transform: translateY(0); }
375
+ to[data-rozie-s-12d4265c] { opacity: 0; transform: translateY(-0.5rem); }
376
+ from[data-rozie-s-12d4265c] { opacity: 1; transform: translateY(0); }
377
+ to[data-rozie-s-12d4265c] { opacity: 0; transform: translateY(0.5rem); }
378
+ .rozie-toast[data-rozie-s-12d4265c] {
379
+ animation: rozie-toast-enter var(--rozie-toast-enter-duration, 200ms) ease-out;
380
+ }
381
+ .rozie-toaster--bottom-left[data-rozie-s-12d4265c] .rozie-toast[data-rozie-s-12d4265c],
382
+ .rozie-toaster--bottom-right[data-rozie-s-12d4265c] .rozie-toast[data-rozie-s-12d4265c],
383
+ .rozie-toaster--bottom-center[data-rozie-s-12d4265c] .rozie-toast[data-rozie-s-12d4265c] {
384
+ animation-name: rozie-toast-enter-from-bottom;
385
+ }
386
+ .rozie-toast--exiting[data-rozie-s-12d4265c] {
387
+ animation: rozie-toast-exit var(--rozie-toast-exit-duration, 200ms) ease-in forwards;
388
+ }
389
+ .rozie-toaster--bottom-left[data-rozie-s-12d4265c] .rozie-toast--exiting[data-rozie-s-12d4265c],
390
+ .rozie-toaster--bottom-right[data-rozie-s-12d4265c] .rozie-toast--exiting[data-rozie-s-12d4265c],
391
+ .rozie-toaster--bottom-center[data-rozie-s-12d4265c] .rozie-toast--exiting[data-rozie-s-12d4265c] {
392
+ animation-name: rozie-toast-exit-to-bottom;
393
+ }
394
+ from[data-rozie-s-12d4265c] { opacity: 0; }
395
+ to[data-rozie-s-12d4265c] { opacity: 1; }
396
+ from[data-rozie-s-12d4265c] { opacity: 1; }
397
+ to[data-rozie-s-12d4265c] { opacity: 0; }
398
+ from[data-rozie-s-12d4265c] { opacity: 1; transform: translateX(0); }
399
+ to[data-rozie-s-12d4265c] { opacity: 0; transform: translateX(calc(var(--rozie-toast-swipe-exit, 1) * 100%)); }
400
+ from[data-rozie-s-12d4265c] { opacity: 1; transform: translateY(0); }
401
+ to[data-rozie-s-12d4265c] { opacity: 0; transform: translateY(calc(var(--rozie-toast-swipe-exit, 1) * 100%)); }
402
+ .rozie-toast--exiting.rozie-toast--swipe-exit[data-rozie-s-12d4265c] {
403
+ animation-name: rozie-toast-swipe-exit-x;
404
+ }
405
+ .rozie-toaster--top-center[data-rozie-s-12d4265c] .rozie-toast--exiting.rozie-toast--swipe-exit[data-rozie-s-12d4265c],
406
+ .rozie-toaster--bottom-center[data-rozie-s-12d4265c] .rozie-toast--exiting.rozie-toast--swipe-exit[data-rozie-s-12d4265c] {
407
+ animation-name: rozie-toast-swipe-exit-y;
408
+ }
409
+ .rozie-toast-spinner[data-rozie-s-12d4265c] {
410
+ flex: 0 0 auto;
411
+ width: var(--rozie-toast-spinner-size, 1em);
412
+ height: var(--rozie-toast-spinner-size, 1em);
413
+ border: 2px solid color-mix(in srgb, var(--rozie-toast-spinner-color, currentColor) 25%, transparent);
414
+ border-top-color: var(--rozie-toast-spinner-color, currentColor);
415
+ border-radius: 50%;
416
+ animation: rozie-toast-spin 0.75s linear infinite;
417
+ }
418
+ to[data-rozie-s-12d4265c] { transform: rotate(360deg); }
419
+ .rozie-toast-message[data-rozie-s-12d4265c] {
420
+ flex: 1 1 auto;
421
+ font-size: var(--rozie-toast-font-size, 0.9rem);
422
+ }
423
+ .rozie-toast-close[data-rozie-s-12d4265c] {
424
+ flex: 0 0 auto;
425
+ display: inline-flex;
426
+ align-items: center;
427
+ justify-content: center;
428
+ width: var(--rozie-toast-close-size, 1.25rem);
429
+ height: var(--rozie-toast-close-size, 1.25rem);
430
+ padding: 0;
431
+ font-size: 1.1rem;
432
+ line-height: 1;
433
+ color: inherit;
434
+ background: transparent;
435
+ border: none;
436
+ border-radius: 0.25rem;
437
+ opacity: var(--rozie-toast-close-opacity, 0.75);
438
+ cursor: pointer;
439
+ }
440
+ .rozie-toast-close[data-rozie-s-12d4265c]:hover {
441
+ opacity: 1;
442
+ }
443
+ `;
444
+ }
445
+ _armListeners() {
446
+ {
447
+ const slotEl = this.shadowRoot?.querySelector("slot[name=\"toast\"]");
448
+ if (slotEl !== null && slotEl !== void 0) {
449
+ const update = () => {
450
+ this._hasSlotToast = this._slotToastElements.length > 0;
451
+ };
452
+ slotEl.addEventListener("slotchange", update);
453
+ this._disconnectCleanups.push(() => slotEl.removeEventListener("slotchange", update));
454
+ update();
455
+ }
456
+ }
457
+ }
458
+ connectedCallback() {
459
+ this._hasSlotToast = Array.from(this.children).some((el) => el.getAttribute("slot") === "toast");
460
+ super.connectedCallback();
461
+ if (this.hasUpdated && this._rozieTornDown) {
462
+ this._rozieTornDown = false;
463
+ this._armListeners();
464
+ }
465
+ }
466
+ firstUpdated() {
467
+ this._armListeners();
468
+ }
469
+ disconnectedCallback() {
470
+ super.disconnectedCallback();
471
+ queueMicrotask(() => {
472
+ if (this.isConnected || this._rozieTornDown) return;
473
+ this._rozieTornDown = true;
474
+ for (const fn of this._disconnectCleanups) fn();
475
+ this._disconnectCleanups = [];
476
+ });
477
+ }
478
+ render() {
479
+ return lit.html`
480
+ <div class="rozie-toaster ${(0, _rozie_runtime_lit.rozieClass)("rozie-toaster--" + this.position + (this.stacked ? " rozie-toaster--stacked" : ""))}" role="region" aria-label=${(0, _rozie_runtime_lit.rozieAttr)(this.regionLabel())} ${(0, _rozie_runtime_lit.rozieSpread)(this.$attrs)} @mouseenter=${($event) => {
481
+ this.onMouseEnter();
482
+ }} @mouseleave=${($event) => {
483
+ this.onMouseLeave();
484
+ }} ${(0, _rozie_runtime_lit.rozieListeners)(this.$listeners)} data-rozie-s-12d4265c>
485
+
486
+ ${(0, lit_directives_repeat_js.repeat)(this._toasts.value, (t, _idx) => t.id, (t, _idx) => lit.html`<div class="rozie-toast ${(0, _rozie_runtime_lit.rozieClass)("rozie-toast--" + t.type + (t.exiting ? " rozie-toast--exiting" : "") + (t.swipeExitSign != null ? " rozie-toast--swipe-exit" : ""))}" key=${(0, _rozie_runtime_lit.rozieAttr)(t.id)} style=${(0, _rozie_runtime_lit.rozieStyle)(this.toastStyle(t))} role="status" aria-live=${(0, _rozie_runtime_lit.rozieAttr)(this.liveFor(t.type))} @animationend=${($event) => {
487
+ t.exiting && this.removeToast(t.id);
488
+ }} @pointerdown=${($event) => {
489
+ this.onToastPointerDown(t, $event);
490
+ }} @pointermove=${($event) => {
491
+ this.onToastPointerMove(t, $event);
492
+ }} @pointerup=${($event) => {
493
+ this.onToastPointerUp(t, $event);
494
+ }} @pointercancel=${($event) => {
495
+ this.onToastPointerCancel(t);
496
+ }} data-rozie-s-12d4265c>
497
+ ${this.toast !== void 0 ? this.toast({
498
+ toast: t,
499
+ dismiss: this.dismiss
500
+ }) : lit.html`<slot name="toast" data-rozie-params=${(() => {
501
+ try {
502
+ return JSON.stringify({ toast: t });
503
+ } catch {
504
+ return "{}";
505
+ }
506
+ })()} @rozie-toast-dismiss=${($event) => this.dismiss($event.detail)}>
507
+ ${t.type === "loading" ? lit.html`<span class="rozie-toast-spinner" aria-hidden="true" data-rozie-s-12d4265c></span>` : lit.nothing}<span class="rozie-toast-message" data-rozie-s-12d4265c>${(0, _rozie_runtime_lit.rozieDisplay)(t.message)}</span>
508
+ <button class="rozie-toast-close" type="button" aria-label="Dismiss" @click=${($event) => {
509
+ this.dismissBegin(t.id, "close");
510
+ }} data-rozie-s-12d4265c>×</button>
511
+ </slot>`}
512
+ </div>`)}
513
+ </div>
514
+ `;
515
+ }
516
+ /**
517
+ * Plan 14-05 — cross-framework attribute fallthrough source. Reads the
518
+ * host custom element's attributes on each call so a consumer-side bound
519
+ * attribute flows through on every render. The `rozieSpread` directive
520
+ * (D-02) does the cross-render diff downstream.
521
+ *
522
+ * Phase 15 follow-up Bug A — declared-prop attribute names are filtered
523
+ * out so `$attrs` returns "rest after declared props" (semantic parity
524
+ * with React/Vue/Svelte/Solid/Angular). Both Lit attribute-naming
525
+ * forms are folded into the skip set: kebab-case for model props
526
+ * (explicit `attribute:`) AND lowercased property name (Lit's default).
527
+ */
528
+ get $attrs() {
529
+ const __skip = new Set([
530
+ "position",
531
+ "duration",
532
+ "max",
533
+ "disable-pause-on-hover",
534
+ "disablepauseonhover",
535
+ "aria-label",
536
+ "arialabel",
537
+ "disable-swipe",
538
+ "disableswipe",
539
+ "stacked"
540
+ ]);
541
+ const out = {};
542
+ for (const a of Array.from(this.attributes)) {
543
+ if (__skip.has(a.name)) continue;
544
+ out[a.name] = a.value;
545
+ }
546
+ return out;
547
+ }
548
+ /**
549
+ * Phase 15 D-19 — consumer-passed listener cluster placeholder.
550
+ * Lit attaches event listeners directly on the host element via
551
+ * `addEventListener` (no per-instance prop rest binding), so the
552
+ * runtime value is undefined; the `rozieListeners` directive's
553
+ * nullish coercion (`obj ?? {}`) handles the no-op cleanly.
554
+ * The declaration exists to satisfy `tsc --noEmit` on consumer
555
+ * projects with strict mode — bare `$listeners` in `render()`
556
+ * would otherwise raise TS2304 (Cannot find name).
557
+ */
558
+ get $listeners() {}
559
+ };
560
+ __decorate([(0, lit_decorators_js.property)({
561
+ type: String,
562
+ reflect: true
563
+ })], Toaster.prototype, "position", void 0);
564
+ __decorate([(0, lit_decorators_js.property)({
565
+ type: Number,
566
+ reflect: true
567
+ })], Toaster.prototype, "duration", void 0);
568
+ __decorate([(0, lit_decorators_js.property)({
569
+ type: Number,
570
+ reflect: true
571
+ })], Toaster.prototype, "max", void 0);
572
+ __decorate([(0, lit_decorators_js.property)({
573
+ type: Boolean,
574
+ reflect: true
575
+ })], Toaster.prototype, "disablePauseOnHover", void 0);
576
+ __decorate([(0, lit_decorators_js.property)({
577
+ type: String,
578
+ reflect: true
579
+ })], Toaster.prototype, "ariaLabel", void 0);
580
+ __decorate([(0, lit_decorators_js.property)({
581
+ type: Boolean,
582
+ reflect: true
583
+ })], Toaster.prototype, "disableSwipe", void 0);
584
+ __decorate([(0, lit_decorators_js.property)({
585
+ type: Boolean,
586
+ reflect: true
587
+ })], Toaster.prototype, "stacked", void 0);
588
+ __decorate([(0, lit_decorators_js.state)()], Toaster.prototype, "_hasSlotToast", void 0);
589
+ __decorate([(0, lit_decorators_js.queryAssignedElements)({
590
+ slot: "toast",
591
+ flatten: true
592
+ })], Toaster.prototype, "_slotToastElements", void 0);
593
+ __decorate([(0, lit_decorators_js.property)({ attribute: false })], Toaster.prototype, "toast", void 0);
594
+ Toaster = __decorate([(0, lit_decorators_js.customElement)("rozie-toaster")], Toaster);
595
+ var Toaster_default = Toaster;
596
+ //#endregion
597
+ exports.Toaster = Toaster_default;
598
+ exports.default = Toaster_default;