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.
@@ -0,0 +1,467 @@
1
+ :root {
2
+ --ma-font: "SF Pro Display", "Segoe UI", system-ui, -apple-system, sans-serif;
3
+ --ma-radius: 24px;
4
+ --ma-ease: cubic-bezier(0.16, 1, 0.3, 1);
5
+ --ma-z: 99999;
6
+ }
7
+
8
+ .ma-overlay {
9
+ --ma-accent: #6cb6ff;
10
+ --ma-accent-soft: rgba(108, 182, 255, 0.16);
11
+ --ma-overlay: rgba(8, 8, 12, 0.58);
12
+ --ma-card: rgba(20, 20, 26, 0.82);
13
+ --ma-card-solid: #16161c;
14
+ --ma-border: rgba(255, 255, 255, 0.08);
15
+ --ma-text: #f4f4f5;
16
+ --ma-muted: #a1a1aa;
17
+ --ma-ghost: rgba(255, 255, 255, 0.06);
18
+ --ma-ghost-hover: rgba(255, 255, 255, 0.1);
19
+ --ma-input: rgba(0, 0, 0, 0.35);
20
+ --ma-input-border: rgba(255, 255, 255, 0.08);
21
+ --ma-shadow: 0 24px 80px rgba(0, 0, 0, 0.45), 0 0 0 1px var(--ma-border);
22
+ --ma-focus: rgba(108, 182, 255, 0.45);
23
+
24
+ position: fixed;
25
+ inset: 0;
26
+ z-index: var(--ma-z);
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ padding: max(16px, env(safe-area-inset-top)) 16px max(16px, env(safe-area-inset-bottom));
31
+ background: var(--ma-overlay);
32
+ backdrop-filter: blur(18px) saturate(1.2);
33
+ -webkit-backdrop-filter: blur(18px) saturate(1.2);
34
+ animation: ma-overlay-in 0.28s var(--ma-ease) both;
35
+ }
36
+
37
+ .ma-overlay[data-ma-theme="light"] {
38
+ --ma-overlay: rgba(24, 24, 32, 0.32);
39
+ --ma-card: rgba(255, 255, 255, 0.86);
40
+ --ma-card-solid: #fff;
41
+ --ma-border: rgba(24, 24, 32, 0.08);
42
+ --ma-text: #18181b;
43
+ --ma-muted: #71717a;
44
+ --ma-ghost: rgba(24, 24, 32, 0.05);
45
+ --ma-ghost-hover: rgba(24, 24, 32, 0.09);
46
+ --ma-input: rgba(255, 255, 255, 0.9);
47
+ --ma-input-border: rgba(24, 24, 32, 0.1);
48
+ --ma-shadow: 0 24px 80px rgba(24, 24, 32, 0.18), 0 0 0 1px var(--ma-border);
49
+ }
50
+
51
+ .ma-overlay[data-ma-type="success"] {
52
+ --ma-accent: #3ecf8e;
53
+ --ma-accent-soft: rgba(62, 207, 142, 0.16);
54
+ --ma-focus: rgba(62, 207, 142, 0.4);
55
+ }
56
+
57
+ .ma-overlay[data-ma-type="error"] {
58
+ --ma-accent: #f07178;
59
+ --ma-accent-soft: rgba(240, 113, 120, 0.16);
60
+ --ma-focus: rgba(240, 113, 120, 0.4);
61
+ }
62
+
63
+ .ma-overlay[data-ma-type="warning"] {
64
+ --ma-accent: #f5c15c;
65
+ --ma-accent-soft: rgba(245, 193, 92, 0.16);
66
+ --ma-focus: rgba(245, 193, 92, 0.4);
67
+ }
68
+
69
+ .ma-overlay[data-ma-type="info"],
70
+ .ma-overlay[data-ma-type="loading"] {
71
+ --ma-accent: #6cb6ff;
72
+ --ma-accent-soft: rgba(108, 182, 255, 0.16);
73
+ --ma-focus: rgba(108, 182, 255, 0.4);
74
+ }
75
+
76
+ .ma-overlay[data-ma-type="question"],
77
+ .ma-overlay[data-ma-type="confirm"] {
78
+ --ma-accent: #b9a0ff;
79
+ --ma-accent-soft: rgba(185, 160, 255, 0.16);
80
+ --ma-focus: rgba(185, 160, 255, 0.4);
81
+ }
82
+
83
+ .ma-overlay--out {
84
+ animation: ma-overlay-out 0.18s ease both;
85
+ }
86
+
87
+ .ma-overlay--clear {
88
+ background: transparent;
89
+ backdrop-filter: none;
90
+ -webkit-backdrop-filter: none;
91
+ animation: none;
92
+ }
93
+
94
+ .ma-overlay--out .ma-dialog {
95
+ animation: ma-dialog-out 0.18s ease both;
96
+ }
97
+
98
+ .ma-dialog {
99
+ width: min(400px, 100%);
100
+ max-height: min(90vh, 720px);
101
+ overflow: auto;
102
+ position: relative;
103
+ padding: 28px 28px 24px;
104
+ border-radius: var(--ma-radius);
105
+ background: var(--ma-card);
106
+ color: var(--ma-text);
107
+ box-shadow: var(--ma-shadow);
108
+ font-family: var(--ma-font);
109
+ -webkit-font-smoothing: antialiased;
110
+ animation: ma-dialog-in 0.38s var(--ma-ease) both;
111
+ }
112
+
113
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
114
+ .ma-dialog {
115
+ background: var(--ma-card-solid);
116
+ }
117
+ }
118
+
119
+ .ma-dialog.ma-swap {
120
+ animation: ma-swap 0.22s var(--ma-ease) both;
121
+ }
122
+
123
+ .ma-dialog--plain {
124
+ background:
125
+ linear-gradient(var(--ma-accent), var(--ma-accent)) 0 0 / 100% 2px no-repeat,
126
+ linear-gradient(180deg, var(--ma-accent-soft) 0%, transparent 6.5rem),
127
+ var(--ma-card);
128
+ }
129
+
130
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
131
+ .ma-dialog--plain {
132
+ background:
133
+ linear-gradient(var(--ma-accent), var(--ma-accent)) 0 0 / 100% 2px no-repeat,
134
+ linear-gradient(180deg, var(--ma-accent-soft) 0%, transparent 6.5rem),
135
+ var(--ma-card-solid);
136
+ }
137
+ }
138
+
139
+ .ma-dialog--plain .ma-title {
140
+ text-align: left;
141
+ font-size: 1.2rem;
142
+ }
143
+
144
+ .ma-dialog--plain .ma-text,
145
+ .ma-dialog--plain .ma-error {
146
+ text-align: left;
147
+ }
148
+
149
+ .ma-dialog--plain .ma-actions {
150
+ margin-top: 22px;
151
+ }
152
+
153
+ .ma-icon {
154
+ width: 72px;
155
+ height: 72px;
156
+ margin: 4px auto 20px;
157
+ display: grid;
158
+ place-items: center;
159
+ border-radius: 50%;
160
+ color: var(--ma-accent);
161
+ background: var(--ma-accent-soft);
162
+ box-shadow: 0 0 48px var(--ma-accent-soft);
163
+ }
164
+
165
+ .ma-svg {
166
+ width: 42px;
167
+ height: 42px;
168
+ display: block;
169
+ }
170
+
171
+ .ma-stroke {
172
+ stroke-dasharray: 1;
173
+ stroke-dashoffset: 1;
174
+ animation: ma-draw 0.7s var(--ma-ease) forwards;
175
+ }
176
+
177
+ .ma-stroke--mark {
178
+ animation-delay: 0.22s;
179
+ }
180
+
181
+ .ma-stroke--dot {
182
+ opacity: 0;
183
+ animation: ma-dot 0.3s 0.45s var(--ma-ease) forwards;
184
+ }
185
+
186
+ .ma-spinner {
187
+ width: 42px;
188
+ height: 42px;
189
+ }
190
+
191
+ .ma-spinner svg {
192
+ width: 42px;
193
+ height: 42px;
194
+ animation: ma-spin 0.9s linear infinite;
195
+ transform-origin: 50% 50%;
196
+ }
197
+
198
+ .ma-spinner circle {
199
+ fill: none;
200
+ stroke: currentColor;
201
+ stroke-width: 2.6;
202
+ stroke-linecap: round;
203
+ stroke-dasharray: 48 120;
204
+ }
205
+
206
+ .ma-title {
207
+ margin: 0;
208
+ font-size: 1.25rem;
209
+ font-weight: 600;
210
+ letter-spacing: -0.03em;
211
+ line-height: 1.3;
212
+ text-align: center;
213
+ }
214
+
215
+ .ma-text {
216
+ margin: 8px 0 0;
217
+ font-size: 0.9375rem;
218
+ line-height: 1.55;
219
+ color: var(--ma-muted);
220
+ text-align: center;
221
+ }
222
+
223
+ .ma-text p {
224
+ margin: 0 0 0.6em;
225
+ }
226
+
227
+ .ma-text p:last-child {
228
+ margin-bottom: 0;
229
+ }
230
+
231
+ .ma-text ul,
232
+ .ma-text ol {
233
+ margin: 0.4em 0 0;
234
+ padding-left: 1.2em;
235
+ text-align: left;
236
+ }
237
+
238
+ .ma-text a {
239
+ color: var(--ma-accent);
240
+ text-decoration: none;
241
+ }
242
+
243
+ .ma-text a:hover {
244
+ text-decoration: underline;
245
+ }
246
+
247
+ .ma-input-wrap {
248
+ margin-top: 18px;
249
+ }
250
+
251
+ .ma-label {
252
+ display: block;
253
+ margin-bottom: 8px;
254
+ font-size: 0.75rem;
255
+ font-weight: 500;
256
+ letter-spacing: 0.02em;
257
+ color: var(--ma-muted);
258
+ }
259
+
260
+ .ma-field,
261
+ .ma-select,
262
+ .ma-textarea {
263
+ width: 100%;
264
+ box-sizing: border-box;
265
+ border: 1px solid var(--ma-input-border);
266
+ border-radius: 14px;
267
+ background: var(--ma-input);
268
+ color: var(--ma-text);
269
+ font: inherit;
270
+ font-size: 0.9375rem;
271
+ outline: none;
272
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
273
+ }
274
+
275
+ .ma-field,
276
+ .ma-select {
277
+ height: 44px;
278
+ padding: 0 14px;
279
+ }
280
+
281
+ .ma-textarea {
282
+ min-height: 96px;
283
+ padding: 12px 14px;
284
+ resize: vertical;
285
+ }
286
+
287
+ .ma-field:focus,
288
+ .ma-select:focus,
289
+ .ma-textarea:focus {
290
+ border-color: var(--ma-accent);
291
+ box-shadow: 0 0 0 3px var(--ma-focus);
292
+ }
293
+
294
+ .ma-field.ma-field--invalid {
295
+ border-color: #f07178;
296
+ box-shadow: 0 0 0 3px rgba(240, 113, 120, 0.25);
297
+ }
298
+
299
+ .ma-error {
300
+ margin-top: 8px;
301
+ min-height: 1.2em;
302
+ font-size: 0.8rem;
303
+ color: #f07178;
304
+ text-align: left;
305
+ }
306
+
307
+ .ma-error[hidden] {
308
+ display: none;
309
+ }
310
+
311
+ .ma-actions {
312
+ display: flex;
313
+ justify-content: flex-end;
314
+ gap: 8px;
315
+ margin-top: 24px;
316
+ }
317
+
318
+ .ma-btn {
319
+ appearance: none;
320
+ border: 0;
321
+ height: 40px;
322
+ padding: 0 16px;
323
+ border-radius: 12px;
324
+ font: inherit;
325
+ font-size: 0.9rem;
326
+ font-weight: 550;
327
+ letter-spacing: -0.01em;
328
+ cursor: pointer;
329
+ color: var(--ma-text);
330
+ background: var(--ma-ghost);
331
+ transition: background 0.15s ease, transform 0.15s var(--ma-ease), opacity 0.15s ease;
332
+ }
333
+
334
+ .ma-btn:hover {
335
+ background: var(--ma-ghost-hover);
336
+ }
337
+
338
+ .ma-btn:active {
339
+ transform: scale(0.98);
340
+ }
341
+
342
+ .ma-btn:focus-visible {
343
+ outline: 2px solid var(--ma-accent);
344
+ outline-offset: 2px;
345
+ }
346
+
347
+ .ma-btn:disabled {
348
+ opacity: 0.55;
349
+ cursor: default;
350
+ transform: none;
351
+ }
352
+
353
+ .ma-btn--solid {
354
+ color: #0c0c10;
355
+ background: var(--ma-accent);
356
+ }
357
+
358
+ .ma-btn--solid:hover {
359
+ background: var(--ma-accent);
360
+ filter: brightness(1.08);
361
+ }
362
+
363
+ .ma-overlay[data-ma-theme="light"] .ma-btn--solid {
364
+ color: #fff;
365
+ }
366
+
367
+ .ma-overlay[data-ma-theme="light"][data-ma-type="warning"] .ma-btn--solid {
368
+ color: #18181b;
369
+ }
370
+
371
+ .ma-btn--solid.ma-btn--busy {
372
+ position: relative;
373
+ color: transparent;
374
+ }
375
+
376
+ .ma-btn--busy::after {
377
+ content: "";
378
+ position: absolute;
379
+ inset: 50% auto auto 50%;
380
+ width: 16px;
381
+ height: 16px;
382
+ margin: -8px 0 0 -8px;
383
+ border: 2px solid currentColor;
384
+ border-right-color: transparent;
385
+ border-radius: 50%;
386
+ color: #0c0c10;
387
+ animation: ma-spin 0.7s linear infinite;
388
+ }
389
+
390
+ .ma-overlay[data-ma-theme="light"] .ma-btn--busy::after {
391
+ color: #fff;
392
+ }
393
+
394
+ body.ma-lock {
395
+ overflow: hidden;
396
+ }
397
+
398
+ @keyframes ma-overlay-in {
399
+ from { opacity: 0; }
400
+ to { opacity: 1; }
401
+ }
402
+
403
+ @keyframes ma-overlay-out {
404
+ from { opacity: 1; }
405
+ to { opacity: 0; }
406
+ }
407
+
408
+ @keyframes ma-dialog-in {
409
+ from {
410
+ opacity: 0;
411
+ transform: translateY(10px) scale(0.96);
412
+ }
413
+ to {
414
+ opacity: 1;
415
+ transform: translateY(0) scale(1);
416
+ }
417
+ }
418
+
419
+ @keyframes ma-dialog-out {
420
+ from {
421
+ opacity: 1;
422
+ transform: scale(1);
423
+ }
424
+ to {
425
+ opacity: 0;
426
+ transform: scale(0.97) translateY(6px);
427
+ }
428
+ }
429
+
430
+ @keyframes ma-swap {
431
+ from { opacity: 0.55; transform: scale(0.985); }
432
+ to { opacity: 1; transform: scale(1); }
433
+ }
434
+
435
+ @keyframes ma-draw {
436
+ to { stroke-dashoffset: 0; }
437
+ }
438
+
439
+ @keyframes ma-dot {
440
+ to { opacity: 1; }
441
+ }
442
+
443
+ @keyframes ma-spin {
444
+ to { transform: rotate(360deg); }
445
+ }
446
+
447
+ @media (prefers-reduced-motion: reduce) {
448
+ .ma-overlay,
449
+ .ma-overlay--out,
450
+ .ma-dialog,
451
+ .ma-dialog.ma-swap,
452
+ .ma-overlay--out .ma-dialog,
453
+ .ma-stroke,
454
+ .ma-stroke--dot,
455
+ .ma-spinner svg,
456
+ .ma-btn--busy::after {
457
+ animation: none !important;
458
+ }
459
+
460
+ .ma-stroke {
461
+ stroke-dashoffset: 0;
462
+ }
463
+
464
+ .ma-stroke--dot {
465
+ opacity: 1;
466
+ }
467
+ }
@@ -0,0 +1,84 @@
1
+ export type DialogType =
2
+ | 'success'
3
+ | 'error'
4
+ | 'warning'
5
+ | 'info'
6
+ | 'question'
7
+ | 'confirm'
8
+ | 'loading'
9
+
10
+ export type Theme = 'auto' | 'light' | 'dark'
11
+
12
+ export type InputType = 'text' | 'email' | 'password' | 'textarea' | 'select'
13
+
14
+ export type DismissReason =
15
+ | 'cancel'
16
+ | 'esc'
17
+ | 'backdrop'
18
+ | 'timer'
19
+ | 'close'
20
+ | 'replace'
21
+
22
+ export interface Options {
23
+ type?: DialogType
24
+ title?: string
25
+ text?: string
26
+ html?: string
27
+ confirmText?: string
28
+ cancelText?: string
29
+ showConfirm?: boolean
30
+ showCancel?: boolean
31
+ allowOutsideClick?: boolean
32
+ allowEscapeKey?: boolean
33
+ timer?: number
34
+ input?: InputType | ''
35
+ inputPlaceholder?: string
36
+ inputValue?: string
37
+ inputLabel?: string
38
+ inputOptions?: Record<string, string> | null
39
+ inputValidator?: ((value: string) => string | false | void | null) | null
40
+ theme?: Theme
41
+ icon?: boolean
42
+ backdrop?: boolean
43
+ }
44
+
45
+ export interface Result {
46
+ isConfirmed: boolean
47
+ isDismissed: boolean
48
+ value: unknown
49
+ dismiss?: DismissReason
50
+ }
51
+
52
+ export type Helper = (
53
+ title?: string,
54
+ text?: string,
55
+ extra?: Options
56
+ ) => Promise<Result>
57
+
58
+ export interface ModernAlertAPI {
59
+ show(options?: Options): Promise<Result>
60
+ show(title: string, text?: string, type?: DialogType): Promise<Result>
61
+ close(): Promise<Result | void>
62
+ isVisible(): boolean
63
+ loading(title?: string, text?: string): Promise<Result>
64
+ success: Helper
65
+ error: Helper
66
+ warning: Helper
67
+ info: Helper
68
+ question: Helper
69
+ confirm: Helper
70
+ }
71
+
72
+ declare const ModernAlert: ModernAlertAPI
73
+
74
+ export as namespace ModernAlert
75
+ export default ModernAlert
76
+
77
+ declare global {
78
+ interface Window {
79
+ ModernAlert: ModernAlertAPI
80
+ ModernAlertIcons?: Record<string, string>
81
+ }
82
+
83
+ const ModernAlert: ModernAlertAPI
84
+ }