@t007/dialog 0.0.30 → 0.0.32
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.css +12 -12
- package/dist/index.d.ts +13 -12
- package/dist/index.global.js +82 -69
- package/package.json +4 -3
package/dist/index.css
CHANGED
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
--t007-dialog-button-padding-block: calc(var(--t007-dialog-unit) * 0.5);
|
|
38
38
|
--t007-dialog-button-border-radius: calc(var(--t007-dialog-unit) * 1.25);
|
|
39
39
|
--t007-dialog-button-gap: calc(var(--t007-dialog-unit) * 0.65);
|
|
40
|
-
--t007-confirm-button-color: grey;
|
|
41
|
-
--t007-confirm-button-background: var(--t007-cancel-button-color);
|
|
42
|
-
--t007-cancel-button-color: greenyellow;
|
|
43
|
-
--t007-cancel-button-background: var(--t007-confirm-button-color);
|
|
44
|
-
--t007-confirm-button-outline-color: var(--t007-cancel-button-color);
|
|
45
|
-
--t007-cancel-button-outline-color: var(--t007-cancel-button-color);
|
|
40
|
+
--t007-dialog-confirm-button-color: grey;
|
|
41
|
+
--t007-dialog-confirm-button-background: var(--t007-dialog-cancel-button-color);
|
|
42
|
+
--t007-dialog-cancel-button-color: greenyellow;
|
|
43
|
+
--t007-dialog-cancel-button-background: var(--t007-dialog-confirm-button-color);
|
|
44
|
+
--t007-dialog-confirm-button-outline-color: var(--t007-dialog-cancel-button-color);
|
|
45
|
+
--t007-dialog-cancel-button-outline-color: var(--t007-dialog-cancel-button-color);
|
|
46
46
|
}
|
|
47
47
|
:where(.t007-dialog) .t007-input-field {
|
|
48
48
|
--t007-input-color: var(--t007-dialog-message-color);
|
|
@@ -213,13 +213,13 @@ body:has(> .t007-dialog) {
|
|
|
213
213
|
transition: 100ms ease;
|
|
214
214
|
}
|
|
215
215
|
.t007-dialog-confirm-button {
|
|
216
|
-
color: var(--t007-confirm-button-color);
|
|
217
|
-
background: var(--t007-confirm-button-background);
|
|
216
|
+
color: var(--t007-dialog-confirm-button-color);
|
|
217
|
+
background: var(--t007-dialog-confirm-button-background);
|
|
218
218
|
opacity: 1;
|
|
219
219
|
}
|
|
220
220
|
.t007-dialog-cancel-button {
|
|
221
|
-
color: var(--t007-cancel-button-color);
|
|
222
|
-
background: var(--t007-cancel-button-background);
|
|
221
|
+
color: var(--t007-dialog-cancel-button-color);
|
|
222
|
+
background: var(--t007-dialog-cancel-button-background);
|
|
223
223
|
opacity: 0.9;
|
|
224
224
|
}
|
|
225
225
|
.t007-dialog button:hover {
|
|
@@ -236,8 +236,8 @@ body:has(> .t007-dialog) {
|
|
|
236
236
|
outline-width: var(--t007-button-outline-width);
|
|
237
237
|
}
|
|
238
238
|
.t007-dialog-confirm-button:focus {
|
|
239
|
-
outline-color: var(--t007-confirm-button-outline-color);
|
|
239
|
+
outline-color: var(--t007-dialog-confirm-button-outline-color);
|
|
240
240
|
}
|
|
241
241
|
.t007-dialog-cancel-button:focus {
|
|
242
|
-
outline-color: var(--t007-cancel-button-outline-color);
|
|
242
|
+
outline-color: var(--t007-dialog-cancel-button-outline-color);
|
|
243
243
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { FieldOptions } from "@t007/input";
|
|
1
|
+
import { FieldOptions } from '@t007/input';
|
|
3
2
|
|
|
4
3
|
/** Shared options for alert, confirm, and prompt dialogs. */
|
|
5
|
-
|
|
4
|
+
interface DialogOptions {
|
|
6
5
|
/** Unique identifier for the dialog for programmatic dismissal. Auto-generated by default. */
|
|
7
6
|
id?: string;
|
|
8
|
-
/** Text for the confirmation button.
|
|
7
|
+
/** Text for the confirmation button. @default "OK". */
|
|
9
8
|
confirmText?: string;
|
|
10
|
-
/** Text for the cancel button where applicable.
|
|
9
|
+
/** Text for the cancel button where applicable. @default "Cancel". */
|
|
11
10
|
cancelText?: string;
|
|
12
|
-
/** Browser behavior for handling dialog closure.
|
|
11
|
+
/** Browser behavior for handling dialog closure. @default "any". */
|
|
13
12
|
closedBy?: HTMLDialogElement["closedBy"];
|
|
14
13
|
/** Render dialog inside a specific root element instead of document body. */
|
|
15
14
|
rootElement?: HTMLElement;
|
|
16
|
-
/** Whether to restrict interactions to `rootElement` if provided.
|
|
15
|
+
/** Whether to restrict interactions to `rootElement` if provided. @default `true`. */
|
|
17
16
|
scoped?: boolean;
|
|
18
17
|
}
|
|
19
18
|
|
|
@@ -23,31 +22,31 @@ export interface DialogOptions {
|
|
|
23
22
|
* @param id Optional unique identifier of the dialog to check.
|
|
24
23
|
* @return `true` if the specified dialog (or any dialog when no id is provided) is active, otherwise `false`.
|
|
25
24
|
*/
|
|
26
|
-
|
|
25
|
+
declare function isActive(id?: string): boolean;
|
|
27
26
|
/** Show an alert dialog and resolve when the user confirms.
|
|
28
27
|
* @param message Message shown in the dialog body.
|
|
29
28
|
* @param options Optional dialog configuration.
|
|
30
29
|
* @returns Promise that resolves to the user choice.
|
|
31
30
|
*/
|
|
32
|
-
|
|
31
|
+
declare function alert(message: string, options?: DialogOptions): Promise<boolean>;
|
|
33
32
|
/** Show a confirm dialog and resolve with the user choice.
|
|
34
33
|
* @param question Question shown in the dialog body.
|
|
35
34
|
* @param options Optional dialog configuration.
|
|
36
35
|
* @returns Promise that resolves to true when confirmed.
|
|
37
36
|
*/
|
|
38
|
-
|
|
37
|
+
declare function confirm(question: string, options?: DialogOptions): Promise<boolean>;
|
|
39
38
|
/** Show a prompt dialog and resolve with the entered value.
|
|
40
39
|
* @param question Question shown in the dialog body.
|
|
41
40
|
* @param defaultValue Initial value for the prompt input.
|
|
42
41
|
* @param options Optional dialog configuration.
|
|
43
42
|
* @returns Promise that resolves to the entered string or null.
|
|
44
43
|
*/
|
|
45
|
-
|
|
44
|
+
declare function prompt(question: string, defaultValue?: string, options?: DialogOptions & FieldOptions): Promise<string | null>;
|
|
46
45
|
/** Dismiss a dialog by id or all dialogs when no id is provided.
|
|
47
46
|
* @param id Optional unique identifier of the dialog to dismiss. If not provided, all dialogs will be dismissed.
|
|
48
47
|
* @param response Optional value to resolve the dialog's promise with. If not provided, defaults to `true` for confirm and alert dialogs, and `null` for prompt dialogs.
|
|
49
48
|
*/
|
|
50
|
-
|
|
49
|
+
declare function dismiss(id?: string, response?: any): void;
|
|
51
50
|
|
|
52
51
|
interface Dialog {
|
|
53
52
|
isActive(id?: string): boolean;
|
|
@@ -74,3 +73,5 @@ declare global {
|
|
|
74
73
|
Prompt?: T007Namespace["prompt"];
|
|
75
74
|
}
|
|
76
75
|
}
|
|
76
|
+
|
|
77
|
+
export { type DialogOptions, alert, confirm, dismiss, isActive, prompt };
|
package/dist/index.global.js
CHANGED
|
@@ -1,32 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
(() => {
|
|
3
|
-
// ../../../sia-reactor/dist/chunk-
|
|
3
|
+
// ../../../sia-reactor/dist/chunk-JGEI2Q4M.js
|
|
4
4
|
function clamp(min = 0, val, max = Infinity) {
|
|
5
5
|
return Math.min(Math.max(val, min), max);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
// ../../../sia-reactor/dist/chunk-
|
|
9
|
-
function createEl(tag, props, dataset, styles, el = tag ? document?.createElement(tag) : null) {
|
|
10
|
-
return assignEl(el, props, dataset, styles), el;
|
|
11
|
-
}
|
|
12
|
-
function assignEl(el, props, dataset, styles) {
|
|
13
|
-
if (!el) return;
|
|
14
|
-
if (props) {
|
|
15
|
-
for (const k of Object.keys(props)) if (props[k] !== void 0) el[k] = props[k];
|
|
16
|
-
}
|
|
17
|
-
if (dataset) {
|
|
18
|
-
for (const k of Object.keys(dataset)) if (dataset[k] !== void 0) el.dataset[k] = String(dataset[k]);
|
|
19
|
-
}
|
|
20
|
-
if (styles) {
|
|
21
|
-
for (const k of Object.keys(styles)) if (styles[k] !== void 0) el.style[k] = styles[k];
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
function getActiveEl(root) {
|
|
25
|
-
const activeEl = (root ?? document).activeElement;
|
|
26
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ../../../sia-reactor/dist/chunk-3OT72G7R.js
|
|
8
|
+
// ../../../sia-reactor/dist/chunk-ORK3EGB6.js
|
|
30
9
|
function onAllMethods(owner, callback, skipOwn = true, nested = false) {
|
|
31
10
|
let proto = owner;
|
|
32
11
|
while (proto && proto !== Object.prototype) {
|
|
@@ -43,52 +22,75 @@
|
|
|
43
22
|
owner2[method] = owner2[method].bind(owner2);
|
|
44
23
|
});
|
|
45
24
|
}
|
|
25
|
+
function createEl(tag, props, dataset, styles, el = tag ? document?.createElement(tag) : null) {
|
|
26
|
+
return assignEl(el, props, dataset, styles);
|
|
27
|
+
}
|
|
28
|
+
function assignEl(el, props, dataset, styles, nodiff = true) {
|
|
29
|
+
if (!el) return null;
|
|
30
|
+
if (props) {
|
|
31
|
+
for (const k of Object.keys(props)) if (props[k] !== void 0) {
|
|
32
|
+
if (nodiff || el[k] !== props[k]) el[k] = props[k];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (dataset) {
|
|
36
|
+
for (const k of Object.keys(dataset)) if (dataset[k] !== void 0) {
|
|
37
|
+
if (nodiff || el.dataset[k] !== dataset[k]) el.dataset[k] = String(dataset[k]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (styles) {
|
|
41
|
+
for (const k of Object.keys(styles)) if (styles[k] !== void 0) {
|
|
42
|
+
if (nodiff || el.style[k] !== styles[k]) el.style[k] = styles[k];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return el;
|
|
46
|
+
}
|
|
47
|
+
function getActiveEl(root) {
|
|
48
|
+
const activeEl = (root ?? document).activeElement;
|
|
49
|
+
return !activeEl ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
50
|
+
}
|
|
46
51
|
|
|
47
|
-
// ../../../sia-reactor/dist/chunk-
|
|
48
|
-
var CTX = {
|
|
49
|
-
/** Flag indicating whether the application is running in development mode. */
|
|
50
|
-
isDevEnv: "undefined" !== typeof process ? process.env.NODE_ENV !== "production" : true,
|
|
51
|
-
/** Flag indicating whether a cascade is currently ongoing so reactors can allow all writes. */
|
|
52
|
-
isCascading: false,
|
|
53
|
-
/** Active `Autotracker` instance, override for automatic dependency collection on `Reactor` traps. */
|
|
54
|
-
autotracker: null
|
|
55
|
-
};
|
|
52
|
+
// ../../../sia-reactor/dist/chunk-SHWIAQD2.js
|
|
56
53
|
var RTR_BATCH = "undefined" !== typeof window ? ("undefined" !== typeof queueMicrotask ? queueMicrotask : setTimeout).bind(window) : "undefined" !== typeof process && process.nextTick ? process.nextTick : setTimeout;
|
|
57
54
|
var RTR_LOG = console.log.bind(console, "[S.I.A Reactor]");
|
|
58
55
|
var NIL = Object.freeze({});
|
|
59
56
|
var NOOP = () => {
|
|
60
57
|
};
|
|
58
|
+
var isDevEnv = false;
|
|
59
|
+
try {
|
|
60
|
+
isDevEnv = process.env.NODE_ENV !== "production";
|
|
61
|
+
} catch (e) {
|
|
62
|
+
}
|
|
61
63
|
|
|
62
|
-
// ../utils/dist/chunk-
|
|
63
|
-
var INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable
|
|
64
|
+
// ../utils/dist/chunk-ZALPHCSJ.js
|
|
65
|
+
var INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
64
66
|
var isInteractive = (target) => target instanceof HTMLElement && target.matches(INTERACTIVE_SELECTOR);
|
|
65
67
|
var VIRTUAL_RESOURCE = /* @__PURE__ */ Symbol.for("T007_VIRTUAL_RESOURCE");
|
|
66
|
-
function loadResource(req, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {},
|
|
67
|
-
|
|
68
|
+
function loadResource(req, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, win = window) {
|
|
69
|
+
win.t007 ??= {}, win.t007._resourceCache ??= {};
|
|
68
70
|
if (req === VIRTUAL_RESOURCE || isSym(req)) return Promise.resolve();
|
|
69
71
|
const src = req;
|
|
70
|
-
if (
|
|
71
|
-
const existing = type === "script" ? Array.prototype.find.call(
|
|
72
|
-
if (existing) return
|
|
73
|
-
|
|
72
|
+
if (win.t007._resourceCache[src]) return win.t007._resourceCache[src];
|
|
73
|
+
const existing = type === "script" ? Array.prototype.find.call(win.document.scripts, (s) => isSameURL(s.src, src)) : type === "style" ? Array.prototype.find.call(win.document.styleSheets, (s) => isSameURL(s.href, src)) : null;
|
|
74
|
+
if (existing) return win.t007._resourceCache[src] = Promise.resolve(existing);
|
|
75
|
+
win.t007._resourceCache[src] = new Promise((resolve, reject) => {
|
|
74
76
|
(function tryLoad(remaining, el) {
|
|
75
77
|
const onerror = () => {
|
|
76
78
|
el?.remove?.();
|
|
77
79
|
if (remaining > 1) {
|
|
78
80
|
setTimeout(tryLoad, 1e3, remaining - 1);
|
|
79
|
-
console.warn(`Retrying ${type} load (${attempts - remaining + 1})
|
|
81
|
+
console.warn(`Retrying ${type} load for "${src}" (${attempts - remaining + 1})...`);
|
|
80
82
|
} else {
|
|
81
|
-
delete
|
|
82
|
-
reject(new Error(`${type} load failed
|
|
83
|
+
delete win.t007._resourceCache[src];
|
|
84
|
+
reject(new Error(`${capitalize(type)} load failed for "${src}" after ${attempts - 1} attempts`));
|
|
83
85
|
}
|
|
84
86
|
};
|
|
85
87
|
const url = retryKey && remaining < attempts ? `${src}${src.includes("?") ? "&" : "?"}_${retryKey}=${Date.now()}` : src;
|
|
86
|
-
if (type === "script")
|
|
87
|
-
else if (type === "style")
|
|
88
|
+
if (type === "script") win.document.body.append(el = createEl("script", { src: url, type: module ? "module" : "text/javascript", crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
|
|
89
|
+
else if (type === "style") win.document.head.append(el = createEl("link", { rel: "stylesheet", href: url, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
|
|
88
90
|
else reject(new Error(`Unsupported resource type: ${type}`));
|
|
89
91
|
})(attempts);
|
|
90
92
|
});
|
|
91
|
-
return
|
|
93
|
+
return win.t007._resourceCache[src];
|
|
92
94
|
}
|
|
93
95
|
function isDef(val) {
|
|
94
96
|
return "undefined" !== typeof val;
|
|
@@ -102,6 +104,9 @@
|
|
|
102
104
|
function uid(prefix = "") {
|
|
103
105
|
return prefix + Date.now().toString(36) + "_" + performance.now().toString(36).replace(".", "") + "_" + Math.random().toString(36).slice(2);
|
|
104
106
|
}
|
|
107
|
+
function capitalize(word = "") {
|
|
108
|
+
return word.replace(/^(\s*)([a-z])/i, (_, s, l) => s + l.toUpperCase());
|
|
109
|
+
}
|
|
105
110
|
function parseCSSTime(time) {
|
|
106
111
|
return time?.endsWith?.("ms") ? parseFloat(time) : parseFloat(time) * 1e3;
|
|
107
112
|
}
|
|
@@ -114,6 +119,7 @@
|
|
|
114
119
|
}
|
|
115
120
|
}
|
|
116
121
|
function isSameURL(url1, url2) {
|
|
122
|
+
if (url1 === url2) return true;
|
|
117
123
|
if (!isStr(url1) || !isStr(url2) || !url1 || !url2) return false;
|
|
118
124
|
return cleanURL(url1) === cleanURL(url2);
|
|
119
125
|
}
|
|
@@ -127,33 +133,33 @@
|
|
|
127
133
|
window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/dist/index.min.css`;
|
|
128
134
|
}
|
|
129
135
|
|
|
130
|
-
// ../utils/dist/chunk-
|
|
136
|
+
// ../utils/dist/chunk-NX2LWYD6.js
|
|
131
137
|
function initOutsideClick(el, { enabled = false, onOutside = NOOP, outOnClick = true, outOnEscape = true, outOnFocusOut = false, allowBounds = false, allowInputs = false, root = window, scoped = true, capture = true } = NIL) {
|
|
132
|
-
const
|
|
138
|
+
const stack = t007._outsiders_stack ??= [], existing = (t007._outsiders ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
133
139
|
if (!enabled || existing) return existing ? existing : void 0;
|
|
134
140
|
scoped = scoped && root instanceof HTMLElement, root = scoped ? root : root === document ? document : window;
|
|
135
|
-
const
|
|
141
|
+
const onScopedOut = (e, t, p = e.touches?.[0] || e, rect = allowBounds ? el.getBoundingClientRect() : null) => {
|
|
136
142
|
if (stack.at(-1) !== el || (allowBounds ? p.clientX >= rect.left && p.clientX <= rect.right && p.clientY >= rect.top && p.clientY <= rect.bottom : el.contains(t))) return false;
|
|
137
143
|
return (!scoped ? true : root.contains(t)) && onOutside(e);
|
|
138
144
|
}, handleClick = ((e) => outOnClick && !(allowInputs && isInteractive(e.target)) && onScopedOut(e, e.target)), handleEscape = ((e) => outOnEscape && e.key === "Escape" && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey && stack.at(-1) === el && onOutside(e)), handleFocusOut = (e) => outOnFocusOut && !el.contains(e.relatedTarget) && onScopedOut(e, e.relatedTarget);
|
|
139
145
|
root.addEventListener("mousedown", handleClick, capture), root.addEventListener("touchstart", handleClick, { passive: true, capture });
|
|
140
146
|
root.addEventListener("keydown", handleEscape, capture);
|
|
141
147
|
el.addEventListener("focusout", handleFocusOut, capture);
|
|
142
|
-
if (!stack.includes(el)) stack.push(el), stacks.set(root, stack);
|
|
143
148
|
const destroy = () => {
|
|
144
149
|
root.removeEventListener("mousedown", handleClick, capture), root.removeEventListener("touchstart", handleClick, capture);
|
|
145
150
|
root.removeEventListener("keydown", handleEscape, capture);
|
|
146
151
|
el.removeEventListener("focusout", handleFocusOut, capture);
|
|
147
152
|
t007._outsiders.delete(el), stack.splice(stack.indexOf(el), 1);
|
|
148
153
|
};
|
|
149
|
-
return t007._outsiders.set(el, destroy), destroy;
|
|
154
|
+
return !stack.includes(el) && stack.push(el), t007._outsiders.set(el, destroy), destroy;
|
|
150
155
|
}
|
|
151
156
|
var removeOutsideClick = (el) => t007._outsiders?.get(el)?.();
|
|
152
157
|
function initFocusTrap(el, { enabled = false, initialSelector = "[data-autofocus]", ringClassName = "focus-outline", root = window, scoped = true, capture = true } = NIL) {
|
|
153
|
-
const
|
|
158
|
+
const stack = t007._ftrappers_stack ??= [], existing = (t007._ftrappers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
154
159
|
if (!enabled || existing) return existing ? existing : void 0;
|
|
155
160
|
scoped = scoped && root instanceof HTMLElement, root = scoped ? root : root === document ? document : window;
|
|
156
|
-
|
|
161
|
+
let recovering = false;
|
|
162
|
+
const focused = document.querySelector(":focus"), initial = el.querySelector(initialSelector), first = createEl("span", { tabIndex: 0 }, { focusGuard: "start" }, { position: "absolute", width: "0", height: "0", pointerEvents: "none" }), last = createEl("span", { tabIndex: 0 }, { focusGuard: "end" }, { position: "absolute", width: "0", height: "0", pointerEvents: "none" }), getFocusable = (c = el) => [...c.querySelectorAll(INTERACTIVE_SELECTOR)], resetFocus = (i = 0, els = getFocusable()) => !recovering && (recovering = true, els?.length ? els.at(i).focus() : (!el.hasAttribute("tabindex") && (el.tabIndex = -1), el.focus()), recovering = false), edgeFocus = (pre = false, rt = root) => {
|
|
157
163
|
if (!scoped) return resetFocus(pre ? -1 : 0);
|
|
158
164
|
if (rt.hasAttribute("tabindex")) return rt.focus();
|
|
159
165
|
const items = getFocusable();
|
|
@@ -163,24 +169,24 @@
|
|
|
163
169
|
while (p !== ceil && (!all.length || (pre ? rt.contains(all[0]) : rt.contains(all.at(-1))))) all = getFocusable(p = p.parentElement || ceil);
|
|
164
170
|
for (let target, len = all.length, i = all.indexOf(items[pre ? 0 : items.length - 1]) + (pre ? -1 : 1); pre ? i >= 0 : i < len; pre ? i-- : i++) if (!rt.contains(target = all[i])) return target.focus();
|
|
165
171
|
(pre ? first : last).blur();
|
|
166
|
-
}, handleFocusIn = () => {
|
|
172
|
+
}, handleFocusIn = (e) => {
|
|
167
173
|
if (document.querySelector("dialog:modal") && !el.matches("dialog:modal")) return;
|
|
168
|
-
stack.at(-1) === el && getActiveEl(el.ownerDocument) !== root && !el.contains(getActiveEl(el.ownerDocument)) && resetFocus();
|
|
174
|
+
stack.at(-1) === el && getActiveEl(el.ownerDocument) !== root && !el.contains(getActiveEl(el.ownerDocument)) && !e.composedPath().includes(el) && resetFocus();
|
|
169
175
|
}, handleInitialBlur = () => initial.classList.remove(ringClassName);
|
|
170
176
|
first.addEventListener("focus", (e) => el.contains(e.relatedTarget) ? edgeFocus(true) : resetFocus(), capture), el.prepend(first);
|
|
171
177
|
last.addEventListener("focus", (e) => el.contains(e.relatedTarget) ? edgeFocus() : resetFocus(-1), capture), el.append(last);
|
|
172
178
|
root.addEventListener("focusin", handleFocusIn, capture);
|
|
173
179
|
if (initial || !el.contains(focused)) !initial ? setTimeout(resetFocus) : setTimeout(() => (initial.classList.add(ringClassName), initial.focus(), initial.addEventListener("blur", handleInitialBlur, capture)));
|
|
174
|
-
if (!stack.includes(el)) stack.push(el), stacks.set(root, stack);
|
|
175
180
|
const destroy = () => {
|
|
176
181
|
focused?.isConnected && focused.focus(), first.remove(), last.remove();
|
|
177
182
|
root.removeEventListener("focusin", handleFocusIn, capture);
|
|
178
183
|
initial?.removeEventListener("blur", handleInitialBlur, capture);
|
|
179
184
|
t007._ftrappers.delete(el), stack.splice(stack.indexOf(el), 1);
|
|
180
185
|
};
|
|
181
|
-
|
|
186
|
+
const handle = { destroy, sync: () => (el.prepend(first), el.append(last)) };
|
|
187
|
+
return !stack.includes(el) && stack.push(el), t007._ftrappers.set(el, handle), handle;
|
|
182
188
|
}
|
|
183
|
-
var removeFocusTrap = (el) => t007._ftrappers?.get(el)?.();
|
|
189
|
+
var removeFocusTrap = (el) => t007._ftrappers?.get(el)?.destroy();
|
|
184
190
|
var getTargetIndex = ({ key, currIndex, length, gridX, gridY, vGridY, loop, ctrlKey = false, rtl }) => {
|
|
185
191
|
const rowStart = currIndex - currIndex % gridX, rowEnd = Math.min(rowStart + gridX - 1, length - 1), colStart = currIndex % gridX, colEnd = Math.min(colStart + gridX * (gridY - 1), length - 1), canX = gridX > 1, canY = gridY > 1, horizontalMove = rtl ? { ArrowRight: canX ? -1 : 0, ArrowLeft: canX ? 1 : 0 } : { ArrowRight: canX ? 1 : 0, ArrowLeft: canX ? -1 : 0 }, move = { ...horizontalMove, ArrowDown: canY ? gridX : 0, ArrowUp: canY ? -gridX : 0, Home: ctrlKey ? 0 : rowStart, End: ctrlKey ? length - 1 : rowEnd, PageDown: (vGridY - 1) * gridX, PageUp: -(vGridY - 1) * gridX }[key] ?? 0;
|
|
186
192
|
let targetIndex = key === "Home" || key === "End" ? move : currIndex + move;
|
|
@@ -240,7 +246,7 @@
|
|
|
240
246
|
rtl: null,
|
|
241
247
|
grid: {},
|
|
242
248
|
activeClass: "focus-outlined",
|
|
243
|
-
inputSelector: "input,textarea,[contenteditable
|
|
249
|
+
inputSelector: "input,textarea,[contenteditable]",
|
|
244
250
|
focusOptions: { preventScroll: false },
|
|
245
251
|
scrollIntoView: { block: "nearest", inline: "nearest" },
|
|
246
252
|
onSelect: NOOP,
|
|
@@ -253,7 +259,7 @@
|
|
|
253
259
|
if (!config.enabled || existing) return existing ? existing : void 0;
|
|
254
260
|
const { enabled: isEnabled, selector, focusOnHover, loop, virtual, typeahead, resetMs, activeClass, inputSelector, defaultTabbableIndex, baseTabIndex, grid, rtl: isRtl, focusOptions, scrollIntoView, onSelect, onFocusOut, rovingTab } = { ...DEFAULT_CONFIG, ...config };
|
|
255
261
|
let gridX = grid.x || 1, gridY = grid.y || 1, vGridY = grid.vY || 1, activeIndex = -1, buffer = "", timeout = null, items = [];
|
|
256
|
-
const enabled = isEnabled ?? virtual, roving = rovingTab ?? !virtual, rtl = isRtl ?? ("undefined" === typeof document ? false : getComputedStyle(container).direction === "rtl"), shouldSnub = () => !enabled || !container, isItemDisabled = (el) => !el || el.
|
|
262
|
+
const enabled = isEnabled ?? virtual, roving = rovingTab ?? !virtual, rtl = isRtl ?? ("undefined" === typeof document ? false : getComputedStyle(container).direction === "rtl"), shouldSnub = () => !enabled || !container, isItemDisabled = (el) => !el || el.matches('[disabled],[aria-disabled="true"],[inert],:disabled'), getItems = () => items = Array.from(container.querySelectorAll(selector));
|
|
257
263
|
const getAbleIndex = (targetIndex, e = { key: "ArrowRight", ctrlKey: false }) => {
|
|
258
264
|
if (shouldSnub() || !items.length) return null;
|
|
259
265
|
let index = targetIndex;
|
|
@@ -328,34 +334,41 @@
|
|
|
328
334
|
if (idx !== -1) goToIndex(idx);
|
|
329
335
|
};
|
|
330
336
|
for (const el of items) el.addEventListener("mouseenter", handleHover);
|
|
331
|
-
const
|
|
337
|
+
const sync = () => {
|
|
332
338
|
const oldEl = items[activeIndex];
|
|
339
|
+
for (const el of items) el.removeEventListener("mouseenter", handleHover);
|
|
333
340
|
getItems();
|
|
341
|
+
for (const el of items) el.addEventListener("mouseenter", handleHover);
|
|
342
|
+
calcGrid();
|
|
334
343
|
const newEl = items[activeIndex];
|
|
335
344
|
updateDOM();
|
|
336
345
|
if (oldEl && newEl && oldEl === newEl) return;
|
|
337
|
-
resetActiveIndex();
|
|
338
|
-
|
|
339
|
-
|
|
346
|
+
resetActiveIndex(), updateDOM();
|
|
347
|
+
};
|
|
348
|
+
const mutationObserver = new MutationObserver(sync);
|
|
340
349
|
mutationObserver.observe(container, { childList: true, subtree: true });
|
|
341
350
|
const setGrid = (g) => {
|
|
342
351
|
if (g.x !== void 0) gridX = g.x;
|
|
343
352
|
if (g.y !== void 0) gridY = g.y;
|
|
344
353
|
if (g.vY !== void 0) vGridY = g.vY;
|
|
345
354
|
};
|
|
346
|
-
|
|
355
|
+
let ancestor = null;
|
|
356
|
+
const resizeObserver = new ResizeObserver(() => calcGrid());
|
|
357
|
+
const calcGrid = () => {
|
|
358
|
+
setGrid(getGrid(items, !grid.x, !grid.y, !grid.vY));
|
|
359
|
+
const next = items.length > 1 ? getCommonAncestor(items[0], items[1]) : container;
|
|
360
|
+
if (next && next !== ancestor) ancestor && resizeObserver.unobserve(ancestor), ancestor = next, resizeObserver.observe(ancestor);
|
|
361
|
+
};
|
|
347
362
|
setGrid(grid), calcGrid();
|
|
348
|
-
const ancestor = items.length > 1 ? getCommonAncestor(items[0], items[1]) : container;
|
|
349
|
-
const resizeObserver = new ResizeObserver(calcGrid);
|
|
350
|
-
if (ancestor) resizeObserver.observe(ancestor);
|
|
351
363
|
const destroy = () => {
|
|
352
364
|
for (const el of interactiveEls) el?.removeEventListener("keydown", simulateKey);
|
|
353
365
|
container.removeEventListener("focusout", handleFocusOut);
|
|
354
366
|
for (const el of items) el.removeEventListener("mouseenter", handleHover);
|
|
355
367
|
mutationObserver.disconnect(), resizeObserver.disconnect();
|
|
356
368
|
if (timeout) clearTimeout(timeout);
|
|
369
|
+
t007._arrownavs.delete(container);
|
|
357
370
|
};
|
|
358
|
-
const handle = { gridX: () => gridX, gridY: () => gridY, vGridY: () => vGridY, items: () => items, activeIndex: () => activeIndex, activeItem: () => items[activeIndex] ?? null, getAbleIndex, typeAhead, goToIndex, simulateKey, destroy };
|
|
371
|
+
const handle = { gridX: () => gridX, gridY: () => gridY, vGridY: () => vGridY, items: () => items, activeIndex: () => activeIndex, activeItem: () => items[activeIndex] ?? null, getAbleIndex, typeAhead, goToIndex, simulateKey, sync, destroy };
|
|
359
372
|
return t007._arrownavs.set(container, handle), handle;
|
|
360
373
|
}
|
|
361
374
|
var removeArrowNavigation = (container) => t007._arrownavs?.get(container)?.destroy();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t007/dialog",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "A lightweight, pure JS dialog system.",
|
|
5
5
|
"author": "Oketade Oluwatobiloba <tobioketade007@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"types": "./dist/index.d.ts",
|
|
22
22
|
"style": "./dist/index.css",
|
|
23
23
|
"sideEffects": [
|
|
24
|
-
"
|
|
24
|
+
"**/*.css",
|
|
25
|
+
"**/*.scss"
|
|
25
26
|
],
|
|
26
27
|
"exports": {
|
|
27
28
|
".": {
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"accessible"
|
|
57
58
|
],
|
|
58
59
|
"dependencies": {
|
|
59
|
-
"@t007/utils": "^0.0.
|
|
60
|
+
"@t007/utils": "^0.0.35"
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
62
63
|
"esbuild-sass-plugin": "^3.7.0"
|