@t007/utils 0.0.26 → 0.0.27
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/{chunk-XVFFZZJA.js → chunk-N5KX6IW4.js} +19 -6
- package/dist/{chunk-AI5O3OGE.js → chunk-NLR4ANGT.js} +18 -15
- package/dist/hooks/react.cjs +23 -22
- package/dist/hooks/react.d.cts +1 -1
- package/dist/hooks/react.d.ts +1 -1
- package/dist/hooks/react.js +8 -7
- package/dist/hooks/vanilla.cjs +32 -31
- package/dist/hooks/vanilla.d.cts +1 -1
- package/dist/hooks/vanilla.d.ts +1 -1
- package/dist/hooks/vanilla.js +14 -13
- package/dist/index.cjs +48 -31
- package/dist/index.d.cts +31 -11
- package/dist/index.d.ts +31 -11
- package/dist/index.js +11 -3
- package/dist/{ripple-DcMWw_AP.d.cts → ripple-CVQx46Xq.d.cts} +5 -5
- package/dist/{ripple-DcMWw_AP.d.ts → ripple-CVQx46Xq.d.ts} +5 -5
- package/package.json +3 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/core/dom.ts
|
|
2
2
|
import { createEl, assignEl } from "sia-reactor/utils";
|
|
3
|
-
|
|
3
|
+
import { getActiveEl } from "sia-reactor/utils";
|
|
4
|
+
var INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable='true'],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
4
5
|
var isInteractive = (target) => target instanceof HTMLElement && target.matches(INTERACTIVE_SELECTOR);
|
|
5
6
|
var VIRTUAL_RESOURCE = /* @__PURE__ */ Symbol.for("T007_VIRTUAL_RESOURCE");
|
|
6
7
|
function loadResource(req, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
|
|
@@ -30,10 +31,6 @@ function loadResource(req, type = "style", { module, media, crossOrigin, integri
|
|
|
30
31
|
});
|
|
31
32
|
return w.t007._resourceCache[src];
|
|
32
33
|
}
|
|
33
|
-
function getActiveElement(root = document) {
|
|
34
|
-
const activeEl = root.activeElement;
|
|
35
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveElement(activeEl.shadowRoot) : activeEl;
|
|
36
|
-
}
|
|
37
34
|
|
|
38
35
|
// src/index.ts
|
|
39
36
|
import { NIL, NOOP } from "sia-reactor";
|
|
@@ -78,6 +75,18 @@ import { clamp } from "sia-reactor/utils";
|
|
|
78
75
|
function uid(prefix = "") {
|
|
79
76
|
return prefix + Date.now().toString(36) + "_" + performance.now().toString(36).replace(".", "") + "_" + Math.random().toString(36).slice(2);
|
|
80
77
|
}
|
|
78
|
+
function remToPx(rem, el = document.documentElement) {
|
|
79
|
+
return rem * parseFloat(getComputedStyle(el).fontSize);
|
|
80
|
+
}
|
|
81
|
+
function pxToRem(px, el = document.documentElement) {
|
|
82
|
+
return px / parseFloat(getComputedStyle(el).fontSize);
|
|
83
|
+
}
|
|
84
|
+
function parseCSSTime(time) {
|
|
85
|
+
return time?.endsWith?.("ms") ? parseFloat(time) : parseFloat(time) * 1e3;
|
|
86
|
+
}
|
|
87
|
+
function parseCSSSize(size, el) {
|
|
88
|
+
return size?.endsWith?.("px") ? parseFloat(size) : remToPx(parseFloat(size), el);
|
|
89
|
+
}
|
|
81
90
|
function isSameURL(src1, src2) {
|
|
82
91
|
if (!isStr(src1) || !isStr(src2) || !src1 || !src2) return false;
|
|
83
92
|
try {
|
|
@@ -143,7 +152,7 @@ export {
|
|
|
143
152
|
isInteractive,
|
|
144
153
|
VIRTUAL_RESOURCE,
|
|
145
154
|
loadResource,
|
|
146
|
-
|
|
155
|
+
getActiveEl,
|
|
147
156
|
isObj,
|
|
148
157
|
isDef,
|
|
149
158
|
isSym,
|
|
@@ -157,6 +166,10 @@ export {
|
|
|
157
166
|
inBoolArrOpt,
|
|
158
167
|
clamp,
|
|
159
168
|
uid,
|
|
169
|
+
remToPx,
|
|
170
|
+
pxToRem,
|
|
171
|
+
parseCSSTime,
|
|
172
|
+
parseCSSSize,
|
|
160
173
|
isSameURL,
|
|
161
174
|
limited,
|
|
162
175
|
mockAsync,
|
|
@@ -2,21 +2,20 @@ import {
|
|
|
2
2
|
INTERACTIVE_SELECTOR,
|
|
3
3
|
clamp,
|
|
4
4
|
createEl,
|
|
5
|
-
|
|
5
|
+
getActiveEl,
|
|
6
6
|
isInteractive
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-N5KX6IW4.js";
|
|
8
8
|
|
|
9
9
|
// src/hooks/vanilla/outsideClick.ts
|
|
10
10
|
import { NIL, NOOP } from "sia-reactor";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const existing = (t007._outsiders ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
11
|
+
function initOutsideClick(el, { enabled = false, onOutsideClick = NOOP, outOnClick = true, outOnEscape = true, outOnFocusOut = false, allowInputs = false, root = window, scoped = true, capture = true } = NIL) {
|
|
12
|
+
const stacks = t007._outsiders_stacks ??= /* @__PURE__ */ new WeakMap(), existing = (t007._outsiders ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
14
13
|
if (!enabled || existing) return existing ? existing : void 0;
|
|
15
14
|
scoped = scoped && root instanceof HTMLElement, root = scoped ? root : root === document ? document : window;
|
|
16
15
|
const stack = stacks.get(root) ?? [], onScopedOut = (e, t, p = e.touches?.[0] || e, rect = el.getBoundingClientRect()) => {
|
|
17
16
|
if (stack.at(-1) !== el || p.clientX >= rect.left && p.clientX <= rect.right && p.clientY >= rect.top && p.clientY <= rect.bottom) return false;
|
|
18
17
|
return (!scoped ? true : root.contains(t)) && onOutsideClick(e);
|
|
19
|
-
}, handleClick = ((e) =>
|
|
18
|
+
}, 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 && onOutsideClick(e)), handleFocusOut = (e) => outOnFocusOut && !el.contains(e.relatedTarget) && onScopedOut(e, e.relatedTarget);
|
|
20
19
|
root.addEventListener("mousedown", handleClick, capture), root.addEventListener("touchstart", handleClick, { passive: true, capture });
|
|
21
20
|
root.addEventListener("keydown", handleEscape, capture), el.addEventListener("focusout", handleFocusOut, capture);
|
|
22
21
|
if (!stack.includes(el)) stack.push(el), stacks.set(root, stack);
|
|
@@ -32,25 +31,29 @@ var removeOutsideClick = (el) => t007._outsiders?.get(el)?.();
|
|
|
32
31
|
|
|
33
32
|
// src/hooks/vanilla/focusTrap.ts
|
|
34
33
|
import { NIL as NIL2 } from "sia-reactor";
|
|
35
|
-
var stacks2 = /* @__PURE__ */ new WeakMap();
|
|
36
34
|
function initFocusTrap(el, { enabled = false, initialSelector = "[data-autofocus]", ringClassName = "focus-outline", root = window, scoped = true, capture = true } = NIL2) {
|
|
37
|
-
const existing = (t007._ftrappers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
35
|
+
const stacks = t007._ftrappers_stacks ??= /* @__PURE__ */ new WeakMap(), existing = (t007._ftrappers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
38
36
|
if (!enabled || existing) return existing ? existing : void 0;
|
|
39
37
|
scoped = scoped && root instanceof HTMLElement, root = scoped ? root : root === document ? document : window;
|
|
40
|
-
const stack =
|
|
38
|
+
const stack = stacks.get(root) ?? [], 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()) => els?.length ? els.at(i).focus() : (!el.hasAttribute("tabindex") && (el.tabIndex = -1), el.focus()), edgeFocus = (pre = false, rt = root) => {
|
|
41
39
|
if (!scoped) return resetFocus(pre ? -1 : 0);
|
|
42
|
-
|
|
40
|
+
if (rt.hasAttribute("tabindex")) return rt.focus();
|
|
43
41
|
const items = getFocusable();
|
|
44
42
|
if (!items.length) return resetFocus(0, null);
|
|
45
|
-
const
|
|
46
|
-
|
|
43
|
+
const ceiling = document.fullscreenElement || document.querySelector("dialog:modal") || document.body;
|
|
44
|
+
let p = rt.parentElement || ceiling, all = getFocusable(p);
|
|
45
|
+
while (p !== ceiling && (!all.length || rt.contains(all[0]) && rt.contains(all.at(-1)))) all = getFocusable(p = p.parentElement || ceiling);
|
|
46
|
+
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();
|
|
47
47
|
(pre ? first : last).blur();
|
|
48
|
-
}, handleFocusIn = () =>
|
|
48
|
+
}, handleFocusIn = () => {
|
|
49
|
+
if (document.querySelector("dialog:modal") && !el.matches("dialog:modal")) return;
|
|
50
|
+
stack.at(-1) === el && getActiveEl(el.ownerDocument) !== root && !el.contains(getActiveEl(el.ownerDocument)) && resetFocus();
|
|
51
|
+
}, handleInitialBlur = () => initial.classList.remove(ringClassName);
|
|
49
52
|
first.addEventListener("focus", (e) => el.contains(e.relatedTarget) ? edgeFocus(true) : resetFocus(), capture), el.prepend(first);
|
|
50
53
|
last.addEventListener("focus", (e) => el.contains(e.relatedTarget) ? edgeFocus() : resetFocus(-1), capture), el.append(last);
|
|
51
54
|
root.addEventListener("focusin", handleFocusIn, capture);
|
|
52
|
-
if (!el.querySelector(":focus")) !initial ? resetFocus
|
|
53
|
-
if (!stack.includes(el)) stack.push(el),
|
|
55
|
+
if (!el.querySelector(":focus")) !initial ? setTimeout(resetFocus) : setTimeout(() => (initial.classList.add(ringClassName), initial.focus(), initial.addEventListener("blur", handleInitialBlur, capture)));
|
|
56
|
+
if (!stack.includes(el)) stack.push(el), stacks.set(root, stack);
|
|
54
57
|
const destroy = () => {
|
|
55
58
|
focused?.isConnected && focused.focus(), first.remove(), last.remove();
|
|
56
59
|
root.removeEventListener("focusin", handleFocusIn, capture);
|
package/dist/hooks/react.cjs
CHANGED
|
@@ -37,12 +37,9 @@ var import_utils = require("sia-reactor/utils");
|
|
|
37
37
|
|
|
38
38
|
// src/core/dom.ts
|
|
39
39
|
var import_utils2 = require("sia-reactor/utils");
|
|
40
|
-
var
|
|
40
|
+
var import_utils3 = require("sia-reactor/utils");
|
|
41
|
+
var INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable='true'],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
41
42
|
var isInteractive = (target) => target instanceof HTMLElement && target.matches(INTERACTIVE_SELECTOR);
|
|
42
|
-
function getActiveElement(root = document) {
|
|
43
|
-
const activeEl = root.activeElement;
|
|
44
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveElement(activeEl.shadowRoot) : activeEl;
|
|
45
|
-
}
|
|
46
43
|
|
|
47
44
|
// src/hooks/react/useScrollAssist.ts
|
|
48
45
|
var import_sia_reactor = require("sia-reactor");
|
|
@@ -128,15 +125,14 @@ var import_react2 = require("react");
|
|
|
128
125
|
|
|
129
126
|
// src/hooks/vanilla/outsideClick.ts
|
|
130
127
|
var import_sia_reactor2 = require("sia-reactor");
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const existing = (t007._outsiders ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
128
|
+
function initOutsideClick(el, { enabled = false, onOutsideClick = import_sia_reactor2.NOOP, outOnClick = true, outOnEscape = true, outOnFocusOut = false, allowInputs = false, root = window, scoped = true, capture = true } = import_sia_reactor2.NIL) {
|
|
129
|
+
const stacks = t007._outsiders_stacks ??= /* @__PURE__ */ new WeakMap(), existing = (t007._outsiders ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
134
130
|
if (!enabled || existing) return existing ? existing : void 0;
|
|
135
131
|
scoped = scoped && root instanceof HTMLElement, root = scoped ? root : root === document ? document : window;
|
|
136
132
|
const stack = stacks.get(root) ?? [], onScopedOut = (e, t, p = e.touches?.[0] || e, rect = el.getBoundingClientRect()) => {
|
|
137
133
|
if (stack.at(-1) !== el || p.clientX >= rect.left && p.clientX <= rect.right && p.clientY >= rect.top && p.clientY <= rect.bottom) return false;
|
|
138
134
|
return (!scoped ? true : root.contains(t)) && onOutsideClick(e);
|
|
139
|
-
}, handleClick = ((e) =>
|
|
135
|
+
}, 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 && onOutsideClick(e)), handleFocusOut = (e) => outOnFocusOut && !el.contains(e.relatedTarget) && onScopedOut(e, e.relatedTarget);
|
|
140
136
|
root.addEventListener("mousedown", handleClick, capture), root.addEventListener("touchstart", handleClick, { passive: true, capture });
|
|
141
137
|
root.addEventListener("keydown", handleEscape, capture), el.addEventListener("focusout", handleFocusOut, capture);
|
|
142
138
|
if (!stack.includes(el)) stack.push(el), stacks.set(root, stack);
|
|
@@ -152,7 +148,7 @@ function initOutsideClick(el, { enabled = false, onOutsideClick = import_sia_rea
|
|
|
152
148
|
// src/hooks/react/useOutsideClick.ts
|
|
153
149
|
var import_sia_reactor3 = require("sia-reactor");
|
|
154
150
|
function useOutsideClick(ref, config = import_sia_reactor3.NIL) {
|
|
155
|
-
(0, import_react2.useEffect)(() => ref.current ? initOutsideClick(ref.current, config) : void 0, [ref, config.enabled, config.onOutsideClick, config.
|
|
151
|
+
(0, import_react2.useEffect)(() => ref.current ? initOutsideClick(ref.current, config) : void 0, [ref, config.enabled, config.onOutsideClick, config.outOnEscape, config.outOnClick, config.outOnFocusOut, config.allowInputs, config.root, config.scoped, config.capture]);
|
|
156
152
|
}
|
|
157
153
|
|
|
158
154
|
// src/hooks/react/useArrowNavigation/index.ts
|
|
@@ -290,15 +286,16 @@ function useArrowNavigation(containerRef, config = {}) {
|
|
|
290
286
|
);
|
|
291
287
|
const simulateKey = (0, import_react3.useCallback)(
|
|
292
288
|
(e) => {
|
|
293
|
-
|
|
289
|
+
const t = e.target;
|
|
290
|
+
if (shouldSnub() || (0, import_utils3.getActiveEl)(t?.ownerDocument)?.matches("option")) return;
|
|
294
291
|
const all = itemsRef.current, { key } = e;
|
|
295
292
|
if (!all.length) return;
|
|
296
293
|
if (virtual && (key === " " || key === "Enter")) return all[activeIndex]?.click();
|
|
297
|
-
if (
|
|
294
|
+
if (t?.matches(DEFAULT_CONFIG.inputSelector) && !virtual) return;
|
|
298
295
|
if (typeahead && key.length === 1 && /^[a-z0-9]$/i.test(key)) return typeAhead(key);
|
|
299
296
|
if (!NAV_KEYS.includes(key)) return;
|
|
300
297
|
if (!(e.currentTarget?.matches(DEFAULT_CONFIG.inputSelector) && gridX <= 1 && H_NAV_KEYS.includes(key))) e.preventDefault?.(), e.stopPropagation?.();
|
|
301
|
-
const currIndex = virtual ? activeIndex : all.indexOf(
|
|
298
|
+
const currIndex = virtual ? activeIndex : all.indexOf((0, import_utils3.getActiveEl)(t?.ownerDocument)), targetIndex = getTargetIndex({ currIndex, gridX, gridY, vGridY, length: all.length, loop, rtl, key, ctrlKey: e.ctrlKey });
|
|
302
299
|
goToIndex(targetIndex, e);
|
|
303
300
|
},
|
|
304
301
|
[shouldSnub, virtual, activeIndex, gridX, gridY, vGridY, loop, rtl, goToIndex, typeahead, typeAhead]
|
|
@@ -381,25 +378,29 @@ var import_react4 = require("react");
|
|
|
381
378
|
|
|
382
379
|
// src/hooks/vanilla/focusTrap.ts
|
|
383
380
|
var import_sia_reactor5 = require("sia-reactor");
|
|
384
|
-
var stacks2 = /* @__PURE__ */ new WeakMap();
|
|
385
381
|
function initFocusTrap(el, { enabled = false, initialSelector = "[data-autofocus]", ringClassName = "focus-outline", root = window, scoped = true, capture = true } = import_sia_reactor5.NIL) {
|
|
386
|
-
const existing = (t007._ftrappers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
382
|
+
const stacks = t007._ftrappers_stacks ??= /* @__PURE__ */ new WeakMap(), existing = (t007._ftrappers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
387
383
|
if (!enabled || existing) return existing ? existing : void 0;
|
|
388
384
|
scoped = scoped && root instanceof HTMLElement, root = scoped ? root : root === document ? document : window;
|
|
389
|
-
const stack =
|
|
385
|
+
const stack = stacks.get(root) ?? [], focused = document.querySelector(":focus"), initial = el.querySelector(initialSelector), first = (0, import_utils2.createEl)("span", { tabIndex: 0 }, { focusGuard: "start" }, { position: "absolute", width: "0", height: "0", pointerEvents: "none" }), last = (0, import_utils2.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()) => els?.length ? els.at(i).focus() : (!el.hasAttribute("tabindex") && (el.tabIndex = -1), el.focus()), edgeFocus = (pre = false, rt = root) => {
|
|
390
386
|
if (!scoped) return resetFocus(pre ? -1 : 0);
|
|
391
|
-
|
|
387
|
+
if (rt.hasAttribute("tabindex")) return rt.focus();
|
|
392
388
|
const items = getFocusable();
|
|
393
389
|
if (!items.length) return resetFocus(0, null);
|
|
394
|
-
const
|
|
395
|
-
|
|
390
|
+
const ceiling = document.fullscreenElement || document.querySelector("dialog:modal") || document.body;
|
|
391
|
+
let p = rt.parentElement || ceiling, all = getFocusable(p);
|
|
392
|
+
while (p !== ceiling && (!all.length || rt.contains(all[0]) && rt.contains(all.at(-1)))) all = getFocusable(p = p.parentElement || ceiling);
|
|
393
|
+
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();
|
|
396
394
|
(pre ? first : last).blur();
|
|
397
|
-
}, handleFocusIn = () =>
|
|
395
|
+
}, handleFocusIn = () => {
|
|
396
|
+
if (document.querySelector("dialog:modal") && !el.matches("dialog:modal")) return;
|
|
397
|
+
stack.at(-1) === el && (0, import_utils3.getActiveEl)(el.ownerDocument) !== root && !el.contains((0, import_utils3.getActiveEl)(el.ownerDocument)) && resetFocus();
|
|
398
|
+
}, handleInitialBlur = () => initial.classList.remove(ringClassName);
|
|
398
399
|
first.addEventListener("focus", (e) => el.contains(e.relatedTarget) ? edgeFocus(true) : resetFocus(), capture), el.prepend(first);
|
|
399
400
|
last.addEventListener("focus", (e) => el.contains(e.relatedTarget) ? edgeFocus() : resetFocus(-1), capture), el.append(last);
|
|
400
401
|
root.addEventListener("focusin", handleFocusIn, capture);
|
|
401
|
-
if (!el.querySelector(":focus")) !initial ? resetFocus
|
|
402
|
-
if (!stack.includes(el)) stack.push(el),
|
|
402
|
+
if (!el.querySelector(":focus")) !initial ? setTimeout(resetFocus) : setTimeout(() => (initial.classList.add(ringClassName), initial.focus(), initial.addEventListener("blur", handleInitialBlur, capture)));
|
|
403
|
+
if (!stack.includes(el)) stack.push(el), stacks.set(root, stack);
|
|
403
404
|
const destroy = () => {
|
|
404
405
|
focused?.isConnected && focused.focus(), first.remove(), last.remove();
|
|
405
406
|
root.removeEventListener("focusin", handleFocusIn, capture);
|
package/dist/hooks/react.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
2
|
import { a as ScrollAssistConfig, C as Config, K as KeyEvent } from '../scrollAssist-y9wFmYgt.cjs';
|
|
3
|
-
import { O as OutsideClickConfig, F as FocusTrapConfig, R as RippleConfig } from '../ripple-
|
|
3
|
+
import { O as OutsideClickConfig, F as FocusTrapConfig, R as RippleConfig } from '../ripple-CVQx46Xq.cjs';
|
|
4
4
|
export { H as HighlightOptions, u as useHighlight } from '../useHighlight-DMpDCILK.cjs';
|
|
5
5
|
|
|
6
6
|
/** Configuration options for the `useScrollAssist` hook. */
|
package/dist/hooks/react.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
2
|
import { a as ScrollAssistConfig, C as Config, K as KeyEvent } from '../scrollAssist-y9wFmYgt.js';
|
|
3
|
-
import { O as OutsideClickConfig, F as FocusTrapConfig, R as RippleConfig } from '../ripple-
|
|
3
|
+
import { O as OutsideClickConfig, F as FocusTrapConfig, R as RippleConfig } from '../ripple-CVQx46Xq.js';
|
|
4
4
|
export { H as HighlightOptions, u as useHighlight } from '../useHighlight-DMpDCILK.js';
|
|
5
5
|
|
|
6
6
|
/** Configuration options for the `useScrollAssist` hook. */
|
package/dist/hooks/react.js
CHANGED
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
initFocusTrap,
|
|
12
12
|
initOutsideClick,
|
|
13
13
|
rippleHandler
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-NLR4ANGT.js";
|
|
15
15
|
import {
|
|
16
16
|
INTERACTIVE_SELECTOR,
|
|
17
|
-
|
|
18
|
-
} from "../chunk-
|
|
17
|
+
getActiveEl
|
|
18
|
+
} from "../chunk-N5KX6IW4.js";
|
|
19
19
|
|
|
20
20
|
// src/hooks/react/useScrollAssist.ts
|
|
21
21
|
import { useEffect, useRef, useCallback } from "react";
|
|
@@ -101,7 +101,7 @@ function useScrollAssist(ref, { enabled = true, pxPerSecond = 80, assistClassNam
|
|
|
101
101
|
import { useEffect as useEffect2 } from "react";
|
|
102
102
|
import { NIL as NIL2 } from "sia-reactor";
|
|
103
103
|
function useOutsideClick(ref, config = NIL2) {
|
|
104
|
-
useEffect2(() => ref.current ? initOutsideClick(ref.current, config) : void 0, [ref, config.enabled, config.onOutsideClick, config.
|
|
104
|
+
useEffect2(() => ref.current ? initOutsideClick(ref.current, config) : void 0, [ref, config.enabled, config.onOutsideClick, config.outOnEscape, config.outOnClick, config.outOnFocusOut, config.allowInputs, config.root, config.scoped, config.capture]);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
// src/hooks/react/useArrowNavigation/index.ts
|
|
@@ -167,15 +167,16 @@ function useArrowNavigation(containerRef, config = {}) {
|
|
|
167
167
|
);
|
|
168
168
|
const simulateKey = useCallback2(
|
|
169
169
|
(e) => {
|
|
170
|
-
|
|
170
|
+
const t = e.target;
|
|
171
|
+
if (shouldSnub() || getActiveEl(t?.ownerDocument)?.matches("option")) return;
|
|
171
172
|
const all = itemsRef.current, { key } = e;
|
|
172
173
|
if (!all.length) return;
|
|
173
174
|
if (virtual && (key === " " || key === "Enter")) return all[activeIndex]?.click();
|
|
174
|
-
if (
|
|
175
|
+
if (t?.matches(DEFAULT_CONFIG.inputSelector) && !virtual) return;
|
|
175
176
|
if (typeahead && key.length === 1 && /^[a-z0-9]$/i.test(key)) return typeAhead(key);
|
|
176
177
|
if (!NAV_KEYS.includes(key)) return;
|
|
177
178
|
if (!(e.currentTarget?.matches(DEFAULT_CONFIG.inputSelector) && gridX <= 1 && H_NAV_KEYS.includes(key))) e.preventDefault?.(), e.stopPropagation?.();
|
|
178
|
-
const currIndex = virtual ? activeIndex : all.indexOf(
|
|
179
|
+
const currIndex = virtual ? activeIndex : all.indexOf(getActiveEl(t?.ownerDocument)), targetIndex = getTargetIndex({ currIndex, gridX, gridY, vGridY, length: all.length, loop, rtl, key, ctrlKey: e.ctrlKey });
|
|
179
180
|
goToIndex(targetIndex, e);
|
|
180
181
|
},
|
|
181
182
|
[shouldSnub, virtual, activeIndex, gridX, gridY, vGridY, loop, rtl, goToIndex, typeahead, typeAhead]
|
package/dist/hooks/vanilla.cjs
CHANGED
|
@@ -38,24 +38,21 @@ var import_sia_reactor = require("sia-reactor");
|
|
|
38
38
|
|
|
39
39
|
// src/core/dom.ts
|
|
40
40
|
var import_utils = require("sia-reactor/utils");
|
|
41
|
-
var
|
|
41
|
+
var import_utils2 = require("sia-reactor/utils");
|
|
42
|
+
var INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable='true'],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
42
43
|
var isInteractive = (target) => target instanceof HTMLElement && target.matches(INTERACTIVE_SELECTOR);
|
|
43
|
-
function getActiveElement(root = document) {
|
|
44
|
-
const activeEl = root.activeElement;
|
|
45
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveElement(activeEl.shadowRoot) : activeEl;
|
|
46
|
-
}
|
|
47
44
|
|
|
48
45
|
// src/core/num.ts
|
|
49
|
-
var
|
|
46
|
+
var import_utils3 = require("sia-reactor/utils");
|
|
50
47
|
|
|
51
48
|
// src/hooks/vanilla/scrollAssist.ts
|
|
52
49
|
function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "t007-scroll-assist", vertical = true, horizontal = true } = import_sia_reactor.NIL) {
|
|
53
50
|
const parent = el?.parentElement, existing = (t007._scrollers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
54
51
|
if (!parent || existing) return existing ? existing : void 0;
|
|
55
|
-
t007.
|
|
52
|
+
t007._scrollers_r_observer ??= new ResizeObserver((entries) => {
|
|
56
53
|
for (const { target } of entries) t007._scrollers.get(target)?.update();
|
|
57
54
|
});
|
|
58
|
-
t007.
|
|
55
|
+
t007._scrollers_m_observer ??= new MutationObserver((entries) => {
|
|
59
56
|
const els = /* @__PURE__ */ new Set();
|
|
60
57
|
for (const entry of entries) {
|
|
61
58
|
let node = entry.target instanceof Element ? entry.target : null;
|
|
@@ -110,12 +107,12 @@ function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "t007-scroll
|
|
|
110
107
|
update,
|
|
111
108
|
destroy() {
|
|
112
109
|
stop(), el.removeEventListener("scroll", update);
|
|
113
|
-
t007.
|
|
110
|
+
t007._scrollers_r_observer.unobserve(el), t007._scrollers.delete(el);
|
|
114
111
|
for (const a of Object.values(assist)) a.remove();
|
|
115
112
|
}
|
|
116
113
|
};
|
|
117
114
|
update(), el.addEventListener("scroll", update);
|
|
118
|
-
t007.
|
|
115
|
+
t007._scrollers_r_observer.observe(el), t007._scrollers_m_observer.observe(el, { childList: true, subtree: true, characterData: true });
|
|
119
116
|
return t007._scrollers.set(el, handle), handle;
|
|
120
117
|
}
|
|
121
118
|
var removeScrollAssist = (el) => t007._scrollers.get(el)?.destroy();
|
|
@@ -139,15 +136,14 @@ function initVScrollerator({ baseSpeed = 3, maxSpeed = 10, stepDelay = 2e3, base
|
|
|
139
136
|
|
|
140
137
|
// src/hooks/vanilla/outsideClick.ts
|
|
141
138
|
var import_sia_reactor3 = require("sia-reactor");
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const existing = (t007._outsiders ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
139
|
+
function initOutsideClick(el, { enabled = false, onOutsideClick = import_sia_reactor3.NOOP, outOnClick = true, outOnEscape = true, outOnFocusOut = false, allowInputs = false, root = window, scoped = true, capture = true } = import_sia_reactor3.NIL) {
|
|
140
|
+
const stacks = t007._outsiders_stacks ??= /* @__PURE__ */ new WeakMap(), existing = (t007._outsiders ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
145
141
|
if (!enabled || existing) return existing ? existing : void 0;
|
|
146
142
|
scoped = scoped && root instanceof HTMLElement, root = scoped ? root : root === document ? document : window;
|
|
147
143
|
const stack = stacks.get(root) ?? [], onScopedOut = (e, t, p = e.touches?.[0] || e, rect = el.getBoundingClientRect()) => {
|
|
148
144
|
if (stack.at(-1) !== el || p.clientX >= rect.left && p.clientX <= rect.right && p.clientY >= rect.top && p.clientY <= rect.bottom) return false;
|
|
149
145
|
return (!scoped ? true : root.contains(t)) && onOutsideClick(e);
|
|
150
|
-
}, handleClick = ((e) =>
|
|
146
|
+
}, 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 && onOutsideClick(e)), handleFocusOut = (e) => outOnFocusOut && !el.contains(e.relatedTarget) && onScopedOut(e, e.relatedTarget);
|
|
151
147
|
root.addEventListener("mousedown", handleClick, capture), root.addEventListener("touchstart", handleClick, { passive: true, capture });
|
|
152
148
|
root.addEventListener("keydown", handleEscape, capture), el.addEventListener("focusout", handleFocusOut, capture);
|
|
153
149
|
if (!stack.includes(el)) stack.push(el), stacks.set(root, stack);
|
|
@@ -163,25 +159,29 @@ var removeOutsideClick = (el) => t007._outsiders?.get(el)?.();
|
|
|
163
159
|
|
|
164
160
|
// src/hooks/vanilla/focusTrap.ts
|
|
165
161
|
var import_sia_reactor4 = require("sia-reactor");
|
|
166
|
-
var stacks2 = /* @__PURE__ */ new WeakMap();
|
|
167
162
|
function initFocusTrap(el, { enabled = false, initialSelector = "[data-autofocus]", ringClassName = "focus-outline", root = window, scoped = true, capture = true } = import_sia_reactor4.NIL) {
|
|
168
|
-
const existing = (t007._ftrappers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
163
|
+
const stacks = t007._ftrappers_stacks ??= /* @__PURE__ */ new WeakMap(), existing = (t007._ftrappers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
169
164
|
if (!enabled || existing) return existing ? existing : void 0;
|
|
170
165
|
scoped = scoped && root instanceof HTMLElement, root = scoped ? root : root === document ? document : window;
|
|
171
|
-
const stack =
|
|
166
|
+
const stack = stacks.get(root) ?? [], focused = document.querySelector(":focus"), initial = el.querySelector(initialSelector), first = (0, import_utils.createEl)("span", { tabIndex: 0 }, { focusGuard: "start" }, { position: "absolute", width: "0", height: "0", pointerEvents: "none" }), last = (0, import_utils.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()) => els?.length ? els.at(i).focus() : (!el.hasAttribute("tabindex") && (el.tabIndex = -1), el.focus()), edgeFocus = (pre = false, rt = root) => {
|
|
172
167
|
if (!scoped) return resetFocus(pre ? -1 : 0);
|
|
173
|
-
|
|
168
|
+
if (rt.hasAttribute("tabindex")) return rt.focus();
|
|
174
169
|
const items = getFocusable();
|
|
175
170
|
if (!items.length) return resetFocus(0, null);
|
|
176
|
-
const
|
|
177
|
-
|
|
171
|
+
const ceiling = document.fullscreenElement || document.querySelector("dialog:modal") || document.body;
|
|
172
|
+
let p = rt.parentElement || ceiling, all = getFocusable(p);
|
|
173
|
+
while (p !== ceiling && (!all.length || rt.contains(all[0]) && rt.contains(all.at(-1)))) all = getFocusable(p = p.parentElement || ceiling);
|
|
174
|
+
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();
|
|
178
175
|
(pre ? first : last).blur();
|
|
179
|
-
}, handleFocusIn = () =>
|
|
176
|
+
}, handleFocusIn = () => {
|
|
177
|
+
if (document.querySelector("dialog:modal") && !el.matches("dialog:modal")) return;
|
|
178
|
+
stack.at(-1) === el && (0, import_utils2.getActiveEl)(el.ownerDocument) !== root && !el.contains((0, import_utils2.getActiveEl)(el.ownerDocument)) && resetFocus();
|
|
179
|
+
}, handleInitialBlur = () => initial.classList.remove(ringClassName);
|
|
180
180
|
first.addEventListener("focus", (e) => el.contains(e.relatedTarget) ? edgeFocus(true) : resetFocus(), capture), el.prepend(first);
|
|
181
181
|
last.addEventListener("focus", (e) => el.contains(e.relatedTarget) ? edgeFocus() : resetFocus(-1), capture), el.append(last);
|
|
182
182
|
root.addEventListener("focusin", handleFocusIn, capture);
|
|
183
|
-
if (!el.querySelector(":focus")) !initial ? resetFocus
|
|
184
|
-
if (!stack.includes(el)) stack.push(el),
|
|
183
|
+
if (!el.querySelector(":focus")) !initial ? setTimeout(resetFocus) : setTimeout(() => (initial.classList.add(ringClassName), initial.focus(), initial.addEventListener("blur", handleInitialBlur, capture)));
|
|
184
|
+
if (!stack.includes(el)) stack.push(el), stacks.set(root, stack);
|
|
185
185
|
const destroy = () => {
|
|
186
186
|
focused?.isConnected && focused.focus(), first.remove(), last.remove();
|
|
187
187
|
root.removeEventListener("focusin", handleFocusIn, capture);
|
|
@@ -231,7 +231,7 @@ var getTargetIndex = ({ key, currIndex, length, gridX, gridY, vGridY, loop, ctrl
|
|
|
231
231
|
} else if (key === "PageUp") {
|
|
232
232
|
if (!loop && targetIndex < 0) targetIndex = colStart;
|
|
233
233
|
}
|
|
234
|
-
return loop ? (targetIndex + length) % length : (0,
|
|
234
|
+
return loop ? (targetIndex + length) % length : (0, import_utils3.clamp)(0, targetIndex, length - 1);
|
|
235
235
|
};
|
|
236
236
|
var getCommonAncestor = (first, second) => {
|
|
237
237
|
if (!first) return null;
|
|
@@ -256,7 +256,7 @@ var getGrid = (all, x = true, y = true, vY = true) => {
|
|
|
256
256
|
if (y) grid.y = rows;
|
|
257
257
|
if (vY) {
|
|
258
258
|
const itemHeight = all[0].offsetHeight ?? 0, containerHeight = getCommonAncestor(all[0], all[1])?.clientHeight ?? 0;
|
|
259
|
-
rows = (0,
|
|
259
|
+
rows = (0, import_utils3.clamp)(1, Math.floor(containerHeight / itemHeight), rows) || rows;
|
|
260
260
|
grid.vY = rows;
|
|
261
261
|
}
|
|
262
262
|
return grid;
|
|
@@ -264,7 +264,7 @@ var getGrid = (all, x = true, y = true, vY = true) => {
|
|
|
264
264
|
|
|
265
265
|
// src/hooks/vanilla/arrowNavigation.ts
|
|
266
266
|
function initArrowNavigation(container, config = {}) {
|
|
267
|
-
const existing = (t007.
|
|
267
|
+
const existing = (t007._arrownavs ??= /* @__PURE__ */ new WeakMap()).get(container);
|
|
268
268
|
if (!config.enabled || existing) return existing ? existing : void 0;
|
|
269
269
|
const { enabled: isEnabled, selector, focusOnHover, loop, virtual, typeahead, resetMs, activeClass, inputSelector, defaultTabbableIndex, baseTabIndex, grid, rtl: isRtl, focusOptions, scrollIntoView, onSelect, onFocusOut, rovingTab } = { ...DEFAULT_CONFIG, ...config };
|
|
270
270
|
let gridX = grid.x || 1, gridY = grid.y || 1, vGridY = grid.vY || 1, activeIndex = -1, buffer = "", timeout = null, items = [];
|
|
@@ -315,15 +315,16 @@ function initArrowNavigation(container, config = {}) {
|
|
|
315
315
|
}
|
|
316
316
|
};
|
|
317
317
|
const simulateKey = (e) => {
|
|
318
|
-
|
|
318
|
+
const t = e.target;
|
|
319
|
+
if (shouldSnub() || (0, import_utils2.getActiveEl)(t?.ownerDocument)?.matches("option")) return;
|
|
319
320
|
const { key } = e;
|
|
320
321
|
if (!items.length) return;
|
|
321
322
|
if (virtual && (key === " " || key === "Enter")) return items[activeIndex]?.click();
|
|
322
|
-
if (
|
|
323
|
+
if (t?.matches(DEFAULT_CONFIG.inputSelector) && !virtual) return;
|
|
323
324
|
if (typeahead && key.length === 1 && /^[a-z0-9]$/i.test(key)) return typeAhead(key);
|
|
324
325
|
if (!NAV_KEYS.includes(key)) return;
|
|
325
326
|
if (!(e.currentTarget?.matches(DEFAULT_CONFIG.inputSelector) && gridX <= 1 && H_NAV_KEYS.includes(key))) e.preventDefault?.(), e.stopPropagation?.();
|
|
326
|
-
const currIndex = virtual ? activeIndex : items.indexOf(
|
|
327
|
+
const currIndex = virtual ? activeIndex : items.indexOf((0, import_utils2.getActiveEl)(t?.ownerDocument)), targetIndex = getTargetIndex({ currIndex, gridX, gridY, vGridY, length: items.length, loop, rtl, key, ctrlKey: e.ctrlKey });
|
|
327
328
|
goToIndex(targetIndex, e);
|
|
328
329
|
};
|
|
329
330
|
getItems(), updateDOM();
|
|
@@ -370,9 +371,9 @@ function initArrowNavigation(container, config = {}) {
|
|
|
370
371
|
if (timeout) clearTimeout(timeout);
|
|
371
372
|
};
|
|
372
373
|
const handle = { gridX: () => gridX, gridY: () => gridY, vGridY: () => vGridY, items: () => items, activeIndex: () => activeIndex, activeItem: () => items[activeIndex] ?? null, getAbleIndex, typeAhead, goToIndex, simulateKey, destroy };
|
|
373
|
-
return t007.
|
|
374
|
+
return t007._arrownavs.set(container, handle), handle;
|
|
374
375
|
}
|
|
375
|
-
var removeArrowNavigation = (container) => t007.
|
|
376
|
+
var removeArrowNavigation = (container) => t007._arrownavs?.get(container)?.destroy();
|
|
376
377
|
|
|
377
378
|
// src/hooks/vanilla/ripple.ts
|
|
378
379
|
var import_sia_reactor6 = require("sia-reactor");
|
package/dist/hooks/vanilla.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { a as ScrollAssistConfig, S as ScrollAssistHandle, b as ScrollDir, i as initScrollAssist, r as removeScrollAssist } from '../scrollAssist-y9wFmYgt.cjs';
|
|
2
|
-
export { F as FocusTrapConfig, O as OutsideClickConfig, R as RippleConfig, i as initFocusTrap, a as initOutsideClick, r as removeFocusTrap, b as removeOutsideClick, c as rippleHandler } from '../ripple-
|
|
2
|
+
export { F as FocusTrapConfig, O as OutsideClickConfig, R as RippleConfig, i as initFocusTrap, a as initOutsideClick, r as removeFocusTrap, b as removeOutsideClick, c as rippleHandler } from '../ripple-CVQx46Xq.cjs';
|
|
3
3
|
export { A as ArrowNavigationHandle, i as initArrowNavigation, r as removeArrowNavigation } from '../arrowNavigation-DK8mqVOk.cjs';
|
|
4
4
|
|
|
5
5
|
/** Configuration for the vertical edge-scrolling helper. */
|
package/dist/hooks/vanilla.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { a as ScrollAssistConfig, S as ScrollAssistHandle, b as ScrollDir, i as initScrollAssist, r as removeScrollAssist } from '../scrollAssist-y9wFmYgt.js';
|
|
2
|
-
export { F as FocusTrapConfig, O as OutsideClickConfig, R as RippleConfig, i as initFocusTrap, a as initOutsideClick, r as removeFocusTrap, b as removeOutsideClick, c as rippleHandler } from '../ripple-
|
|
2
|
+
export { F as FocusTrapConfig, O as OutsideClickConfig, R as RippleConfig, i as initFocusTrap, a as initOutsideClick, r as removeFocusTrap, b as removeOutsideClick, c as rippleHandler } from '../ripple-CVQx46Xq.js';
|
|
3
3
|
export { A as ArrowNavigationHandle, i as initArrowNavigation, r as removeArrowNavigation } from '../arrowNavigation-VenvPI4H.js';
|
|
4
4
|
|
|
5
5
|
/** Configuration for the vertical edge-scrolling helper. */
|
package/dist/hooks/vanilla.js
CHANGED
|
@@ -10,22 +10,22 @@ import {
|
|
|
10
10
|
removeFocusTrap,
|
|
11
11
|
removeOutsideClick,
|
|
12
12
|
rippleHandler
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-NLR4ANGT.js";
|
|
14
14
|
import {
|
|
15
15
|
INTERACTIVE_SELECTOR,
|
|
16
16
|
createEl,
|
|
17
|
-
|
|
18
|
-
} from "../chunk-
|
|
17
|
+
getActiveEl
|
|
18
|
+
} from "../chunk-N5KX6IW4.js";
|
|
19
19
|
|
|
20
20
|
// src/hooks/vanilla/scrollAssist.ts
|
|
21
21
|
import { NIL } from "sia-reactor";
|
|
22
22
|
function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "t007-scroll-assist", vertical = true, horizontal = true } = NIL) {
|
|
23
23
|
const parent = el?.parentElement, existing = (t007._scrollers ??= /* @__PURE__ */ new WeakMap()).get(el);
|
|
24
24
|
if (!parent || existing) return existing ? existing : void 0;
|
|
25
|
-
t007.
|
|
25
|
+
t007._scrollers_r_observer ??= new ResizeObserver((entries) => {
|
|
26
26
|
for (const { target } of entries) t007._scrollers.get(target)?.update();
|
|
27
27
|
});
|
|
28
|
-
t007.
|
|
28
|
+
t007._scrollers_m_observer ??= new MutationObserver((entries) => {
|
|
29
29
|
const els = /* @__PURE__ */ new Set();
|
|
30
30
|
for (const entry of entries) {
|
|
31
31
|
let node = entry.target instanceof Element ? entry.target : null;
|
|
@@ -80,12 +80,12 @@ function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "t007-scroll
|
|
|
80
80
|
update,
|
|
81
81
|
destroy() {
|
|
82
82
|
stop(), el.removeEventListener("scroll", update);
|
|
83
|
-
t007.
|
|
83
|
+
t007._scrollers_r_observer.unobserve(el), t007._scrollers.delete(el);
|
|
84
84
|
for (const a of Object.values(assist)) a.remove();
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
87
|
update(), el.addEventListener("scroll", update);
|
|
88
|
-
t007.
|
|
88
|
+
t007._scrollers_r_observer.observe(el), t007._scrollers_m_observer.observe(el, { childList: true, subtree: true, characterData: true });
|
|
89
89
|
return t007._scrollers.set(el, handle), handle;
|
|
90
90
|
}
|
|
91
91
|
var removeScrollAssist = (el) => t007._scrollers.get(el)?.destroy();
|
|
@@ -109,7 +109,7 @@ function initVScrollerator({ baseSpeed = 3, maxSpeed = 10, stepDelay = 2e3, base
|
|
|
109
109
|
|
|
110
110
|
// src/hooks/vanilla/arrowNavigation.ts
|
|
111
111
|
function initArrowNavigation(container, config = {}) {
|
|
112
|
-
const existing = (t007.
|
|
112
|
+
const existing = (t007._arrownavs ??= /* @__PURE__ */ new WeakMap()).get(container);
|
|
113
113
|
if (!config.enabled || existing) return existing ? existing : void 0;
|
|
114
114
|
const { enabled: isEnabled, selector, focusOnHover, loop, virtual, typeahead, resetMs, activeClass, inputSelector, defaultTabbableIndex, baseTabIndex, grid, rtl: isRtl, focusOptions, scrollIntoView, onSelect, onFocusOut, rovingTab } = { ...DEFAULT_CONFIG, ...config };
|
|
115
115
|
let gridX = grid.x || 1, gridY = grid.y || 1, vGridY = grid.vY || 1, activeIndex = -1, buffer = "", timeout = null, items = [];
|
|
@@ -160,15 +160,16 @@ function initArrowNavigation(container, config = {}) {
|
|
|
160
160
|
}
|
|
161
161
|
};
|
|
162
162
|
const simulateKey = (e) => {
|
|
163
|
-
|
|
163
|
+
const t = e.target;
|
|
164
|
+
if (shouldSnub() || getActiveEl(t?.ownerDocument)?.matches("option")) return;
|
|
164
165
|
const { key } = e;
|
|
165
166
|
if (!items.length) return;
|
|
166
167
|
if (virtual && (key === " " || key === "Enter")) return items[activeIndex]?.click();
|
|
167
|
-
if (
|
|
168
|
+
if (t?.matches(DEFAULT_CONFIG.inputSelector) && !virtual) return;
|
|
168
169
|
if (typeahead && key.length === 1 && /^[a-z0-9]$/i.test(key)) return typeAhead(key);
|
|
169
170
|
if (!NAV_KEYS.includes(key)) return;
|
|
170
171
|
if (!(e.currentTarget?.matches(DEFAULT_CONFIG.inputSelector) && gridX <= 1 && H_NAV_KEYS.includes(key))) e.preventDefault?.(), e.stopPropagation?.();
|
|
171
|
-
const currIndex = virtual ? activeIndex : items.indexOf(
|
|
172
|
+
const currIndex = virtual ? activeIndex : items.indexOf(getActiveEl(t?.ownerDocument)), targetIndex = getTargetIndex({ currIndex, gridX, gridY, vGridY, length: items.length, loop, rtl, key, ctrlKey: e.ctrlKey });
|
|
172
173
|
goToIndex(targetIndex, e);
|
|
173
174
|
};
|
|
174
175
|
getItems(), updateDOM();
|
|
@@ -215,9 +216,9 @@ function initArrowNavigation(container, config = {}) {
|
|
|
215
216
|
if (timeout) clearTimeout(timeout);
|
|
216
217
|
};
|
|
217
218
|
const handle = { gridX: () => gridX, gridY: () => gridY, vGridY: () => vGridY, items: () => items, activeIndex: () => activeIndex, activeItem: () => items[activeIndex] ?? null, getAbleIndex, typeAhead, goToIndex, simulateKey, destroy };
|
|
218
|
-
return t007.
|
|
219
|
+
return t007._arrownavs.set(container, handle), handle;
|
|
219
220
|
}
|
|
220
|
-
var removeArrowNavigation = (container) => t007.
|
|
221
|
+
var removeArrowNavigation = (container) => t007._arrownavs?.get(container)?.destroy();
|
|
221
222
|
export {
|
|
222
223
|
initArrowNavigation,
|
|
223
224
|
initFocusTrap,
|
package/dist/index.cjs
CHANGED
|
@@ -25,20 +25,20 @@ __export(index_exports, {
|
|
|
25
25
|
NOOP: () => import_sia_reactor.NOOP,
|
|
26
26
|
VIRTUAL_RESOURCE: () => VIRTUAL_RESOURCE,
|
|
27
27
|
assignEl: () => import_utils.assignEl,
|
|
28
|
-
bindAllMethods: () =>
|
|
28
|
+
bindAllMethods: () => import_utils7.bindAllMethods,
|
|
29
29
|
bindCleanupToSignal: () => bindCleanupToSignal,
|
|
30
30
|
breath: () => breath,
|
|
31
|
-
clamp: () =>
|
|
32
|
-
cleanKeyCombo: () =>
|
|
31
|
+
clamp: () => import_utils4.clamp,
|
|
32
|
+
cleanKeyCombo: () => import_utils6.cleanKeyCombo,
|
|
33
33
|
createEl: () => import_utils.createEl,
|
|
34
34
|
deepBreath: () => deepBreath,
|
|
35
|
-
formatKeyForDisplay: () =>
|
|
36
|
-
formatKeyShortcutsForDisplay: () =>
|
|
35
|
+
formatKeyForDisplay: () => import_utils6.formatKeyForDisplay,
|
|
36
|
+
formatKeyShortcutsForDisplay: () => import_utils6.formatKeyShortcutsForDisplay,
|
|
37
37
|
formatSize: () => formatSize,
|
|
38
|
-
|
|
39
|
-
getTermsForKey: () =>
|
|
40
|
-
guardAllMethods: () =>
|
|
41
|
-
guardMethod: () =>
|
|
38
|
+
getActiveEl: () => import_utils2.getActiveEl,
|
|
39
|
+
getTermsForKey: () => import_utils6.getTermsForKey,
|
|
40
|
+
guardAllMethods: () => import_utils7.guardAllMethods,
|
|
41
|
+
guardMethod: () => import_utils7.guardMethod,
|
|
42
42
|
inBoolArrOpt: () => inBoolArrOpt,
|
|
43
43
|
isArr: () => isArr,
|
|
44
44
|
isBool: () => isBool,
|
|
@@ -47,30 +47,35 @@ __export(index_exports, {
|
|
|
47
47
|
isInteractive: () => isInteractive,
|
|
48
48
|
isIter: () => isIter,
|
|
49
49
|
isNum: () => isNum,
|
|
50
|
-
isObj: () =>
|
|
50
|
+
isObj: () => import_utils3.isObj,
|
|
51
51
|
isPOJO: () => isPOJO,
|
|
52
52
|
isSameURL: () => isSameURL,
|
|
53
53
|
isStr: () => isStr,
|
|
54
54
|
isSym: () => isSym,
|
|
55
|
-
keyEventAllowed: () =>
|
|
55
|
+
keyEventAllowed: () => import_utils6.keyEventAllowed,
|
|
56
56
|
limited: () => limited,
|
|
57
57
|
loadResource: () => loadResource,
|
|
58
|
-
matchKeys: () =>
|
|
58
|
+
matchKeys: () => import_utils6.matchKeys,
|
|
59
59
|
mockAsync: () => mockAsync,
|
|
60
|
-
onAllMethods: () =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
onAllMethods: () => import_utils7.onAllMethods,
|
|
61
|
+
parseCSSSize: () => parseCSSSize,
|
|
62
|
+
parseCSSTime: () => parseCSSTime,
|
|
63
|
+
parseForARIAKS: () => import_utils6.parseForARIAKS,
|
|
64
|
+
parseKeyCombo: () => import_utils6.parseKeyCombo,
|
|
65
|
+
pxToRem: () => pxToRem,
|
|
66
|
+
remToPx: () => remToPx,
|
|
67
|
+
requestAnimationFrame: () => import_utils5.requestAnimationFrame,
|
|
68
|
+
setInterval: () => import_utils5.setInterval,
|
|
69
|
+
setTimeout: () => import_utils5.setTimeout,
|
|
70
|
+
stringifyKeyEvent: () => import_utils6.stringifyKeyEvent,
|
|
67
71
|
uid: () => uid
|
|
68
72
|
});
|
|
69
73
|
module.exports = __toCommonJS(index_exports);
|
|
70
74
|
|
|
71
75
|
// src/core/dom.ts
|
|
72
76
|
var import_utils = require("sia-reactor/utils");
|
|
73
|
-
var
|
|
77
|
+
var import_utils2 = require("sia-reactor/utils");
|
|
78
|
+
var INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable='true'],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
74
79
|
var isInteractive = (target) => target instanceof HTMLElement && target.matches(INTERACTIVE_SELECTOR);
|
|
75
80
|
var VIRTUAL_RESOURCE = /* @__PURE__ */ Symbol.for("T007_VIRTUAL_RESOURCE");
|
|
76
81
|
function loadResource(req, type = "style", { module: module2, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
|
|
@@ -100,16 +105,12 @@ function loadResource(req, type = "style", { module: module2, media, crossOrigin
|
|
|
100
105
|
});
|
|
101
106
|
return w.t007._resourceCache[src];
|
|
102
107
|
}
|
|
103
|
-
function getActiveElement(root = document) {
|
|
104
|
-
const activeEl = root.activeElement;
|
|
105
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveElement(activeEl.shadowRoot) : activeEl;
|
|
106
|
-
}
|
|
107
108
|
|
|
108
109
|
// src/index.ts
|
|
109
110
|
var import_sia_reactor = require("sia-reactor");
|
|
110
111
|
|
|
111
112
|
// src/core/obj.ts
|
|
112
|
-
var
|
|
113
|
+
var import_utils3 = require("sia-reactor/utils");
|
|
113
114
|
function isDef(val) {
|
|
114
115
|
return "undefined" !== typeof val;
|
|
115
116
|
}
|
|
@@ -129,7 +130,7 @@ function isArr(obj) {
|
|
|
129
130
|
return Array.isArray(obj);
|
|
130
131
|
}
|
|
131
132
|
function isPOJO(obj, crossRealms = false, typecheck = true) {
|
|
132
|
-
return (typecheck ? (0,
|
|
133
|
+
return (typecheck ? (0, import_utils3.isObj)(obj, false) : true) && (crossRealms ? Object.prototype.toString.call(obj) === "[object Object]" : obj.constructor === Object);
|
|
133
134
|
}
|
|
134
135
|
function isIter(obj) {
|
|
135
136
|
return obj != null && "function" === typeof obj[Symbol.iterator];
|
|
@@ -142,12 +143,24 @@ function inBoolArrOpt(opt, str) {
|
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
// src/core/num.ts
|
|
145
|
-
var
|
|
146
|
+
var import_utils4 = require("sia-reactor/utils");
|
|
146
147
|
|
|
147
148
|
// src/core/str.ts
|
|
148
149
|
function uid(prefix = "") {
|
|
149
150
|
return prefix + Date.now().toString(36) + "_" + performance.now().toString(36).replace(".", "") + "_" + Math.random().toString(36).slice(2);
|
|
150
151
|
}
|
|
152
|
+
function remToPx(rem, el = document.documentElement) {
|
|
153
|
+
return rem * parseFloat(getComputedStyle(el).fontSize);
|
|
154
|
+
}
|
|
155
|
+
function pxToRem(px, el = document.documentElement) {
|
|
156
|
+
return px / parseFloat(getComputedStyle(el).fontSize);
|
|
157
|
+
}
|
|
158
|
+
function parseCSSTime(time) {
|
|
159
|
+
return time?.endsWith?.("ms") ? parseFloat(time) : parseFloat(time) * 1e3;
|
|
160
|
+
}
|
|
161
|
+
function parseCSSSize(size, el) {
|
|
162
|
+
return size?.endsWith?.("px") ? parseFloat(size) : remToPx(parseFloat(size), el);
|
|
163
|
+
}
|
|
151
164
|
function isSameURL(src1, src2) {
|
|
152
165
|
if (!isStr(src1) || !isStr(src2) || !src1 || !src2) return false;
|
|
153
166
|
try {
|
|
@@ -159,7 +172,7 @@ function isSameURL(src1, src2) {
|
|
|
159
172
|
}
|
|
160
173
|
|
|
161
174
|
// src/core/fn.ts
|
|
162
|
-
var
|
|
175
|
+
var import_utils5 = require("sia-reactor/utils");
|
|
163
176
|
function limited(FN_KEY, fn, opts = {}) {
|
|
164
177
|
let count = 0, { key, maxTimes: max = 1 } = isStr(opts) ? { key: opts } : opts;
|
|
165
178
|
const getReg = () => JSON.parse(localStorage.getItem(FN_KEY) || "{}"), setReg = (r) => localStorage.setItem(FN_KEY, JSON.stringify(r));
|
|
@@ -183,7 +196,7 @@ function bindCleanupToSignal(cleanup, signal) {
|
|
|
183
196
|
}
|
|
184
197
|
|
|
185
198
|
// src/core/keys.ts
|
|
186
|
-
var
|
|
199
|
+
var import_utils6 = require("sia-reactor/utils");
|
|
187
200
|
|
|
188
201
|
// src/core/file.ts
|
|
189
202
|
function formatSize(bytes, decimals = 3, base = 1e3) {
|
|
@@ -193,7 +206,7 @@ function formatSize(bytes, decimals = 3, base = 1e3) {
|
|
|
193
206
|
}
|
|
194
207
|
|
|
195
208
|
// src/mixins/methd.ts
|
|
196
|
-
var
|
|
209
|
+
var import_utils7 = require("sia-reactor/utils");
|
|
197
210
|
|
|
198
211
|
// src/index.ts
|
|
199
212
|
if ("undefined" !== typeof window) {
|
|
@@ -222,7 +235,7 @@ if ("undefined" !== typeof window) {
|
|
|
222
235
|
formatKeyForDisplay,
|
|
223
236
|
formatKeyShortcutsForDisplay,
|
|
224
237
|
formatSize,
|
|
225
|
-
|
|
238
|
+
getActiveEl,
|
|
226
239
|
getTermsForKey,
|
|
227
240
|
guardAllMethods,
|
|
228
241
|
guardMethod,
|
|
@@ -245,8 +258,12 @@ if ("undefined" !== typeof window) {
|
|
|
245
258
|
matchKeys,
|
|
246
259
|
mockAsync,
|
|
247
260
|
onAllMethods,
|
|
261
|
+
parseCSSSize,
|
|
262
|
+
parseCSSTime,
|
|
248
263
|
parseForARIAKS,
|
|
249
264
|
parseKeyCombo,
|
|
265
|
+
pxToRem,
|
|
266
|
+
remToPx,
|
|
250
267
|
requestAnimationFrame,
|
|
251
268
|
setInterval,
|
|
252
269
|
setTimeout,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { A as ArrowNavigationHandle } from './arrowNavigation-DK8mqVOk.cjs';
|
|
2
2
|
import { S as ScrollAssistHandle } from './scrollAssist-y9wFmYgt.cjs';
|
|
3
3
|
export { NIL, NOOP } from 'sia-reactor';
|
|
4
|
-
export { KeyStruct, assignEl, bindAllMethods, clamp, cleanKeyCombo, createEl, formatKeyForDisplay, formatKeyShortcutsForDisplay, getTermsForKey, guardAllMethods, guardMethod, isObj, keyEventAllowed, keysSettings, matchKeys, onAllMethods, parseForARIAKS, parseKeyCombo, requestAnimationFrame, setInterval, setTimeout, stringifyKeyEvent } from 'sia-reactor/utils';
|
|
4
|
+
export { KeyStruct, assignEl, bindAllMethods, clamp, cleanKeyCombo, createEl, formatKeyForDisplay, formatKeyShortcutsForDisplay, getActiveEl, getTermsForKey, guardAllMethods, guardMethod, isObj, keyEventAllowed, keysSettings, matchKeys, onAllMethods, parseForARIAKS, parseKeyCombo, requestAnimationFrame, setInterval, setTimeout, stringifyKeyEvent } from 'sia-reactor/utils';
|
|
5
5
|
|
|
6
6
|
declare global {
|
|
7
7
|
interface T007Namespace {
|
|
@@ -10,10 +10,12 @@ declare global {
|
|
|
10
10
|
_resourceCache: Partial<Record<string, Promise<HTMLElement | void>>>;
|
|
11
11
|
_ftrappers?: WeakMap<HTMLElement, () => void>;
|
|
12
12
|
_outsiders?: WeakMap<HTMLElement, () => void>;
|
|
13
|
-
|
|
13
|
+
_arrownavs?: WeakMap<HTMLElement, ArrowNavigationHandle>;
|
|
14
14
|
_scrollers?: WeakMap<HTMLElement, ScrollAssistHandle>;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
_ftrappers_stacks?: WeakMap<EventTarget, HTMLElement[]>;
|
|
16
|
+
_outsiders_stacks?: WeakMap<EventTarget, HTMLElement[]>;
|
|
17
|
+
_scrollers_r_observer?: ResizeObserver;
|
|
18
|
+
_scrollers_m_observer?: MutationObserver;
|
|
17
19
|
}
|
|
18
20
|
interface Window {
|
|
19
21
|
/** Shared T007 namespace. */
|
|
@@ -52,6 +54,29 @@ declare function inBoolArrOpt(opt: any, str: string): boolean;
|
|
|
52
54
|
* @returns A browser-safe unique id string.
|
|
53
55
|
*/
|
|
54
56
|
declare function uid(prefix?: string): string;
|
|
57
|
+
/** Convert a rem value to pixels based on the font size of a given element.
|
|
58
|
+
* @param rem The rem value to convert.
|
|
59
|
+
* @param el The element to use for font size reference. Defaults to the root element.
|
|
60
|
+
* @returns The equivalent pixel value.
|
|
61
|
+
*/
|
|
62
|
+
declare function remToPx(rem: number, el?: HTMLElement): number;
|
|
63
|
+
/** Convert a pixel value to rem based on the font size of a given element.
|
|
64
|
+
* @param px The pixel value to convert.
|
|
65
|
+
* @param el The element to use for font size reference. Defaults to the root element.
|
|
66
|
+
* @returns The equivalent rem value.
|
|
67
|
+
*/
|
|
68
|
+
declare function pxToRem(px: number, el?: HTMLElement): number;
|
|
69
|
+
/** Parse a CSS time value (e.g. "200ms", "0.5s") into milliseconds.
|
|
70
|
+
* @param time The CSS time string to parse.
|
|
71
|
+
* @returns The equivalent time in milliseconds.
|
|
72
|
+
*/
|
|
73
|
+
declare function parseCSSTime(time: string): number;
|
|
74
|
+
/** Parse a CSS size value (i.e. "16px" or "1.5rem") into pixels.
|
|
75
|
+
* @param size The CSS size string to parse.
|
|
76
|
+
* @param el The element to use for rem reference if needed. Defaults to the root element.
|
|
77
|
+
* @returns The equivalent value in pixels.
|
|
78
|
+
*/
|
|
79
|
+
declare function parseCSSSize(size: string, el?: HTMLElement): number;
|
|
55
80
|
/** Compare two URLs after normalizing origin, pathname, and separators.
|
|
56
81
|
* @param src1 First URL or path.
|
|
57
82
|
* @param src2 Second URL or path.
|
|
@@ -107,7 +132,7 @@ declare const deepBreath: (w?: Window & typeof globalThis) => Promise<unknown>;
|
|
|
107
132
|
declare function bindCleanupToSignal<Cb extends () => any>(cleanup: Cb, signal?: AbortSignal): Cb;
|
|
108
133
|
|
|
109
134
|
/** Exhaustive Selector used for interactive, tabbable UI controls. */
|
|
110
|
-
declare const INTERACTIVE_SELECTOR = "button,[href],input,
|
|
135
|
+
declare const INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable='true'],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
111
136
|
/** Check whether an event target points to an interactive element. */
|
|
112
137
|
declare const isInteractive: (target: EventTarget | null) => target is HTMLElement;
|
|
113
138
|
/** Resource type accepted by loadResource. */
|
|
@@ -143,11 +168,6 @@ declare const VIRTUAL_RESOURCE: symbol;
|
|
|
143
168
|
* @returns Promise resolving to the created element or void.
|
|
144
169
|
*/
|
|
145
170
|
declare function loadResource(req: string | symbol, type?: ResourceType, { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts, retryKey }?: LoadResourceOptions, w?: Window & typeof globalThis): Promise<HTMLElement | void>;
|
|
146
|
-
/** Get the currently active element, traversing into shadow roots if necessary.
|
|
147
|
-
* @param root Root node to start searching from, defaults to the main document.
|
|
148
|
-
* @returns The active element or null if none found.
|
|
149
|
-
*/
|
|
150
|
-
declare function getActiveElement(root?: Document | ShadowRoot): Element | null;
|
|
151
171
|
|
|
152
172
|
/** Format a file size for display.
|
|
153
173
|
* @param size Size in bytes.
|
|
@@ -157,4 +177,4 @@ declare function getActiveElement(root?: Document | ShadowRoot): Element | null;
|
|
|
157
177
|
*/
|
|
158
178
|
declare function formatSize(bytes: number, decimals?: number, base?: number): string;
|
|
159
179
|
|
|
160
|
-
export { INTERACTIVE_SELECTOR, type LimitedHandle, type LimitedOptions, type LoadResourceOptions, type ResourceType, VIRTUAL_RESOURCE, bindCleanupToSignal, breath, deepBreath, formatSize,
|
|
180
|
+
export { INTERACTIVE_SELECTOR, type LimitedHandle, type LimitedOptions, type LoadResourceOptions, type ResourceType, VIRTUAL_RESOURCE, bindCleanupToSignal, breath, deepBreath, formatSize, inBoolArrOpt, isArr, isBool, isDef, isFunc, isInteractive, isIter, isNum, isPOJO, isSameURL, isStr, isSym, limited, loadResource, mockAsync, parseCSSSize, parseCSSTime, pxToRem, remToPx, uid };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { A as ArrowNavigationHandle } from './arrowNavigation-VenvPI4H.js';
|
|
2
2
|
import { S as ScrollAssistHandle } from './scrollAssist-y9wFmYgt.js';
|
|
3
3
|
export { NIL, NOOP } from 'sia-reactor';
|
|
4
|
-
export { KeyStruct, assignEl, bindAllMethods, clamp, cleanKeyCombo, createEl, formatKeyForDisplay, formatKeyShortcutsForDisplay, getTermsForKey, guardAllMethods, guardMethod, isObj, keyEventAllowed, keysSettings, matchKeys, onAllMethods, parseForARIAKS, parseKeyCombo, requestAnimationFrame, setInterval, setTimeout, stringifyKeyEvent } from 'sia-reactor/utils';
|
|
4
|
+
export { KeyStruct, assignEl, bindAllMethods, clamp, cleanKeyCombo, createEl, formatKeyForDisplay, formatKeyShortcutsForDisplay, getActiveEl, getTermsForKey, guardAllMethods, guardMethod, isObj, keyEventAllowed, keysSettings, matchKeys, onAllMethods, parseForARIAKS, parseKeyCombo, requestAnimationFrame, setInterval, setTimeout, stringifyKeyEvent } from 'sia-reactor/utils';
|
|
5
5
|
|
|
6
6
|
declare global {
|
|
7
7
|
interface T007Namespace {
|
|
@@ -10,10 +10,12 @@ declare global {
|
|
|
10
10
|
_resourceCache: Partial<Record<string, Promise<HTMLElement | void>>>;
|
|
11
11
|
_ftrappers?: WeakMap<HTMLElement, () => void>;
|
|
12
12
|
_outsiders?: WeakMap<HTMLElement, () => void>;
|
|
13
|
-
|
|
13
|
+
_arrownavs?: WeakMap<HTMLElement, ArrowNavigationHandle>;
|
|
14
14
|
_scrollers?: WeakMap<HTMLElement, ScrollAssistHandle>;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
_ftrappers_stacks?: WeakMap<EventTarget, HTMLElement[]>;
|
|
16
|
+
_outsiders_stacks?: WeakMap<EventTarget, HTMLElement[]>;
|
|
17
|
+
_scrollers_r_observer?: ResizeObserver;
|
|
18
|
+
_scrollers_m_observer?: MutationObserver;
|
|
17
19
|
}
|
|
18
20
|
interface Window {
|
|
19
21
|
/** Shared T007 namespace. */
|
|
@@ -52,6 +54,29 @@ declare function inBoolArrOpt(opt: any, str: string): boolean;
|
|
|
52
54
|
* @returns A browser-safe unique id string.
|
|
53
55
|
*/
|
|
54
56
|
declare function uid(prefix?: string): string;
|
|
57
|
+
/** Convert a rem value to pixels based on the font size of a given element.
|
|
58
|
+
* @param rem The rem value to convert.
|
|
59
|
+
* @param el The element to use for font size reference. Defaults to the root element.
|
|
60
|
+
* @returns The equivalent pixel value.
|
|
61
|
+
*/
|
|
62
|
+
declare function remToPx(rem: number, el?: HTMLElement): number;
|
|
63
|
+
/** Convert a pixel value to rem based on the font size of a given element.
|
|
64
|
+
* @param px The pixel value to convert.
|
|
65
|
+
* @param el The element to use for font size reference. Defaults to the root element.
|
|
66
|
+
* @returns The equivalent rem value.
|
|
67
|
+
*/
|
|
68
|
+
declare function pxToRem(px: number, el?: HTMLElement): number;
|
|
69
|
+
/** Parse a CSS time value (e.g. "200ms", "0.5s") into milliseconds.
|
|
70
|
+
* @param time The CSS time string to parse.
|
|
71
|
+
* @returns The equivalent time in milliseconds.
|
|
72
|
+
*/
|
|
73
|
+
declare function parseCSSTime(time: string): number;
|
|
74
|
+
/** Parse a CSS size value (i.e. "16px" or "1.5rem") into pixels.
|
|
75
|
+
* @param size The CSS size string to parse.
|
|
76
|
+
* @param el The element to use for rem reference if needed. Defaults to the root element.
|
|
77
|
+
* @returns The equivalent value in pixels.
|
|
78
|
+
*/
|
|
79
|
+
declare function parseCSSSize(size: string, el?: HTMLElement): number;
|
|
55
80
|
/** Compare two URLs after normalizing origin, pathname, and separators.
|
|
56
81
|
* @param src1 First URL or path.
|
|
57
82
|
* @param src2 Second URL or path.
|
|
@@ -107,7 +132,7 @@ declare const deepBreath: (w?: Window & typeof globalThis) => Promise<unknown>;
|
|
|
107
132
|
declare function bindCleanupToSignal<Cb extends () => any>(cleanup: Cb, signal?: AbortSignal): Cb;
|
|
108
133
|
|
|
109
134
|
/** Exhaustive Selector used for interactive, tabbable UI controls. */
|
|
110
|
-
declare const INTERACTIVE_SELECTOR = "button,[href],input,
|
|
135
|
+
declare const INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable='true'],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
111
136
|
/** Check whether an event target points to an interactive element. */
|
|
112
137
|
declare const isInteractive: (target: EventTarget | null) => target is HTMLElement;
|
|
113
138
|
/** Resource type accepted by loadResource. */
|
|
@@ -143,11 +168,6 @@ declare const VIRTUAL_RESOURCE: symbol;
|
|
|
143
168
|
* @returns Promise resolving to the created element or void.
|
|
144
169
|
*/
|
|
145
170
|
declare function loadResource(req: string | symbol, type?: ResourceType, { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts, retryKey }?: LoadResourceOptions, w?: Window & typeof globalThis): Promise<HTMLElement | void>;
|
|
146
|
-
/** Get the currently active element, traversing into shadow roots if necessary.
|
|
147
|
-
* @param root Root node to start searching from, defaults to the main document.
|
|
148
|
-
* @returns The active element or null if none found.
|
|
149
|
-
*/
|
|
150
|
-
declare function getActiveElement(root?: Document | ShadowRoot): Element | null;
|
|
151
171
|
|
|
152
172
|
/** Format a file size for display.
|
|
153
173
|
* @param size Size in bytes.
|
|
@@ -157,4 +177,4 @@ declare function getActiveElement(root?: Document | ShadowRoot): Element | null;
|
|
|
157
177
|
*/
|
|
158
178
|
declare function formatSize(bytes: number, decimals?: number, base?: number): string;
|
|
159
179
|
|
|
160
|
-
export { INTERACTIVE_SELECTOR, type LimitedHandle, type LimitedOptions, type LoadResourceOptions, type ResourceType, VIRTUAL_RESOURCE, bindCleanupToSignal, breath, deepBreath, formatSize,
|
|
180
|
+
export { INTERACTIVE_SELECTOR, type LimitedHandle, type LimitedOptions, type LoadResourceOptions, type ResourceType, VIRTUAL_RESOURCE, bindCleanupToSignal, breath, deepBreath, formatSize, inBoolArrOpt, isArr, isBool, isDef, isFunc, isInteractive, isIter, isNum, isPOJO, isSameURL, isStr, isSym, limited, loadResource, mockAsync, parseCSSSize, parseCSSTime, pxToRem, remToPx, uid };
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
formatKeyForDisplay,
|
|
15
15
|
formatKeyShortcutsForDisplay,
|
|
16
16
|
formatSize,
|
|
17
|
-
|
|
17
|
+
getActiveEl,
|
|
18
18
|
getTermsForKey,
|
|
19
19
|
guardAllMethods,
|
|
20
20
|
guardMethod,
|
|
@@ -37,14 +37,18 @@ import {
|
|
|
37
37
|
matchKeys,
|
|
38
38
|
mockAsync,
|
|
39
39
|
onAllMethods,
|
|
40
|
+
parseCSSSize,
|
|
41
|
+
parseCSSTime,
|
|
40
42
|
parseForARIAKS,
|
|
41
43
|
parseKeyCombo,
|
|
44
|
+
pxToRem,
|
|
45
|
+
remToPx,
|
|
42
46
|
requestAnimationFrame,
|
|
43
47
|
setInterval,
|
|
44
48
|
setTimeout,
|
|
45
49
|
stringifyKeyEvent,
|
|
46
50
|
uid
|
|
47
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-N5KX6IW4.js";
|
|
48
52
|
export {
|
|
49
53
|
INTERACTIVE_SELECTOR,
|
|
50
54
|
NIL,
|
|
@@ -61,7 +65,7 @@ export {
|
|
|
61
65
|
formatKeyForDisplay,
|
|
62
66
|
formatKeyShortcutsForDisplay,
|
|
63
67
|
formatSize,
|
|
64
|
-
|
|
68
|
+
getActiveEl,
|
|
65
69
|
getTermsForKey,
|
|
66
70
|
guardAllMethods,
|
|
67
71
|
guardMethod,
|
|
@@ -84,8 +88,12 @@ export {
|
|
|
84
88
|
matchKeys,
|
|
85
89
|
mockAsync,
|
|
86
90
|
onAllMethods,
|
|
91
|
+
parseCSSSize,
|
|
92
|
+
parseCSSTime,
|
|
87
93
|
parseForARIAKS,
|
|
88
94
|
parseKeyCombo,
|
|
95
|
+
pxToRem,
|
|
96
|
+
remToPx,
|
|
89
97
|
requestAnimationFrame,
|
|
90
98
|
setInterval,
|
|
91
99
|
setTimeout,
|
|
@@ -4,12 +4,12 @@ interface OutsideClickConfig {
|
|
|
4
4
|
/** Callback invoked when an outside interaction is detected. Defaults to `()=>{}`. */
|
|
5
5
|
onOutsideClick?: (e: MouseEvent | TouchEvent | KeyboardEvent | FocusEvent) => void;
|
|
6
6
|
/** Whether pointer/touch outside interactions should trigger callback. Defaults to `true`. */
|
|
7
|
-
|
|
7
|
+
outOnClick?: boolean;
|
|
8
8
|
/** Whether Escape key should trigger callback. Defaults to `true`. */
|
|
9
|
-
|
|
9
|
+
outOnEscape?: boolean;
|
|
10
10
|
/** Whether focus leaving the container should trigger callback. Defaults to `false`. */
|
|
11
|
-
|
|
12
|
-
/** Allow interactive elements
|
|
11
|
+
outOnFocusOut?: boolean;
|
|
12
|
+
/** Allow interactive elements including outsiders to bypass click callback. Defaults to `false`. */
|
|
13
13
|
allowInputs?: boolean;
|
|
14
14
|
/** Optional root used to scope focus listeners to an element instead of the window. Defaults to `window`. */
|
|
15
15
|
root?: HTMLElement | Document | Window;
|
|
@@ -19,7 +19,7 @@ interface OutsideClickConfig {
|
|
|
19
19
|
capture?: boolean;
|
|
20
20
|
}
|
|
21
21
|
/** Hook to attach outside-click, escape, and optional focus-out handling to an element. */
|
|
22
|
-
declare function initOutsideClick(el: HTMLElement, { enabled, onOutsideClick,
|
|
22
|
+
declare function initOutsideClick(el: HTMLElement, { enabled, onOutsideClick, outOnClick, outOnEscape, outOnFocusOut, allowInputs, root, scoped, capture }?: OutsideClickConfig): (() => void) | void;
|
|
23
23
|
/** Remove outside-click handling from an element. */
|
|
24
24
|
declare const removeOutsideClick: (el: HTMLElement) => void | undefined;
|
|
25
25
|
|
|
@@ -4,12 +4,12 @@ interface OutsideClickConfig {
|
|
|
4
4
|
/** Callback invoked when an outside interaction is detected. Defaults to `()=>{}`. */
|
|
5
5
|
onOutsideClick?: (e: MouseEvent | TouchEvent | KeyboardEvent | FocusEvent) => void;
|
|
6
6
|
/** Whether pointer/touch outside interactions should trigger callback. Defaults to `true`. */
|
|
7
|
-
|
|
7
|
+
outOnClick?: boolean;
|
|
8
8
|
/** Whether Escape key should trigger callback. Defaults to `true`. */
|
|
9
|
-
|
|
9
|
+
outOnEscape?: boolean;
|
|
10
10
|
/** Whether focus leaving the container should trigger callback. Defaults to `false`. */
|
|
11
|
-
|
|
12
|
-
/** Allow interactive elements
|
|
11
|
+
outOnFocusOut?: boolean;
|
|
12
|
+
/** Allow interactive elements including outsiders to bypass click callback. Defaults to `false`. */
|
|
13
13
|
allowInputs?: boolean;
|
|
14
14
|
/** Optional root used to scope focus listeners to an element instead of the window. Defaults to `window`. */
|
|
15
15
|
root?: HTMLElement | Document | Window;
|
|
@@ -19,7 +19,7 @@ interface OutsideClickConfig {
|
|
|
19
19
|
capture?: boolean;
|
|
20
20
|
}
|
|
21
21
|
/** Hook to attach outside-click, escape, and optional focus-out handling to an element. */
|
|
22
|
-
declare function initOutsideClick(el: HTMLElement, { enabled, onOutsideClick,
|
|
22
|
+
declare function initOutsideClick(el: HTMLElement, { enabled, onOutsideClick, outOnClick, outOnEscape, outOnFocusOut, allowInputs, root, scoped, capture }?: OutsideClickConfig): (() => void) | void;
|
|
23
23
|
/** Remove outside-click handling from an element. */
|
|
24
24
|
declare const removeOutsideClick: (el: HTMLElement) => void | undefined;
|
|
25
25
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t007/utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.27",
|
|
4
4
|
"description": "High-performance, zero-dependency utility functions for the t007 ecosystem.",
|
|
5
5
|
"author": "Oketade Oluwatobiloba <tobioketade007@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"react-dom": "^18.3.1"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@t007/input": "^0.0.
|
|
78
|
-
"sia-reactor": "^0.0.
|
|
77
|
+
"@t007/input": "^0.0.25",
|
|
78
|
+
"sia-reactor": "^0.0.31"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
81
|
"react": "^18.0.0"
|