minisnackbar 2.0.0 → 3.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 -21
- package/README.md +33 -19
- package/dist/constants.d.ts +10 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/controller.d.ts +27 -0
- package/dist/controller.d.ts.map +1 -0
- package/dist/index.d.ts +3 -33
- package/dist/index.d.ts.map +1 -1
- package/dist/minisnackbar.cjs +406 -357
- package/dist/minisnackbar.cjs.map +1 -1
- package/dist/minisnackbar.esm.js +372 -317
- package/dist/minisnackbar.esm.js.map +1 -1
- package/dist/minisnackbar.js +420 -367
- package/dist/minisnackbar.js.map +1 -1
- package/dist/minisnackbar.min.js +11 -10
- package/dist/minisnackbar.min.js.map +1 -1
- package/dist/renderer.d.ts +18 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/styles.d.ts +4 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/validation.d.ts +6 -0
- package/dist/validation.d.ts.map +1 -0
- package/docs.md +514 -0
- package/package.json +64 -63
- package/dist/minisnackbar.min.cjs +0 -12
- package/dist/minisnackbar.min.cjs.map +0 -1
package/docs.md
ADDED
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
# MiniSnackbar Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
MiniSnackbar is a lightweight, zero-dependency vanilla JavaScript library for displaying snackbar/toast notifications. It provides a simple API for showing temporary messages with optional action buttons, queue management, and customizable styling.
|
|
6
|
+
|
|
7
|
+
**Key Feature:** MiniSnackbar automatically integrates with [Material Web](https://material-web.dev/) components and matches your site's default Material theme. Since Material Web doesn't provide a snackbar component, this library fills that gap while maintaining design consistency.
|
|
8
|
+
|
|
9
|
+
**Author:** Shanto Islam ([shantoislamdev.web.app](https://shantoislamdev.web.app)) <shantoislamdev@gmail.com>
|
|
10
|
+
**Version:** 3.0.0
|
|
11
|
+
**License:** MIT
|
|
12
|
+
**Repository:** [github.com/shantoislamdev/minisnackbar](https://github.com/shantoislamdev/minisnackbar)
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Features](#features)
|
|
17
|
+
- [Installation](#installation)
|
|
18
|
+
- [Quick Start](#quick-start)
|
|
19
|
+
- [API Reference](#api-reference)
|
|
20
|
+
- [Configuration](#configuration)
|
|
21
|
+
- [Styling and Theming](#styling-and-theming)
|
|
22
|
+
- [Advanced Usage](#advanced-usage)
|
|
23
|
+
- [Browser Support](#browser-support)
|
|
24
|
+
- [Accessibility](#accessibility)
|
|
25
|
+
- [Troubleshooting](#troubleshooting)
|
|
26
|
+
- [Contributing](#contributing)
|
|
27
|
+
- [License](#license)
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- **Zero Dependencies**: Works standalone without external libraries
|
|
32
|
+
- **Customizable Styling**: Extensive CSS variable support for theming
|
|
33
|
+
- **Mobile Responsive**: Optimized for all screen sizes
|
|
34
|
+
- **Lightweight**: Small browser bundle with no runtime dependencies
|
|
35
|
+
- **Queue Management**: Handles multiple messages automatically
|
|
36
|
+
- **Action Buttons**: Support for interactive buttons with Material Design integration
|
|
37
|
+
- **Multiple Formats**: Browser global, ESM, and CommonJS builds
|
|
38
|
+
- **TypeScript**: Native TypeScript support with bundled type definitions
|
|
39
|
+
- **Accessible**: ARIA attributes and keyboard-accessible fallback buttons
|
|
40
|
+
- **Material Design**: Optional integration with Material Design web components
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
### NPM
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install minisnackbar
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### CDN
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<script src="https://unpkg.com/minisnackbar/dist/minisnackbar.min.js"></script>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> **Note:** Omitting the version number will always load the latest version. For production stability, consider pinning to a specific version (e.g., `@3.0.0`).
|
|
57
|
+
|
|
58
|
+
### Manual Download
|
|
59
|
+
|
|
60
|
+
Download the latest release from the [GitHub releases page](https://github.com/shantoislamdev/minisnackbar/releases) and include the `dist/minisnackbar.js` file in your project.
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
### Basic Setup
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
import { Snackbar } from 'minisnackbar'
|
|
68
|
+
|
|
69
|
+
// Initialize (required)
|
|
70
|
+
Snackbar.init()
|
|
71
|
+
|
|
72
|
+
// Show a simple message
|
|
73
|
+
Snackbar.add('Hello, world!')
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Browser Usage
|
|
77
|
+
|
|
78
|
+
```html
|
|
79
|
+
<!DOCTYPE html>
|
|
80
|
+
<html>
|
|
81
|
+
<head>
|
|
82
|
+
<title>My App</title>
|
|
83
|
+
</head>
|
|
84
|
+
<body>
|
|
85
|
+
<button id="show-btn">Show Message</button>
|
|
86
|
+
|
|
87
|
+
<script src="dist/minisnackbar.js"></script>
|
|
88
|
+
<script>
|
|
89
|
+
// Initialize first
|
|
90
|
+
Snackbar.init()
|
|
91
|
+
|
|
92
|
+
// Add event listener
|
|
93
|
+
document.getElementById('show-btn').addEventListener('click', () => {
|
|
94
|
+
Snackbar.add('Button clicked!')
|
|
95
|
+
})
|
|
96
|
+
</script>
|
|
97
|
+
</body>
|
|
98
|
+
</html>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## API Reference
|
|
102
|
+
|
|
103
|
+
### Initialization
|
|
104
|
+
|
|
105
|
+
#### `Snackbar.init(options?)`
|
|
106
|
+
|
|
107
|
+
Initializes the MiniSnackbar library. This method must be called before using any other methods.
|
|
108
|
+
|
|
109
|
+
**Parameters:**
|
|
110
|
+
|
|
111
|
+
- `options` (Object, optional): Configuration options
|
|
112
|
+
- `transitionDuration` (number, optional): Animation duration in milliseconds (default: 250)
|
|
113
|
+
|
|
114
|
+
**Returns:** `void`
|
|
115
|
+
|
|
116
|
+
**Example:**
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
// Basic initialization
|
|
120
|
+
Snackbar.init()
|
|
121
|
+
|
|
122
|
+
// With custom transition duration
|
|
123
|
+
Snackbar.init({ transitionDuration: 500 })
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Message Display
|
|
127
|
+
|
|
128
|
+
#### `Snackbar.add(message, action?, duration?)`
|
|
129
|
+
|
|
130
|
+
Adds a message to the display queue. Messages are shown in order, respecting the current display state.
|
|
131
|
+
|
|
132
|
+
**Parameters:**
|
|
133
|
+
|
|
134
|
+
- `message` (string): The text content to display
|
|
135
|
+
- `action` (Object, optional): Action button configuration
|
|
136
|
+
- `text` (string): Button label text
|
|
137
|
+
- `handler` (function): Click event handler function
|
|
138
|
+
- `duration` (number, optional): Display duration in milliseconds (default: 3000)
|
|
139
|
+
|
|
140
|
+
**Returns:** `void`
|
|
141
|
+
|
|
142
|
+
**Examples:**
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// Simple message
|
|
146
|
+
Snackbar.add('File saved successfully')
|
|
147
|
+
|
|
148
|
+
// With action button
|
|
149
|
+
Snackbar.add('Item deleted', {
|
|
150
|
+
text: 'UNDO',
|
|
151
|
+
handler: () => {
|
|
152
|
+
// Restore the deleted item
|
|
153
|
+
restoreItem()
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// Custom duration
|
|
158
|
+
Snackbar.add('Long message', null, 5000)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### `Snackbar.show(message, action?, duration?)`
|
|
162
|
+
|
|
163
|
+
Immediately displays a message, interrupting any currently shown snackbar.
|
|
164
|
+
|
|
165
|
+
**Parameters:** Same as `Snackbar.add()`
|
|
166
|
+
|
|
167
|
+
**Returns:** `void`
|
|
168
|
+
|
|
169
|
+
**Example:**
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
// Interrupt current message
|
|
173
|
+
Snackbar.show('Urgent notification!')
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Queue Management
|
|
177
|
+
|
|
178
|
+
#### `Snackbar.clearQueue()`
|
|
179
|
+
|
|
180
|
+
Removes all pending messages from the queue.
|
|
181
|
+
|
|
182
|
+
**Returns:** `void`
|
|
183
|
+
|
|
184
|
+
**Example:**
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
Snackbar.clearQueue()
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### `Snackbar.hideCurrent()`
|
|
191
|
+
|
|
192
|
+
Hides the currently displayed snackbar immediately.
|
|
193
|
+
|
|
194
|
+
**Returns:** `void`
|
|
195
|
+
|
|
196
|
+
**Example:**
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
Snackbar.hideCurrent()
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### State Management
|
|
203
|
+
|
|
204
|
+
#### `Snackbar.destroy()`
|
|
205
|
+
|
|
206
|
+
Completely cleans up the snackbar instance, removing DOM elements and resetting all state.
|
|
207
|
+
|
|
208
|
+
**Returns:** `void`
|
|
209
|
+
|
|
210
|
+
**Example:**
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
// Clean up when done
|
|
214
|
+
Snackbar.destroy()
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### `Snackbar.isInitialized()`
|
|
218
|
+
|
|
219
|
+
Checks if the snackbar has been initialized.
|
|
220
|
+
|
|
221
|
+
**Returns:** `boolean` - True if initialized, false otherwise
|
|
222
|
+
|
|
223
|
+
**Example:**
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
if (Snackbar.isInitialized()) {
|
|
227
|
+
Snackbar.add('Already initialized')
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### `Snackbar.getTransitionDuration()`
|
|
232
|
+
|
|
233
|
+
Gets the current transition duration in milliseconds.
|
|
234
|
+
|
|
235
|
+
**Returns:** `number` - Transition duration
|
|
236
|
+
|
|
237
|
+
**Example:**
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
const duration = Snackbar.getTransitionDuration()
|
|
241
|
+
console.log(`Transition takes ${duration}ms`)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Configuration
|
|
245
|
+
|
|
246
|
+
### Transition Duration
|
|
247
|
+
|
|
248
|
+
You can customize the animation speed by setting the transition duration during initialization:
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
Snackbar.init({ transitionDuration: 300 }) // Faster animations
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
This affects both show and hide transitions.
|
|
255
|
+
|
|
256
|
+
## Styling and Theming
|
|
257
|
+
|
|
258
|
+
MiniSnackbar uses CSS variables for easy customization. Define these variables in your stylesheet before initializing the library.
|
|
259
|
+
|
|
260
|
+
### CSS Variables
|
|
261
|
+
|
|
262
|
+
```css
|
|
263
|
+
:root {
|
|
264
|
+
/* Color scheme */
|
|
265
|
+
--mini-snackbar-bg: #323232; /* Background color */
|
|
266
|
+
--mini-snackbar-text: #ffffff; /* Text color */
|
|
267
|
+
|
|
268
|
+
/* Button styling */
|
|
269
|
+
--mini-snackbar-btn-text: #4caf50; /* Button text color */
|
|
270
|
+
--mini-snackbar-btn-bg: transparent; /* Button background */
|
|
271
|
+
|
|
272
|
+
/* Shape and layout */
|
|
273
|
+
--mini-snackbar-radius: 4px; /* Border radius */
|
|
274
|
+
--mini-snackbar-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); /* Box shadow */
|
|
275
|
+
|
|
276
|
+
/* Typography */
|
|
277
|
+
--mini-snackbar-font-family: inherit; /* Font family */
|
|
278
|
+
|
|
279
|
+
/* Advanced button properties */
|
|
280
|
+
--mini-snackbar-btn-radius: 4px; /* Button border radius */
|
|
281
|
+
--mini-snackbar-btn-hover-opacity: 0.8; /* Button hover opacity */
|
|
282
|
+
--mini-snackbar-btn-hover-outline: 2px solid var(--mini-snackbar-btn-text);
|
|
283
|
+
--mini-snackbar-btn-outline-offset: 2px;
|
|
284
|
+
--mini-snackbar-btn-focus-outline: 2px solid var(--mini-snackbar-btn-text);
|
|
285
|
+
|
|
286
|
+
/* Animation */
|
|
287
|
+
--mini-snackbar-transition: transform 250ms ease-in-out;
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Dark Theme Example
|
|
292
|
+
|
|
293
|
+
```css
|
|
294
|
+
/* Dark theme */
|
|
295
|
+
:root {
|
|
296
|
+
--mini-snackbar-bg: #1a1a1a;
|
|
297
|
+
--mini-snackbar-text: #ffffff;
|
|
298
|
+
--mini-snackbar-btn-text: #64b5f6;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* Light theme */
|
|
302
|
+
.light-theme {
|
|
303
|
+
--mini-snackbar-bg: #ffffff;
|
|
304
|
+
--mini-snackbar-text: #1a1a1a;
|
|
305
|
+
--mini-snackbar-btn-text: #1976d2;
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### CSS Class Overrides
|
|
310
|
+
|
|
311
|
+
For more advanced customization, override the default CSS classes:
|
|
312
|
+
|
|
313
|
+
```css
|
|
314
|
+
/* Custom snackbar styles */
|
|
315
|
+
.mini-snackbar {
|
|
316
|
+
font-family: 'Roboto', sans-serif;
|
|
317
|
+
font-weight: 400;
|
|
318
|
+
letter-spacing: 0.5px;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* Custom show animation */
|
|
322
|
+
.mini-snackbar.show {
|
|
323
|
+
animation: slideIn 0.3s ease-out;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@keyframes slideIn {
|
|
327
|
+
from {
|
|
328
|
+
transform: translateX(-50%) translateY(100%);
|
|
329
|
+
opacity: 0;
|
|
330
|
+
}
|
|
331
|
+
to {
|
|
332
|
+
transform: translateX(-50%) translateY(0);
|
|
333
|
+
opacity: 1;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Material Design Integration
|
|
339
|
+
|
|
340
|
+
MiniSnackbar automatically detects and integrates with Material Design web components:
|
|
341
|
+
|
|
342
|
+
```html
|
|
343
|
+
<script type="importmap">
|
|
344
|
+
{
|
|
345
|
+
"imports": {
|
|
346
|
+
"@material/web/": "https://esm.run/@material/web/"
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
</script>
|
|
350
|
+
<script type="module">
|
|
351
|
+
import '@material/web/all.js'
|
|
352
|
+
</script>
|
|
353
|
+
<script src="dist/minisnackbar.js"></script>
|
|
354
|
+
<script>
|
|
355
|
+
Snackbar.init()
|
|
356
|
+
// Now uses native md-text-button components
|
|
357
|
+
</script>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Advanced Usage
|
|
361
|
+
|
|
362
|
+
### Queue Management
|
|
363
|
+
|
|
364
|
+
Messages are automatically queued and displayed sequentially:
|
|
365
|
+
|
|
366
|
+
```javascript
|
|
367
|
+
// Multiple messages will queue automatically
|
|
368
|
+
Snackbar.add('First message')
|
|
369
|
+
Snackbar.add('Second message')
|
|
370
|
+
Snackbar.add('Third message')
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Interrupting Messages
|
|
374
|
+
|
|
375
|
+
Use `show()` to interrupt the current message:
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
Snackbar.add('This will be interrupted', null, 10000)
|
|
379
|
+
setTimeout(() => {
|
|
380
|
+
Snackbar.show('Urgent message!') // Interrupts the long message
|
|
381
|
+
}, 1000)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Cleanup and Memory Management
|
|
385
|
+
|
|
386
|
+
Always clean up when you're done:
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
// In a single-page application
|
|
390
|
+
window.addEventListener('beforeunload', () => {
|
|
391
|
+
Snackbar.destroy()
|
|
392
|
+
})
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Error Handling
|
|
396
|
+
|
|
397
|
+
The library includes built-in error handling and warnings:
|
|
398
|
+
|
|
399
|
+
```javascript
|
|
400
|
+
// These will log warnings but not throw errors
|
|
401
|
+
Snackbar.add('') // Empty message - warning logged
|
|
402
|
+
Snackbar.add('Valid message', { text: 'OK' }) // Invalid action - missing handler
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## Browser Support
|
|
406
|
+
|
|
407
|
+
- **Chrome**: 60+
|
|
408
|
+
- **Firefox**: 55+
|
|
409
|
+
- **Safari**: 12+
|
|
410
|
+
- **Edge**: 79+
|
|
411
|
+
|
|
412
|
+
### Polyfills
|
|
413
|
+
|
|
414
|
+
For older browsers, consider adding these polyfills:
|
|
415
|
+
|
|
416
|
+
```html
|
|
417
|
+
<!-- CSS color-mix() support -->
|
|
418
|
+
<script src="https://unpkg.com/css-color-mix-polyfill@1.0.0/dist/index.js"></script>
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## Accessibility
|
|
422
|
+
|
|
423
|
+
MiniSnackbar follows accessibility best practices:
|
|
424
|
+
|
|
425
|
+
- **ARIA Attributes**: Uses `role="alert"` and `aria-live="assertive"`
|
|
426
|
+
- **Keyboard Navigation**: Action buttons are focusable and keyboard accessible
|
|
427
|
+
- **Screen Readers**: Messages are announced to assistive technologies
|
|
428
|
+
- **Reduced Motion**: Respects `prefers-reduced-motion` media query
|
|
429
|
+
|
|
430
|
+
### Custom ARIA Labels
|
|
431
|
+
|
|
432
|
+
```javascript
|
|
433
|
+
// The library automatically handles ARIA attributes
|
|
434
|
+
// No additional configuration needed
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## Troubleshooting
|
|
438
|
+
|
|
439
|
+
### Common Issues
|
|
440
|
+
|
|
441
|
+
#### Snackbar not showing
|
|
442
|
+
|
|
443
|
+
- Ensure `Snackbar.init()` has been called
|
|
444
|
+
- Check that the DOM is ready (`DOMContentLoaded` event)
|
|
445
|
+
- Verify no JavaScript errors in the console
|
|
446
|
+
|
|
447
|
+
#### Styling not applying
|
|
448
|
+
|
|
449
|
+
- Define CSS variables before calling `init()`
|
|
450
|
+
- Ensure CSS is loaded before JavaScript
|
|
451
|
+
- Check for CSS specificity conflicts
|
|
452
|
+
|
|
453
|
+
#### Action buttons not working
|
|
454
|
+
|
|
455
|
+
- Verify the `handler` is a function
|
|
456
|
+
- Check for JavaScript errors in the handler
|
|
457
|
+
- If Material Web is not loaded, MiniSnackbar uses a standard `<button>` fallback
|
|
458
|
+
|
|
459
|
+
### Debug Mode
|
|
460
|
+
|
|
461
|
+
Enable debug logging:
|
|
462
|
+
|
|
463
|
+
```javascript
|
|
464
|
+
// The library logs warnings for invalid inputs
|
|
465
|
+
// Check browser console for debugging information
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Contributing
|
|
469
|
+
|
|
470
|
+
Issues and pull requests are welcome on the GitHub repository.
|
|
471
|
+
|
|
472
|
+
### Development Setup
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
# Clone the repository
|
|
476
|
+
git clone https://github.com/shantoislamdev/minisnackbar.git
|
|
477
|
+
cd minisnackbar
|
|
478
|
+
|
|
479
|
+
# Install dependencies
|
|
480
|
+
npm install
|
|
481
|
+
|
|
482
|
+
# Run tests
|
|
483
|
+
npm test
|
|
484
|
+
|
|
485
|
+
# Build for production
|
|
486
|
+
npm run build
|
|
487
|
+
|
|
488
|
+
# Lint code
|
|
489
|
+
npm run lint
|
|
490
|
+
|
|
491
|
+
# Check types
|
|
492
|
+
npm run typecheck
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### Testing
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
# Run unit tests
|
|
499
|
+
npm test
|
|
500
|
+
|
|
501
|
+
# Run tests in watch mode
|
|
502
|
+
npm test -- --watch
|
|
503
|
+
|
|
504
|
+
# Run tests with coverage
|
|
505
|
+
npm test -- --coverage
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
## License
|
|
509
|
+
|
|
510
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
For more information, visit the [GitHub repository](https://github.com/shantoislamdev/minisnackbar).
|
package/package.json
CHANGED
|
@@ -1,63 +1,64 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "minisnackbar",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A simple vanilla JavaScript snackbar/toast library",
|
|
6
|
+
"main": "dist/minisnackbar.cjs",
|
|
7
|
+
"module": "dist/minisnackbar.esm.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"unpkg": "dist/minisnackbar.min.js",
|
|
10
|
+
"jsdelivr": "dist/minisnackbar.min.js",
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/minisnackbar.esm.js",
|
|
16
|
+
"require": "./dist/minisnackbar.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"docs.md"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "rollup -c",
|
|
25
|
+
"test": "npm run build && jest",
|
|
26
|
+
"lint": "eslint \"src/**/*.{ts,js,cjs}\"",
|
|
27
|
+
"format": "prettier --write \"src/**/*.{ts,js,cjs}\" \"*.{js,json,md,html}\"",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"snackbar",
|
|
32
|
+
"toast",
|
|
33
|
+
"notification",
|
|
34
|
+
"vanilla-js",
|
|
35
|
+
"typescript"
|
|
36
|
+
],
|
|
37
|
+
"author": "Shanto Islam <shantoislamdev@gmail.com>",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/shantoislamdev/minisnackbar.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/shantoislamdev/minisnackbar/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/shantoislamdev/minisnackbar#readme",
|
|
47
|
+
"jest": {
|
|
48
|
+
"testEnvironment": "jsdom",
|
|
49
|
+
"transform": {}
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
53
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
54
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
55
|
+
"eslint": "^9.36.0",
|
|
56
|
+
"jest": "^30.2.0",
|
|
57
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
58
|
+
"jsdom": "^27.0.0",
|
|
59
|
+
"prettier": "^3.6.2",
|
|
60
|
+
"rollup": "^4.52.3",
|
|
61
|
+
"tslib": "^2.8.1",
|
|
62
|
+
"typescript": "^5.7.3"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).Snackbar={})}(this,function(t){"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* MiniSnackbar - A simple vanilla JavaScript snackbar/toast library
|
|
4
|
-
*
|
|
5
|
-
* @version 2.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 n{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, rgba(27, 27, 27, 1)));\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;const s=a.querySelector(".mini-snackbar-text");if(s&&(s.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 t=this._queue.shift();if(t){const{message:n,action:i,duration:e}=t;this._showSnackbar(n,i,e,()=>{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}}n._queue=[],n._isShowing=!1,n._currentTimeout=null,n._state="idle",n._currentActionHandler=null,n._transitionDuration=250,n._initialized=!1,"undefined"!=typeof window&&(window.Snackbar=n),t.Snackbar=n,t.default=n,Object.defineProperty(t,"__esModule",{value:!0})});
|
|
12
|
-
//# sourceMappingURL=minisnackbar.min.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"minisnackbar.min.cjs","sources":["../src/index.ts"],"sourcesContent":[null],"names":["Snackbar","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","item","shift","isInitialized","queue","isShowing","currentTimeout","state"],"mappings":"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"}
|