modern-alert 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Paul's Digital Studio
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,214 @@
1
+ # ModernAlert
2
+
3
+ A small dialog library for the browser. No npm dependencies, no framework.
4
+
5
+ Drop in three files. Call `ModernAlert.show()`. Get a promise back.
6
+
7
+ ```js
8
+ const result = await ModernAlert.confirm(
9
+ 'Delete this project?',
10
+ 'Files stay in the trash for 30 days.'
11
+ )
12
+
13
+ if (result.isConfirmed) {
14
+ await deleteProject()
15
+ }
16
+ ```
17
+
18
+ The default card is left-aligned, with the type color as a thin top line. Light, dark, or follow the system. The circular icon is opt-in.
19
+
20
+ ## What you get
21
+
22
+ - Dialog first, decoration second (`icon` is off by default)
23
+ - Semantic types: `success`, `error`, `warning`, `info`, `question`, `confirm`, `loading`
24
+ - Backdrop you can keep, drop, or keep invisible while still blocking the page
25
+ - Inputs, HTML, loading, and a timer — still three files, no bundler
26
+
27
+ ## Setup
28
+
29
+ Load the three files in this order. `window.ModernAlert` is ready after the last script.
30
+
31
+ ### npm
32
+
33
+ ```bash
34
+ npm install modern-alert
35
+ ```
36
+
37
+ ```html
38
+ <link rel="stylesheet" href="node_modules/modern-alert/src/modern-alert.css">
39
+ <script src="node_modules/modern-alert/src/icons.js"></script>
40
+ <script src="node_modules/modern-alert/src/modern-alert.js"></script>
41
+ ```
42
+
43
+ If your bundler can import CSS:
44
+
45
+ ```js
46
+ import 'modern-alert/src/icons.js'
47
+ import 'modern-alert'
48
+ import 'modern-alert/modern-alert.css'
49
+ ```
50
+
51
+ ### CDN
52
+
53
+ After the package is on npm:
54
+
55
+ ```html
56
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/modern-alert@1.0.0/src/modern-alert.css">
57
+ <script src="https://cdn.jsdelivr.net/npm/modern-alert@1.0.0/src/icons.js"></script>
58
+ <script src="https://cdn.jsdelivr.net/npm/modern-alert@1.0.0/src/modern-alert.js"></script>
59
+ ```
60
+
61
+ Pin a version. `@latest` will follow new releases.
62
+
63
+ TypeScript types ship in the package (`src/modern-alert.d.ts`).
64
+
65
+ ### Copy the files
66
+
67
+ Copy `src/modern-alert.css`, `src/icons.js`, and `src/modern-alert.js` into your project:
68
+
69
+ ```html
70
+ <link rel="stylesheet" href="src/modern-alert.css">
71
+ <script src="src/icons.js"></script>
72
+ <script src="src/modern-alert.js"></script>
73
+ ```
74
+
75
+ ## Usage
76
+
77
+ ### A simple message
78
+
79
+ ```js
80
+ await ModernAlert.success('Saved', 'The file is already in the library.')
81
+ await ModernAlert.error('Could not save', 'Check your connection and try again.')
82
+ ```
83
+
84
+ ### Confirm something destructive
85
+
86
+ ```js
87
+ const { isConfirmed } = await ModernAlert.confirm(
88
+ 'Delete this project?',
89
+ 'You can restore it from the trash.'
90
+ )
91
+ ```
92
+
93
+ `confirm` shows Cancel and a primary action. Other types show a single button unless you pass `cancelText`.
94
+
95
+ ### Ask for a value
96
+
97
+ ```js
98
+ const result = await ModernAlert.show({
99
+ type: 'question',
100
+ title: 'What should we call it?',
101
+ input: 'text',
102
+ inputPlaceholder: 'Project name',
103
+ inputValidator: (value) => !String(value).trim() && 'Give it a name'
104
+ })
105
+
106
+ if (result.isConfirmed) {
107
+ createProject(result.value)
108
+ }
109
+ ```
110
+
111
+ `input` can be `text`, `email`, `password`, `textarea`, or `select` (`inputOptions` + `inputValue` for select).
112
+
113
+ ### Loading, then done
114
+
115
+ ```js
116
+ ModernAlert.loading('Saving…')
117
+
118
+ await api.save()
119
+
120
+ await ModernAlert.success('Saved', 'You can keep working.')
121
+ ```
122
+
123
+ A loading dialog does not close on backdrop click or Escape. Close it with `ModernAlert.close()`, or replace it with the next `show()` / `success()`.
124
+
125
+ ### HTML inside the body
126
+
127
+ ```js
128
+ await ModernAlert.show({
129
+ title: "What's new",
130
+ html: '<p>You can pass <strong>your own markup</strong>.</p>'
131
+ })
132
+ ```
133
+
134
+ Markup is sanitized: scripts, event handlers, and `javascript:` URLs are stripped.
135
+
136
+ ## Look
137
+
138
+ ```js
139
+ await ModernAlert.show({
140
+ title: 'Deployed',
141
+ text: 'v2.4.1 is live.',
142
+ theme: 'dark', // auto | light | dark
143
+ icon: true, // circular SVG mascot
144
+ backdrop: false // no dim; the page still cannot be clicked
145
+ })
146
+ ```
147
+
148
+ Shorthand helpers take an optional third argument for any option:
149
+
150
+ ```js
151
+ ModernAlert.success('Saved', 'All set.', { theme: 'dark', timer: 2000 })
152
+ ```
153
+
154
+ ## Options
155
+
156
+ | Option | Default | Meaning |
157
+ | --- | --- | --- |
158
+ | `type` | `'info'` | `success` `error` `warning` `info` `question` `confirm` `loading` |
159
+ | `title` | `''` | Heading |
160
+ | `text` | `''` | Body text. Ignored if `html` is set |
161
+ | `html` | `''` | Sanitized markup for the body |
162
+ | `confirmText` | `'OK'` | Primary button label |
163
+ | `cancelText` | `''` | Secondary button label. Any non-empty value also shows Cancel |
164
+ | `showConfirm` | `true` | Show the primary button |
165
+ | `showCancel` | `false` | Show Cancel. `type: 'confirm'` turns this on |
166
+ | `input` | `''` | `text` `email` `password` `textarea` `select` |
167
+ | `inputPlaceholder` | `''` | Placeholder for text-like inputs |
168
+ | `inputValue` | `''` | Initial value, or the selected key for `select` |
169
+ | `inputLabel` | `''` | Label above the field |
170
+ | `inputOptions` | `null` | `{ value: 'Label' }` map for `select` |
171
+ | `inputValidator` | `null` | `(value) => errorMessage`. Return a string to block confirm |
172
+ | `theme` | `'auto'` | Follows `prefers-color-scheme`, or `'light'` / `'dark'` |
173
+ | `icon` | `false` | `true` shows the animated 72px type icon. Forced on for `loading` |
174
+ | `backdrop` | `true` | `false` removes the dim and blur, not the click shield |
175
+ | `timer` | `0` | Auto-dismiss after N milliseconds. Ignored for `loading` |
176
+ | `allowOutsideClick` | `true` | Click outside the card to dismiss. Off for `loading` |
177
+ | `allowEscapeKey` | `true` | Escape to dismiss. Off for `loading` |
178
+
179
+ ## The promise
180
+
181
+ Every call returns:
182
+
183
+ ```ts
184
+ {
185
+ isConfirmed: boolean
186
+ isDismissed: boolean
187
+ value: any // true, or the input string
188
+ dismiss: string // 'cancel' | 'esc' | 'backdrop' | 'timer' | 'close' | 'replace'
189
+ }
190
+ ```
191
+
192
+ `dismiss` is set only when the dialog was not confirmed.
193
+
194
+ ```js
195
+ ModernAlert.show({ title: 'Ping' })
196
+ ModernAlert.isVisible() // true
197
+ ModernAlert.close() // dismiss: 'close'
198
+ ```
199
+
200
+ ## API map
201
+
202
+ | Call | What it does |
203
+ | --- | --- |
204
+ | `show(options)` | Full dialog |
205
+ | `show(title, text, type)` | Same, positional |
206
+ | `success` `error` `warning` `info` `question` | Typed helpers |
207
+ | `confirm(title, text, options?)` | Two actions |
208
+ | `loading(title, text?)` | Spinner, no buttons |
209
+ | `close()` | Dismiss the open dialog |
210
+ | `isVisible()` | Whether a dialog is on screen |
211
+
212
+ ## License
213
+
214
+ MIT
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "modern-alert",
3
+ "version": "1.0.0",
4
+ "description": "Modern modal dialogs for the browser. No dependencies.",
5
+ "license": "MIT",
6
+ "author": {
7
+ "name": "Paul's Digital Studio",
8
+ "url": "https://github.com/PaulsDigital"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/PaulsDigital/modern-alert.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/PaulsDigital/modern-alert/issues"
16
+ },
17
+ "homepage": "https://github.com/PaulsDigital/modern-alert#readme",
18
+ "keywords": [
19
+ "alert",
20
+ "dialog",
21
+ "modal",
22
+ "confirm",
23
+ "prompt",
24
+ "popup",
25
+ "vanilla-js"
26
+ ],
27
+ "main": "src/modern-alert.js",
28
+ "browser": "src/modern-alert.js",
29
+ "style": "src/modern-alert.css",
30
+ "types": "src/modern-alert.d.ts",
31
+ "unpkg": "src/modern-alert.js",
32
+ "jsdelivr": "src/modern-alert.js",
33
+ "files": [
34
+ "src",
35
+ "LICENSE"
36
+ ],
37
+ "exports": {
38
+ ".": {
39
+ "types": "./src/modern-alert.d.ts",
40
+ "default": "./src/modern-alert.js"
41
+ },
42
+ "./modern-alert.css": "./src/modern-alert.css",
43
+ "./src/modern-alert.css": "./src/modern-alert.css",
44
+ "./src/modern-alert.js": "./src/modern-alert.js",
45
+ "./src/icons.js": "./src/icons.js",
46
+ "./package.json": "./package.json"
47
+ },
48
+ "sideEffects": [
49
+ "./src/modern-alert.js",
50
+ "./src/icons.js",
51
+ "*.css"
52
+ ]
53
+ }
package/src/icons.js ADDED
@@ -0,0 +1,41 @@
1
+ (function (global) {
2
+ 'use strict';
3
+
4
+ const stroke =
5
+ 'fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" pathLength="1"';
6
+
7
+ global.ModernAlertIcons = {
8
+ success:
9
+ '<svg class="ma-svg" viewBox="0 0 64 64" aria-hidden="true">' +
10
+ '<circle class="ma-stroke ma-stroke--ring" cx="32" cy="32" r="26" ' + stroke + '></circle>' +
11
+ '<path class="ma-stroke ma-stroke--mark" d="M20.5 33.2l8.2 8.3 15.6-18" ' + stroke + '></path>' +
12
+ '</svg>',
13
+
14
+ error:
15
+ '<svg class="ma-svg" viewBox="0 0 64 64" aria-hidden="true">' +
16
+ '<circle class="ma-stroke ma-stroke--ring" cx="32" cy="32" r="26" ' + stroke + '></circle>' +
17
+ '<path class="ma-stroke ma-stroke--mark" d="M24 24l16 16M40 24L24 40" ' + stroke + '></path>' +
18
+ '</svg>',
19
+
20
+ warning:
21
+ '<svg class="ma-svg" viewBox="0 0 64 64" aria-hidden="true">' +
22
+ '<path class="ma-stroke ma-stroke--ring" d="M32 12.5L54 51.5H10z" ' + stroke + '></path>' +
23
+ '<path class="ma-stroke ma-stroke--mark" d="M32 26v12" ' + stroke + '></path>' +
24
+ '<circle class="ma-stroke ma-stroke--dot" cx="32" cy="46" r="1.4" fill="currentColor" stroke="none"></circle>' +
25
+ '</svg>',
26
+
27
+ info:
28
+ '<svg class="ma-svg" viewBox="0 0 64 64" aria-hidden="true">' +
29
+ '<circle class="ma-stroke ma-stroke--ring" cx="32" cy="32" r="26" ' + stroke + '></circle>' +
30
+ '<path class="ma-stroke ma-stroke--mark" d="M32 29.5V42" ' + stroke + '></path>' +
31
+ '<circle class="ma-stroke ma-stroke--dot" cx="32" cy="23" r="1.6" fill="currentColor" stroke="none"></circle>' +
32
+ '</svg>',
33
+
34
+ question:
35
+ '<svg class="ma-svg" viewBox="0 0 64 64" aria-hidden="true">' +
36
+ '<circle class="ma-stroke ma-stroke--ring" cx="32" cy="32" r="26" ' + stroke + '></circle>' +
37
+ '<path class="ma-stroke ma-stroke--mark" d="M26 25.5c1.2-3.6 6.8-5 10.2-2.4 3 2.3 2.6 6.2-.2 8.2-1.8 1.3-4 2.2-4 5.2" ' + stroke + '></path>' +
38
+ '<circle class="ma-stroke ma-stroke--dot" cx="32" cy="44.5" r="1.6" fill="currentColor" stroke="none"></circle>' +
39
+ '</svg>'
40
+ };
41
+ })(typeof window !== 'undefined' ? window : this);