minisnackbar 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 MiniSnackbar
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,33 @@
1
+ # MiniSnackbar
2
+
3
+ A simple, lightweight vanilla JavaScript snackbar/toast library with no dependencies. Works standalone or seamlessly blends with [Material Web](https://material-web.dev/) components, adapting to your site's theme when available. Since Material Web doesn't provide a snackbar component, this library fills that gap.
4
+
5
+ **Author:** Shanto Islam ([shantoislamdev.web.app](https://shantoislamdev.web.app))
6
+ **License:** MIT
7
+ **Repository:** [github.com/shantoislamdev/minisnackbar](https://github.com/shantoislamdev/minisnackbar)
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install minisnackbar
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```javascript
18
+ import Snackbar from 'minisnackbar';
19
+
20
+ // Initialize
21
+ Snackbar.init();
22
+
23
+ // Show a message
24
+ Snackbar.add('Hello, world!');
25
+ ```
26
+
27
+ ## Documentation
28
+
29
+ For full documentation, API reference, and advanced usage, see [docs.md](docs.md).
30
+
31
+ ## License
32
+
33
+ MIT
@@ -0,0 +1,382 @@
1
+ /**
2
+ * MiniSnackbar - A simple vanilla JavaScript snackbar/toast library
3
+ *
4
+ * @version 1.0.0
5
+ * @author Shanto Islam <shantoislamdev@gmail.com>
6
+ * @license MIT
7
+ * @description A lightweight, zero-dependency snackbar library with Material Design integration
8
+ * @repository https://github.com/shantoislamdev/minisnackbar
9
+ * @homepage https://github.com/shantoislamdev/minisnackbar#readme
10
+ */
11
+
12
+ class Snackbar {
13
+ static _queue = []
14
+ static _isShowing = false
15
+ static _currentTimeout = null
16
+ static _state = 'idle' // idle, showing, transitioning
17
+ static _currentActionHandler = null
18
+ static _transitionDuration = 250
19
+ static _initialized = false
20
+
21
+ static init(options = {}) {
22
+ if (this._initialized) return
23
+
24
+ if (typeof document === 'undefined' || !document.body) {
25
+ console.error('Snackbar: DOM is not available');
26
+ return
27
+ }
28
+
29
+ if (options.transitionDuration && typeof options.transitionDuration === 'number') {
30
+ this._transitionDuration = options.transitionDuration;
31
+ }
32
+
33
+ if (document.getElementById('mini-snackbar')) {
34
+ this._initialized = true;
35
+ return
36
+ }
37
+
38
+ if (!document.getElementById('mini-snackbar-styles')) {
39
+ const style = document.createElement('style');
40
+ style.id = 'mini-snackbar-styles';
41
+ style.textContent = `
42
+ .mini-snackbar {
43
+ /* Positioning */
44
+ position: fixed;
45
+ z-index: 1000;
46
+ left: 50%;
47
+ bottom: 30px;
48
+ transform: translateX(-50%) translateY(100%);
49
+
50
+ /* Sizing */
51
+ min-width: 250px;
52
+ max-width: 90%;
53
+
54
+ /* Layout */
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: space-between;
58
+ gap: 8px;
59
+ padding: 0.875rem 1rem;
60
+
61
+ /* Visibility */
62
+ visibility: hidden;
63
+
64
+ /* Theming */
65
+ background-color: var(--mini-snackbar-bg, var(--md-sys-color-inverse-surface, rgba(255, 255, 255, 1)));
66
+ color: var(--mini-snackbar-text, var(--md-sys-color-inverse-on-surface, inherit));
67
+ border: var(--mini-snackbar-border, none);
68
+ font-family: var(--mini-snackbar-font-family, inherit);
69
+ font-size: 0.875rem;
70
+ text-align: left;
71
+ border-radius: var(--mini-snackbar-radius, 1rem);
72
+ box-shadow: var(--mini-snackbar-shadow, 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12));
73
+
74
+ /* Animation */
75
+ transition: var(--mini-snackbar-transition, transform ${this._transitionDuration}ms ease-in-out);
76
+ }
77
+
78
+ .mini-snackbar.show {
79
+ visibility: visible;
80
+ transform: translateX(-50%) translateY(0);
81
+ }
82
+
83
+ /* Material Component Action Button */
84
+ .mini-snackbar .mini-snackbar-action {
85
+ flex-shrink: 0;
86
+ padding: 0.5rem 1rem;
87
+ margin: -0.5rem -0.5rem -0.5rem 0;
88
+ }
89
+
90
+ /* Fallback Action Button (when Material Components unavailable) */
91
+ .mini-snackbar md-text-button[data-fallback] {
92
+ display: inline-block;
93
+ flex-shrink: 0;
94
+ padding: 0.5rem 1rem;
95
+ margin: -0.5rem -0.5rem -0.5rem 0;
96
+ border: none;
97
+ background: var(--mini-snackbar-btn-bg, transparent);
98
+ font-size: inherit;
99
+ font-family: inherit;
100
+ font-weight: 500;
101
+ letter-spacing: 0.0892857143em;
102
+ text-transform: uppercase;
103
+ color: var(--mini-snackbar-btn-text, inherit);
104
+ cursor: pointer;
105
+ user-select: none;
106
+ border-radius: var(--mini-snackbar-btn-radius, 1rem);
107
+ transition: opacity 0.2s ease;
108
+ }
109
+
110
+ .mini-snackbar md-text-button[data-fallback]:hover {
111
+ opacity: var(--mini-snackbar-btn-hover-opacity, 0.8);
112
+ outline: var(--mini-snackbar-btn-hover-outline, 2px solid var(--mini-snackbar-btn-text, inherit));
113
+ outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);
114
+ background-color: var(--mini-snackbar-btn-hover-bg, transparent);
115
+ }
116
+
117
+ .mini-snackbar md-text-button[data-fallback]:focus {
118
+ outline: var(--mini-snackbar-btn-focus-outline, 2px solid var(--mini-snackbar-btn-text, inherit));
119
+ outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);
120
+ }
121
+
122
+ /* Mobile responsive */
123
+ @media (max-width: 600px) {
124
+ .mini-snackbar {
125
+ bottom: 90px;
126
+ }
127
+ }
128
+
129
+ /* Accessibility: Reduced motion */
130
+ @media (prefers-reduced-motion: reduce) {
131
+ .mini-snackbar {
132
+ transition: opacity 0.15s ease;
133
+ }
134
+ }
135
+ `;
136
+ document.head.appendChild(style);
137
+ }
138
+
139
+ const snackbar = document.createElement('div');
140
+ snackbar.id = 'mini-snackbar';
141
+ snackbar.className = 'mini-snackbar';
142
+ snackbar.setAttribute('role', 'alert');
143
+ snackbar.setAttribute('aria-live', 'assertive');
144
+ snackbar.setAttribute('aria-atomic', 'true');
145
+
146
+ const snackbarText = document.createElement('span');
147
+ snackbarText.className = 'mini-snackbar-text';
148
+ snackbar.appendChild(snackbarText);
149
+
150
+ document.body.appendChild(snackbar);
151
+ this._initialized = true;
152
+ }
153
+
154
+ static destroy() {
155
+ this.hideCurrent();
156
+ this.clearQueue();
157
+
158
+ const snackbar = document.getElementById('mini-snackbar');
159
+ if (snackbar) snackbar.remove();
160
+
161
+ const styles = document.getElementById('mini-snackbar-styles');
162
+ if (styles) styles.remove();
163
+
164
+ this._state = 'idle';
165
+ this._isShowing = false;
166
+ this._currentActionHandler = null;
167
+ this._currentTimeout = null;
168
+ this._initialized = false;
169
+ }
170
+
171
+ static getTransitionDuration() {
172
+ const snackbar = document.getElementById('mini-snackbar');
173
+ if (!snackbar) return this._transitionDuration
174
+
175
+ try {
176
+ const computedStyle = window.getComputedStyle(snackbar);
177
+ const duration = computedStyle.transitionDuration;
178
+ if (duration && duration !== '0s') {
179
+ const value = parseFloat(duration);
180
+ return duration.includes('ms') ? value : value * 1000
181
+ }
182
+ } catch (e) {
183
+ console.warn('Snackbar: Could not read transition duration from CSS', e);
184
+ }
185
+
186
+ return this._transitionDuration
187
+ }
188
+
189
+ static add(message, action = null, duration = 3000) {
190
+ if (!this._initialized) {
191
+ console.warn('Snackbar: Not initialized. Call Snackbar.init() first.');
192
+ return
193
+ }
194
+
195
+ if (typeof message !== 'string' || message.trim() === '') {
196
+ console.warn('Snackbar: Message must be a non-empty string');
197
+ return
198
+ }
199
+ if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {
200
+ console.warn('Snackbar: Action must be an object with "text" (string) and "handler" (function) properties');
201
+ return
202
+ }
203
+ if (typeof duration !== 'number' || duration <= 0) {
204
+ console.warn('Snackbar: Duration must be a positive number');
205
+ return
206
+ }
207
+
208
+ this._queue.push({ message, action, duration });
209
+ if (this._state === 'idle') this.showNext();
210
+ }
211
+
212
+ static _cleanupAction() {
213
+ const snackbar = document.getElementById('mini-snackbar');
214
+ if (!snackbar) return
215
+
216
+ const actionButton = snackbar.querySelector('.mini-snackbar-action');
217
+ if (actionButton && this._currentActionHandler) {
218
+ actionButton.removeEventListener('click', this._currentActionHandler);
219
+ this._currentActionHandler = null;
220
+ actionButton.remove();
221
+ }
222
+ }
223
+
224
+ static _showSnackbar(message, action, duration, onHide = null) {
225
+ const snackbar = document.getElementById('mini-snackbar');
226
+ if (!snackbar) {
227
+ console.error('Snackbar: Snackbar element not found. Ensure init() has been called.');
228
+ return
229
+ }
230
+
231
+ this._state = 'showing';
232
+ this._isShowing = true;
233
+ const snackbarText = snackbar.querySelector('.mini-snackbar-text');
234
+ snackbarText.textContent = message;
235
+
236
+ if (action) {
237
+ const actionButton = document.createElement('md-text-button');
238
+ actionButton.classList.add('mini-snackbar-action');
239
+
240
+ // Fallback for when Material Components are not available
241
+ if (customElements.get('md-text-button') === undefined) {
242
+ actionButton.setAttribute('data-fallback', '');
243
+ }
244
+
245
+ actionButton.textContent = action.text;
246
+
247
+ this._currentActionHandler = () => {
248
+ action.handler();
249
+ this._hideSnackbar(onHide);
250
+ };
251
+
252
+ actionButton.addEventListener('click', this._currentActionHandler);
253
+ snackbar.appendChild(actionButton);
254
+ }
255
+
256
+ snackbar.classList.add('show');
257
+
258
+ this._currentTimeout = setTimeout(() => {
259
+ this._hideSnackbar(onHide);
260
+ }, duration);
261
+ }
262
+
263
+ static _hideSnackbar(onHide = null) {
264
+ if (this._currentTimeout) {
265
+ clearTimeout(this._currentTimeout);
266
+ this._currentTimeout = null;
267
+ }
268
+
269
+ this._state = 'transitioning';
270
+ const snackbar = document.getElementById('mini-snackbar');
271
+ if (snackbar) {
272
+ snackbar.classList.remove('show');
273
+ }
274
+
275
+ this._cleanupAction();
276
+
277
+ // Wait for CSS transition to complete
278
+ const transitionDuration = this.getTransitionDuration();
279
+ setTimeout(() => {
280
+ this._isShowing = false;
281
+ this._state = 'idle';
282
+ if (onHide) onHide();
283
+ }, transitionDuration);
284
+ }
285
+
286
+ static show(message, action = null, duration = 3000) {
287
+ if (!this._initialized) {
288
+ console.warn('Snackbar: Not initialized. Call Snackbar.init() first.');
289
+ return
290
+ }
291
+
292
+ if (typeof message !== 'string' || message.trim() === '') {
293
+ console.warn('Snackbar: Message must be a non-empty string');
294
+ return
295
+ }
296
+ if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {
297
+ console.warn('Snackbar: Action must be an object with "text" (string) and "handler" (function) properties');
298
+ return
299
+ }
300
+ if (typeof duration !== 'number' || duration <= 0) {
301
+ console.warn('Snackbar: Duration must be a positive number');
302
+ return
303
+ }
304
+
305
+ // Queue message if currently transitioning
306
+ if (this._state === 'transitioning') {
307
+ this.add(message, action, duration);
308
+ return
309
+ }
310
+
311
+ // Interrupt current snackbar if showing
312
+ if (this._isShowing) {
313
+ this._state = 'transitioning';
314
+ if (this._currentTimeout) {
315
+ clearTimeout(this._currentTimeout);
316
+ this._currentTimeout = null;
317
+ }
318
+ const snackbar = document.getElementById('mini-snackbar');
319
+ if (snackbar) {
320
+ snackbar.classList.remove('show');
321
+ }
322
+ this._cleanupAction();
323
+
324
+ const transitionDuration = this.getTransitionDuration();
325
+ setTimeout(() => {
326
+ this._isShowing = false;
327
+ this._state = 'idle';
328
+ this._showSnackbar(message, action, duration);
329
+ }, transitionDuration);
330
+ } else {
331
+ this._showSnackbar(message, action, duration);
332
+ }
333
+ }
334
+
335
+ static showNext() {
336
+ if (this._queue.length === 0) {
337
+ this._isShowing = false;
338
+ this._state = 'idle';
339
+ return
340
+ }
341
+
342
+ const { message, action, duration } = this._queue.shift();
343
+ this._showSnackbar(message, action, duration, () => {
344
+ setTimeout(() => this.showNext(), 200);
345
+ });
346
+ }
347
+
348
+ static clearQueue() {
349
+ this._queue = [];
350
+ }
351
+
352
+ static hideCurrent() {
353
+ if (this._isShowing && this._state !== 'transitioning') {
354
+ this._hideSnackbar();
355
+ }
356
+ }
357
+
358
+ static isInitialized() {
359
+ return this._initialized
360
+ }
361
+
362
+ // Getters/setters for testing
363
+ static get queue() { return this._queue }
364
+ static set queue(value) { this._queue = value; }
365
+ static get isShowing() { return this._isShowing }
366
+ static set isShowing(value) { this._isShowing = value; }
367
+ static get currentTimeout() { return this._currentTimeout }
368
+ static set currentTimeout(value) { this._currentTimeout = value; }
369
+ static get state() { return this._state }
370
+ static set state(value) { this._state = value; }
371
+ }
372
+
373
+ // Module exports
374
+ if (typeof module !== 'undefined' && module.exports) {
375
+ module.exports = Snackbar;
376
+ }
377
+
378
+ // Make available globally in browser
379
+ if (typeof window !== 'undefined') {
380
+ window.Snackbar = Snackbar;
381
+ }
382
+ //# sourceMappingURL=minisnackbar.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minisnackbar.esm.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * MiniSnackbar - A simple vanilla JavaScript snackbar/toast library\r\n *\r\n * @version 1.0.0\r\n * @author Shanto Islam <shantoislamdev@gmail.com>\r\n * @license MIT\r\n * @description A lightweight, zero-dependency snackbar library with Material Design integration\r\n * @repository https://github.com/shantoislamdev/minisnackbar\r\n * @homepage https://github.com/shantoislamdev/minisnackbar#readme\r\n */\r\n\r\nclass Snackbar {\r\n static _queue = []\r\n static _isShowing = false\r\n static _currentTimeout = null\r\n static _state = 'idle' // idle, showing, transitioning\r\n static _currentActionHandler = null\r\n static _transitionDuration = 250\r\n static _initialized = false\r\n\r\n static init(options = {}) {\r\n if (this._initialized) return\r\n\r\n if (typeof document === 'undefined' || !document.body) {\r\n console.error('Snackbar: DOM is not available')\r\n return\r\n }\r\n\r\n if (options.transitionDuration && typeof options.transitionDuration === 'number') {\r\n this._transitionDuration = options.transitionDuration\r\n }\r\n\r\n if (document.getElementById('mini-snackbar')) {\r\n this._initialized = true\r\n return\r\n }\r\n\r\n if (!document.getElementById('mini-snackbar-styles')) {\r\n const style = document.createElement('style')\r\n style.id = 'mini-snackbar-styles'\r\n style.textContent = `\r\n .mini-snackbar {\r\n /* Positioning */\r\n position: fixed;\r\n z-index: 1000;\r\n left: 50%;\r\n bottom: 30px;\r\n transform: translateX(-50%) translateY(100%);\r\n \r\n /* Sizing */\r\n min-width: 250px;\r\n max-width: 90%;\r\n \r\n /* Layout */\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 0.875rem 1rem;\r\n \r\n /* Visibility */\r\n visibility: hidden;\r\n \r\n /* Theming */\r\n background-color: var(--mini-snackbar-bg, var(--md-sys-color-inverse-surface, rgba(255, 255, 255, 1)));\r\n color: var(--mini-snackbar-text, var(--md-sys-color-inverse-on-surface, inherit));\r\n border: var(--mini-snackbar-border, none);\r\n font-family: var(--mini-snackbar-font-family, inherit);\r\n font-size: 0.875rem;\r\n text-align: left;\r\n border-radius: var(--mini-snackbar-radius, 1rem);\r\n box-shadow: var(--mini-snackbar-shadow, 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12));\r\n \r\n /* Animation */\r\n transition: var(--mini-snackbar-transition, transform ${this._transitionDuration}ms ease-in-out);\r\n }\r\n\r\n .mini-snackbar.show {\r\n visibility: visible;\r\n transform: translateX(-50%) translateY(0);\r\n }\r\n\r\n /* Material Component Action Button */\r\n .mini-snackbar .mini-snackbar-action {\r\n flex-shrink: 0;\r\n padding: 0.5rem 1rem;\r\n margin: -0.5rem -0.5rem -0.5rem 0;\r\n }\r\n\r\n /* Fallback Action Button (when Material Components unavailable) */\r\n .mini-snackbar md-text-button[data-fallback] {\r\n display: inline-block;\r\n flex-shrink: 0;\r\n padding: 0.5rem 1rem;\r\n margin: -0.5rem -0.5rem -0.5rem 0;\r\n border: none;\r\n background: var(--mini-snackbar-btn-bg, transparent);\r\n font-size: inherit;\r\n font-family: inherit;\r\n font-weight: 500;\r\n letter-spacing: 0.0892857143em;\r\n text-transform: uppercase;\r\n color: var(--mini-snackbar-btn-text, inherit);\r\n cursor: pointer;\r\n user-select: none;\r\n border-radius: var(--mini-snackbar-btn-radius, 1rem);\r\n transition: opacity 0.2s ease;\r\n }\r\n\r\n .mini-snackbar md-text-button[data-fallback]:hover {\r\n opacity: var(--mini-snackbar-btn-hover-opacity, 0.8);\r\n outline: var(--mini-snackbar-btn-hover-outline, 2px solid var(--mini-snackbar-btn-text, inherit));\r\n outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);\r\n background-color: var(--mini-snackbar-btn-hover-bg, transparent);\r\n }\r\n\r\n .mini-snackbar md-text-button[data-fallback]:focus {\r\n outline: var(--mini-snackbar-btn-focus-outline, 2px solid var(--mini-snackbar-btn-text, inherit));\r\n outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);\r\n }\r\n\r\n /* Mobile responsive */\r\n @media (max-width: 600px) {\r\n .mini-snackbar {\r\n bottom: 90px;\r\n }\r\n }\r\n\r\n /* Accessibility: Reduced motion */\r\n @media (prefers-reduced-motion: reduce) {\r\n .mini-snackbar {\r\n transition: opacity 0.15s ease;\r\n }\r\n }\r\n `\r\n document.head.appendChild(style)\r\n }\r\n\r\n const snackbar = document.createElement('div')\r\n snackbar.id = 'mini-snackbar'\r\n snackbar.className = 'mini-snackbar'\r\n snackbar.setAttribute('role', 'alert')\r\n snackbar.setAttribute('aria-live', 'assertive')\r\n snackbar.setAttribute('aria-atomic', 'true')\r\n\r\n const snackbarText = document.createElement('span')\r\n snackbarText.className = 'mini-snackbar-text'\r\n snackbar.appendChild(snackbarText)\r\n\r\n document.body.appendChild(snackbar)\r\n this._initialized = true\r\n }\r\n\r\n static destroy() {\r\n this.hideCurrent()\r\n this.clearQueue()\r\n\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) snackbar.remove()\r\n\r\n const styles = document.getElementById('mini-snackbar-styles')\r\n if (styles) styles.remove()\r\n\r\n this._state = 'idle'\r\n this._isShowing = false\r\n this._currentActionHandler = null\r\n this._currentTimeout = null\r\n this._initialized = false\r\n }\r\n\r\n static getTransitionDuration() {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) return this._transitionDuration\r\n\r\n try {\r\n const computedStyle = window.getComputedStyle(snackbar)\r\n const duration = computedStyle.transitionDuration\r\n if (duration && duration !== '0s') {\r\n const value = parseFloat(duration)\r\n return duration.includes('ms') ? value : value * 1000\r\n }\r\n } catch (e) {\r\n console.warn('Snackbar: Could not read transition duration from CSS', e)\r\n }\r\n\r\n return this._transitionDuration\r\n }\r\n\r\n static add(message, action = null, duration = 3000) {\r\n if (!this._initialized) {\r\n console.warn('Snackbar: Not initialized. Call Snackbar.init() first.')\r\n return\r\n }\r\n\r\n if (typeof message !== 'string' || message.trim() === '') {\r\n console.warn('Snackbar: Message must be a non-empty string')\r\n return\r\n }\r\n if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {\r\n console.warn('Snackbar: Action must be an object with \"text\" (string) and \"handler\" (function) properties')\r\n return\r\n }\r\n if (typeof duration !== 'number' || duration <= 0) {\r\n console.warn('Snackbar: Duration must be a positive number')\r\n return\r\n }\r\n\r\n this._queue.push({ message, action, duration })\r\n if (this._state === 'idle') this.showNext()\r\n }\r\n\r\n static _cleanupAction() {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) return\r\n\r\n const actionButton = snackbar.querySelector('.mini-snackbar-action')\r\n if (actionButton && this._currentActionHandler) {\r\n actionButton.removeEventListener('click', this._currentActionHandler)\r\n this._currentActionHandler = null\r\n actionButton.remove()\r\n }\r\n }\r\n\r\n static _showSnackbar(message, action, duration, onHide = null) {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) {\r\n console.error('Snackbar: Snackbar element not found. Ensure init() has been called.')\r\n return\r\n }\r\n\r\n this._state = 'showing'\r\n this._isShowing = true\r\n const snackbarText = snackbar.querySelector('.mini-snackbar-text')\r\n snackbarText.textContent = message\r\n\r\n if (action) {\r\n const actionButton = document.createElement('md-text-button')\r\n actionButton.classList.add('mini-snackbar-action')\r\n\r\n // Fallback for when Material Components are not available\r\n if (customElements.get('md-text-button') === undefined) {\r\n actionButton.setAttribute('data-fallback', '')\r\n }\r\n\r\n actionButton.textContent = action.text\r\n\r\n this._currentActionHandler = () => {\r\n action.handler()\r\n this._hideSnackbar(onHide)\r\n }\r\n\r\n actionButton.addEventListener('click', this._currentActionHandler)\r\n snackbar.appendChild(actionButton)\r\n }\r\n\r\n snackbar.classList.add('show')\r\n\r\n this._currentTimeout = setTimeout(() => {\r\n this._hideSnackbar(onHide)\r\n }, duration)\r\n }\r\n\r\n static _hideSnackbar(onHide = null) {\r\n if (this._currentTimeout) {\r\n clearTimeout(this._currentTimeout)\r\n this._currentTimeout = null\r\n }\r\n\r\n this._state = 'transitioning'\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) {\r\n snackbar.classList.remove('show')\r\n }\r\n\r\n this._cleanupAction()\r\n\r\n // Wait for CSS transition to complete\r\n const transitionDuration = this.getTransitionDuration()\r\n setTimeout(() => {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n if (onHide) onHide()\r\n }, transitionDuration)\r\n }\r\n\r\n static show(message, action = null, duration = 3000) {\r\n if (!this._initialized) {\r\n console.warn('Snackbar: Not initialized. Call Snackbar.init() first.')\r\n return\r\n }\r\n\r\n if (typeof message !== 'string' || message.trim() === '') {\r\n console.warn('Snackbar: Message must be a non-empty string')\r\n return\r\n }\r\n if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {\r\n console.warn('Snackbar: Action must be an object with \"text\" (string) and \"handler\" (function) properties')\r\n return\r\n }\r\n if (typeof duration !== 'number' || duration <= 0) {\r\n console.warn('Snackbar: Duration must be a positive number')\r\n return\r\n }\r\n\r\n // Queue message if currently transitioning\r\n if (this._state === 'transitioning') {\r\n this.add(message, action, duration)\r\n return\r\n }\r\n\r\n // Interrupt current snackbar if showing\r\n if (this._isShowing) {\r\n this._state = 'transitioning'\r\n if (this._currentTimeout) {\r\n clearTimeout(this._currentTimeout)\r\n this._currentTimeout = null\r\n }\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) {\r\n snackbar.classList.remove('show')\r\n }\r\n this._cleanupAction()\r\n\r\n const transitionDuration = this.getTransitionDuration()\r\n setTimeout(() => {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n this._showSnackbar(message, action, duration)\r\n }, transitionDuration)\r\n } else {\r\n this._showSnackbar(message, action, duration)\r\n }\r\n }\r\n\r\n static showNext() {\r\n if (this._queue.length === 0) {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n return\r\n }\r\n\r\n const { message, action, duration } = this._queue.shift()\r\n this._showSnackbar(message, action, duration, () => {\r\n setTimeout(() => this.showNext(), 200)\r\n })\r\n }\r\n\r\n static clearQueue() {\r\n this._queue = []\r\n }\r\n\r\n static hideCurrent() {\r\n if (this._isShowing && this._state !== 'transitioning') {\r\n this._hideSnackbar()\r\n }\r\n }\r\n\r\n static isInitialized() {\r\n return this._initialized\r\n }\r\n\r\n // Getters/setters for testing\r\n static get queue() { return this._queue }\r\n static set queue(value) { this._queue = value }\r\n static get isShowing() { return this._isShowing }\r\n static set isShowing(value) { this._isShowing = value }\r\n static get currentTimeout() { return this._currentTimeout }\r\n static set currentTimeout(value) { this._currentTimeout = value }\r\n static get state() { return this._state }\r\n static set state(value) { this._state = value }\r\n}\r\n\r\n// Module exports\r\nif (typeof module !== 'undefined' && module.exports) {\r\n module.exports = Snackbar\r\n}\r\n\r\n// Make available globally in browser\r\nif (typeof window !== 'undefined') {\r\n window.Snackbar = Snackbar\r\n}\r\n\r\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,389 @@
1
+ (function (factory) {
2
+ typeof define === 'function' && define.amd ? define(factory) :
3
+ factory();
4
+ })((function () { 'use strict';
5
+
6
+ /**
7
+ * MiniSnackbar - A simple vanilla JavaScript snackbar/toast library
8
+ *
9
+ * @version 1.0.0
10
+ * @author Shanto Islam <shantoislamdev@gmail.com>
11
+ * @license MIT
12
+ * @description A lightweight, zero-dependency snackbar library with Material Design integration
13
+ * @repository https://github.com/shantoislamdev/minisnackbar
14
+ * @homepage https://github.com/shantoislamdev/minisnackbar#readme
15
+ */
16
+
17
+ class Snackbar {
18
+ static _queue = []
19
+ static _isShowing = false
20
+ static _currentTimeout = null
21
+ static _state = 'idle' // idle, showing, transitioning
22
+ static _currentActionHandler = null
23
+ static _transitionDuration = 250
24
+ static _initialized = false
25
+
26
+ static init(options = {}) {
27
+ if (this._initialized) return
28
+
29
+ if (typeof document === 'undefined' || !document.body) {
30
+ console.error('Snackbar: DOM is not available');
31
+ return
32
+ }
33
+
34
+ if (options.transitionDuration && typeof options.transitionDuration === 'number') {
35
+ this._transitionDuration = options.transitionDuration;
36
+ }
37
+
38
+ if (document.getElementById('mini-snackbar')) {
39
+ this._initialized = true;
40
+ return
41
+ }
42
+
43
+ if (!document.getElementById('mini-snackbar-styles')) {
44
+ const style = document.createElement('style');
45
+ style.id = 'mini-snackbar-styles';
46
+ style.textContent = `
47
+ .mini-snackbar {
48
+ /* Positioning */
49
+ position: fixed;
50
+ z-index: 1000;
51
+ left: 50%;
52
+ bottom: 30px;
53
+ transform: translateX(-50%) translateY(100%);
54
+
55
+ /* Sizing */
56
+ min-width: 250px;
57
+ max-width: 90%;
58
+
59
+ /* Layout */
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: space-between;
63
+ gap: 8px;
64
+ padding: 0.875rem 1rem;
65
+
66
+ /* Visibility */
67
+ visibility: hidden;
68
+
69
+ /* Theming */
70
+ background-color: var(--mini-snackbar-bg, var(--md-sys-color-inverse-surface, rgba(255, 255, 255, 1)));
71
+ color: var(--mini-snackbar-text, var(--md-sys-color-inverse-on-surface, inherit));
72
+ border: var(--mini-snackbar-border, none);
73
+ font-family: var(--mini-snackbar-font-family, inherit);
74
+ font-size: 0.875rem;
75
+ text-align: left;
76
+ border-radius: var(--mini-snackbar-radius, 1rem);
77
+ box-shadow: var(--mini-snackbar-shadow, 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12));
78
+
79
+ /* Animation */
80
+ transition: var(--mini-snackbar-transition, transform ${this._transitionDuration}ms ease-in-out);
81
+ }
82
+
83
+ .mini-snackbar.show {
84
+ visibility: visible;
85
+ transform: translateX(-50%) translateY(0);
86
+ }
87
+
88
+ /* Material Component Action Button */
89
+ .mini-snackbar .mini-snackbar-action {
90
+ flex-shrink: 0;
91
+ padding: 0.5rem 1rem;
92
+ margin: -0.5rem -0.5rem -0.5rem 0;
93
+ }
94
+
95
+ /* Fallback Action Button (when Material Components unavailable) */
96
+ .mini-snackbar md-text-button[data-fallback] {
97
+ display: inline-block;
98
+ flex-shrink: 0;
99
+ padding: 0.5rem 1rem;
100
+ margin: -0.5rem -0.5rem -0.5rem 0;
101
+ border: none;
102
+ background: var(--mini-snackbar-btn-bg, transparent);
103
+ font-size: inherit;
104
+ font-family: inherit;
105
+ font-weight: 500;
106
+ letter-spacing: 0.0892857143em;
107
+ text-transform: uppercase;
108
+ color: var(--mini-snackbar-btn-text, inherit);
109
+ cursor: pointer;
110
+ user-select: none;
111
+ border-radius: var(--mini-snackbar-btn-radius, 1rem);
112
+ transition: opacity 0.2s ease;
113
+ }
114
+
115
+ .mini-snackbar md-text-button[data-fallback]:hover {
116
+ opacity: var(--mini-snackbar-btn-hover-opacity, 0.8);
117
+ outline: var(--mini-snackbar-btn-hover-outline, 2px solid var(--mini-snackbar-btn-text, inherit));
118
+ outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);
119
+ background-color: var(--mini-snackbar-btn-hover-bg, transparent);
120
+ }
121
+
122
+ .mini-snackbar md-text-button[data-fallback]:focus {
123
+ outline: var(--mini-snackbar-btn-focus-outline, 2px solid var(--mini-snackbar-btn-text, inherit));
124
+ outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);
125
+ }
126
+
127
+ /* Mobile responsive */
128
+ @media (max-width: 600px) {
129
+ .mini-snackbar {
130
+ bottom: 90px;
131
+ }
132
+ }
133
+
134
+ /* Accessibility: Reduced motion */
135
+ @media (prefers-reduced-motion: reduce) {
136
+ .mini-snackbar {
137
+ transition: opacity 0.15s ease;
138
+ }
139
+ }
140
+ `;
141
+ document.head.appendChild(style);
142
+ }
143
+
144
+ const snackbar = document.createElement('div');
145
+ snackbar.id = 'mini-snackbar';
146
+ snackbar.className = 'mini-snackbar';
147
+ snackbar.setAttribute('role', 'alert');
148
+ snackbar.setAttribute('aria-live', 'assertive');
149
+ snackbar.setAttribute('aria-atomic', 'true');
150
+
151
+ const snackbarText = document.createElement('span');
152
+ snackbarText.className = 'mini-snackbar-text';
153
+ snackbar.appendChild(snackbarText);
154
+
155
+ document.body.appendChild(snackbar);
156
+ this._initialized = true;
157
+ }
158
+
159
+ static destroy() {
160
+ this.hideCurrent();
161
+ this.clearQueue();
162
+
163
+ const snackbar = document.getElementById('mini-snackbar');
164
+ if (snackbar) snackbar.remove();
165
+
166
+ const styles = document.getElementById('mini-snackbar-styles');
167
+ if (styles) styles.remove();
168
+
169
+ this._state = 'idle';
170
+ this._isShowing = false;
171
+ this._currentActionHandler = null;
172
+ this._currentTimeout = null;
173
+ this._initialized = false;
174
+ }
175
+
176
+ static getTransitionDuration() {
177
+ const snackbar = document.getElementById('mini-snackbar');
178
+ if (!snackbar) return this._transitionDuration
179
+
180
+ try {
181
+ const computedStyle = window.getComputedStyle(snackbar);
182
+ const duration = computedStyle.transitionDuration;
183
+ if (duration && duration !== '0s') {
184
+ const value = parseFloat(duration);
185
+ return duration.includes('ms') ? value : value * 1000
186
+ }
187
+ } catch (e) {
188
+ console.warn('Snackbar: Could not read transition duration from CSS', e);
189
+ }
190
+
191
+ return this._transitionDuration
192
+ }
193
+
194
+ static add(message, action = null, duration = 3000) {
195
+ if (!this._initialized) {
196
+ console.warn('Snackbar: Not initialized. Call Snackbar.init() first.');
197
+ return
198
+ }
199
+
200
+ if (typeof message !== 'string' || message.trim() === '') {
201
+ console.warn('Snackbar: Message must be a non-empty string');
202
+ return
203
+ }
204
+ if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {
205
+ console.warn('Snackbar: Action must be an object with "text" (string) and "handler" (function) properties');
206
+ return
207
+ }
208
+ if (typeof duration !== 'number' || duration <= 0) {
209
+ console.warn('Snackbar: Duration must be a positive number');
210
+ return
211
+ }
212
+
213
+ this._queue.push({ message, action, duration });
214
+ if (this._state === 'idle') this.showNext();
215
+ }
216
+
217
+ static _cleanupAction() {
218
+ const snackbar = document.getElementById('mini-snackbar');
219
+ if (!snackbar) return
220
+
221
+ const actionButton = snackbar.querySelector('.mini-snackbar-action');
222
+ if (actionButton && this._currentActionHandler) {
223
+ actionButton.removeEventListener('click', this._currentActionHandler);
224
+ this._currentActionHandler = null;
225
+ actionButton.remove();
226
+ }
227
+ }
228
+
229
+ static _showSnackbar(message, action, duration, onHide = null) {
230
+ const snackbar = document.getElementById('mini-snackbar');
231
+ if (!snackbar) {
232
+ console.error('Snackbar: Snackbar element not found. Ensure init() has been called.');
233
+ return
234
+ }
235
+
236
+ this._state = 'showing';
237
+ this._isShowing = true;
238
+ const snackbarText = snackbar.querySelector('.mini-snackbar-text');
239
+ snackbarText.textContent = message;
240
+
241
+ if (action) {
242
+ const actionButton = document.createElement('md-text-button');
243
+ actionButton.classList.add('mini-snackbar-action');
244
+
245
+ // Fallback for when Material Components are not available
246
+ if (customElements.get('md-text-button') === undefined) {
247
+ actionButton.setAttribute('data-fallback', '');
248
+ }
249
+
250
+ actionButton.textContent = action.text;
251
+
252
+ this._currentActionHandler = () => {
253
+ action.handler();
254
+ this._hideSnackbar(onHide);
255
+ };
256
+
257
+ actionButton.addEventListener('click', this._currentActionHandler);
258
+ snackbar.appendChild(actionButton);
259
+ }
260
+
261
+ snackbar.classList.add('show');
262
+
263
+ this._currentTimeout = setTimeout(() => {
264
+ this._hideSnackbar(onHide);
265
+ }, duration);
266
+ }
267
+
268
+ static _hideSnackbar(onHide = null) {
269
+ if (this._currentTimeout) {
270
+ clearTimeout(this._currentTimeout);
271
+ this._currentTimeout = null;
272
+ }
273
+
274
+ this._state = 'transitioning';
275
+ const snackbar = document.getElementById('mini-snackbar');
276
+ if (snackbar) {
277
+ snackbar.classList.remove('show');
278
+ }
279
+
280
+ this._cleanupAction();
281
+
282
+ // Wait for CSS transition to complete
283
+ const transitionDuration = this.getTransitionDuration();
284
+ setTimeout(() => {
285
+ this._isShowing = false;
286
+ this._state = 'idle';
287
+ if (onHide) onHide();
288
+ }, transitionDuration);
289
+ }
290
+
291
+ static show(message, action = null, duration = 3000) {
292
+ if (!this._initialized) {
293
+ console.warn('Snackbar: Not initialized. Call Snackbar.init() first.');
294
+ return
295
+ }
296
+
297
+ if (typeof message !== 'string' || message.trim() === '') {
298
+ console.warn('Snackbar: Message must be a non-empty string');
299
+ return
300
+ }
301
+ if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {
302
+ console.warn('Snackbar: Action must be an object with "text" (string) and "handler" (function) properties');
303
+ return
304
+ }
305
+ if (typeof duration !== 'number' || duration <= 0) {
306
+ console.warn('Snackbar: Duration must be a positive number');
307
+ return
308
+ }
309
+
310
+ // Queue message if currently transitioning
311
+ if (this._state === 'transitioning') {
312
+ this.add(message, action, duration);
313
+ return
314
+ }
315
+
316
+ // Interrupt current snackbar if showing
317
+ if (this._isShowing) {
318
+ this._state = 'transitioning';
319
+ if (this._currentTimeout) {
320
+ clearTimeout(this._currentTimeout);
321
+ this._currentTimeout = null;
322
+ }
323
+ const snackbar = document.getElementById('mini-snackbar');
324
+ if (snackbar) {
325
+ snackbar.classList.remove('show');
326
+ }
327
+ this._cleanupAction();
328
+
329
+ const transitionDuration = this.getTransitionDuration();
330
+ setTimeout(() => {
331
+ this._isShowing = false;
332
+ this._state = 'idle';
333
+ this._showSnackbar(message, action, duration);
334
+ }, transitionDuration);
335
+ } else {
336
+ this._showSnackbar(message, action, duration);
337
+ }
338
+ }
339
+
340
+ static showNext() {
341
+ if (this._queue.length === 0) {
342
+ this._isShowing = false;
343
+ this._state = 'idle';
344
+ return
345
+ }
346
+
347
+ const { message, action, duration } = this._queue.shift();
348
+ this._showSnackbar(message, action, duration, () => {
349
+ setTimeout(() => this.showNext(), 200);
350
+ });
351
+ }
352
+
353
+ static clearQueue() {
354
+ this._queue = [];
355
+ }
356
+
357
+ static hideCurrent() {
358
+ if (this._isShowing && this._state !== 'transitioning') {
359
+ this._hideSnackbar();
360
+ }
361
+ }
362
+
363
+ static isInitialized() {
364
+ return this._initialized
365
+ }
366
+
367
+ // Getters/setters for testing
368
+ static get queue() { return this._queue }
369
+ static set queue(value) { this._queue = value; }
370
+ static get isShowing() { return this._isShowing }
371
+ static set isShowing(value) { this._isShowing = value; }
372
+ static get currentTimeout() { return this._currentTimeout }
373
+ static set currentTimeout(value) { this._currentTimeout = value; }
374
+ static get state() { return this._state }
375
+ static set state(value) { this._state = value; }
376
+ }
377
+
378
+ // Module exports
379
+ if (typeof module !== 'undefined' && module.exports) {
380
+ module.exports = Snackbar;
381
+ }
382
+
383
+ // Make available globally in browser
384
+ if (typeof window !== 'undefined') {
385
+ window.Snackbar = Snackbar;
386
+ }
387
+
388
+ }));
389
+ //# sourceMappingURL=minisnackbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minisnackbar.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * MiniSnackbar - A simple vanilla JavaScript snackbar/toast library\r\n *\r\n * @version 1.0.0\r\n * @author Shanto Islam <shantoislamdev@gmail.com>\r\n * @license MIT\r\n * @description A lightweight, zero-dependency snackbar library with Material Design integration\r\n * @repository https://github.com/shantoislamdev/minisnackbar\r\n * @homepage https://github.com/shantoislamdev/minisnackbar#readme\r\n */\r\n\r\nclass Snackbar {\r\n static _queue = []\r\n static _isShowing = false\r\n static _currentTimeout = null\r\n static _state = 'idle' // idle, showing, transitioning\r\n static _currentActionHandler = null\r\n static _transitionDuration = 250\r\n static _initialized = false\r\n\r\n static init(options = {}) {\r\n if (this._initialized) return\r\n\r\n if (typeof document === 'undefined' || !document.body) {\r\n console.error('Snackbar: DOM is not available')\r\n return\r\n }\r\n\r\n if (options.transitionDuration && typeof options.transitionDuration === 'number') {\r\n this._transitionDuration = options.transitionDuration\r\n }\r\n\r\n if (document.getElementById('mini-snackbar')) {\r\n this._initialized = true\r\n return\r\n }\r\n\r\n if (!document.getElementById('mini-snackbar-styles')) {\r\n const style = document.createElement('style')\r\n style.id = 'mini-snackbar-styles'\r\n style.textContent = `\r\n .mini-snackbar {\r\n /* Positioning */\r\n position: fixed;\r\n z-index: 1000;\r\n left: 50%;\r\n bottom: 30px;\r\n transform: translateX(-50%) translateY(100%);\r\n \r\n /* Sizing */\r\n min-width: 250px;\r\n max-width: 90%;\r\n \r\n /* Layout */\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 0.875rem 1rem;\r\n \r\n /* Visibility */\r\n visibility: hidden;\r\n \r\n /* Theming */\r\n background-color: var(--mini-snackbar-bg, var(--md-sys-color-inverse-surface, rgba(255, 255, 255, 1)));\r\n color: var(--mini-snackbar-text, var(--md-sys-color-inverse-on-surface, inherit));\r\n border: var(--mini-snackbar-border, none);\r\n font-family: var(--mini-snackbar-font-family, inherit);\r\n font-size: 0.875rem;\r\n text-align: left;\r\n border-radius: var(--mini-snackbar-radius, 1rem);\r\n box-shadow: var(--mini-snackbar-shadow, 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12));\r\n \r\n /* Animation */\r\n transition: var(--mini-snackbar-transition, transform ${this._transitionDuration}ms ease-in-out);\r\n }\r\n\r\n .mini-snackbar.show {\r\n visibility: visible;\r\n transform: translateX(-50%) translateY(0);\r\n }\r\n\r\n /* Material Component Action Button */\r\n .mini-snackbar .mini-snackbar-action {\r\n flex-shrink: 0;\r\n padding: 0.5rem 1rem;\r\n margin: -0.5rem -0.5rem -0.5rem 0;\r\n }\r\n\r\n /* Fallback Action Button (when Material Components unavailable) */\r\n .mini-snackbar md-text-button[data-fallback] {\r\n display: inline-block;\r\n flex-shrink: 0;\r\n padding: 0.5rem 1rem;\r\n margin: -0.5rem -0.5rem -0.5rem 0;\r\n border: none;\r\n background: var(--mini-snackbar-btn-bg, transparent);\r\n font-size: inherit;\r\n font-family: inherit;\r\n font-weight: 500;\r\n letter-spacing: 0.0892857143em;\r\n text-transform: uppercase;\r\n color: var(--mini-snackbar-btn-text, inherit);\r\n cursor: pointer;\r\n user-select: none;\r\n border-radius: var(--mini-snackbar-btn-radius, 1rem);\r\n transition: opacity 0.2s ease;\r\n }\r\n\r\n .mini-snackbar md-text-button[data-fallback]:hover {\r\n opacity: var(--mini-snackbar-btn-hover-opacity, 0.8);\r\n outline: var(--mini-snackbar-btn-hover-outline, 2px solid var(--mini-snackbar-btn-text, inherit));\r\n outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);\r\n background-color: var(--mini-snackbar-btn-hover-bg, transparent);\r\n }\r\n\r\n .mini-snackbar md-text-button[data-fallback]:focus {\r\n outline: var(--mini-snackbar-btn-focus-outline, 2px solid var(--mini-snackbar-btn-text, inherit));\r\n outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);\r\n }\r\n\r\n /* Mobile responsive */\r\n @media (max-width: 600px) {\r\n .mini-snackbar {\r\n bottom: 90px;\r\n }\r\n }\r\n\r\n /* Accessibility: Reduced motion */\r\n @media (prefers-reduced-motion: reduce) {\r\n .mini-snackbar {\r\n transition: opacity 0.15s ease;\r\n }\r\n }\r\n `\r\n document.head.appendChild(style)\r\n }\r\n\r\n const snackbar = document.createElement('div')\r\n snackbar.id = 'mini-snackbar'\r\n snackbar.className = 'mini-snackbar'\r\n snackbar.setAttribute('role', 'alert')\r\n snackbar.setAttribute('aria-live', 'assertive')\r\n snackbar.setAttribute('aria-atomic', 'true')\r\n\r\n const snackbarText = document.createElement('span')\r\n snackbarText.className = 'mini-snackbar-text'\r\n snackbar.appendChild(snackbarText)\r\n\r\n document.body.appendChild(snackbar)\r\n this._initialized = true\r\n }\r\n\r\n static destroy() {\r\n this.hideCurrent()\r\n this.clearQueue()\r\n\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) snackbar.remove()\r\n\r\n const styles = document.getElementById('mini-snackbar-styles')\r\n if (styles) styles.remove()\r\n\r\n this._state = 'idle'\r\n this._isShowing = false\r\n this._currentActionHandler = null\r\n this._currentTimeout = null\r\n this._initialized = false\r\n }\r\n\r\n static getTransitionDuration() {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) return this._transitionDuration\r\n\r\n try {\r\n const computedStyle = window.getComputedStyle(snackbar)\r\n const duration = computedStyle.transitionDuration\r\n if (duration && duration !== '0s') {\r\n const value = parseFloat(duration)\r\n return duration.includes('ms') ? value : value * 1000\r\n }\r\n } catch (e) {\r\n console.warn('Snackbar: Could not read transition duration from CSS', e)\r\n }\r\n\r\n return this._transitionDuration\r\n }\r\n\r\n static add(message, action = null, duration = 3000) {\r\n if (!this._initialized) {\r\n console.warn('Snackbar: Not initialized. Call Snackbar.init() first.')\r\n return\r\n }\r\n\r\n if (typeof message !== 'string' || message.trim() === '') {\r\n console.warn('Snackbar: Message must be a non-empty string')\r\n return\r\n }\r\n if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {\r\n console.warn('Snackbar: Action must be an object with \"text\" (string) and \"handler\" (function) properties')\r\n return\r\n }\r\n if (typeof duration !== 'number' || duration <= 0) {\r\n console.warn('Snackbar: Duration must be a positive number')\r\n return\r\n }\r\n\r\n this._queue.push({ message, action, duration })\r\n if (this._state === 'idle') this.showNext()\r\n }\r\n\r\n static _cleanupAction() {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) return\r\n\r\n const actionButton = snackbar.querySelector('.mini-snackbar-action')\r\n if (actionButton && this._currentActionHandler) {\r\n actionButton.removeEventListener('click', this._currentActionHandler)\r\n this._currentActionHandler = null\r\n actionButton.remove()\r\n }\r\n }\r\n\r\n static _showSnackbar(message, action, duration, onHide = null) {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) {\r\n console.error('Snackbar: Snackbar element not found. Ensure init() has been called.')\r\n return\r\n }\r\n\r\n this._state = 'showing'\r\n this._isShowing = true\r\n const snackbarText = snackbar.querySelector('.mini-snackbar-text')\r\n snackbarText.textContent = message\r\n\r\n if (action) {\r\n const actionButton = document.createElement('md-text-button')\r\n actionButton.classList.add('mini-snackbar-action')\r\n\r\n // Fallback for when Material Components are not available\r\n if (customElements.get('md-text-button') === undefined) {\r\n actionButton.setAttribute('data-fallback', '')\r\n }\r\n\r\n actionButton.textContent = action.text\r\n\r\n this._currentActionHandler = () => {\r\n action.handler()\r\n this._hideSnackbar(onHide)\r\n }\r\n\r\n actionButton.addEventListener('click', this._currentActionHandler)\r\n snackbar.appendChild(actionButton)\r\n }\r\n\r\n snackbar.classList.add('show')\r\n\r\n this._currentTimeout = setTimeout(() => {\r\n this._hideSnackbar(onHide)\r\n }, duration)\r\n }\r\n\r\n static _hideSnackbar(onHide = null) {\r\n if (this._currentTimeout) {\r\n clearTimeout(this._currentTimeout)\r\n this._currentTimeout = null\r\n }\r\n\r\n this._state = 'transitioning'\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) {\r\n snackbar.classList.remove('show')\r\n }\r\n\r\n this._cleanupAction()\r\n\r\n // Wait for CSS transition to complete\r\n const transitionDuration = this.getTransitionDuration()\r\n setTimeout(() => {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n if (onHide) onHide()\r\n }, transitionDuration)\r\n }\r\n\r\n static show(message, action = null, duration = 3000) {\r\n if (!this._initialized) {\r\n console.warn('Snackbar: Not initialized. Call Snackbar.init() first.')\r\n return\r\n }\r\n\r\n if (typeof message !== 'string' || message.trim() === '') {\r\n console.warn('Snackbar: Message must be a non-empty string')\r\n return\r\n }\r\n if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {\r\n console.warn('Snackbar: Action must be an object with \"text\" (string) and \"handler\" (function) properties')\r\n return\r\n }\r\n if (typeof duration !== 'number' || duration <= 0) {\r\n console.warn('Snackbar: Duration must be a positive number')\r\n return\r\n }\r\n\r\n // Queue message if currently transitioning\r\n if (this._state === 'transitioning') {\r\n this.add(message, action, duration)\r\n return\r\n }\r\n\r\n // Interrupt current snackbar if showing\r\n if (this._isShowing) {\r\n this._state = 'transitioning'\r\n if (this._currentTimeout) {\r\n clearTimeout(this._currentTimeout)\r\n this._currentTimeout = null\r\n }\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) {\r\n snackbar.classList.remove('show')\r\n }\r\n this._cleanupAction()\r\n\r\n const transitionDuration = this.getTransitionDuration()\r\n setTimeout(() => {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n this._showSnackbar(message, action, duration)\r\n }, transitionDuration)\r\n } else {\r\n this._showSnackbar(message, action, duration)\r\n }\r\n }\r\n\r\n static showNext() {\r\n if (this._queue.length === 0) {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n return\r\n }\r\n\r\n const { message, action, duration } = this._queue.shift()\r\n this._showSnackbar(message, action, duration, () => {\r\n setTimeout(() => this.showNext(), 200)\r\n })\r\n }\r\n\r\n static clearQueue() {\r\n this._queue = []\r\n }\r\n\r\n static hideCurrent() {\r\n if (this._isShowing && this._state !== 'transitioning') {\r\n this._hideSnackbar()\r\n }\r\n }\r\n\r\n static isInitialized() {\r\n return this._initialized\r\n }\r\n\r\n // Getters/setters for testing\r\n static get queue() { return this._queue }\r\n static set queue(value) { this._queue = value }\r\n static get isShowing() { return this._isShowing }\r\n static set isShowing(value) { this._isShowing = value }\r\n static get currentTimeout() { return this._currentTimeout }\r\n static set currentTimeout(value) { this._currentTimeout = value }\r\n static get state() { return this._state }\r\n static set state(value) { this._state = value }\r\n}\r\n\r\n// Module exports\r\nif (typeof module !== 'undefined' && module.exports) {\r\n module.exports = Snackbar\r\n}\r\n\r\n// Make available globally in browser\r\nif (typeof window !== 'undefined') {\r\n window.Snackbar = Snackbar\r\n}\r\n\r\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ !function(t){"function"==typeof define&&define.amd?define(t):t()}(function(){"use strict";
2
+ /**
3
+ * MiniSnackbar - A simple vanilla JavaScript snackbar/toast library
4
+ *
5
+ * @version 1.0.0
6
+ * @author Shanto Islam <shantoislamdev@gmail.com>
7
+ * @license MIT
8
+ * @description A lightweight, zero-dependency snackbar library with Material Design integration
9
+ * @repository https://github.com/shantoislamdev/minisnackbar
10
+ * @homepage https://github.com/shantoislamdev/minisnackbar#readme
11
+ */class t{static _queue=[];static _isShowing=!1;static _currentTimeout=null;static _state="idle";static _currentActionHandler=null;static _transitionDuration=250;static _initialized=!1;static init(t={}){if(this._initialized)return;if("undefined"==typeof document||!document.body)return void console.error("Snackbar: DOM is not available");if(t.transitionDuration&&"number"==typeof t.transitionDuration&&(this._transitionDuration=t.transitionDuration),document.getElementById("mini-snackbar"))return void(this._initialized=!0);if(!document.getElementById("mini-snackbar-styles")){const t=document.createElement("style");t.id="mini-snackbar-styles",t.textContent=`\n .mini-snackbar {\n /* Positioning */\n position: fixed;\n z-index: 1000;\n left: 50%;\n bottom: 30px;\n transform: translateX(-50%) translateY(100%);\n \n /* Sizing */\n min-width: 250px;\n max-width: 90%;\n \n /* Layout */\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 0.875rem 1rem;\n \n /* Visibility */\n visibility: hidden;\n \n /* Theming */\n background-color: var(--mini-snackbar-bg, var(--md-sys-color-inverse-surface, rgba(255, 255, 255, 1)));\n color: var(--mini-snackbar-text, var(--md-sys-color-inverse-on-surface, inherit));\n border: var(--mini-snackbar-border, none);\n font-family: var(--mini-snackbar-font-family, inherit);\n font-size: 0.875rem;\n text-align: left;\n border-radius: var(--mini-snackbar-radius, 1rem);\n box-shadow: var(--mini-snackbar-shadow, 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12));\n \n /* Animation */\n transition: var(--mini-snackbar-transition, transform ${this._transitionDuration}ms ease-in-out);\n }\n\n .mini-snackbar.show {\n visibility: visible;\n transform: translateX(-50%) translateY(0);\n }\n\n /* Material Component Action Button */\n .mini-snackbar .mini-snackbar-action {\n flex-shrink: 0;\n padding: 0.5rem 1rem;\n margin: -0.5rem -0.5rem -0.5rem 0;\n }\n\n /* Fallback Action Button (when Material Components unavailable) */\n .mini-snackbar md-text-button[data-fallback] {\n display: inline-block;\n flex-shrink: 0;\n padding: 0.5rem 1rem;\n margin: -0.5rem -0.5rem -0.5rem 0;\n border: none;\n background: var(--mini-snackbar-btn-bg, transparent);\n font-size: inherit;\n font-family: inherit;\n font-weight: 500;\n letter-spacing: 0.0892857143em;\n text-transform: uppercase;\n color: var(--mini-snackbar-btn-text, inherit);\n cursor: pointer;\n user-select: none;\n border-radius: var(--mini-snackbar-btn-radius, 1rem);\n transition: opacity 0.2s ease;\n }\n\n .mini-snackbar md-text-button[data-fallback]:hover {\n opacity: var(--mini-snackbar-btn-hover-opacity, 0.8);\n outline: var(--mini-snackbar-btn-hover-outline, 2px solid var(--mini-snackbar-btn-text, inherit));\n outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);\n background-color: var(--mini-snackbar-btn-hover-bg, transparent);\n }\n\n .mini-snackbar md-text-button[data-fallback]:focus {\n outline: var(--mini-snackbar-btn-focus-outline, 2px solid var(--mini-snackbar-btn-text, inherit));\n outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);\n }\n\n /* Mobile responsive */\n @media (max-width: 600px) {\n .mini-snackbar {\n bottom: 90px;\n }\n }\n\n /* Accessibility: Reduced motion */\n @media (prefers-reduced-motion: reduce) {\n .mini-snackbar {\n transition: opacity 0.15s ease;\n }\n }\n `,document.head.appendChild(t)}const n=document.createElement("div");n.id="mini-snackbar",n.className="mini-snackbar",n.setAttribute("role","alert"),n.setAttribute("aria-live","assertive"),n.setAttribute("aria-atomic","true");const i=document.createElement("span");i.className="mini-snackbar-text",n.appendChild(i),document.body.appendChild(n),this._initialized=!0}static destroy(){this.hideCurrent(),this.clearQueue();const t=document.getElementById("mini-snackbar");t&&t.remove();const n=document.getElementById("mini-snackbar-styles");n&&n.remove(),this._state="idle",this._isShowing=!1,this._currentActionHandler=null,this._currentTimeout=null,this._initialized=!1}static getTransitionDuration(){const t=document.getElementById("mini-snackbar");if(!t)return this._transitionDuration;try{const n=window.getComputedStyle(t).transitionDuration;if(n&&"0s"!==n){const t=parseFloat(n);return n.includes("ms")?t:1e3*t}}catch(t){console.warn("Snackbar: Could not read transition duration from CSS",t)}return this._transitionDuration}static add(t,n=null,i=3e3){this._initialized?"string"==typeof t&&""!==t.trim()?null===n||"object"==typeof n&&"string"==typeof n.text&&"function"==typeof n.handler?"number"!=typeof i||i<=0?console.warn("Snackbar: Duration must be a positive number"):(this._queue.push({message:t,action:n,duration:i}),"idle"===this._state&&this.showNext()):console.warn('Snackbar: Action must be an object with "text" (string) and "handler" (function) properties'):console.warn("Snackbar: Message must be a non-empty string"):console.warn("Snackbar: Not initialized. Call Snackbar.init() first.")}static _cleanupAction(){const t=document.getElementById("mini-snackbar");if(!t)return;const n=t.querySelector(".mini-snackbar-action");n&&this._currentActionHandler&&(n.removeEventListener("click",this._currentActionHandler),this._currentActionHandler=null,n.remove())}static _showSnackbar(t,n,i,e=null){const a=document.getElementById("mini-snackbar");if(!a)return void console.error("Snackbar: Snackbar element not found. Ensure init() has been called.");this._state="showing",this._isShowing=!0;if(a.querySelector(".mini-snackbar-text").textContent=t,n){const t=document.createElement("md-text-button");t.classList.add("mini-snackbar-action"),void 0===customElements.get("md-text-button")&&t.setAttribute("data-fallback",""),t.textContent=n.text,this._currentActionHandler=()=>{n.handler(),this._hideSnackbar(e)},t.addEventListener("click",this._currentActionHandler),a.appendChild(t)}a.classList.add("show"),this._currentTimeout=setTimeout(()=>{this._hideSnackbar(e)},i)}static _hideSnackbar(t=null){this._currentTimeout&&(clearTimeout(this._currentTimeout),this._currentTimeout=null),this._state="transitioning";const n=document.getElementById("mini-snackbar");n&&n.classList.remove("show"),this._cleanupAction();const i=this.getTransitionDuration();setTimeout(()=>{this._isShowing=!1,this._state="idle",t&&t()},i)}static show(t,n=null,i=3e3){if(this._initialized)if("string"==typeof t&&""!==t.trim())if(null===n||"object"==typeof n&&"string"==typeof n.text&&"function"==typeof n.handler)if("number"!=typeof i||i<=0)console.warn("Snackbar: Duration must be a positive number");else if("transitioning"!==this._state)if(this._isShowing){this._state="transitioning",this._currentTimeout&&(clearTimeout(this._currentTimeout),this._currentTimeout=null);const e=document.getElementById("mini-snackbar");e&&e.classList.remove("show"),this._cleanupAction();const a=this.getTransitionDuration();setTimeout(()=>{this._isShowing=!1,this._state="idle",this._showSnackbar(t,n,i)},a)}else this._showSnackbar(t,n,i);else this.add(t,n,i);else console.warn('Snackbar: Action must be an object with "text" (string) and "handler" (function) properties');else console.warn("Snackbar: Message must be a non-empty string");else console.warn("Snackbar: Not initialized. Call Snackbar.init() first.")}static showNext(){if(0===this._queue.length)return this._isShowing=!1,void(this._state="idle");const{message:t,action:n,duration:i}=this._queue.shift();this._showSnackbar(t,n,i,()=>{setTimeout(()=>this.showNext(),200)})}static clearQueue(){this._queue=[]}static hideCurrent(){this._isShowing&&"transitioning"!==this._state&&this._hideSnackbar()}static isInitialized(){return this._initialized}static get queue(){return this._queue}static set queue(t){this._queue=t}static get isShowing(){return this._isShowing}static set isShowing(t){this._isShowing=t}static get currentTimeout(){return this._currentTimeout}static set currentTimeout(t){this._currentTimeout=t}static get state(){return this._state}static set state(t){this._state=t}}"undefined"!=typeof module&&module.exports&&(module.exports=t),"undefined"!=typeof window&&(window.Snackbar=t)});
12
+ //# sourceMappingURL=minisnackbar.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minisnackbar.min.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * MiniSnackbar - A simple vanilla JavaScript snackbar/toast library\r\n *\r\n * @version 1.0.0\r\n * @author Shanto Islam <shantoislamdev@gmail.com>\r\n * @license MIT\r\n * @description A lightweight, zero-dependency snackbar library with Material Design integration\r\n * @repository https://github.com/shantoislamdev/minisnackbar\r\n * @homepage https://github.com/shantoislamdev/minisnackbar#readme\r\n */\r\n\r\nclass Snackbar {\r\n static _queue = []\r\n static _isShowing = false\r\n static _currentTimeout = null\r\n static _state = 'idle' // idle, showing, transitioning\r\n static _currentActionHandler = null\r\n static _transitionDuration = 250\r\n static _initialized = false\r\n\r\n static init(options = {}) {\r\n if (this._initialized) return\r\n\r\n if (typeof document === 'undefined' || !document.body) {\r\n console.error('Snackbar: DOM is not available')\r\n return\r\n }\r\n\r\n if (options.transitionDuration && typeof options.transitionDuration === 'number') {\r\n this._transitionDuration = options.transitionDuration\r\n }\r\n\r\n if (document.getElementById('mini-snackbar')) {\r\n this._initialized = true\r\n return\r\n }\r\n\r\n if (!document.getElementById('mini-snackbar-styles')) {\r\n const style = document.createElement('style')\r\n style.id = 'mini-snackbar-styles'\r\n style.textContent = `\r\n .mini-snackbar {\r\n /* Positioning */\r\n position: fixed;\r\n z-index: 1000;\r\n left: 50%;\r\n bottom: 30px;\r\n transform: translateX(-50%) translateY(100%);\r\n \r\n /* Sizing */\r\n min-width: 250px;\r\n max-width: 90%;\r\n \r\n /* Layout */\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 0.875rem 1rem;\r\n \r\n /* Visibility */\r\n visibility: hidden;\r\n \r\n /* Theming */\r\n background-color: var(--mini-snackbar-bg, var(--md-sys-color-inverse-surface, rgba(255, 255, 255, 1)));\r\n color: var(--mini-snackbar-text, var(--md-sys-color-inverse-on-surface, inherit));\r\n border: var(--mini-snackbar-border, none);\r\n font-family: var(--mini-snackbar-font-family, inherit);\r\n font-size: 0.875rem;\r\n text-align: left;\r\n border-radius: var(--mini-snackbar-radius, 1rem);\r\n box-shadow: var(--mini-snackbar-shadow, 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12));\r\n \r\n /* Animation */\r\n transition: var(--mini-snackbar-transition, transform ${this._transitionDuration}ms ease-in-out);\r\n }\r\n\r\n .mini-snackbar.show {\r\n visibility: visible;\r\n transform: translateX(-50%) translateY(0);\r\n }\r\n\r\n /* Material Component Action Button */\r\n .mini-snackbar .mini-snackbar-action {\r\n flex-shrink: 0;\r\n padding: 0.5rem 1rem;\r\n margin: -0.5rem -0.5rem -0.5rem 0;\r\n }\r\n\r\n /* Fallback Action Button (when Material Components unavailable) */\r\n .mini-snackbar md-text-button[data-fallback] {\r\n display: inline-block;\r\n flex-shrink: 0;\r\n padding: 0.5rem 1rem;\r\n margin: -0.5rem -0.5rem -0.5rem 0;\r\n border: none;\r\n background: var(--mini-snackbar-btn-bg, transparent);\r\n font-size: inherit;\r\n font-family: inherit;\r\n font-weight: 500;\r\n letter-spacing: 0.0892857143em;\r\n text-transform: uppercase;\r\n color: var(--mini-snackbar-btn-text, inherit);\r\n cursor: pointer;\r\n user-select: none;\r\n border-radius: var(--mini-snackbar-btn-radius, 1rem);\r\n transition: opacity 0.2s ease;\r\n }\r\n\r\n .mini-snackbar md-text-button[data-fallback]:hover {\r\n opacity: var(--mini-snackbar-btn-hover-opacity, 0.8);\r\n outline: var(--mini-snackbar-btn-hover-outline, 2px solid var(--mini-snackbar-btn-text, inherit));\r\n outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);\r\n background-color: var(--mini-snackbar-btn-hover-bg, transparent);\r\n }\r\n\r\n .mini-snackbar md-text-button[data-fallback]:focus {\r\n outline: var(--mini-snackbar-btn-focus-outline, 2px solid var(--mini-snackbar-btn-text, inherit));\r\n outline-offset: var(--mini-snackbar-btn-outline-offset, 2px);\r\n }\r\n\r\n /* Mobile responsive */\r\n @media (max-width: 600px) {\r\n .mini-snackbar {\r\n bottom: 90px;\r\n }\r\n }\r\n\r\n /* Accessibility: Reduced motion */\r\n @media (prefers-reduced-motion: reduce) {\r\n .mini-snackbar {\r\n transition: opacity 0.15s ease;\r\n }\r\n }\r\n `\r\n document.head.appendChild(style)\r\n }\r\n\r\n const snackbar = document.createElement('div')\r\n snackbar.id = 'mini-snackbar'\r\n snackbar.className = 'mini-snackbar'\r\n snackbar.setAttribute('role', 'alert')\r\n snackbar.setAttribute('aria-live', 'assertive')\r\n snackbar.setAttribute('aria-atomic', 'true')\r\n\r\n const snackbarText = document.createElement('span')\r\n snackbarText.className = 'mini-snackbar-text'\r\n snackbar.appendChild(snackbarText)\r\n\r\n document.body.appendChild(snackbar)\r\n this._initialized = true\r\n }\r\n\r\n static destroy() {\r\n this.hideCurrent()\r\n this.clearQueue()\r\n\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) snackbar.remove()\r\n\r\n const styles = document.getElementById('mini-snackbar-styles')\r\n if (styles) styles.remove()\r\n\r\n this._state = 'idle'\r\n this._isShowing = false\r\n this._currentActionHandler = null\r\n this._currentTimeout = null\r\n this._initialized = false\r\n }\r\n\r\n static getTransitionDuration() {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) return this._transitionDuration\r\n\r\n try {\r\n const computedStyle = window.getComputedStyle(snackbar)\r\n const duration = computedStyle.transitionDuration\r\n if (duration && duration !== '0s') {\r\n const value = parseFloat(duration)\r\n return duration.includes('ms') ? value : value * 1000\r\n }\r\n } catch (e) {\r\n console.warn('Snackbar: Could not read transition duration from CSS', e)\r\n }\r\n\r\n return this._transitionDuration\r\n }\r\n\r\n static add(message, action = null, duration = 3000) {\r\n if (!this._initialized) {\r\n console.warn('Snackbar: Not initialized. Call Snackbar.init() first.')\r\n return\r\n }\r\n\r\n if (typeof message !== 'string' || message.trim() === '') {\r\n console.warn('Snackbar: Message must be a non-empty string')\r\n return\r\n }\r\n if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {\r\n console.warn('Snackbar: Action must be an object with \"text\" (string) and \"handler\" (function) properties')\r\n return\r\n }\r\n if (typeof duration !== 'number' || duration <= 0) {\r\n console.warn('Snackbar: Duration must be a positive number')\r\n return\r\n }\r\n\r\n this._queue.push({ message, action, duration })\r\n if (this._state === 'idle') this.showNext()\r\n }\r\n\r\n static _cleanupAction() {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) return\r\n\r\n const actionButton = snackbar.querySelector('.mini-snackbar-action')\r\n if (actionButton && this._currentActionHandler) {\r\n actionButton.removeEventListener('click', this._currentActionHandler)\r\n this._currentActionHandler = null\r\n actionButton.remove()\r\n }\r\n }\r\n\r\n static _showSnackbar(message, action, duration, onHide = null) {\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (!snackbar) {\r\n console.error('Snackbar: Snackbar element not found. Ensure init() has been called.')\r\n return\r\n }\r\n\r\n this._state = 'showing'\r\n this._isShowing = true\r\n const snackbarText = snackbar.querySelector('.mini-snackbar-text')\r\n snackbarText.textContent = message\r\n\r\n if (action) {\r\n const actionButton = document.createElement('md-text-button')\r\n actionButton.classList.add('mini-snackbar-action')\r\n\r\n // Fallback for when Material Components are not available\r\n if (customElements.get('md-text-button') === undefined) {\r\n actionButton.setAttribute('data-fallback', '')\r\n }\r\n\r\n actionButton.textContent = action.text\r\n\r\n this._currentActionHandler = () => {\r\n action.handler()\r\n this._hideSnackbar(onHide)\r\n }\r\n\r\n actionButton.addEventListener('click', this._currentActionHandler)\r\n snackbar.appendChild(actionButton)\r\n }\r\n\r\n snackbar.classList.add('show')\r\n\r\n this._currentTimeout = setTimeout(() => {\r\n this._hideSnackbar(onHide)\r\n }, duration)\r\n }\r\n\r\n static _hideSnackbar(onHide = null) {\r\n if (this._currentTimeout) {\r\n clearTimeout(this._currentTimeout)\r\n this._currentTimeout = null\r\n }\r\n\r\n this._state = 'transitioning'\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) {\r\n snackbar.classList.remove('show')\r\n }\r\n\r\n this._cleanupAction()\r\n\r\n // Wait for CSS transition to complete\r\n const transitionDuration = this.getTransitionDuration()\r\n setTimeout(() => {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n if (onHide) onHide()\r\n }, transitionDuration)\r\n }\r\n\r\n static show(message, action = null, duration = 3000) {\r\n if (!this._initialized) {\r\n console.warn('Snackbar: Not initialized. Call Snackbar.init() first.')\r\n return\r\n }\r\n\r\n if (typeof message !== 'string' || message.trim() === '') {\r\n console.warn('Snackbar: Message must be a non-empty string')\r\n return\r\n }\r\n if (action !== null && (typeof action !== 'object' || typeof action.text !== 'string' || typeof action.handler !== 'function')) {\r\n console.warn('Snackbar: Action must be an object with \"text\" (string) and \"handler\" (function) properties')\r\n return\r\n }\r\n if (typeof duration !== 'number' || duration <= 0) {\r\n console.warn('Snackbar: Duration must be a positive number')\r\n return\r\n }\r\n\r\n // Queue message if currently transitioning\r\n if (this._state === 'transitioning') {\r\n this.add(message, action, duration)\r\n return\r\n }\r\n\r\n // Interrupt current snackbar if showing\r\n if (this._isShowing) {\r\n this._state = 'transitioning'\r\n if (this._currentTimeout) {\r\n clearTimeout(this._currentTimeout)\r\n this._currentTimeout = null\r\n }\r\n const snackbar = document.getElementById('mini-snackbar')\r\n if (snackbar) {\r\n snackbar.classList.remove('show')\r\n }\r\n this._cleanupAction()\r\n\r\n const transitionDuration = this.getTransitionDuration()\r\n setTimeout(() => {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n this._showSnackbar(message, action, duration)\r\n }, transitionDuration)\r\n } else {\r\n this._showSnackbar(message, action, duration)\r\n }\r\n }\r\n\r\n static showNext() {\r\n if (this._queue.length === 0) {\r\n this._isShowing = false\r\n this._state = 'idle'\r\n return\r\n }\r\n\r\n const { message, action, duration } = this._queue.shift()\r\n this._showSnackbar(message, action, duration, () => {\r\n setTimeout(() => this.showNext(), 200)\r\n })\r\n }\r\n\r\n static clearQueue() {\r\n this._queue = []\r\n }\r\n\r\n static hideCurrent() {\r\n if (this._isShowing && this._state !== 'transitioning') {\r\n this._hideSnackbar()\r\n }\r\n }\r\n\r\n static isInitialized() {\r\n return this._initialized\r\n }\r\n\r\n // Getters/setters for testing\r\n static get queue() { return this._queue }\r\n static set queue(value) { this._queue = value }\r\n static get isShowing() { return this._isShowing }\r\n static set isShowing(value) { this._isShowing = value }\r\n static get currentTimeout() { return this._currentTimeout }\r\n static set currentTimeout(value) { this._currentTimeout = value }\r\n static get state() { return this._state }\r\n static set state(value) { this._state = value }\r\n}\r\n\r\n// Module exports\r\nif (typeof module !== 'undefined' && module.exports) {\r\n module.exports = Snackbar\r\n}\r\n\r\n// Make available globally in browser\r\nif (typeof window !== 'undefined') {\r\n window.Snackbar = Snackbar\r\n}\r\n\r\n"],"names":["Snackbar","static","init","options","this","_initialized","document","body","console","error","transitionDuration","_transitionDuration","getElementById","style","createElement","id","textContent","head","appendChild","snackbar","className","setAttribute","snackbarText","destroy","hideCurrent","clearQueue","remove","styles","_state","_isShowing","_currentActionHandler","_currentTimeout","getTransitionDuration","duration","window","getComputedStyle","value","parseFloat","includes","e","warn","add","message","action","trim","text","handler","_queue","push","showNext","_cleanupAction","actionButton","querySelector","removeEventListener","_showSnackbar","onHide","classList","undefined","customElements","get","_hideSnackbar","addEventListener","setTimeout","clearTimeout","show","length","shift","isInitialized","queue","isShowing","currentTimeout","state","module","exports"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "minisnackbar",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "A simple vanilla JavaScript snackbar/toast library",
6
+ "main": "dist/minisnackbar.js",
7
+ "module": "dist/minisnackbar.esm.js",
8
+ "types": "src/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./src/index.d.ts",
12
+ "import": "./dist/minisnackbar.esm.js",
13
+ "require": "./dist/minisnackbar.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "src/index.d.ts"
19
+ ],
20
+ "scripts": {
21
+ "build": "rollup -c",
22
+ "test": "jest",
23
+ "lint": "eslint src/index.js",
24
+ "format": "prettier --write src/index.js"
25
+ },
26
+ "keywords": [
27
+ "snackbar",
28
+ "toast",
29
+ "notification",
30
+ "vanilla-js"
31
+ ],
32
+ "author": "Shanto Islam <shantoislamdev@gmail.com>",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/shantoislamdev/minisnackbar.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/shantoislamdev/minisnackbar/issues"
40
+ },
41
+ "homepage": "https://github.com/shantoislamdev/minisnackbar#readme",
42
+ "jest": {
43
+ "testEnvironment": "jsdom"
44
+ },
45
+ "devDependencies": {
46
+ "@rollup/plugin-node-resolve": "^16.0.1",
47
+ "@rollup/plugin-terser": "^0.4.4",
48
+ "eslint": "^9.36.0",
49
+ "jest": "^30.2.0",
50
+ "jest-environment-jsdom": "^30.2.0",
51
+ "jsdom": "^27.0.0",
52
+ "prettier": "^3.6.2",
53
+ "rollup": "^4.52.3"
54
+ }
55
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ interface SnackbarAction {
2
+ text: string;
3
+ handler: () => void;
4
+ }
5
+
6
+ interface SnackbarOptions {
7
+ transitionDuration?: number;
8
+ }
9
+
10
+ interface Snackbar {
11
+ add(message: string, action?: SnackbarAction | null, duration?: number): void;
12
+ show(message: string, action?: SnackbarAction | null, duration?: number): void;
13
+ showNext(): void;
14
+ clearQueue(): void;
15
+ hideCurrent(): void;
16
+ init(options?: SnackbarOptions): void;
17
+ destroy(): void;
18
+ getTransitionDuration(): number;
19
+ isInitialized(): boolean;
20
+ readonly queue: SnackbarItem[];
21
+ readonly isShowing: boolean;
22
+ readonly currentTimeout: number | null;
23
+ readonly state: string;
24
+ }
25
+
26
+ interface SnackbarItem {
27
+ message: string;
28
+ action?: SnackbarAction | null;
29
+ duration: number;
30
+ }
31
+
32
+ declare const Snackbar: Snackbar;
33
+
34
+ export default Snackbar;
35
+ export { Snackbar, SnackbarAction, SnackbarItem, SnackbarOptions };