@yusufceng1z/ding 0.0.2 → 0.0.3
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/dist/index.cjs +28 -10
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +28 -10
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -94,8 +94,10 @@ var TIMING = {
|
|
|
94
94
|
duration: 5e3
|
|
95
95
|
};
|
|
96
96
|
var autoDuration = (type, hasAction) => type === "loading" || type === "error" || hasAction ? 0 : TIMING.duration;
|
|
97
|
+
var DEFAULT_LABELS = { region: "Notifications", dismiss: "Dismiss notification" };
|
|
98
|
+
var definedOnly = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
|
|
97
99
|
function createToaster() {
|
|
98
|
-
let state = { toasts: [], position: "top-center", theme: "system", status: "", alert: "" };
|
|
100
|
+
let state = { toasts: [], position: "top-center", theme: "system", labels: DEFAULT_LABELS, status: "", alert: "" };
|
|
99
101
|
let flip = false;
|
|
100
102
|
const subs = /* @__PURE__ */ new Set();
|
|
101
103
|
const entries = /* @__PURE__ */ new Map();
|
|
@@ -278,7 +280,13 @@ function createToaster() {
|
|
|
278
280
|
configure(c) {
|
|
279
281
|
if (c.sound !== void 0) sound = c.sound;
|
|
280
282
|
if (c.volume !== void 0) volume = c.volume;
|
|
281
|
-
state = {
|
|
283
|
+
state = {
|
|
284
|
+
...state,
|
|
285
|
+
...c.position && { position: c.position },
|
|
286
|
+
...c.theme && { theme: c.theme },
|
|
287
|
+
// undefined keys are skipped so `{ region: undefined }` keeps the current label
|
|
288
|
+
...c.labels && { labels: { ...state.labels, ...definedOnly(c.labels) } }
|
|
289
|
+
};
|
|
282
290
|
emit();
|
|
283
291
|
},
|
|
284
292
|
subscribe(fn) {
|
|
@@ -363,7 +371,7 @@ position:fixed;inset:0;z-index:2147483647;pointer-events:none;font:500 14px/1.3
|
|
|
363
371
|
.tst-viewport[data-position$=left]{--tst-ox:0%;--tx:0px}
|
|
364
372
|
.tst-viewport[data-position$=right]{--tst-ox:100%;--tx:0px}
|
|
365
373
|
.tst-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
|
|
366
|
-
.tst-slot{position:absolute;pointer-events:auto;touch-action:none;user-select:none;cursor:grab;--tst-i:0;
|
|
374
|
+
.tst-slot{position:absolute;pointer-events:auto;touch-action:none;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;cursor:grab;--tst-i:0;
|
|
367
375
|
--y:calc(var(--tst-dir)*-1*var(--tst-i)*var(--tst-stack-offset));--s:calc(1 - var(--tst-i)*var(--tst-stack-scale));
|
|
368
376
|
transform:translate(calc(var(--tx) + var(--dx,0px)),calc(var(--y) + var(--dy,0px))) scale(var(--s));
|
|
369
377
|
transform-origin:var(--tst-ox) var(--tst-oy);z-index:calc(100 - var(--tst-i));
|
|
@@ -388,7 +396,7 @@ translate:0 var(--tst-y0);scale:var(--tst-enter-scale,.5);opacity:0;will-change:
|
|
|
388
396
|
.tst[data-type=warning]{--c:var(--tst-warning)}
|
|
389
397
|
.tst[data-type=info]{--c:var(--tst-info)}
|
|
390
398
|
|
|
391
|
-
.tst-icon{position:absolute;inset-inline-start
|
|
399
|
+
.tst-icon{position:absolute;inset-inline-start:-1px;top:-1px;width:var(--tst-size);height:var(--tst-size);display:grid;place-items:center}
|
|
392
400
|
.tst-media{width:28px;height:28px;border-radius:50%;object-fit:cover;outline:1px solid light-dark(oklch(0 0 0/.1),oklch(1 0 0/.1));outline-offset:-1px;animation:tst-swap var(--tst-stack-dur) var(--tst-stack) .1s both}
|
|
393
401
|
.tst-badge{position:relative;width:24px;height:24px;display:grid;place-items:center}
|
|
394
402
|
.tst-svg{width:22px;height:22px;fill:none;stroke:var(--c);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:stroke .3s cubic-bezier(.2,0,0,1);animation:tst-swap var(--tst-stack-dur) var(--tst-stack) .1s both}
|
|
@@ -409,7 +417,7 @@ translate:0 var(--tst-y0);scale:var(--tst-enter-scale,.5);opacity:0;will-change:
|
|
|
409
417
|
.tst[data-type=info] .tst-svg path:nth-child(3){stroke-dasharray:none;stroke-dashoffset:0;animation:tst-dot .4s var(--tst-pop) var(--md) both}
|
|
410
418
|
.tst[data-type=info] .tst-svg path:nth-child(2){animation-delay:calc(var(--md) + .16s)}
|
|
411
419
|
|
|
412
|
-
.tst-body{position:absolute;inset-inline-start:calc(var(--tst-size) - 1px);top:-1px;display:flex;flex-wrap:wrap;align-items:center;gap:0 8px;width:max-content;max-width:calc(100vw - 2*var(--tst-pad) - var(--tst-size) + 1px);min-height:var(--tst-size);padding-inline-end:
|
|
420
|
+
.tst-body{position:absolute;inset-inline-start:calc(var(--tst-size) - 1px);top:-1px;display:flex;flex-wrap:wrap;align-items:center;gap:0 8px;width:max-content;max-width:calc(100vw - 2*var(--tst-pad) - var(--tst-size) + 1px);min-height:var(--tst-size);padding-inline-end:8px;
|
|
413
421
|
opacity:calc(var(--tp)*1.5 - .25);filter:blur(calc((1 - var(--tp))*10px));transform:translateX(calc((1 - var(--tp))*-12px*var(--tst-flip,1)))}
|
|
414
422
|
.tst-body:has(.tst-action,.tst-close){padding-inline-end:8px;padding-bottom:0}
|
|
415
423
|
.tst-body[data-wrapped]{padding-bottom:10px}
|
|
@@ -429,12 +437,16 @@ opacity:calc(var(--tp)*1.5 - .25);filter:blur(calc((1 - var(--tp))*10px));transf
|
|
|
429
437
|
.tst[data-phase=open] .tst-desc{animation:tst-in-up var(--tst-pop-dur) var(--tst-pop) .1s both}
|
|
430
438
|
.tst[data-phase=open] .tst-action,.tst[data-phase=open] .tst-close{animation:tst-in-btn var(--tst-pop-dur) var(--tst-pop) .16s backwards}
|
|
431
439
|
.tst[data-phase=open] .tst-secondary{animation-delay:.1s}
|
|
432
|
-
.tst-action,.tst-close{flex:none;border:0;color:inherit;font:inherit;cursor:pointer;background:transparent;
|
|
440
|
+
.tst-action,.tst-close{position:relative;flex:none;margin:0;border:0;color:inherit;font:inherit;cursor:pointer;background:transparent;
|
|
433
441
|
opacity:calc(var(--ap)*1.3 - .15);transform:scale(calc(.85 + var(--ap)*.15));
|
|
434
442
|
transition-property:background-color,scale;transition-duration:.15s;transition-timing-function:ease-out}
|
|
435
443
|
.tst-action{height:30px;padding:0 14px;border-radius:999px;font-size:13px;font-weight:600;background:var(--tst-fg);color:var(--tst-bg)}
|
|
436
444
|
.tst-secondary{background:transparent;color:color-mix(in srgb,var(--tst-fg) 65%,transparent);padding:0 10px}
|
|
437
445
|
.tst-close{width:30px;height:30px;padding:0;border-radius:50%;display:grid;place-items:center}
|
|
446
|
+
/* 30px look, 44px target: taller hit area, narrow enough sideways that neighbours (8px apart) never overlap */
|
|
447
|
+
.tst-action::before,.tst-close::before{content:'';position:absolute;inset:-7px -3px}
|
|
448
|
+
.tst-slot:focus-visible{outline:none}
|
|
449
|
+
.tst-slot:focus-visible .tst{outline:2px solid var(--tst-fg);outline-offset:-5px}
|
|
438
450
|
.tst-close svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round}
|
|
439
451
|
@media (hover:hover){.tst-action:hover{background:color-mix(in srgb,var(--tst-fg) 82%,var(--tst-bg))}.tst-secondary:hover,.tst-close:hover{background:color-mix(in srgb,var(--tst-fg) 10%,transparent);color:var(--tst-fg)}}
|
|
440
452
|
.tst-action:not(:disabled):active,.tst-close:not(:disabled):active{scale:.96}
|
|
@@ -777,10 +789,15 @@ var ICONS = {
|
|
|
777
789
|
};
|
|
778
790
|
|
|
779
791
|
// src/vanilla.ts
|
|
792
|
+
var BUSY = "dialog,[role=dialog],[aria-modal=true],[role=menu],[role=listbox],input,textarea,select,[contenteditable]";
|
|
780
793
|
function onToastKey(e) {
|
|
781
794
|
if (e.defaultPrevented || !toast.getState().toasts.length) return;
|
|
782
|
-
if (e.key === "Escape")
|
|
783
|
-
|
|
795
|
+
if (e.key === "Escape") {
|
|
796
|
+
if (!document.activeElement?.closest(BUSY)) toast.dismiss();
|
|
797
|
+
} else if (e.altKey && e.code === "KeyT") {
|
|
798
|
+
const slots = document.querySelectorAll(".tst-viewport .tst-slot");
|
|
799
|
+
(document.querySelector('.tst-viewport button:not([tabindex="-1"])') ?? slots[slots.length - 1])?.focus();
|
|
800
|
+
}
|
|
784
801
|
}
|
|
785
802
|
var el = (tag, cls, parent) => {
|
|
786
803
|
const n = document.createElement(tag);
|
|
@@ -808,7 +825,6 @@ function mountToaster(opts = {}) {
|
|
|
808
825
|
toast.configure(opts);
|
|
809
826
|
const vp = el("div", "tst-viewport", document.body);
|
|
810
827
|
vp.setAttribute("role", "region");
|
|
811
|
-
vp.setAttribute("aria-label", "Notifications");
|
|
812
828
|
const status = el("div", "tst-sr", vp);
|
|
813
829
|
status.setAttribute("role", "status");
|
|
814
830
|
const alert = el("div", "tst-sr", vp);
|
|
@@ -821,6 +837,7 @@ function mountToaster(opts = {}) {
|
|
|
821
837
|
const nodes = /* @__PURE__ */ new Map();
|
|
822
838
|
function build(t) {
|
|
823
839
|
const slot = el("div", "tst-slot", vp);
|
|
840
|
+
slot.tabIndex = -1;
|
|
824
841
|
el("div", "tst", slot);
|
|
825
842
|
return { slot };
|
|
826
843
|
}
|
|
@@ -828,6 +845,7 @@ function mountToaster(opts = {}) {
|
|
|
828
845
|
const s = toast.getState();
|
|
829
846
|
vp.dataset.position = s.position;
|
|
830
847
|
vp.dataset.theme = s.theme;
|
|
848
|
+
vp.setAttribute("aria-label", s.labels.region);
|
|
831
849
|
status.textContent = s.status;
|
|
832
850
|
alert.textContent = s.alert;
|
|
833
851
|
const live = new Set(s.toasts.map((t) => t.id));
|
|
@@ -907,10 +925,10 @@ function mountToaster(opts = {}) {
|
|
|
907
925
|
if (!close) {
|
|
908
926
|
close = el("button", "tst-close", body);
|
|
909
927
|
close.type = "button";
|
|
910
|
-
close.setAttribute("aria-label", "Dismiss notification");
|
|
911
928
|
close.append(svg("", ["M6 6l12 12M18 6L6 18"]));
|
|
912
929
|
close.onclick = () => toast.dismiss(t.id);
|
|
913
930
|
}
|
|
931
|
+
close.setAttribute("aria-label", s.labels.dismiss);
|
|
914
932
|
close.tabIndex = t.phase === "open" ? 0 : -1;
|
|
915
933
|
}
|
|
916
934
|
n.off ??= bindToast(n.slot, t.id);
|
package/dist/index.d.cts
CHANGED
|
@@ -3,6 +3,13 @@ type ToastType = 'success' | 'error' | 'warning' | 'info' | 'loading';
|
|
|
3
3
|
type Phase = 'enter' | 'open' | 'closing' | 'exit';
|
|
4
4
|
type Position = 'top-center' | 'top-left' | 'top-right' | 'bottom-center' | 'bottom-left' | 'bottom-right';
|
|
5
5
|
type Theme = 'system' | 'light' | 'dark';
|
|
6
|
+
/** Accessible names read by screen readers. Pass your own strings to localize them. */
|
|
7
|
+
interface ToastLabels {
|
|
8
|
+
/** Name of the notifications region. Default `Notifications` */
|
|
9
|
+
region: string;
|
|
10
|
+
/** Name of the close button on sticky toasts. Default `Dismiss notification` */
|
|
11
|
+
dismiss: string;
|
|
12
|
+
}
|
|
6
13
|
interface ToastAction {
|
|
7
14
|
label: string;
|
|
8
15
|
/** Return a patch to morph this toast in place (e.g. Undo → "Restored"). Return nothing to dismiss it. */
|
|
@@ -58,6 +65,7 @@ interface ToasterState {
|
|
|
58
65
|
toasts: ToastItem[];
|
|
59
66
|
position: Position;
|
|
60
67
|
theme: Theme;
|
|
68
|
+
labels: ToastLabels;
|
|
61
69
|
/** text for the persistent polite live region (role=status) */
|
|
62
70
|
status: string;
|
|
63
71
|
/** text for the persistent assertive live region (role=alert) */
|
|
@@ -96,6 +104,8 @@ declare function createToaster(): {
|
|
|
96
104
|
configure(c: {
|
|
97
105
|
position?: Position;
|
|
98
106
|
theme?: Theme;
|
|
107
|
+
/** Partial: keys you leave out keep their current value. */
|
|
108
|
+
labels?: Partial<ToastLabels>;
|
|
99
109
|
sound?: boolean | ((type: ToastType) => void);
|
|
100
110
|
volume?: number;
|
|
101
111
|
}): void;
|
|
@@ -147,12 +157,13 @@ declare function injectStyles(doc?: Document): void;
|
|
|
147
157
|
/** Adapter hook-up: call with the `.tst-slot` element (its first child is the pill). Returns cleanup. */
|
|
148
158
|
declare function bindToast(slot: HTMLElement, id: string, t?: Toaster): () => void;
|
|
149
159
|
|
|
150
|
-
/** Shared keyboard handling for every adapter: Escape dismisses, Alt+T moves focus into the toast. */
|
|
160
|
+
/** Shared keyboard handling for every adapter: Escape dismisses, Alt+T moves focus into the toast (which also pauses its timer). */
|
|
151
161
|
declare function onToastKey(e: KeyboardEvent): void;
|
|
152
162
|
/** Framework-free renderer. Returns an unmount function. */
|
|
153
163
|
declare function mountToaster(opts?: {
|
|
154
164
|
position?: Position;
|
|
155
165
|
theme?: Theme;
|
|
166
|
+
labels?: Partial<ToastLabels>;
|
|
156
167
|
}): () => void;
|
|
157
168
|
|
|
158
169
|
/** Play the cue for a toast type. Silent for types without one, and wherever Web Audio is missing or still locked. */
|
|
@@ -161,4 +172,4 @@ declare function chime(type: ToastType, volume?: number): void;
|
|
|
161
172
|
declare const ICONS: Record<ToastType, string[]>;
|
|
162
173
|
|
|
163
174
|
export { ICONS, TIMING, bindToast, buildCss, chime, createToaster, getSprings, injectStyles, mountToaster, onToastKey, setSprings, springEasing, toast };
|
|
164
|
-
export type { Phase, Position, PromiseMessages, SpringConfig, Theme, ToastAction, ToastItem, ToastOptions, ToastPatch, ToastType, Toaster, ToasterState };
|
|
175
|
+
export type { Phase, Position, PromiseMessages, SpringConfig, Theme, ToastAction, ToastItem, ToastLabels, ToastOptions, ToastPatch, ToastType, Toaster, ToasterState };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,13 @@ type ToastType = 'success' | 'error' | 'warning' | 'info' | 'loading';
|
|
|
3
3
|
type Phase = 'enter' | 'open' | 'closing' | 'exit';
|
|
4
4
|
type Position = 'top-center' | 'top-left' | 'top-right' | 'bottom-center' | 'bottom-left' | 'bottom-right';
|
|
5
5
|
type Theme = 'system' | 'light' | 'dark';
|
|
6
|
+
/** Accessible names read by screen readers. Pass your own strings to localize them. */
|
|
7
|
+
interface ToastLabels {
|
|
8
|
+
/** Name of the notifications region. Default `Notifications` */
|
|
9
|
+
region: string;
|
|
10
|
+
/** Name of the close button on sticky toasts. Default `Dismiss notification` */
|
|
11
|
+
dismiss: string;
|
|
12
|
+
}
|
|
6
13
|
interface ToastAction {
|
|
7
14
|
label: string;
|
|
8
15
|
/** Return a patch to morph this toast in place (e.g. Undo → "Restored"). Return nothing to dismiss it. */
|
|
@@ -58,6 +65,7 @@ interface ToasterState {
|
|
|
58
65
|
toasts: ToastItem[];
|
|
59
66
|
position: Position;
|
|
60
67
|
theme: Theme;
|
|
68
|
+
labels: ToastLabels;
|
|
61
69
|
/** text for the persistent polite live region (role=status) */
|
|
62
70
|
status: string;
|
|
63
71
|
/** text for the persistent assertive live region (role=alert) */
|
|
@@ -96,6 +104,8 @@ declare function createToaster(): {
|
|
|
96
104
|
configure(c: {
|
|
97
105
|
position?: Position;
|
|
98
106
|
theme?: Theme;
|
|
107
|
+
/** Partial: keys you leave out keep their current value. */
|
|
108
|
+
labels?: Partial<ToastLabels>;
|
|
99
109
|
sound?: boolean | ((type: ToastType) => void);
|
|
100
110
|
volume?: number;
|
|
101
111
|
}): void;
|
|
@@ -147,12 +157,13 @@ declare function injectStyles(doc?: Document): void;
|
|
|
147
157
|
/** Adapter hook-up: call with the `.tst-slot` element (its first child is the pill). Returns cleanup. */
|
|
148
158
|
declare function bindToast(slot: HTMLElement, id: string, t?: Toaster): () => void;
|
|
149
159
|
|
|
150
|
-
/** Shared keyboard handling for every adapter: Escape dismisses, Alt+T moves focus into the toast. */
|
|
160
|
+
/** Shared keyboard handling for every adapter: Escape dismisses, Alt+T moves focus into the toast (which also pauses its timer). */
|
|
151
161
|
declare function onToastKey(e: KeyboardEvent): void;
|
|
152
162
|
/** Framework-free renderer. Returns an unmount function. */
|
|
153
163
|
declare function mountToaster(opts?: {
|
|
154
164
|
position?: Position;
|
|
155
165
|
theme?: Theme;
|
|
166
|
+
labels?: Partial<ToastLabels>;
|
|
156
167
|
}): () => void;
|
|
157
168
|
|
|
158
169
|
/** Play the cue for a toast type. Silent for types without one, and wherever Web Audio is missing or still locked. */
|
|
@@ -161,4 +172,4 @@ declare function chime(type: ToastType, volume?: number): void;
|
|
|
161
172
|
declare const ICONS: Record<ToastType, string[]>;
|
|
162
173
|
|
|
163
174
|
export { ICONS, TIMING, bindToast, buildCss, chime, createToaster, getSprings, injectStyles, mountToaster, onToastKey, setSprings, springEasing, toast };
|
|
164
|
-
export type { Phase, Position, PromiseMessages, SpringConfig, Theme, ToastAction, ToastItem, ToastOptions, ToastPatch, ToastType, Toaster, ToasterState };
|
|
175
|
+
export type { Phase, Position, PromiseMessages, SpringConfig, Theme, ToastAction, ToastItem, ToastLabels, ToastOptions, ToastPatch, ToastType, Toaster, ToasterState };
|
package/dist/index.js
CHANGED
|
@@ -56,8 +56,10 @@ var TIMING = {
|
|
|
56
56
|
duration: 5e3
|
|
57
57
|
};
|
|
58
58
|
var autoDuration = (type, hasAction) => type === "loading" || type === "error" || hasAction ? 0 : TIMING.duration;
|
|
59
|
+
var DEFAULT_LABELS = { region: "Notifications", dismiss: "Dismiss notification" };
|
|
60
|
+
var definedOnly = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
|
|
59
61
|
function createToaster() {
|
|
60
|
-
let state = { toasts: [], position: "top-center", theme: "system", status: "", alert: "" };
|
|
62
|
+
let state = { toasts: [], position: "top-center", theme: "system", labels: DEFAULT_LABELS, status: "", alert: "" };
|
|
61
63
|
let flip = false;
|
|
62
64
|
const subs = /* @__PURE__ */ new Set();
|
|
63
65
|
const entries = /* @__PURE__ */ new Map();
|
|
@@ -240,7 +242,13 @@ function createToaster() {
|
|
|
240
242
|
configure(c) {
|
|
241
243
|
if (c.sound !== void 0) sound = c.sound;
|
|
242
244
|
if (c.volume !== void 0) volume = c.volume;
|
|
243
|
-
state = {
|
|
245
|
+
state = {
|
|
246
|
+
...state,
|
|
247
|
+
...c.position && { position: c.position },
|
|
248
|
+
...c.theme && { theme: c.theme },
|
|
249
|
+
// undefined keys are skipped so `{ region: undefined }` keeps the current label
|
|
250
|
+
...c.labels && { labels: { ...state.labels, ...definedOnly(c.labels) } }
|
|
251
|
+
};
|
|
244
252
|
emit();
|
|
245
253
|
},
|
|
246
254
|
subscribe(fn) {
|
|
@@ -325,7 +333,7 @@ position:fixed;inset:0;z-index:2147483647;pointer-events:none;font:500 14px/1.3
|
|
|
325
333
|
.tst-viewport[data-position$=left]{--tst-ox:0%;--tx:0px}
|
|
326
334
|
.tst-viewport[data-position$=right]{--tst-ox:100%;--tx:0px}
|
|
327
335
|
.tst-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
|
|
328
|
-
.tst-slot{position:absolute;pointer-events:auto;touch-action:none;user-select:none;cursor:grab;--tst-i:0;
|
|
336
|
+
.tst-slot{position:absolute;pointer-events:auto;touch-action:none;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;cursor:grab;--tst-i:0;
|
|
329
337
|
--y:calc(var(--tst-dir)*-1*var(--tst-i)*var(--tst-stack-offset));--s:calc(1 - var(--tst-i)*var(--tst-stack-scale));
|
|
330
338
|
transform:translate(calc(var(--tx) + var(--dx,0px)),calc(var(--y) + var(--dy,0px))) scale(var(--s));
|
|
331
339
|
transform-origin:var(--tst-ox) var(--tst-oy);z-index:calc(100 - var(--tst-i));
|
|
@@ -350,7 +358,7 @@ translate:0 var(--tst-y0);scale:var(--tst-enter-scale,.5);opacity:0;will-change:
|
|
|
350
358
|
.tst[data-type=warning]{--c:var(--tst-warning)}
|
|
351
359
|
.tst[data-type=info]{--c:var(--tst-info)}
|
|
352
360
|
|
|
353
|
-
.tst-icon{position:absolute;inset-inline-start
|
|
361
|
+
.tst-icon{position:absolute;inset-inline-start:-1px;top:-1px;width:var(--tst-size);height:var(--tst-size);display:grid;place-items:center}
|
|
354
362
|
.tst-media{width:28px;height:28px;border-radius:50%;object-fit:cover;outline:1px solid light-dark(oklch(0 0 0/.1),oklch(1 0 0/.1));outline-offset:-1px;animation:tst-swap var(--tst-stack-dur) var(--tst-stack) .1s both}
|
|
355
363
|
.tst-badge{position:relative;width:24px;height:24px;display:grid;place-items:center}
|
|
356
364
|
.tst-svg{width:22px;height:22px;fill:none;stroke:var(--c);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:stroke .3s cubic-bezier(.2,0,0,1);animation:tst-swap var(--tst-stack-dur) var(--tst-stack) .1s both}
|
|
@@ -371,7 +379,7 @@ translate:0 var(--tst-y0);scale:var(--tst-enter-scale,.5);opacity:0;will-change:
|
|
|
371
379
|
.tst[data-type=info] .tst-svg path:nth-child(3){stroke-dasharray:none;stroke-dashoffset:0;animation:tst-dot .4s var(--tst-pop) var(--md) both}
|
|
372
380
|
.tst[data-type=info] .tst-svg path:nth-child(2){animation-delay:calc(var(--md) + .16s)}
|
|
373
381
|
|
|
374
|
-
.tst-body{position:absolute;inset-inline-start:calc(var(--tst-size) - 1px);top:-1px;display:flex;flex-wrap:wrap;align-items:center;gap:0 8px;width:max-content;max-width:calc(100vw - 2*var(--tst-pad) - var(--tst-size) + 1px);min-height:var(--tst-size);padding-inline-end:
|
|
382
|
+
.tst-body{position:absolute;inset-inline-start:calc(var(--tst-size) - 1px);top:-1px;display:flex;flex-wrap:wrap;align-items:center;gap:0 8px;width:max-content;max-width:calc(100vw - 2*var(--tst-pad) - var(--tst-size) + 1px);min-height:var(--tst-size);padding-inline-end:8px;
|
|
375
383
|
opacity:calc(var(--tp)*1.5 - .25);filter:blur(calc((1 - var(--tp))*10px));transform:translateX(calc((1 - var(--tp))*-12px*var(--tst-flip,1)))}
|
|
376
384
|
.tst-body:has(.tst-action,.tst-close){padding-inline-end:8px;padding-bottom:0}
|
|
377
385
|
.tst-body[data-wrapped]{padding-bottom:10px}
|
|
@@ -391,12 +399,16 @@ opacity:calc(var(--tp)*1.5 - .25);filter:blur(calc((1 - var(--tp))*10px));transf
|
|
|
391
399
|
.tst[data-phase=open] .tst-desc{animation:tst-in-up var(--tst-pop-dur) var(--tst-pop) .1s both}
|
|
392
400
|
.tst[data-phase=open] .tst-action,.tst[data-phase=open] .tst-close{animation:tst-in-btn var(--tst-pop-dur) var(--tst-pop) .16s backwards}
|
|
393
401
|
.tst[data-phase=open] .tst-secondary{animation-delay:.1s}
|
|
394
|
-
.tst-action,.tst-close{flex:none;border:0;color:inherit;font:inherit;cursor:pointer;background:transparent;
|
|
402
|
+
.tst-action,.tst-close{position:relative;flex:none;margin:0;border:0;color:inherit;font:inherit;cursor:pointer;background:transparent;
|
|
395
403
|
opacity:calc(var(--ap)*1.3 - .15);transform:scale(calc(.85 + var(--ap)*.15));
|
|
396
404
|
transition-property:background-color,scale;transition-duration:.15s;transition-timing-function:ease-out}
|
|
397
405
|
.tst-action{height:30px;padding:0 14px;border-radius:999px;font-size:13px;font-weight:600;background:var(--tst-fg);color:var(--tst-bg)}
|
|
398
406
|
.tst-secondary{background:transparent;color:color-mix(in srgb,var(--tst-fg) 65%,transparent);padding:0 10px}
|
|
399
407
|
.tst-close{width:30px;height:30px;padding:0;border-radius:50%;display:grid;place-items:center}
|
|
408
|
+
/* 30px look, 44px target: taller hit area, narrow enough sideways that neighbours (8px apart) never overlap */
|
|
409
|
+
.tst-action::before,.tst-close::before{content:'';position:absolute;inset:-7px -3px}
|
|
410
|
+
.tst-slot:focus-visible{outline:none}
|
|
411
|
+
.tst-slot:focus-visible .tst{outline:2px solid var(--tst-fg);outline-offset:-5px}
|
|
400
412
|
.tst-close svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round}
|
|
401
413
|
@media (hover:hover){.tst-action:hover{background:color-mix(in srgb,var(--tst-fg) 82%,var(--tst-bg))}.tst-secondary:hover,.tst-close:hover{background:color-mix(in srgb,var(--tst-fg) 10%,transparent);color:var(--tst-fg)}}
|
|
402
414
|
.tst-action:not(:disabled):active,.tst-close:not(:disabled):active{scale:.96}
|
|
@@ -739,10 +751,15 @@ var ICONS = {
|
|
|
739
751
|
};
|
|
740
752
|
|
|
741
753
|
// src/vanilla.ts
|
|
754
|
+
var BUSY = "dialog,[role=dialog],[aria-modal=true],[role=menu],[role=listbox],input,textarea,select,[contenteditable]";
|
|
742
755
|
function onToastKey(e) {
|
|
743
756
|
if (e.defaultPrevented || !toast.getState().toasts.length) return;
|
|
744
|
-
if (e.key === "Escape")
|
|
745
|
-
|
|
757
|
+
if (e.key === "Escape") {
|
|
758
|
+
if (!document.activeElement?.closest(BUSY)) toast.dismiss();
|
|
759
|
+
} else if (e.altKey && e.code === "KeyT") {
|
|
760
|
+
const slots = document.querySelectorAll(".tst-viewport .tst-slot");
|
|
761
|
+
(document.querySelector('.tst-viewport button:not([tabindex="-1"])') ?? slots[slots.length - 1])?.focus();
|
|
762
|
+
}
|
|
746
763
|
}
|
|
747
764
|
var el = (tag, cls, parent) => {
|
|
748
765
|
const n = document.createElement(tag);
|
|
@@ -770,7 +787,6 @@ function mountToaster(opts = {}) {
|
|
|
770
787
|
toast.configure(opts);
|
|
771
788
|
const vp = el("div", "tst-viewport", document.body);
|
|
772
789
|
vp.setAttribute("role", "region");
|
|
773
|
-
vp.setAttribute("aria-label", "Notifications");
|
|
774
790
|
const status = el("div", "tst-sr", vp);
|
|
775
791
|
status.setAttribute("role", "status");
|
|
776
792
|
const alert = el("div", "tst-sr", vp);
|
|
@@ -783,6 +799,7 @@ function mountToaster(opts = {}) {
|
|
|
783
799
|
const nodes = /* @__PURE__ */ new Map();
|
|
784
800
|
function build(t) {
|
|
785
801
|
const slot = el("div", "tst-slot", vp);
|
|
802
|
+
slot.tabIndex = -1;
|
|
786
803
|
el("div", "tst", slot);
|
|
787
804
|
return { slot };
|
|
788
805
|
}
|
|
@@ -790,6 +807,7 @@ function mountToaster(opts = {}) {
|
|
|
790
807
|
const s = toast.getState();
|
|
791
808
|
vp.dataset.position = s.position;
|
|
792
809
|
vp.dataset.theme = s.theme;
|
|
810
|
+
vp.setAttribute("aria-label", s.labels.region);
|
|
793
811
|
status.textContent = s.status;
|
|
794
812
|
alert.textContent = s.alert;
|
|
795
813
|
const live = new Set(s.toasts.map((t) => t.id));
|
|
@@ -869,10 +887,10 @@ function mountToaster(opts = {}) {
|
|
|
869
887
|
if (!close) {
|
|
870
888
|
close = el("button", "tst-close", body);
|
|
871
889
|
close.type = "button";
|
|
872
|
-
close.setAttribute("aria-label", "Dismiss notification");
|
|
873
890
|
close.append(svg("", ["M6 6l12 12M18 6L6 18"]));
|
|
874
891
|
close.onclick = () => toast.dismiss(t.id);
|
|
875
892
|
}
|
|
893
|
+
close.setAttribute("aria-label", s.labels.dismiss);
|
|
876
894
|
close.tabIndex = t.phase === "open" ? 0 : -1;
|
|
877
895
|
}
|
|
878
896
|
n.off ??= bindToast(n.slot, t.id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yusufceng1z/ding",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Framework-agnostic toast engine: spring solver, timers, state machine.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"author": "Yusuf Cengiz",
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
47
|
-
"test": "node --test src
|
|
47
|
+
"test": "node --test \"src/**/*.test.ts\"",
|
|
48
48
|
"typecheck": "tsc -p ."
|
|
49
49
|
}
|
|
50
50
|
}
|