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 +21 -0
- package/README.md +33 -0
- package/dist/minisnackbar.esm.js +382 -0
- package/dist/minisnackbar.esm.js.map +1 -0
- package/dist/minisnackbar.js +389 -0
- package/dist/minisnackbar.js.map +1 -0
- package/dist/minisnackbar.min.js +12 -0
- package/dist/minisnackbar.min.js.map +1 -0
- package/package.json +55 -0
- package/src/index.d.ts +35 -0
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":";;;;;EAAA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACA;EACA,MAAM,QAAQ,CAAC;EACf,EAAE,OAAO,MAAM,GAAG,EAAE;EACpB,EAAE,OAAO,UAAU,GAAG,KAAK;EAC3B,EAAE,OAAO,eAAe,GAAG,IAAI;EAC/B,EAAE,OAAO,MAAM,GAAG,MAAM;EACxB,EAAE,OAAO,qBAAqB,GAAG,IAAI;EACrC,EAAE,OAAO,mBAAmB,GAAG,GAAG;EAClC,EAAE,OAAO,YAAY,GAAG,KAAK;AAC7B;EACA,EAAE,OAAO,IAAI,CAAC,OAAO,GAAG,EAAE,EAAE;EAC5B,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,MAAM;AACjC;EACA,IAAI,IAAI,OAAO,QAAQ,KAAK,WAAW,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;EAC3D,MAAM,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAC;EACrD,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA,IAAI,IAAI,OAAO,CAAC,kBAAkB,IAAI,OAAO,OAAO,CAAC,kBAAkB,KAAK,QAAQ,EAAE;EACtF,MAAM,IAAI,CAAC,mBAAmB,GAAG,OAAO,CAAC,mBAAkB;EAC3D,IAAI,CAAC;AACL;EACA,IAAI,IAAI,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE;EAClD,MAAM,IAAI,CAAC,YAAY,GAAG,KAAI;EAC9B,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,sBAAsB,CAAC,EAAE;EAC1D,MAAM,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAC;EACnD,MAAM,KAAK,CAAC,EAAE,GAAG,uBAAsB;EACvC,MAAM,KAAK,CAAC,WAAW,GAAG,CAAC;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gEAAgE,EAAE,IAAI,CAAC,mBAAmB,CAAC;AAC3F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,EAAC;EACP,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAC;EACtC,IAAI,CAAC;AACL;EACA,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAC;EAClD,IAAI,QAAQ,CAAC,EAAE,GAAG,gBAAe;EACjC,IAAI,QAAQ,CAAC,SAAS,GAAG,gBAAe;EACxC,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAC;EAC1C,IAAI,QAAQ,CAAC,YAAY,CAAC,WAAW,EAAE,WAAW,EAAC;EACnD,IAAI,QAAQ,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,EAAC;AAChD;EACA,IAAI,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,EAAC;EACvD,IAAI,YAAY,CAAC,SAAS,GAAG,qBAAoB;EACjD,IAAI,QAAQ,CAAC,WAAW,CAAC,YAAY,EAAC;AACtC;EACA,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAC;EACvC,IAAI,IAAI,CAAC,YAAY,GAAG,KAAI;EAC5B,EAAE,CAAC;AACH;EACA,EAAE,OAAO,OAAO,GAAG;EACnB,IAAI,IAAI,CAAC,WAAW,GAAE;EACtB,IAAI,IAAI,CAAC,UAAU,GAAE;AACrB;EACA,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,EAAC;EAC7D,IAAI,IAAI,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAE;AACnC;EACA,IAAI,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC,sBAAsB,EAAC;EAClE,IAAI,IAAI,MAAM,EAAE,MAAM,CAAC,MAAM,GAAE;AAC/B;EACA,IAAI,IAAI,CAAC,MAAM,GAAG,OAAM;EACxB,IAAI,IAAI,CAAC,UAAU,GAAG,MAAK;EAC3B,IAAI,IAAI,CAAC,qBAAqB,GAAG,KAAI;EACrC,IAAI,IAAI,CAAC,eAAe,GAAG,KAAI;EAC/B,IAAI,IAAI,CAAC,YAAY,GAAG,MAAK;EAC7B,EAAE,CAAC;AACH;EACA,EAAE,OAAO,qBAAqB,GAAG;EACjC,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,EAAC;EAC7D,IAAI,IAAI,CAAC,QAAQ,EAAE,OAAO,IAAI,CAAC,mBAAmB;AAClD;EACA,IAAI,IAAI;EACR,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAC;EAC7D,MAAM,MAAM,QAAQ,GAAG,aAAa,CAAC,mBAAkB;EACvD,MAAM,IAAI,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE;EACzC,QAAQ,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,EAAC;EAC1C,QAAQ,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI;EAC7D,MAAM,CAAC;EACP,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE;EAChB,MAAM,OAAO,CAAC,IAAI,CAAC,uDAAuD,EAAE,CAAC,EAAC;EAC9E,IAAI,CAAC;AACL;EACA,IAAI,OAAO,IAAI,CAAC,mBAAmB;EACnC,EAAE,CAAC;AACH;EACA,EAAE,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE;EACtD,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;EAC5B,MAAM,OAAO,CAAC,IAAI,CAAC,wDAAwD,EAAC;EAC5E,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;EAC9D,MAAM,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAC;EAClE,MAAM,MAAM;EACZ,IAAI,CAAC;EACL,IAAI,IAAI,MAAM,KAAK,IAAI,KAAK,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,UAAU,CAAC,EAAE;EACpI,MAAM,OAAO,CAAC,IAAI,CAAC,6FAA6F,EAAC;EACjH,MAAM,MAAM;EACZ,IAAI,CAAC;EACL,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,IAAI,CAAC,EAAE;EACvD,MAAM,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAC;EAClE,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAC;EACnD,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,IAAI,CAAC,QAAQ,GAAE;EAC/C,EAAE,CAAC;AACH;EACA,EAAE,OAAO,cAAc,GAAG;EAC1B,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,EAAC;EAC7D,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM;AACzB;EACA,IAAI,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,uBAAuB,EAAC;EACxE,IAAI,IAAI,YAAY,IAAI,IAAI,CAAC,qBAAqB,EAAE;EACpD,MAAM,YAAY,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAC;EAC3E,MAAM,IAAI,CAAC,qBAAqB,GAAG,KAAI;EACvC,MAAM,YAAY,CAAC,MAAM,GAAE;EAC3B,IAAI,CAAC;EACL,EAAE,CAAC;AACH;EACA,EAAE,OAAO,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE;EACjE,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,EAAC;EAC7D,IAAI,IAAI,CAAC,QAAQ,EAAE;EACnB,MAAM,OAAO,CAAC,KAAK,CAAC,sEAAsE,EAAC;EAC3F,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA,IAAI,IAAI,CAAC,MAAM,GAAG,UAAS;EAC3B,IAAI,IAAI,CAAC,UAAU,GAAG,KAAI;EAC1B,IAAI,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,qBAAqB,EAAC;EACtE,IAAI,YAAY,CAAC,WAAW,GAAG,QAAO;AACtC;EACA,IAAI,IAAI,MAAM,EAAE;EAChB,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,gBAAgB,EAAC;EACnE,MAAM,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,sBAAsB,EAAC;AACxD;EACA;EACA,MAAM,IAAI,cAAc,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,SAAS,EAAE;EAC9D,QAAQ,YAAY,CAAC,YAAY,CAAC,eAAe,EAAE,EAAE,EAAC;EACtD,MAAM,CAAC;AACP;EACA,MAAM,YAAY,CAAC,WAAW,GAAG,MAAM,CAAC,KAAI;AAC5C;EACA,MAAM,IAAI,CAAC,qBAAqB,GAAG,MAAM;EACzC,QAAQ,MAAM,CAAC,OAAO,GAAE;EACxB,QAAQ,IAAI,CAAC,aAAa,CAAC,MAAM,EAAC;EAClC,MAAM,EAAC;AACP;EACA,MAAM,YAAY,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,qBAAqB,EAAC;EACxE,MAAM,QAAQ,CAAC,WAAW,CAAC,YAAY,EAAC;EACxC,IAAI,CAAC;AACL;EACA,IAAI,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAC;AAClC;EACA,IAAI,IAAI,CAAC,eAAe,GAAG,UAAU,CAAC,MAAM;EAC5C,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,EAAC;EAChC,IAAI,CAAC,EAAE,QAAQ,EAAC;EAChB,EAAE,CAAC;AACH;EACA,EAAE,OAAO,aAAa,CAAC,MAAM,GAAG,IAAI,EAAE;EACtC,IAAI,IAAI,IAAI,CAAC,eAAe,EAAE;EAC9B,MAAM,YAAY,CAAC,IAAI,CAAC,eAAe,EAAC;EACxC,MAAM,IAAI,CAAC,eAAe,GAAG,KAAI;EACjC,IAAI,CAAC;AACL;EACA,IAAI,IAAI,CAAC,MAAM,GAAG,gBAAe;EACjC,IAAI,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,EAAC;EAC7D,IAAI,IAAI,QAAQ,EAAE;EAClB,MAAM,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAC;EACvC,IAAI,CAAC;AACL;EACA,IAAI,IAAI,CAAC,cAAc,GAAE;AACzB;EACA;EACA,IAAI,MAAM,kBAAkB,GAAG,IAAI,CAAC,qBAAqB,GAAE;EAC3D,IAAI,UAAU,CAAC,MAAM;EACrB,MAAM,IAAI,CAAC,UAAU,GAAG,MAAK;EAC7B,MAAM,IAAI,CAAC,MAAM,GAAG,OAAM;EAC1B,MAAM,IAAI,MAAM,EAAE,MAAM,GAAE;EAC1B,IAAI,CAAC,EAAE,kBAAkB,EAAC;EAC1B,EAAE,CAAC;AACH;EACA,EAAE,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE;EACvD,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;EAC5B,MAAM,OAAO,CAAC,IAAI,CAAC,wDAAwD,EAAC;EAC5E,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;EAC9D,MAAM,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAC;EAClE,MAAM,MAAM;EACZ,IAAI,CAAC;EACL,IAAI,IAAI,MAAM,KAAK,IAAI,KAAK,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,UAAU,CAAC,EAAE;EACpI,MAAM,OAAO,CAAC,IAAI,CAAC,6FAA6F,EAAC;EACjH,MAAM,MAAM;EACZ,IAAI,CAAC;EACL,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,IAAI,CAAC,EAAE;EACvD,MAAM,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAC;EAClE,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA;EACA,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,eAAe,EAAE;EACzC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAC;EACzC,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA;EACA,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;EACzB,MAAM,IAAI,CAAC,MAAM,GAAG,gBAAe;EACnC,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE;EAChC,QAAQ,YAAY,CAAC,IAAI,CAAC,eAAe,EAAC;EAC1C,QAAQ,IAAI,CAAC,eAAe,GAAG,KAAI;EACnC,MAAM,CAAC;EACP,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,EAAC;EAC/D,MAAM,IAAI,QAAQ,EAAE;EACpB,QAAQ,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAC;EACzC,MAAM,CAAC;EACP,MAAM,IAAI,CAAC,cAAc,GAAE;AAC3B;EACA,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,qBAAqB,GAAE;EAC7D,MAAM,UAAU,CAAC,MAAM;EACvB,QAAQ,IAAI,CAAC,UAAU,GAAG,MAAK;EAC/B,QAAQ,IAAI,CAAC,MAAM,GAAG,OAAM;EAC5B,QAAQ,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAC;EACrD,MAAM,CAAC,EAAE,kBAAkB,EAAC;EAC5B,IAAI,CAAC,MAAM;EACX,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAC;EACnD,IAAI,CAAC;EACL,EAAE,CAAC;AACH;EACA,EAAE,OAAO,QAAQ,GAAG;EACpB,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;EAClC,MAAM,IAAI,CAAC,UAAU,GAAG,MAAK;EAC7B,MAAM,IAAI,CAAC,MAAM,GAAG,OAAM;EAC1B,MAAM,MAAM;EACZ,IAAI,CAAC;AACL;EACA,IAAI,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,GAAE;EAC7D,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;EACxD,MAAM,UAAU,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAC;EAC5C,IAAI,CAAC,EAAC;EACN,EAAE,CAAC;AACH;EACA,EAAE,OAAO,UAAU,GAAG;EACtB,IAAI,IAAI,CAAC,MAAM,GAAG,GAAE;EACpB,EAAE,CAAC;AACH;EACA,EAAE,OAAO,WAAW,GAAG;EACvB,IAAI,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,KAAK,eAAe,EAAE;EAC5D,MAAM,IAAI,CAAC,aAAa,GAAE;EAC1B,IAAI,CAAC;EACL,EAAE,CAAC;AACH;EACA,EAAE,OAAO,aAAa,GAAG;EACzB,IAAI,OAAO,IAAI,CAAC,YAAY;EAC5B,EAAE,CAAC;AACH;EACA;EACA,EAAE,WAAW,KAAK,GAAG,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;EAC3C,EAAE,WAAW,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,MAAM,GAAG,MAAK,CAAC,CAAC;EACjD,EAAE,WAAW,SAAS,GAAG,EAAE,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC;EACnD,EAAE,WAAW,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,UAAU,GAAG,MAAK,CAAC,CAAC;EACzD,EAAE,WAAW,cAAc,GAAG,EAAE,OAAO,IAAI,CAAC,eAAe,CAAC,CAAC;EAC7D,EAAE,WAAW,cAAc,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,eAAe,GAAG,MAAK,CAAC,CAAC;EACnE,EAAE,WAAW,KAAK,GAAG,EAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;EAC3C,EAAE,WAAW,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,MAAM,GAAG,MAAK,CAAC,CAAC;EACjD,CAAC;AACD;EACA;EACA,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,OAAO,EAAE;EACrD,EAAE,MAAM,CAAC,OAAO,GAAG,SAAQ;EAC3B,CAAC;AACD;EACA;EACA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;EACnC,EAAE,MAAM,CAAC,QAAQ,GAAG,SAAQ;EAC5B;;;;;;"}
|
|
@@ -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 };
|