@t007/toast 0.0.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/index.js ADDED
@@ -0,0 +1,446 @@
1
+ // src/index.js
2
+ import { clamp, uid, bindAllMethods, createEl, loadResource } from "@t007/utils";
3
+ var T007_Toast = class {
4
+ #autoCloseInterval;
5
+ #progressInterval;
6
+ #timeVisible = 0;
7
+ #isPaused = false;
8
+ #shouldUnPause;
9
+ queue = [];
10
+ destroyed = true;
11
+ #visiblityChange = () => this.#shouldUnPause = document.visibilityState === "visible";
12
+ constructor(options) {
13
+ bindAllMethods(this);
14
+ this.opts = { ...options };
15
+ this.id = this.opts.id ??= uid(this.opts.idPrefix ?? "t007_toast_");
16
+ t007.toasts.set(this.id, this);
17
+ "number" !== typeof this.opts.delay ? this.init() : this.queue.push(setTimeout(this.init, this.opts.delay));
18
+ this.update(this.opts);
19
+ }
20
+ init() {
21
+ this.toastElement = createEl("div", { className: "t007-toast", id: this.id, ariaAtomic: "true" }, { idPrefix: this.opts.idPrefix });
22
+ requestAnimationFrame(() => this.toastElement.classList.add("t007-toast-show"));
23
+ this.destroyed = false;
24
+ }
25
+ update(options) {
26
+ if (!options || typeof options !== "object") return this.opts.id;
27
+ try {
28
+ this.opts = { ...this.opts, ...options };
29
+ const run = () => Object.keys(options).forEach((key) => this[key] = options[key]);
30
+ "number" !== typeof this.opts.delay ? run() : this.queue.push(setTimeout(run, this.opts.delay));
31
+ this.opts.delay = null;
32
+ } catch (err) {
33
+ console.error("toast update failed:", err);
34
+ }
35
+ return this.opts.id;
36
+ }
37
+ play = () => setTimeout(() => this.#isPaused = false);
38
+ pause = () => this.#isPaused = true;
39
+ set rootElement(value) {
40
+ const container = value?.querySelector(`.t007-toast-container[data-position="${this.opts.position}"]`);
41
+ container?.style.setProperty("--t007-toast-container-position", value === document.body ? "fixed" : "absolute");
42
+ container && !value.contains(container) && value.append(container);
43
+ }
44
+ set type(value) {
45
+ this.toastElement.classList.remove("info", "success", "error", "warning");
46
+ value && this.toastElement.classList.add(value);
47
+ this.toastElement.role = value === "error" || value === "warning" ? "alert" : "status";
48
+ this.toastElement.ariaLive = value === "error" || value === "warning" ? "assertive" : "polite";
49
+ if (value) this.icon = this.opts.icon;
50
+ }
51
+ set bodyHTML(value) {
52
+ this.toastElement.querySelectorAll(".t007-toast > *:not(.t007-toast-cancel-button)").forEach((el) => el.remove());
53
+ this.toastElement.insertAdjacentHTML("afterbegin", `${value ? typeof value === "function" ? value() : value : ""}`);
54
+ }
55
+ set render(value) {
56
+ const bodyText = () => this.toastElement.querySelector(".t007-toast-body-text");
57
+ if (value) {
58
+ this._setUpBodyHTML();
59
+ this.toastElement.querySelector(".t007-toast-body").prepend(bodyText() || createEl("p", { className: "t007-toast-body-text" }));
60
+ const text = bodyText();
61
+ text.innerHTML = text.dataset.render = typeof value === "function" ? value() : value;
62
+ } else bodyText()?.remove();
63
+ }
64
+ set actions(value) {
65
+ const actionsWrapper = () => this.toastElement.querySelector(".t007-toast-actions-wrapper"), values = value ? Object.entries(value) : [];
66
+ if (values.length) {
67
+ this._setUpBodyHTML();
68
+ this.toastElement.querySelector(".t007-toast-body").insertAdjacentElement("afterend", actionsWrapper() || createEl("div", { className: "t007-toast-actions-wrapper" }));
69
+ const wrapper = actionsWrapper();
70
+ wrapper.innerHTML = values.map(([label]) => label ? `<button class="t007-toast-action-button" data-action="${label}">${label}</button>` : "").join("");
71
+ wrapper.querySelectorAll(".t007-toast-action-button").forEach((btn, i) => btn.onclick = (e) => values[i][1]?.(e, this));
72
+ } else actionsWrapper()?.remove();
73
+ }
74
+ set image(value) {
75
+ const image = () => this.toastElement.querySelector(".t007-toast-image");
76
+ if (value) {
77
+ this._setUpBodyHTML();
78
+ this.toastElement.querySelector(".t007-toast-image-wrapper").prepend(
79
+ image() || createEl("img", {
80
+ className: "t007-toast-image",
81
+ alt: "toast-image"
82
+ })
83
+ );
84
+ const img = image();
85
+ img.src = value;
86
+ img.onload = img.onerror = () => img.dataset.loaded = img.complete && img.naturalWidth > 0;
87
+ } else image()?.remove();
88
+ }
89
+ get icon() {
90
+ return this.opts.icon === true ? t007.TOAST_ICONS[this.opts.type] || "" : this.opts.icon || "";
91
+ }
92
+ set icon(value) {
93
+ if (this.opts.isLoading) return;
94
+ const icon = () => this.toastElement.querySelector(".t007-toast-icon:not(.t007-toast-loader)");
95
+ if (value) {
96
+ this._setUpBodyHTML();
97
+ this.toastElement.querySelector(".t007-toast-image-wrapper").appendChild(icon() || createEl("span", { className: "t007-toast-icon" }));
98
+ const icn = icon();
99
+ icn.innerHTML = icn.dataset.icon = this.icon;
100
+ } else icon()?.remove();
101
+ }
102
+ set isLoading(value) {
103
+ const loader = () => this.toastElement.querySelector(".t007-toast-loader");
104
+ if (value) {
105
+ this._setUpBodyHTML();
106
+ this.toastElement.querySelectorAll(".t007-toast-icon:not(.t007-toast-loader)").forEach((i) => i.remove());
107
+ this.toastElement.querySelector(".t007-toast-image-wrapper").appendChild(
108
+ loader() || createEl("span", {
109
+ className: "t007-toast-icon t007-toast-loader"
110
+ })
111
+ );
112
+ loader().innerHTML = typeof value === "string" ? value : t007.TOAST_ICONS.loading;
113
+ } else {
114
+ loader()?.remove();
115
+ this.icon = this.opts.icon;
116
+ }
117
+ }
118
+ set closeButton(value) {
119
+ const btn = this.toastElement.querySelector(".t007-toast-cancel-button");
120
+ if (value)
121
+ this.toastElement.appendChild(
122
+ btn || createEl("button", {
123
+ title: "Close",
124
+ ariaLabel: "Close notification",
125
+ className: "t007-toast-cancel-button",
126
+ innerHTML: "&times;",
127
+ onclick: this._remove
128
+ })
129
+ );
130
+ else btn?.remove();
131
+ }
132
+ get animation() {
133
+ if (this.opts.animation === true || this.opts.animation === "slide")
134
+ switch (this.opts.position) {
135
+ case "top-right":
136
+ case "center-right":
137
+ case "bottom-right":
138
+ return "slide-left";
139
+ case "top-center":
140
+ case "center-center":
141
+ case "bottom-center":
142
+ return this.opts.position === "top-center" ? "slide-down" : "slide-up";
143
+ case "top-left":
144
+ case "center-left":
145
+ case "bottom-left":
146
+ default:
147
+ return "slide-right";
148
+ }
149
+ return this.opts.animation;
150
+ }
151
+ set animation(value) {
152
+ this.toastElement.dataset.animation = this.animation;
153
+ }
154
+ get autoClose() {
155
+ return this.opts.autoClose === true ? t007.TOAST_DURATIONS[this.opts.type] || t007.TOAST_DURATIONS.info : this.opts.autoClose;
156
+ }
157
+ set autoClose(value) {
158
+ cancelAnimationFrame(this.#autoCloseInterval);
159
+ this.#timeVisible = 0;
160
+ let lastTime;
161
+ const loop = (time) => {
162
+ if (this.#shouldUnPause) {
163
+ lastTime = null;
164
+ this.#shouldUnPause = false;
165
+ }
166
+ if (lastTime == null) {
167
+ lastTime = time;
168
+ return this.#autoCloseInterval = requestAnimationFrame(loop);
169
+ }
170
+ if (!this.#isPaused) {
171
+ this.#timeVisible += time - lastTime;
172
+ this.onTimeUpdate?.(this.#timeVisible);
173
+ if ("number" == typeof this.autoClose && this.#timeVisible >= this.autoClose) return this._remove("smooth", true);
174
+ }
175
+ lastTime = time;
176
+ this.#autoCloseInterval = requestAnimationFrame(loop);
177
+ };
178
+ if (value) this.#autoCloseInterval = requestAnimationFrame(loop);
179
+ }
180
+ set position(value) {
181
+ const currentContainer = this.toastElement.parentElement;
182
+ const container = this.opts.rootElement?.querySelector(`.t007-toast-container[data-position="${value}"]`) || this._createContainer(value);
183
+ container[this.opts.newestOnTop ? "prepend" : "append"](this.toastElement);
184
+ if (!(currentContainer == null || currentContainer.hasChildNodes())) currentContainer.remove();
185
+ }
186
+ set closeOnClick(value) {
187
+ this.toastElement.onclick = value ? () => this._remove() : null;
188
+ }
189
+ set hideProgressBar(value) {
190
+ this.toastElement.classList.toggle("progress", !value);
191
+ this.nprogress = 0;
192
+ cancelAnimationFrame(this.#progressInterval);
193
+ const loop = () => {
194
+ if ("number" == typeof this.autoClose && !this.#isPaused) this.nprogress = 1 - this.#timeVisible / this.autoClose;
195
+ this.#progressInterval = requestAnimationFrame(loop);
196
+ };
197
+ if (!value) this.#progressInterval = requestAnimationFrame(loop);
198
+ }
199
+ get nprogress() {
200
+ return Number(this.toastElement.style.getProperty("--progress"));
201
+ }
202
+ set nprogress(value) {
203
+ this.toastElement.style.setProperty("--progress", value);
204
+ }
205
+ set pauseOnHover(value) {
206
+ this.toastElement.onmouseover = value ? this.pause : null;
207
+ this.toastElement.onmouseleave = value ? this.play : null;
208
+ this.toastElement[value ? "addEventListener" : "removeEventListener"]("touchend", this.play);
209
+ }
210
+ set pauseOnFocusLoss(value) {
211
+ value ? document.addEventListener("visibilitychange", this.#visiblityChange) : document.removeEventListener("visibilitychange", this.#visiblityChange);
212
+ }
213
+ set tag(value) {
214
+ this.toastElement.dataset.tag = value;
215
+ }
216
+ set renotify(value) {
217
+ value && this.opts.tag && t007.toasts.entries().forEach(([id, toast2]) => id !== this.id && (toast2.opts.tag ?? 1) === (this.opts.tag ?? 0) && toast2._remove("instant"));
218
+ }
219
+ get vibrate() {
220
+ return this.opts.vibrate === true ? t007.TOAST_VIBRATIONS[this.opts.type] || t007.TOAST_VIBRATIONS.info : this.opts.vibrate;
221
+ }
222
+ set vibrate(value) {
223
+ value && navigator?.vibrate?.(this.vibrate);
224
+ }
225
+ set maxToasts(value) {
226
+ const toastsInContainer = [...this.toastElement?.parentElement?.children || []];
227
+ if (!toastsInContainer.length) return;
228
+ for (let i = 0; i < toastsInContainer.length - value; i++) {
229
+ [...t007.toasts.values()].find((t) => t.toastElement === (this.opts.newestOnTop ? toastsInContainer[toastsInContainer.length - 1 - i] : toastsInContainer[i]))?._remove("instant");
230
+ }
231
+ }
232
+ set newestOnTop(value) {
233
+ this.toastElement?.parentElement?.[value ? "prepend" : "append"](this.toastElement);
234
+ }
235
+ set dragToClose(value) {
236
+ this.toastElement.dataset.dragToClose = this._ptrType = value;
237
+ this.toastElement.onpointerdown = value ? this._handleToastPointerStart : null;
238
+ this.toastElement.onpointerup = value ? this._handleToastPointerUp : null;
239
+ }
240
+ _handleToastPointerStart(e) {
241
+ if (typeof this._ptrType === "string" && e.pointerType !== this._ptrType) return;
242
+ if (e.touches?.length > 1) return;
243
+ !e.target?.matches('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])') && this.toastElement.setPointerCapture(e.pointerId);
244
+ this.#isPaused = true;
245
+ this._ptrTicker = this._ptrDirSet = this._ptrDir = false;
246
+ this._ptrStartX = e.clientX ?? e.targetTouches[0]?.clientX;
247
+ this._ptrStartY = e.clientY ?? e.targetTouches[0]?.clientY;
248
+ this.toastElement.addEventListener("pointermove", this._handleToastPointerMove, { passive: false });
249
+ this.toastElement.style.setProperty("transition", "none", "important");
250
+ }
251
+ _handleToastPointerMove(e) {
252
+ e.preventDefault();
253
+ if (this._ptrTicker) return;
254
+ this._ptrRAF = requestAnimationFrame(() => {
255
+ const has = (str) => this.opts.dragToCloseDir.includes(str), x = e.clientX ?? e.targetTouches[0]?.clientX, y = e.clientY ?? e.targetTouches[0]?.clientY;
256
+ this._ptrDir ||= Math.abs(x - this._ptrStartX) >= Math.abs(y - this._ptrStartY) ? "x" : "y";
257
+ this._ptrDeltaX = (has("|") ? this._ptrDir == "x" : has("x")) && !has(x - this._ptrStartX > 0 ? "-" : "+") ? x - this._ptrStartX : 0;
258
+ this._ptrDeltaY = (has("|") ? this._ptrDir == "y" : has("y")) && !has(y - this._ptrStartY > 0 ? "+" : "-") ? y - this._ptrStartY : 0;
259
+ this.toastElement.style.setProperty("transform", `translate(${this._ptrDeltaX}px, ${this._ptrDeltaY}px)`, "important");
260
+ const xR = Math.abs(this._ptrDeltaX) / this.toastElement.offsetWidth, yR = Math.abs(this._ptrDeltaY) / this.toastElement.offsetHeight;
261
+ this.toastElement.style.setProperty("opacity", clamp(0, 1 - (yR > 0.5 ? yR : xR), 1), "important");
262
+ if (!this._ptrDirSet && !xR && !yR) this._ptrDir = false;
263
+ if (this._ptrDir) this._ptrDirSet = has("||");
264
+ this._ptrTicker = false;
265
+ });
266
+ this._ptrTicker = true;
267
+ }
268
+ _handleToastPointerUp(e) {
269
+ if (typeof this._ptrType === "string" && e.pointerType !== this._ptrType) return;
270
+ cancelAnimationFrame(this._ptrRAF);
271
+ if (Math.abs(this._ptrDeltaX) > this.toastElement.offsetWidth * (this.opts.dragToClosePercent.x ?? this.opts.dragToClosePercent / 100) || Math.abs(this._ptrDeltaY) > this.toastElement.offsetHeight * (this.opts.dragToClosePercent.y ?? this.opts.dragToClosePercent / 100)) return this._remove("instant");
272
+ this.#isPaused = this._ptrTicker = this._ptrDirSet = this._ptrDir = false;
273
+ this.toastElement.removeEventListener("pointermove", this._handleToastPointerMove, { passive: false });
274
+ this.toastElement.style.removeProperty("transition");
275
+ this.toastElement.style.removeProperty("transform");
276
+ this.toastElement.style.removeProperty("opacity");
277
+ }
278
+ _remove(manner = "smooth", timeElapsed = false) {
279
+ if (!this.opts.isLoading) t007.toasts.delete(this.id);
280
+ this.queue.forEach(clearTimeout);
281
+ document.removeEventListener("visibilitychange", this.#visiblityChange);
282
+ cancelAnimationFrame(this.#autoCloseInterval);
283
+ cancelAnimationFrame(this.#progressInterval);
284
+ if (this.destroyed || manner === "instant" || !this.animation) this._cleanUpToast();
285
+ else this.toastElement.onanimationend = this._cleanUpToast;
286
+ this.toastElement.classList.remove("t007-toast-show");
287
+ this.onClose?.(timeElapsed);
288
+ }
289
+ _createContainer(position) {
290
+ const container = document.createElement("div");
291
+ container.classList.add("t007-toast-container");
292
+ container.style.setProperty("--t007-toast-container-position", this.opts.rootElement === document.body ? "fixed" : "absolute");
293
+ container.dataset.position = position;
294
+ this.opts.rootElement?.append(container);
295
+ return container;
296
+ }
297
+ _setUpBodyHTML() {
298
+ this.toastElement.querySelectorAll(".t007-toast > *:not(.t007-toast-image-wrapper, .t007-toast-body, .t007-toast-actions-wrapper, .t007-toast-cancel-button)").forEach((el) => el.remove());
299
+ const imageWrapper = () => this.toastElement.querySelector(".t007-toast-image-wrapper");
300
+ if (!imageWrapper()) this.toastElement.prepend(createEl("div", { className: "t007-toast-image-wrapper" }));
301
+ if (!this.toastElement.querySelector(".t007-toast-body")) imageWrapper().insertAdjacentElement("afterend", createEl("div", { className: "t007-toast-body" }));
302
+ }
303
+ _cleanUpToast() {
304
+ const container = this.toastElement.parentElement;
305
+ this.toastElement.remove();
306
+ if (!container?.hasChildNodes()) container?.remove();
307
+ this.destroyed = true;
308
+ }
309
+ };
310
+ var toasting = {
311
+ update(base, id, options) {
312
+ const toast2 = t007.toasts.get(id);
313
+ toast2?.queue.forEach(clearTimeout);
314
+ return !!toast2 && (toast2.destroyed ? base(options.render, { ...toast2.opts, id, ...options }) : toast2.update(options));
315
+ },
316
+ message: (base, defaults, action) => base[action] = (renderOrId, options = {}) => {
317
+ options = { ...options, type: action === "warn" ? "warning" : action };
318
+ if (!t007.toasts.get(renderOrId)) return base(renderOrId, options);
319
+ const { autoClose, closeButton, closeOnClick, dragToClose } = defaults();
320
+ return base.update(renderOrId, {
321
+ ...t007.toasts.get(renderOrId)?.opts.isLoading ? { autoClose, closeButton, closeOnClick, dragToClose } : {},
322
+ ...options,
323
+ isLoading: false
324
+ });
325
+ },
326
+ loading: (base, renderOrId, options = {}) => (t007.toasts.get(renderOrId) ? base.update : base)(renderOrId, {
327
+ autoClose: false,
328
+ closeButton: false,
329
+ closeOnClick: false,
330
+ dragToClose: false,
331
+ ...options,
332
+ isLoading: options.isLoading || true,
333
+ type: ""
334
+ }),
335
+ promise(base, promise = new Promise((res, rej) => setTimeout(Math.round(Math.random()) ? res : rej, 3e3)), { pending, success, error } = {}) {
336
+ if (!promise || typeof promise.then !== "function") return console.error("toast.promise() requires a valid promise");
337
+ const NFC = (input, type) => typeof input === "string" ? { render: input, type } : typeof input === "object" ? { ...input, type } : { type };
338
+ const pendingConfig = NFC(pending);
339
+ const pendingToastId = base.loading(pendingConfig.render || "Promise pending...", { ...pendingConfig });
340
+ promise.then(
341
+ (response) => {
342
+ const successConfig = NFC(success || "Promise resolved", "success");
343
+ const { render, bodyHTML } = successConfig;
344
+ if (typeof render === "function") successConfig.render = (response2) => render(response2);
345
+ if (typeof bodyHTML === "function") successConfig.bodyHTML = (response2) => bodyHTML(response2);
346
+ base.success(pendingToastId, successConfig);
347
+ return response;
348
+ },
349
+ (err) => {
350
+ const errorConfig = NFC(error || "Promise rejected", "error");
351
+ const { render, bodyHTML } = errorConfig;
352
+ if (typeof render === "function") errorConfig.render = (err2) => render(err2);
353
+ if (typeof bodyHTML === "function") errorConfig.bodyHTML = (err2) => bodyHTML(err2);
354
+ base.error(pendingToastId, errorConfig);
355
+ return Promise.reject(err);
356
+ }
357
+ );
358
+ return promise;
359
+ },
360
+ dismiss(base, id, manner, timeElapsed) {
361
+ return !arguments.length ? base.dismissAll() : t007.toasts.get(id)?._remove(manner, timeElapsed);
362
+ },
363
+ dismissAll(base, idPrefix) {
364
+ t007.toasts.values().forEach((toast2) => (!arguments.length ? true : toast2.id.startsWith(idPrefix)) && toast2._remove());
365
+ },
366
+ doForAll(base, action, options, idPrefix) {
367
+ t007.toasts.keys().forEach((id) => (!arguments.length ? true : id.startsWith(idPrefix)) && base[action]?.(id, options));
368
+ },
369
+ getAll(base, idPrefix) {
370
+ return t007.toasts.values().filter((toast2) => !arguments.length ? true : toast2.id.startsWith(idPrefix));
371
+ }
372
+ };
373
+ var toaster = (defOptions = {}, idPrefix = "t007_toast_") => {
374
+ const defaults = () => ({ ...t007.TOAST_DEFAULT_OPTIONS, ...defOptions }), base = (render, options = {}) => new T007_Toast({
375
+ ...defaults(),
376
+ ...options,
377
+ id: render?.startsWith?.(idPrefix) ? render : options.id,
378
+ render: render?.startsWith?.(idPrefix) ? options.render : render,
379
+ idPrefix
380
+ }).id;
381
+ base.update = (id, options) => toasting.update(base, id, options);
382
+ ["info", "success", "warn", "error"].forEach((action) => toasting.message(base, defaults, action));
383
+ base.loading = (render, options) => toasting.loading(base, render, options);
384
+ base.promise = (promise, options) => toasting.promise(base, promise, options);
385
+ base.dismiss = (id, manner, timeElapsed) => toasting.dismiss(base, id, manner, timeElapsed);
386
+ base.dismissAll = (idPrefix2) => toasting.dismissAll(base, idPrefix2);
387
+ base.doForAll = (action, options, idPrefix2) => toasting.doForAll(base, action, options, idPrefix2);
388
+ base.getAll = (idPrefix2) => toasting.getAll(base, idPrefix2);
389
+ return base;
390
+ };
391
+ var toast = toaster();
392
+ var index_default = toast;
393
+ if (typeof window !== "undefined") {
394
+ window.t007 ??= {};
395
+ t007.toast = toast;
396
+ t007.toasting = toasting;
397
+ t007.toaster = toaster;
398
+ t007.toasts = /* @__PURE__ */ new Map();
399
+ t007.TOAST_DEFAULT_OPTIONS ??= {};
400
+ t007.TOAST_DURATIONS ??= {};
401
+ t007.TOAST_VIBRATIONS ??= {};
402
+ t007.TOAST_ICONS ??= {};
403
+ t007.TOAST_DEFAULT_OPTIONS.rootElement ??= document.body;
404
+ t007.TOAST_DEFAULT_OPTIONS.render ??= "";
405
+ t007.TOAST_DEFAULT_OPTIONS.type ??= "";
406
+ t007.TOAST_DEFAULT_OPTIONS.icon ??= true;
407
+ t007.TOAST_DEFAULT_OPTIONS.image ??= false;
408
+ t007.TOAST_DEFAULT_OPTIONS.autoClose ??= true;
409
+ t007.TOAST_DEFAULT_OPTIONS.position ??= "top-right";
410
+ t007.TOAST_DEFAULT_OPTIONS.isLoading ??= false;
411
+ t007.TOAST_DEFAULT_OPTIONS.closeButton ??= !/Mobi|Android|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
412
+ t007.TOAST_DEFAULT_OPTIONS.closeOnClick ??= false;
413
+ t007.TOAST_DEFAULT_OPTIONS.hideProgressBar ??= false;
414
+ t007.TOAST_DEFAULT_OPTIONS.pauseOnHover ??= true;
415
+ t007.TOAST_DEFAULT_OPTIONS.pauseOnFocusLoss ??= true;
416
+ t007.TOAST_DEFAULT_OPTIONS.dragToClose ??= true;
417
+ t007.TOAST_DEFAULT_OPTIONS.dragToClosePercent ??= 40;
418
+ t007.TOAST_DEFAULT_OPTIONS.dragToCloseDir ??= "x";
419
+ t007.TOAST_DEFAULT_OPTIONS.renotify ??= true;
420
+ t007.TOAST_DEFAULT_OPTIONS.vibrate ??= false;
421
+ t007.TOAST_DEFAULT_OPTIONS.animation ??= true;
422
+ t007.TOAST_DEFAULT_OPTIONS.newestOnTop ??= false;
423
+ t007.TOAST_DEFAULT_OPTIONS.maxToasts ??= 1e3;
424
+ t007.TOAST_DURATIONS.success ??= 2500;
425
+ t007.TOAST_DURATIONS.error ??= 4500;
426
+ t007.TOAST_DURATIONS.warning ??= 3500;
427
+ t007.TOAST_DURATIONS.info ??= 4e3;
428
+ t007.TOAST_VIBRATIONS.success ??= [100, 50, 100];
429
+ t007.TOAST_VIBRATIONS.warning ??= [300, 100, 300];
430
+ t007.TOAST_VIBRATIONS.error ??= [500, 200, 500];
431
+ t007.TOAST_VIBRATIONS.info ??= [200];
432
+ t007.TOAST_ICONS.success ??= `<svg class="no-css-fill" width="24" height="24" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="#27ae60"/><path fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 12l3 3l6-6"/></svg>`;
433
+ t007.TOAST_ICONS.error ??= `<svg class="no-css-fill" width="24" height="24" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="#e74c3c"/><path fill="#fff" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M8 8l8 8M16 8l-8 8"/></svg>`;
434
+ t007.TOAST_ICONS.warning ??= `<svg class="no-css-fill" width="24" height="24" viewBox="0 0 24 24"><path fill="#f1c40f" stroke="#f39c12" stroke-width="2" stroke-linejoin="round" d="M12 3L2.5 20.5A2 2 0 0 0 4.5 23h15a2 2 0 0 0 2-2.5L12 3z"/><circle cx="12" cy="17" r="1.5" fill="#fff"/><path fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M12 8v6"/></svg>`;
435
+ t007.TOAST_ICONS.info ??= `<svg class="no-css-fill" width="24" height="24" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="#3498db"/><path fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M12 10v6"/><circle cx="12" cy="7" r="1.5" fill="#fff"/></svg>`;
436
+ t007.TOAST_ICONS.loading ??= `<svg class="no-css-fill" width="24" height="24" viewBox="0 0 16 16" fill="none" style="scale:0.75;"><g fill-rule="evenodd" clip-rule="evenodd"><path fill="whitesmoke" d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8"/><path fill="gray" d="M7.25.75A.75.75 0 0 1 8 0a8 8 0 0 1 8 8 .75.75 0 0 1-1.5 0A6.5 6.5 0 0 0 8 1.5a.75.75 0 0 1-.75-.75"/></g><animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="360" dur="600ms" repeatCount="indefinite"/></svg>`;
437
+ window.T007_TOAST_CSS_SRC ??= `https://unpkg.com/@t007/toast@latest/style.css`;
438
+ loadResource(T007_TOAST_CSS_SRC);
439
+ window.Toast ??= t007.toast;
440
+ console.log("%cT007 Toasts attached to window!", "color: darkturquoise");
441
+ }
442
+ export {
443
+ index_default as default,
444
+ toaster,
445
+ toasting
446
+ };
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@t007/toast",
3
+ "version": "0.0.1",
4
+ "description": "A lightweight, pure JS toast system.",
5
+ "author": "Oketade Oluwatobiloba <tobioketade007@gmail.com>",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/tobi007-del/t007-tools.git",
10
+ "directory": "packages/toast"
11
+ },
12
+ "homepage": "https://github.com/tobi007-del/t007-tools/tree/main/packages/toast#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/tobi007-del/t007-tools/issues"
15
+ },
16
+ "type": "module",
17
+ "main": "./dist/index.js",
18
+ "module": "./dist/index.js",
19
+ "browser": "./dist/index.global.js",
20
+ "unpkg": "./dist/index.global.js",
21
+ "types": "./src/ts/types/index.d.ts",
22
+ "style": "./src/css/index.css",
23
+ "sideEffects": [
24
+ "*.css"
25
+ ],
26
+ "exports": {
27
+ ".": {
28
+ "types": "./src/ts/types/index.d.ts",
29
+ "import": "./dist/index.js",
30
+ "default": "./dist/index.global.js"
31
+ },
32
+ "./style.css": "./src/css/index.css"
33
+ },
34
+ "scripts": {
35
+ "build": "tsup src/index.js --format esm,iife --clean"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "./src/ts/types/index.d.ts",
40
+ "./src/css/index.css"
41
+ ],
42
+ "keywords": [
43
+ "t007",
44
+ "toast",
45
+ "snackbar",
46
+ "notification",
47
+ "alert",
48
+ "promise",
49
+ "ui",
50
+ "vanilla-js",
51
+ "zero-dependency"
52
+ ],
53
+ "dependencies": {
54
+ "@t007/utils": "*"
55
+ }
56
+ }