@t007/toast 0.0.4 → 0.0.6

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 OLUWATOBILOBA OKETADE
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,236 @@
1
+ # @t007/toast
2
+
3
+ > A high-performance, physics-driven vanilla JavaScript toast notification system. Features multi-touch drag-to-close gestures, hardware-accelerated animations, and a seamless Promise-resolution API.
4
+
5
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+ [![NPM Version](https://img.shields.io/npm/v/@t007/toast.svg)](https://www.npmjs.com/package/@t007/toast)
7
+
8
+ [Live Demo](https://tobi007-del.github.io/t007-tools/packages/toast/src/index.html) | [Report Bug](https://github.com/Tobi007-del/t007-tools/issues)
9
+
10
+ ---
11
+
12
+ ## Table of contents
13
+
14
+ - [@t007/toast](#t007toast)
15
+ - [Table of contents](#table-of-contents)
16
+ - [Overview](#overview)
17
+ - [Demo \& Screenshots](#demo--screenshots)
18
+ - [Features](#features)
19
+ - [Tech Stack](#tech-stack)
20
+ - [Getting Started](#getting-started)
21
+ - [Usage](#usage)
22
+ - [API Reference](#api-reference)
23
+ - [Advanced Customization](#advanced-customization)
24
+ - [Author](#author)
25
+ - [Acknowledgments](#acknowledgments)
26
+
27
+ ---
28
+
29
+ ## Overview
30
+
31
+ **@t007/toast** is not just another notification library. It is a highly optimized, requestAnimationFrame-driven notification engine that mimics native mobile OS behaviors. It handles complex pointer gestures, pauses on window blur/hover, and manages a dynamic queue to prevent screen flooding.
32
+
33
+ ### Why @t007/toast?
34
+
35
+ - ✅ **Physics-Driven Gestures:** Native-feeling "drag-to-close" utilizing Pointer Events (`x`, `y`, and directional configuration).
36
+ - ✅ **Intelligent Lifecycle:** Automatically pauses the auto-close timer and progress bar when hovered or when the browser tab loses focus.
37
+ - ✅ **Promise Integration:** Pass an async operation and the toast will automatically transition from "loading" to "success" or "error".
38
+ - ✅ **Haptic Feedback:** Optional built-in `navigator.vibrate` integration for physical feedback on mobile devices.
39
+ - ✅ **Zero Frameworks:** Pure vanilla JS, meaning it works flawlessly in React, Vue, Angular, or raw HTML.
40
+
41
+ ---
42
+
43
+ ## Demo & Screenshots
44
+
45
+ ### Standard Toast Notifications
46
+ Features built-in SVG icons, custom actions, and smooth hardware-accelerated animations.
47
+ <img src="https://raw.githubusercontent.com/Tobi007-del/t007-tools/refs/heads/main/assets/images/toast_library_toast_preview.png" alt="Toast Preview" width="600" />
48
+
49
+ ---
50
+
51
+ ## Features
52
+
53
+ - **9 Positioning Zones**: Anchor toasts anywhere on the screen (e.g., `top-right`, `bottom-center`, `center-center`).
54
+ - **Dynamic Updating**: Update the text, icon, or type of an active toast without breaking its animation loop.
55
+ - **Queue Management**: Strict enforcement of `maxToasts` and `renotify` to keep the UI clean.
56
+ - **Custom Hardware Vibrations**: Unique vibration patterns for different alert types (`success`, `error`, `warning`).
57
+
58
+ ---
59
+
60
+ ## Tech Stack
61
+
62
+ ### Built with
63
+
64
+ - Vanilla JavaScript (ES6+)
65
+ - `requestAnimationFrame` Time Loops
66
+ - Pointer Events API
67
+ - Vibration API
68
+ - Bundled via `tsup` (ESM, CJS, IIFE outputs)
69
+
70
+ ---
71
+
72
+ ## Getting Started
73
+
74
+ ### Installation
75
+
76
+ Install via your preferred package manager:
77
+
78
+ ```bash
79
+ npm install @t007/toast @t007/utils
80
+ # or
81
+ yarn add @t007/toast @t007/utils
82
+ # or
83
+ pnpm add @t007/toast @t007/utils
84
+ ````
85
+
86
+ -----
87
+
88
+ ## Usage
89
+
90
+ ### Modern Bundlers (ESM)
91
+
92
+ ```javascript
93
+ import '@t007/toast/style.css';
94
+ import toast from '@t007/toast'; // also attached to window.t007
95
+
96
+ // 1. Simple success toast
97
+ toast.success("File uploaded successfully!");
98
+
99
+ // 2. Error toast with custom actions
100
+ toast.error("Connection failed", {
101
+ position: "bottom-right",
102
+ actions: {
103
+ "Retry": (e, instance) => {
104
+ console.log("Retrying...");
105
+ instance._remove();
106
+ }
107
+ }
108
+ });
109
+
110
+ // 3. Promise Handling
111
+ const myFetch = fetch('[https://api.example.com/data](https://api.example.com/data)');
112
+
113
+ toast.promise(myFetch, {
114
+ pending: "Loading data...",
115
+ success: "Data loaded successfully!",
116
+ error: "Failed to load data."
117
+ });
118
+ ```
119
+
120
+ ### CDN / Browser (Global)
121
+
122
+ If you are not using a bundler, the library automatically injects itself into the global `t007` object and provides the convenient `window.Toast` fallback.
123
+
124
+ ```html
125
+ <!DOCTYPE html>
126
+ <html>
127
+ <head>
128
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@t007/toast@latest/dist/index.min.css">
129
+ </head>
130
+ <body>
131
+
132
+ <button id="notifyBtn">Show Toast</button>
133
+
134
+ <script src="https://cdn.jsdelivr.net/npm/@t007/toast@latest"></script>
135
+
136
+ <script>
137
+ document.getElementById('notifyBtn').addEventListener('click', () => {
138
+ Toast.info("System running smoothly.", {
139
+ pauseOnHover: true,
140
+ dragToClose: true
141
+ }); // or use `t007.toast -> t007.toast.info()`
142
+ });
143
+ </script>
144
+ </body>
145
+ </html>
146
+ ```
147
+
148
+ -----
149
+
150
+ ## API Reference
151
+
152
+ ### Basic Toasts
153
+
154
+ Trigger toasts based on their severity. Returns the unique `id` of the generated toast.
155
+
156
+ - `toast(render, options)` (Default / Info)
157
+ - `toast.info(render, options)`
158
+ - `toast.success(render, options)`
159
+ - `toast.warn(render, options)`
160
+ - `toast.error(render, options)`
161
+
162
+ ### Toast Updating
163
+
164
+ You can dynamically update a toast that is currently on the screen.
165
+
166
+ ```javascript
167
+ const toastId = toast.loading("Processing...");
168
+
169
+ // Later in your code...
170
+ toast.update(toastId, {
171
+ render: "Processing complete!",
172
+ type: "success",
173
+ isLoading: false,
174
+ autoClose: 3000
175
+ });
176
+ ```
177
+
178
+ ### Promise Handling
179
+
180
+ Automatically maps a JavaScript Promise to the lifecycle of a toast.
181
+
182
+ ```javascript
183
+ toast.promise(promiseFunction, {
184
+ pending: { render: "Waiting...", type: "info" },
185
+ success: { render: (res) => `Success: ${res.data}`, type: "success" },
186
+ error: { render: (err) => `Failed: ${err.message}`, type: "error" }
187
+ });
188
+ ```
189
+
190
+ ### Configuration Options
191
+
192
+ The second argument of any toast call accepts a massive configuration object.
193
+
194
+ | Property | Type | Default | Description |
195
+ | ------------------ | -------------- | ------------- | --------------------------------------------------------- |
196
+ | `position` | String | `"top-right"` | The screen anchor point. |
197
+ | `autoClose` | Boolean/Number | `true` | MS to close, or false to disable. |
198
+ | `dragToClose` | Boolean/String | `true` | Allows swipe-to-dismiss via Pointer Events. |
199
+ | `dragToCloseDir` | String | `"x"` | Direction allowed for swiping (`x`, `y`, `x\|y`). |
200
+ | `pauseOnHover` | Boolean | `true` | Pauses timer when mouse enters toast. |
201
+ | `pauseOnFocusLoss` | Boolean | `true` | Pauses timer when window loses focus. |
202
+ | `vibrate` | Boolean/Array | `false` | Triggers device haptic feedback based on severity. |
203
+ | `actions` | Object | `null` | Key/Value object of button labels and callback functions. |
204
+
205
+ *(See source code for global configuration overrides via `t007.TOAST_DEFAULT_OPTIONS`).*
206
+
207
+ -----
208
+
209
+ ## Advanced Customization
210
+
211
+ ### The Global Config
212
+
213
+ You can override the default behavior for all toasts globally:
214
+
215
+ ```javascript
216
+ window.t007.TOAST_DEFAULT_OPTIONS.position = "bottom-center";
217
+ window.t007.TOAST_DEFAULT_OPTIONS.vibrate = true;
218
+
219
+ // Custom Durations
220
+ window.t007.TOAST_DURATIONS.error = 10000; // Leave errors up for 10 seconds
221
+ ```
222
+
223
+ ### CSS Variables
224
+
225
+ You can easily override the progress bar, animations, and container spacing by targeting `.t007-toast` in your stylesheet.
226
+
227
+ -----
228
+
229
+ ## Author
230
+
231
+ - Developer - [Oketade Oluwatobiloba (Tobi007-del)](https://github.com/Tobi007-del)
232
+ - Project - [t007-tools](https://github.com/Tobi007-del/t007-tools)
233
+
234
+ ## Acknowledgments
235
+
236
+ Designed to bring native mobile OS notification physics to the web. Part of the `@t007` utility ecosystem.
@@ -1,3 +1,4 @@
1
+ /* src/css/index.css */
1
2
  :where(:root) {
2
3
  --t007-toast-font-family: inherit;
3
4
  --t007-toast-info-color: #3498db;
@@ -20,7 +21,6 @@
20
21
  --t007-toast-action-button-font-weight: 500;
21
22
  --t007-toast-x-color: red;
22
23
  }
23
-
24
24
  :where(:root, .t007-toast) {
25
25
  --t007-toast-type-color: whitesmoke;
26
26
  --t007-toast-focus-visible-color: var(--t007-toast-font-color);
@@ -33,7 +33,6 @@
33
33
  --t007-toast-action-button-background: rgba(from currentColor r g b / 0.1);
34
34
  --t007-toast-action-button-active-background: rgba(from currentColor r g b / 0.2);
35
35
  }
36
-
37
36
  :where(:root, .t007-toast-container) {
38
37
  --t007-toast-unit: 1rem;
39
38
  --t007-toast-container-margin-top: calc(var(--t007-toast-unit) / 2);
@@ -71,7 +70,6 @@
71
70
  --t007-toast-font-weight: inherit;
72
71
  --t007-toast-x-size: calc(var(--t007-toast-unit) * 1.75);
73
72
  }
74
-
75
73
  @keyframes t007-x-slide-bounce-in {
76
74
  from {
77
75
  transform: translateX(var(--t-from));
@@ -194,7 +192,6 @@
194
192
  transform: rotate(0deg) scale(1) translateZ(0);
195
193
  }
196
194
  }
197
-
198
195
  .t007-toast-container,
199
196
  .t007-toast-container *,
200
197
  .t007-toast-container *::after,
@@ -202,12 +199,10 @@
202
199
  box-sizing: border-box;
203
200
  font-family: var(--t007-toast-font-family);
204
201
  }
205
-
206
202
  .t007-toast-container *:focus-visible {
207
203
  outline: var(--t007-toast-focus-visible-outline);
208
204
  outline-offset: calc(var(--t007-toast-unit) / 7.5);
209
205
  }
210
-
211
206
  .t007-toast-container {
212
207
  position: var(--t007-toast-container-position);
213
208
  margin-top: var(--t007-toast-container-margin-top);
@@ -215,44 +210,38 @@
215
210
  margin-left: var(--t007-toast-container-margin-left);
216
211
  margin-right: var(--t007-toast-container-margin-right);
217
212
  max-width: calc(100% - var(--t007-toast-container-margin-left) - var(--t007-toast-container-margin-right));
218
- /* remove next block to clip container viewport, clips sliding too */
219
- /* max-height: calc(100% - var(--t007-toast-container-margin-top) - var(--t007-toast-container-margin-bottom));
220
- overflow: hidden; */
221
213
  display: flex;
222
214
  flex-direction: column;
223
215
  gap: var(--t007-toast-container-gap);
224
216
  z-index: 2147483647;
225
217
  contain: layout;
226
218
  }
227
-
228
219
  .t007-toast-container *:disabled {
229
220
  filter: grayscale(100%);
230
221
  cursor: not-allowed;
231
222
  }
232
-
233
- .t007-toast-container[data-position^="top-"] {
223
+ .t007-toast-container[data-position^=top-] {
234
224
  top: 0;
235
225
  }
236
- .t007-toast-container[data-position^="bottom-"] {
226
+ .t007-toast-container[data-position^=bottom-] {
237
227
  bottom: 0;
238
228
  }
239
- .t007-toast-container[data-position^="center-"] {
229
+ .t007-toast-container[data-position^=center-] {
240
230
  top: 50%;
241
231
  transform: translateY(-50%);
242
232
  margin-block: 0;
243
233
  }
244
- .t007-toast-container[data-position$="-right"] {
234
+ .t007-toast-container[data-position$=-right] {
245
235
  right: 0;
246
236
  }
247
- .t007-toast-container[data-position$="-left"] {
237
+ .t007-toast-container[data-position$=-left] {
248
238
  left: 0;
249
239
  }
250
- .t007-toast-container[data-position$="-center"] {
240
+ .t007-toast-container[data-position$=-center] {
251
241
  left: 50%;
252
242
  translate: -50%;
253
243
  margin-inline: 0;
254
244
  }
255
-
256
245
  .t007-toast {
257
246
  position: relative;
258
247
  flex-shrink: 0;
@@ -280,85 +269,72 @@
280
269
  backdrop-filter: blur(var(--t007-toast-background-blur));
281
270
  overflow: hidden;
282
271
  will-change: transform, opacity;
283
- transition:
284
- transform 300ms ease,
285
- opacity 300ms ease;
272
+ transition: transform 300ms ease, opacity 300ms ease;
286
273
  animation-timing-function: var(--t007-toast-animation-timing-function);
287
274
  animation-fill-mode: forwards;
288
275
  animation-duration: var(--t007-toast-animation-duration);
289
276
  touch-action: none;
290
277
  }
291
-
292
278
  .t007-toast:not(:has(.t007-toast-image, .t007-toast-icon:not(:empty))):has(.t007-toast-body) {
293
279
  padding-left: max(var(--t007-toast-padding), var(--t007-toast-smart-padding-left));
294
280
  }
295
-
296
281
  .t007-toast:not(:has(.t007-toast-cancel-button)) {
297
282
  padding-right: max(var(--t007-toast-padding), var(--t007-toast-smart-padding-right));
298
283
  }
299
-
300
- .t007-toast:is([data-drag-to-close="mouse"], [data-drag-to-close="true"]) {
284
+ .t007-toast:is([data-drag-to-close=mouse], [data-drag-to-close=true]) {
301
285
  cursor: grab;
302
286
  }
303
- .t007-toast:is([data-drag-to-close="mouse"], [data-drag-to-close="true"]):active {
287
+ .t007-toast:is([data-drag-to-close=mouse], [data-drag-to-close=true]):active {
304
288
  cursor: grabbing;
305
289
  }
306
-
307
- .t007-toast[data-animation^="slide"] {
290
+ .t007-toast[data-animation^=slide] {
308
291
  --t-to: 0;
309
292
  }
310
-
311
- .t007-toast[data-animation="slide-left"] {
293
+ .t007-toast[data-animation=slide-left] {
312
294
  --t-from: 100%;
313
295
  --t-bounce: -0%;
314
296
  }
315
- .t007-toast[data-animation="slide-right"] {
297
+ .t007-toast[data-animation=slide-right] {
316
298
  --t-from: -100%;
317
299
  --t-bounce: 10%;
318
300
  }
319
- .t007-toast[data-animation="slide-up"] {
301
+ .t007-toast[data-animation=slide-up] {
320
302
  --t-from: 100%;
321
303
  --t-bounce: -10%;
322
304
  }
323
- .t007-toast[data-animation="slide-down"] {
305
+ .t007-toast[data-animation=slide-down] {
324
306
  --t-from: -100%;
325
307
  --t-bounce: 10%;
326
308
  }
327
-
328
- .t007-toast:is([data-animation="slide-left"], [data-animation="slide-right"]) {
309
+ .t007-toast:is([data-animation=slide-left], [data-animation=slide-right]) {
329
310
  animation-name: t007-x-slide-bounce-out;
330
311
  }
331
- .t007-toast:is([data-animation="slide-left"], [data-animation="slide-right"]).t007-toast-show {
312
+ .t007-toast:is([data-animation=slide-left], [data-animation=slide-right]).t007-toast-show {
332
313
  animation-name: t007-x-slide-bounce-in;
333
314
  }
334
-
335
- .t007-toast:is([data-animation="slide-up"], [data-animation="slide-down"]) {
315
+ .t007-toast:is([data-animation=slide-up], [data-animation=slide-down]) {
336
316
  animation-name: t007-y-slide-bounce-out;
337
317
  }
338
- .t007-toast:is([data-animation="slide-up"], [data-animation="slide-down"]).t007-toast-show {
318
+ .t007-toast:is([data-animation=slide-up], [data-animation=slide-down]).t007-toast-show {
339
319
  animation-name: t007-y-slide-bounce-in;
340
320
  }
341
-
342
- .t007-toast[data-animation="fade"] {
321
+ .t007-toast[data-animation=fade] {
343
322
  animation-name: t007-fade-out;
344
323
  }
345
- .t007-toast[data-animation="fade"].t007-toast-show {
324
+ .t007-toast[data-animation=fade].t007-toast-show {
346
325
  animation-name: t007-fade-in;
347
326
  }
348
-
349
- .t007-toast[data-animation="zoom"] {
327
+ .t007-toast[data-animation=zoom] {
350
328
  animation-name: t007-zoom-out;
351
329
  }
352
- .t007-toast[data-animation="zoom"].t007-toast-show {
330
+ .t007-toast[data-animation=zoom].t007-toast-show {
353
331
  animation-name: t007-zoom-in;
354
332
  }
355
-
356
333
  .t007-toast:is(.info, .success, .error, .warning) {
357
334
  --t007-toast-font-color: var(--t007-toast-type-color);
358
335
  --t007-toast-progress-background: var(--t007-toast-type-color);
359
336
  --t007-toast-progress-backdrop-background: rgb(from var(--t007-toast-type-color) r g b/0);
360
337
  }
361
-
362
338
  .t007-toast.info {
363
339
  --t007-toast-type-color: var(--t007-toast-info-color);
364
340
  }
@@ -371,7 +347,6 @@
371
347
  .t007-toast.warning {
372
348
  --t007-toast-type-color: var(--t007-toast-warning-color);
373
349
  }
374
-
375
350
  .t007-toast.progress::before,
376
351
  .t007-toast.progress::after {
377
352
  content: "";
@@ -381,17 +356,14 @@
381
356
  height: var(--t007-toast-progress-height);
382
357
  transition: width ease;
383
358
  }
384
-
385
359
  .t007-toast.progress::before {
386
360
  width: calc(var(--progress, 0) * 100%);
387
361
  background: var(--t007-toast-progress-background);
388
362
  }
389
-
390
363
  .t007-toast.progress::after {
391
364
  width: 100%;
392
365
  background: var(--t007-toast-progress-backdrop-background);
393
366
  }
394
-
395
367
  .t007-toast-image-wrapper {
396
368
  position: relative;
397
369
  flex: 0 0 var(--t007-toast-image-width);
@@ -400,7 +372,6 @@
400
372
  border-radius: var(--t007-toast-image-border-radius);
401
373
  overflow: hidden;
402
374
  }
403
-
404
375
  .t007-toast-image-wrapper:not(:has(.t007-toast-image)) {
405
376
  flex: 0 0 var(--t007-toast-icon-width);
406
377
  width: var(--t007-toast-icon-width);
@@ -410,11 +381,9 @@
410
381
  border-radius: 0;
411
382
  overflow: visible;
412
383
  }
413
-
414
384
  .t007-toast-image-wrapper:not(:has(.t007-toast-image, .t007-toast-icon:not(:empty))) {
415
385
  display: none;
416
386
  }
417
-
418
387
  .t007-toast-icon {
419
388
  position: absolute;
420
389
  inset: 0;
@@ -428,17 +397,15 @@
428
397
  .t007-toast-icon:where(:not(.t007-toast-loader)) {
429
398
  animation: t007-icon-expand 300ms ease;
430
399
  }
431
- .t007-toast-icon[data-icon="👋"] {
400
+ .t007-toast-icon[data-icon=\1f44b] {
432
401
  transform-origin: bottom center;
433
- animation: t007-icon-handwave 1800ms ease-in-out 2 1000ms; /* just a progressive enhancement surprise */
402
+ animation: t007-icon-handwave 1800ms ease-in-out 2 1000ms;
434
403
  will-change: transform;
435
404
  }
436
-
437
405
  .t007-toast .t007-toast-icon > svg {
438
406
  width: var(--t007-toast-icon-width);
439
407
  height: var(--t007-toast-icon-height);
440
408
  }
441
-
442
409
  .t007-toast-image-wrapper .t007-toast-image {
443
410
  min-height: 100%;
444
411
  height: 100%;
@@ -447,11 +414,9 @@
447
414
  object-fit: var(--t007-toast-image-object-fit);
448
415
  background: var(--t007-toast-no-image-background);
449
416
  }
450
-
451
- .t007-toast-image-wrapper [data-loaded="true"] {
417
+ .t007-toast-image-wrapper [data-loaded=true] {
452
418
  background: var(--t007-toast-image-background);
453
419
  }
454
-
455
420
  .t007-toast-body {
456
421
  flex-grow: 1;
457
422
  height: fit-content;
@@ -459,7 +424,6 @@
459
424
  padding: calc(var(--t007-toast-unit) / 7.5);
460
425
  overflow: hidden;
461
426
  }
462
-
463
427
  .t007-toast-body-text {
464
428
  display: -webkit-box;
465
429
  -webkit-box-orient: vertical;
@@ -468,7 +432,6 @@
468
432
  margin: 0;
469
433
  z-index: 1;
470
434
  }
471
-
472
435
  .t007-toast-actions-wrapper {
473
436
  width: var(--t007-toast-actions-container-width);
474
437
  max-width: var(--t007-toast-actions-container-max-width);
@@ -477,7 +440,6 @@
477
440
  flex-wrap: wrap;
478
441
  gap: var(--t007-toast-actions-container-gap);
479
442
  }
480
-
481
443
  .t007-toast-action-button {
482
444
  display: flex;
483
445
  justify-content: center;
@@ -496,14 +458,12 @@
496
458
  color 200ms ease,
497
459
  background-color 200ms ease;
498
460
  }
499
-
500
461
  .t007-toast-action-button:is(:hover, :focus-visible) {
501
462
  cursor: pointer;
502
463
  opacity: 1;
503
464
  color: var(--t007-toast-action-button-active-color);
504
465
  background: var(--t007-toast-action-button-active-background);
505
466
  }
506
-
507
467
  .t007-toast-cancel-button {
508
468
  display: flex;
509
469
  align-self: start;
@@ -515,12 +475,10 @@
515
475
  font-size: var(--t007-toast-x-size);
516
476
  opacity: 0.6;
517
477
  }
518
-
519
478
  .t007-toast-cancel-button:is(:hover, :focus-visible) {
520
479
  cursor: pointer;
521
480
  opacity: 1;
522
481
  }
523
-
524
482
  @media (max-width: 36rem) {
525
483
  :where(:root) {
526
484
  --t007-toast-unit: 0.9rem;
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
  (() => {
3
3
  // ../utils/dist/index.js
4
- function clamp(min = 0, val, max = Infinity) {
5
- return Math.min(Math.max(val, min), max);
6
- }
7
4
  function uid(prefix = "") {
8
5
  return prefix + Date.now().toString(36) + "_" + performance.now().toString(36).replace(".", "") + "_" + Math.random().toString(36).slice(2);
9
6
  }
@@ -31,8 +28,11 @@
31
28
  for (const k of Object.keys(styles)) if (styles[k] !== void 0) el.style[k] = styles[k];
32
29
  }
33
30
  }
34
- function loadResource(src, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
31
+ var VIRTUAL_RESOURCE = /* @__PURE__ */ Symbol.for("T007_VIRTUAL_RESOURCE");
32
+ function loadResource(req, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
35
33
  w.t007._resourceCache ??= {};
34
+ if (req === VIRTUAL_RESOURCE || "symbol" === typeof req) return Promise.resolve();
35
+ const src = req;
36
36
  if (w.t007._resourceCache[src]) return w.t007._resourceCache[src];
37
37
  const existing = type === "script" ? Array.prototype.find.call(w.document.scripts, (s) => isSameURL(s.src, src)) : type === "style" ? Array.prototype.find.call(w.document.styleSheets, (s) => isSameURL(s.href, src)) : null;
38
38
  if (existing) return w.t007._resourceCache[src] = Promise.resolve(existing);
@@ -56,6 +56,9 @@
56
56
  });
57
57
  return w.t007._resourceCache[src];
58
58
  }
59
+ function clamp(min = 0, val, max = Infinity) {
60
+ return Math.min(Math.max(val, min), max);
61
+ }
59
62
  function onAllMethods(owner, callback) {
60
63
  let proto = owner;
61
64
  while (proto && proto !== Object.prototype) {
@@ -74,12 +77,13 @@
74
77
  }
75
78
  if (typeof window !== "undefined") {
76
79
  window.t007 ??= {};
80
+ t007.VIRTUAL_RESOURCE = VIRTUAL_RESOURCE;
77
81
  window.T007_TOAST_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest`;
78
82
  window.T007_INPUT_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest`;
79
83
  window.T007_DIALOG_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest`;
80
- window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/style.css`;
81
- window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/style.css`;
82
- window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/style.css`;
84
+ window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/dist/index.min.css`;
85
+ window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/dist/index.min.css`;
86
+ window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/dist/index.min.css`;
83
87
  }
84
88
 
85
89
  // src/index.js
@@ -1,7 +1,4 @@
1
1
  // ../utils/dist/index.js
2
- function clamp(min = 0, val, max = Infinity) {
3
- return Math.min(Math.max(val, min), max);
4
- }
5
2
  function uid(prefix = "") {
6
3
  return prefix + Date.now().toString(36) + "_" + performance.now().toString(36).replace(".", "") + "_" + Math.random().toString(36).slice(2);
7
4
  }
@@ -29,8 +26,11 @@ function assignEl(el, props, dataset, styles) {
29
26
  for (const k of Object.keys(styles)) if (styles[k] !== void 0) el.style[k] = styles[k];
30
27
  }
31
28
  }
32
- function loadResource(src, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
29
+ var VIRTUAL_RESOURCE = /* @__PURE__ */ Symbol.for("T007_VIRTUAL_RESOURCE");
30
+ function loadResource(req, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
33
31
  w.t007._resourceCache ??= {};
32
+ if (req === VIRTUAL_RESOURCE || "symbol" === typeof req) return Promise.resolve();
33
+ const src = req;
34
34
  if (w.t007._resourceCache[src]) return w.t007._resourceCache[src];
35
35
  const existing = type === "script" ? Array.prototype.find.call(w.document.scripts, (s) => isSameURL(s.src, src)) : type === "style" ? Array.prototype.find.call(w.document.styleSheets, (s) => isSameURL(s.href, src)) : null;
36
36
  if (existing) return w.t007._resourceCache[src] = Promise.resolve(existing);
@@ -54,6 +54,9 @@ function loadResource(src, type = "style", { module, media, crossOrigin, integri
54
54
  });
55
55
  return w.t007._resourceCache[src];
56
56
  }
57
+ function clamp(min = 0, val, max = Infinity) {
58
+ return Math.min(Math.max(val, min), max);
59
+ }
57
60
  function onAllMethods(owner, callback) {
58
61
  let proto = owner;
59
62
  while (proto && proto !== Object.prototype) {
@@ -72,12 +75,13 @@ function bindAllMethods(owner) {
72
75
  }
73
76
  if (typeof window !== "undefined") {
74
77
  window.t007 ??= {};
78
+ t007.VIRTUAL_RESOURCE = VIRTUAL_RESOURCE;
75
79
  window.T007_TOAST_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest`;
76
80
  window.T007_INPUT_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest`;
77
81
  window.T007_DIALOG_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest`;
78
- window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/style.css`;
79
- window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/style.css`;
80
- window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/style.css`;
82
+ window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/dist/index.min.css`;
83
+ window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/dist/index.min.css`;
84
+ window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/dist/index.min.css`;
81
85
  }
82
86
 
83
87
  // src/index.js
package/package.json CHANGED
@@ -1,56 +1,58 @@
1
1
  {
2
2
  "name": "@t007/toast",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "A lightweight, pure JS toast system.",
5
5
  "author": "Oketade Oluwatobiloba <tobioketade007@gmail.com>",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/tobi007-del/t007-tools.git",
9
+ "url": "git+https://github.com/Tobi007-del/t007-tools.git",
10
10
  "directory": "packages/toast"
11
11
  },
12
- "homepage": "https://github.com/tobi007-del/t007-tools/tree/main/packages/toast#readme",
12
+ "homepage": "https://github.com/Tobi007-del/t007-tools/blob/main/packages/toast#readme",
13
13
  "bugs": {
14
- "url": "https://github.com/tobi007-del/t007-tools/issues"
14
+ "url": "https://github.com/Tobi007-del/t007-tools/issues"
15
15
  },
16
16
  "type": "module",
17
17
  "main": "./dist/index.js",
18
18
  "module": "./dist/index.js",
19
19
  "unpkg": "./dist/index.global.js",
20
20
  "jsdelivr": "./dist/index.global.js",
21
- "types": "./src/ts/types/index.d.ts",
22
- "style": "./src/css/index.css",
21
+ "types": "./dist/index.d.ts",
22
+ "style": "./dist/index.css",
23
23
  "sideEffects": [
24
24
  "*.css"
25
25
  ],
26
26
  "exports": {
27
27
  ".": {
28
- "types": "./src/ts/types/index.d.ts",
28
+ "types": "./dist/index.d.ts",
29
29
  "import": "./dist/index.js",
30
30
  "default": "./dist/index.js"
31
31
  },
32
32
  "./standalone": "./dist/standalone.js",
33
33
  "./global": "./dist/index.global.js",
34
- "./style.css": "./src/css/index.css"
34
+ "./style.css": "./dist/index.css"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public"
35
38
  },
36
39
  "scripts": {
37
- "build": "tsup --config ../../tsup.config.ts"
40
+ "build": "tsup --config ../../tsup.config.ts",
41
+ "prepublishOnly": "shx cp ../../LICENSE ."
38
42
  },
39
43
  "files": [
40
- "dist",
41
- "./src/ts/types/index.d.ts",
42
- "./src/css/index.css"
44
+ "dist"
43
45
  ],
44
46
  "keywords": [
45
47
  "t007",
48
+ "ecosystem",
49
+ "ui",
50
+ "vanilla-js",
46
51
  "toast",
47
52
  "snackbar",
48
53
  "notification",
49
54
  "alert",
50
- "promise",
51
- "ui",
52
- "vanilla-js",
53
- "zero-dependency"
55
+ "promise"
54
56
  ],
55
57
  "dependencies": {
56
58
  "@t007/utils": "*"
File without changes