@t007/utils 0.0.25 → 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/index.d.cts CHANGED
@@ -1,75 +1,21 @@
1
- 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';
2
-
3
- /** Configuration for the vertical edge-scrolling helper. */
4
- interface ScrolleratorOptions {
5
- /** Starting lines-per-second speed. */
6
- baseSpeed?: number;
7
- /** Maximum accelerated speed. */
8
- maxSpeed?: number;
9
- /** Delay before acceleration kicks in. */
10
- stepDelay?: number;
11
- /** Base frame rate used to estimate movement. */
12
- baseRate?: number;
13
- /** Approximate line height in pixels. */
14
- lineHeight?: number;
15
- /** Edge margin that triggers scrolling. */
16
- margin?: number;
17
- /** Scroll container or window target. */
18
- car?: Window | HTMLElement;
19
- }
20
- /** Scrolling controls returned by initVScrollerator. */
21
- interface Scrollerator {
22
- /** Trigger a scroll frame and return the computed distance. */
23
- drive: (clientY: number, brake?: boolean, offsetY?: number) => number;
24
- /** Reset speed and timers. */
25
- reset: () => void;
26
- }
27
- /** Create an edge-driven vertical scrolling controller.
28
- * @param options Scrollerator configuration.
29
- * @returns Drive and reset controls for the controller.
30
- */
31
- declare function initVScrollerator({ baseSpeed, maxSpeed, stepDelay, baseRate, lineHeight, margin, car }?: ScrolleratorOptions): Scrollerator;
32
- /** Scroll assist control object returned by initScrollAssist. */
33
- interface ScrollAssistControl {
34
- /** Recompute assist visibility. */
35
- update: () => void;
36
- /** Tear down observers and assist elements. */
37
- destroy: () => void;
38
- }
39
- /** Configuration for scroll assist overlays. */
40
- interface ScrollAssistOptions {
41
- /** Scroll speed in pixels per second. */
42
- pxPerSecond?: number;
43
- /** Class name applied to assist overlays. */
44
- assistClassName?: string;
45
- /** Enable vertical assist overlays. */
46
- vertical?: boolean;
47
- /** Enable horizontal assist overlays. */
48
- horizontal?: boolean;
49
- }
50
- /** Attach directional scroll assist overlays to an element.
51
- * @param el Scrollable element to enhance.
52
- * @param options Scroll assist configuration.
53
- * @returns Scroll assist controls or void when the element is already managed.
54
- */
55
- declare function initScrollAssist(el: HTMLElement, { pxPerSecond, assistClassName, vertical, horizontal }?: ScrollAssistOptions): ScrollAssistControl | void;
56
- /** Remove scroll assist from an element.
57
- * @param el Target element.
58
- */
59
- declare const removeScrollAssist: (el: HTMLElement) => void | undefined;
1
+ import { A as ArrowNavigationHandle } from './arrowNavigation-DK8mqVOk.cjs';
2
+ import { S as ScrollAssistHandle } from './scrollAssist-y9wFmYgt.cjs';
3
+ export { NIL, NOOP } from 'sia-reactor';
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';
60
5
 
61
6
  declare global {
62
7
  interface T007Namespace {
63
8
  /** Symbol used to mark virtual resources that should not load a real asset. */
64
9
  VIRTUAL_RESOURCE: symbol;
65
- /** Cache used to deduplicate resource loading promises. */
66
10
  _resourceCache: Partial<Record<string, Promise<HTMLElement | void>>>;
67
- /** Active scroll assist controllers keyed by element. */
68
- _scrollers?: WeakMap<HTMLElement, ScrollAssistControl>;
69
- /** Resize observer used by scroll assist controllers. */
70
- _scroller_r_observer?: ResizeObserver;
71
- /** Mutation observer used by scroll assist controllers. */
72
- _scroller_m_observer?: MutationObserver;
11
+ _ftrappers?: WeakMap<HTMLElement, () => void>;
12
+ _outsiders?: WeakMap<HTMLElement, () => void>;
13
+ _arrownavs?: WeakMap<HTMLElement, ArrowNavigationHandle>;
14
+ _scrollers?: WeakMap<HTMLElement, ScrollAssistHandle>;
15
+ _ftrappers_stacks?: WeakMap<EventTarget, HTMLElement[]>;
16
+ _outsiders_stacks?: WeakMap<EventTarget, HTMLElement[]>;
17
+ _scrollers_r_observer?: ResizeObserver;
18
+ _scrollers_m_observer?: MutationObserver;
73
19
  }
74
20
  interface Window {
75
21
  /** Shared T007 namespace. */
@@ -108,6 +54,29 @@ declare function inBoolArrOpt(opt: any, str: string): boolean;
108
54
  * @returns A browser-safe unique id string.
109
55
  */
110
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;
111
80
  /** Compare two URLs after normalizing origin, pathname, and separators.
112
81
  * @param src1 First URL or path.
113
82
  * @param src2 Second URL or path.
@@ -162,6 +131,10 @@ declare const deepBreath: (w?: Window & typeof globalThis) => Promise<unknown>;
162
131
  */
163
132
  declare function bindCleanupToSignal<Cb extends () => any>(cleanup: Cb, signal?: AbortSignal): Cb;
164
133
 
134
+ /** Exhaustive Selector used for interactive, tabbable UI controls. */
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] *)";
136
+ /** Check whether an event target points to an interactive element. */
137
+ declare const isInteractive: (target: EventTarget | null) => target is HTMLElement;
165
138
  /** Resource type accepted by loadResource. */
166
139
  type ResourceType = "style" | "script" | string;
167
140
  /** Options used when loading a script or stylesheet resource. */
@@ -185,7 +158,6 @@ type LoadResourceOptions = Partial<{
185
158
  /** Cache-busting retry token key. */
186
159
  retryKey: boolean | string;
187
160
  }>;
188
-
189
161
  /** Virtual resource marker used to skip real network loading. */
190
162
  declare const VIRTUAL_RESOURCE: symbol;
191
163
  /** Load a stylesheet or script into the current document with retry support.
@@ -197,4 +169,12 @@ declare const VIRTUAL_RESOURCE: symbol;
197
169
  */
198
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>;
199
171
 
200
- export { type LimitedHandle, type LimitedOptions, type LoadResourceOptions, type ResourceType, type ScrollAssistControl, VIRTUAL_RESOURCE, bindCleanupToSignal, breath, deepBreath, inBoolArrOpt, initScrollAssist, initVScrollerator, isArr, isBool, isDef, isFunc, isIter, isNum, isPOJO, isSameURL, isStr, isSym, limited, loadResource, mockAsync, removeScrollAssist, uid };
172
+ /** Format a file size for display.
173
+ * @param size Size in bytes.
174
+ * @param decimals Decimal precision.
175
+ * @param base Size base, usually 1000 or 1024.
176
+ * @returns Human-readable size string, i.e., "1.234 KB".
177
+ */
178
+ declare function formatSize(bytes: number, decimals?: number, base?: number): string;
179
+
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,75 +1,21 @@
1
- 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';
2
-
3
- /** Configuration for the vertical edge-scrolling helper. */
4
- interface ScrolleratorOptions {
5
- /** Starting lines-per-second speed. */
6
- baseSpeed?: number;
7
- /** Maximum accelerated speed. */
8
- maxSpeed?: number;
9
- /** Delay before acceleration kicks in. */
10
- stepDelay?: number;
11
- /** Base frame rate used to estimate movement. */
12
- baseRate?: number;
13
- /** Approximate line height in pixels. */
14
- lineHeight?: number;
15
- /** Edge margin that triggers scrolling. */
16
- margin?: number;
17
- /** Scroll container or window target. */
18
- car?: Window | HTMLElement;
19
- }
20
- /** Scrolling controls returned by initVScrollerator. */
21
- interface Scrollerator {
22
- /** Trigger a scroll frame and return the computed distance. */
23
- drive: (clientY: number, brake?: boolean, offsetY?: number) => number;
24
- /** Reset speed and timers. */
25
- reset: () => void;
26
- }
27
- /** Create an edge-driven vertical scrolling controller.
28
- * @param options Scrollerator configuration.
29
- * @returns Drive and reset controls for the controller.
30
- */
31
- declare function initVScrollerator({ baseSpeed, maxSpeed, stepDelay, baseRate, lineHeight, margin, car }?: ScrolleratorOptions): Scrollerator;
32
- /** Scroll assist control object returned by initScrollAssist. */
33
- interface ScrollAssistControl {
34
- /** Recompute assist visibility. */
35
- update: () => void;
36
- /** Tear down observers and assist elements. */
37
- destroy: () => void;
38
- }
39
- /** Configuration for scroll assist overlays. */
40
- interface ScrollAssistOptions {
41
- /** Scroll speed in pixels per second. */
42
- pxPerSecond?: number;
43
- /** Class name applied to assist overlays. */
44
- assistClassName?: string;
45
- /** Enable vertical assist overlays. */
46
- vertical?: boolean;
47
- /** Enable horizontal assist overlays. */
48
- horizontal?: boolean;
49
- }
50
- /** Attach directional scroll assist overlays to an element.
51
- * @param el Scrollable element to enhance.
52
- * @param options Scroll assist configuration.
53
- * @returns Scroll assist controls or void when the element is already managed.
54
- */
55
- declare function initScrollAssist(el: HTMLElement, { pxPerSecond, assistClassName, vertical, horizontal }?: ScrollAssistOptions): ScrollAssistControl | void;
56
- /** Remove scroll assist from an element.
57
- * @param el Target element.
58
- */
59
- declare const removeScrollAssist: (el: HTMLElement) => void | undefined;
1
+ import { A as ArrowNavigationHandle } from './arrowNavigation-VenvPI4H.js';
2
+ import { S as ScrollAssistHandle } from './scrollAssist-y9wFmYgt.js';
3
+ export { NIL, NOOP } from 'sia-reactor';
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';
60
5
 
61
6
  declare global {
62
7
  interface T007Namespace {
63
8
  /** Symbol used to mark virtual resources that should not load a real asset. */
64
9
  VIRTUAL_RESOURCE: symbol;
65
- /** Cache used to deduplicate resource loading promises. */
66
10
  _resourceCache: Partial<Record<string, Promise<HTMLElement | void>>>;
67
- /** Active scroll assist controllers keyed by element. */
68
- _scrollers?: WeakMap<HTMLElement, ScrollAssistControl>;
69
- /** Resize observer used by scroll assist controllers. */
70
- _scroller_r_observer?: ResizeObserver;
71
- /** Mutation observer used by scroll assist controllers. */
72
- _scroller_m_observer?: MutationObserver;
11
+ _ftrappers?: WeakMap<HTMLElement, () => void>;
12
+ _outsiders?: WeakMap<HTMLElement, () => void>;
13
+ _arrownavs?: WeakMap<HTMLElement, ArrowNavigationHandle>;
14
+ _scrollers?: WeakMap<HTMLElement, ScrollAssistHandle>;
15
+ _ftrappers_stacks?: WeakMap<EventTarget, HTMLElement[]>;
16
+ _outsiders_stacks?: WeakMap<EventTarget, HTMLElement[]>;
17
+ _scrollers_r_observer?: ResizeObserver;
18
+ _scrollers_m_observer?: MutationObserver;
73
19
  }
74
20
  interface Window {
75
21
  /** Shared T007 namespace. */
@@ -108,6 +54,29 @@ declare function inBoolArrOpt(opt: any, str: string): boolean;
108
54
  * @returns A browser-safe unique id string.
109
55
  */
110
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;
111
80
  /** Compare two URLs after normalizing origin, pathname, and separators.
112
81
  * @param src1 First URL or path.
113
82
  * @param src2 Second URL or path.
@@ -162,6 +131,10 @@ declare const deepBreath: (w?: Window & typeof globalThis) => Promise<unknown>;
162
131
  */
163
132
  declare function bindCleanupToSignal<Cb extends () => any>(cleanup: Cb, signal?: AbortSignal): Cb;
164
133
 
134
+ /** Exhaustive Selector used for interactive, tabbable UI controls. */
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] *)";
136
+ /** Check whether an event target points to an interactive element. */
137
+ declare const isInteractive: (target: EventTarget | null) => target is HTMLElement;
165
138
  /** Resource type accepted by loadResource. */
166
139
  type ResourceType = "style" | "script" | string;
167
140
  /** Options used when loading a script or stylesheet resource. */
@@ -185,7 +158,6 @@ type LoadResourceOptions = Partial<{
185
158
  /** Cache-busting retry token key. */
186
159
  retryKey: boolean | string;
187
160
  }>;
188
-
189
161
  /** Virtual resource marker used to skip real network loading. */
190
162
  declare const VIRTUAL_RESOURCE: symbol;
191
163
  /** Load a stylesheet or script into the current document with retry support.
@@ -197,4 +169,12 @@ declare const VIRTUAL_RESOURCE: symbol;
197
169
  */
198
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>;
199
171
 
200
- export { type LimitedHandle, type LimitedOptions, type LoadResourceOptions, type ResourceType, type ScrollAssistControl, VIRTUAL_RESOURCE, bindCleanupToSignal, breath, deepBreath, inBoolArrOpt, initScrollAssist, initVScrollerator, isArr, isBool, isDef, isFunc, isIter, isNum, isPOJO, isSameURL, isStr, isSym, limited, loadResource, mockAsync, removeScrollAssist, uid };
172
+ /** Format a file size for display.
173
+ * @param size Size in bytes.
174
+ * @param decimals Decimal precision.
175
+ * @param base Size base, usually 1000 or 1024.
176
+ * @returns Human-readable size string, i.e., "1.234 KB".
177
+ */
178
+ declare function formatSize(bytes: number, decimals?: number, base?: number): string;
179
+
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
@@ -1,214 +1,58 @@
1
- // src/core/dom.ts
2
- import { createEl, assignEl } from "sia-reactor/utils";
3
- var VIRTUAL_RESOURCE = /* @__PURE__ */ Symbol.for("T007_VIRTUAL_RESOURCE");
4
- function loadResource(req, type = "style", { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, w = window) {
5
- w.t007 ??= {}, w.t007._resourceCache ??= {};
6
- if (req === VIRTUAL_RESOURCE || isSym(req)) return Promise.resolve();
7
- const src = req;
8
- if (w.t007._resourceCache[src]) return w.t007._resourceCache[src];
9
- const existing = type === "script" ? Array.prototype.find.call(w.document.scripts, (s) => isSameURL(s.src, src)) : type === "style" ? Array.prototype.find.call(w.document.styleSheets, (s) => isSameURL(s.href, src)) : null;
10
- if (existing) return w.t007._resourceCache[src] = Promise.resolve(existing);
11
- w.t007._resourceCache[src] = new Promise((resolve, reject) => {
12
- (function tryLoad(remaining, el) {
13
- const onerror = () => {
14
- el?.remove?.();
15
- if (remaining > 1) {
16
- setTimeout(tryLoad, 1e3, remaining - 1);
17
- console.warn(`Retrying ${type} load (${attempts - remaining + 1}): ${src}...`);
18
- } else {
19
- delete w.t007._resourceCache[src];
20
- reject(new Error(`${type} load failed after ${attempts} attempts: ${src}`));
21
- }
22
- };
23
- const url = retryKey && remaining < attempts ? `${src}${src.includes("?") ? "&" : "?"}_${retryKey}=${Date.now()}` : src;
24
- if (type === "script") w.document.body.append(el = createEl("script", { src: url, type: module ? "module" : "text/javascript", crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
25
- else if (type === "style") w.document.head.append(el = createEl("link", { rel: "stylesheet", href: url, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
26
- else reject(new Error(`Unsupported resource type: ${type}`));
27
- })(attempts);
28
- });
29
- return w.t007._resourceCache[src];
30
- }
31
-
32
- // src/core/obj.ts
33
- import { isObj } from "sia-reactor/utils";
34
- function isDef(val) {
35
- return "undefined" !== typeof val;
36
- }
37
- function isSym(val) {
38
- return "symbol" === typeof val;
39
- }
40
- function isBool(val) {
41
- return "boolean" === typeof val;
42
- }
43
- function isNum(val) {
44
- return "number" === typeof val;
45
- }
46
- function isStr(val) {
47
- return "string" === typeof val;
48
- }
49
- function isArr(obj) {
50
- return Array.isArray(obj);
51
- }
52
- function isPOJO(obj, crossRealms = false, typecheck = true) {
53
- return (typecheck ? isObj(obj, false) : true) && (crossRealms ? Object.prototype.toString.call(obj) === "[object Object]" : obj.constructor === Object);
54
- }
55
- function isIter(obj) {
56
- return obj != null && "function" === typeof obj[Symbol.iterator];
57
- }
58
- function isFunc(val) {
59
- return "function" === typeof val;
60
- }
61
- function inBoolArrOpt(opt, str) {
62
- return opt?.includes?.(str) ?? opt;
63
- }
64
-
65
- // src/core/num.ts
66
- import { clamp } from "sia-reactor/utils";
67
-
68
- // src/core/str.ts
69
- function uid(prefix = "") {
70
- return prefix + Date.now().toString(36) + "_" + performance.now().toString(36).replace(".", "") + "_" + Math.random().toString(36).slice(2);
71
- }
72
- function isSameURL(src1, src2) {
73
- if (!isStr(src1) || !isStr(src2) || !src1 || !src2) return false;
74
- try {
75
- const u1 = new URL(src1, window.location.href), u2 = new URL(src2, window.location.href);
76
- return decodeURIComponent(u1.origin + u1.pathname) === decodeURIComponent(u2.origin + u2.pathname);
77
- } catch {
78
- return src1.replace(/\\/g, "/").split("?")[0].trim() === src2.replace(/\\/g, "/").split("?")[0].trim();
79
- }
80
- }
81
-
82
- // src/core/fn.ts
83
- import { setTimeout as setTimeout2, setInterval, requestAnimationFrame as requestAnimationFrame2 } from "sia-reactor/utils";
84
- function limited(FN_KEY, fn, opts = {}) {
85
- let count = 0, { key, maxTimes: max = 1 } = isStr(opts) ? { key: opts } : opts;
86
- const getReg = () => JSON.parse(localStorage.getItem(FN_KEY) || "{}"), setReg = (r) => localStorage.setItem(FN_KEY, JSON.stringify(r));
87
- const handle = (...args) => {
88
- if (!key) return count++ < max ? fn(...args) : void 0;
89
- const r = getReg(), c = r[key] || 0;
90
- return c < max ? (r[key] = c + 1, setReg(r), fn(...args)) : void 0;
91
- };
92
- handle.left = max - (handle.count = count);
93
- handle.reset = () => (count = 0, key && ((r) => (delete r[key], setReg(r)))(getReg()));
94
- handle.block = () => (count = max, key && ((r) => (r[key] = max, setReg(r)))(getReg()));
95
- return handle;
96
- }
97
- var mockAsync = (timeout = 250) => new Promise((resolve) => setTimeout(resolve, timeout));
98
- var breath = (w = window) => new Promise((res) => w.requestAnimationFrame(res));
99
- var deepBreath = (w = window) => new Promise((res) => w.requestAnimationFrame(() => w.requestAnimationFrame(res)));
100
- function bindCleanupToSignal(cleanup, signal) {
101
- signal?.aborted ? cleanup() : signal?.addEventListener("abort", cleanup, { once: true });
102
- if (signal && !signal.aborted) cleanup = (() => (signal.removeEventListener("abort", cleanup), cleanup()));
103
- return cleanup;
104
- }
105
-
106
- // src/core/keys.ts
107
- import { parseKeyCombo, stringifyKeyEvent, cleanKeyCombo, matchKeys, getTermsForKey, keyEventAllowed, formatKeyForDisplay, formatKeyShortcutsForDisplay, parseForARIAKS } from "sia-reactor/utils";
108
-
109
- // src/mixins/methd.ts
110
- import { onAllMethods, bindAllMethods, guardAllMethods, guardMethod } from "sia-reactor/utils";
111
-
112
- // src/quirks/scroll.ts
113
- function initVScrollerator({ baseSpeed = 3, maxSpeed = 10, stepDelay = 2e3, baseRate = 16, lineHeight = 80, margin = 80, car = window } = {}) {
114
- let linesPerSec = baseSpeed, accelId = null, lastTime = null;
115
- const drive = (clientY, brake = false, offsetY = 0) => {
116
- if (car !== window) clientY -= offsetY;
117
- const now = performance.now(), speed = linesPerSec * lineHeight * ((lastTime ? now - lastTime : baseRate) / 1e3);
118
- if (!brake && (clientY < margin || clientY > (car.innerHeight ?? car.offsetHeight) - margin)) {
119
- accelId === null ? accelId = setTimeout(() => linesPerSec += 1, stepDelay) : linesPerSec > baseSpeed && (linesPerSec = Math.min(linesPerSec + 1, maxSpeed));
120
- car.scrollBy?.(0, clientY < margin ? -speed : speed);
121
- } else reset();
122
- return lastTime = !brake ? now : null, speed;
123
- };
124
- const reset = () => (accelId && clearTimeout(accelId), accelId = null, linesPerSec = baseSpeed, lastTime = null);
125
- return { drive, reset };
126
- }
127
- function initScrollAssist(el, { pxPerSecond = 80, assistClassName = "t007-scroll-assist", vertical = true, horizontal = true } = {}) {
128
- t007._scrollers ??= /* @__PURE__ */ new WeakMap();
129
- t007._scroller_r_observer ??= new ResizeObserver((entries) => entries.forEach(({ target }) => t007._scrollers.get(target)?.update()));
130
- t007._scroller_m_observer ??= new MutationObserver((entries) => {
131
- const els = /* @__PURE__ */ new Set();
132
- for (const entry of entries) {
133
- let node = entry.target instanceof Element ? entry.target : null;
134
- while (node && !t007._scrollers.has(node)) node = node.parentElement;
135
- if (node) els.add(node);
136
- }
137
- for (const el2 of els) t007._scrollers.get(el2)?.update();
138
- });
139
- const parent = el?.parentElement;
140
- if (!parent || t007._scrollers.has(el)) return;
141
- const assist = {};
142
- let scrollId = null, last = performance.now(), assistWidth = 20, assistHeight = 20;
143
- const update = () => {
144
- const hasInteractive = !!parent.querySelector('button, a[href], input, select, textarea, [contenteditable="true"], [tabindex]:not([tabindex="-1"])');
145
- if (horizontal) {
146
- const w = assist.left?.offsetWidth || assistWidth, check = hasInteractive ? el.clientWidth < w * 2 : false;
147
- assist.left.style.display = check ? "none" : el.scrollLeft > 0 ? "block" : "none";
148
- assist.right.style.display = check ? "none" : el.scrollLeft + el.clientWidth < el.scrollWidth - 1 ? "block" : "none";
149
- assistWidth = w;
150
- }
151
- if (vertical) {
152
- const h = assist.up?.offsetHeight || assistHeight, check = hasInteractive ? el.clientHeight < h * 2 : false;
153
- assist.up.style.display = check ? "none" : el.scrollTop > 0 ? "block" : "none";
154
- assist.down.style.display = check ? "none" : el.scrollTop + el.clientHeight < el.scrollHeight - 1 ? "block" : "none";
155
- assistHeight = h;
156
- }
157
- };
158
- const scroll = (dir) => {
159
- const frame = () => {
160
- const now = performance.now(), dt = now - last;
161
- last = now;
162
- const d = pxPerSecond * dt / 1e3;
163
- if (dir === "left") el.scrollLeft = Math.max(0, el.scrollLeft - d);
164
- if (dir === "right") el.scrollLeft = Math.min(el.scrollWidth - el.clientWidth, el.scrollLeft + d);
165
- if (dir === "up") el.scrollTop = Math.max(0, el.scrollTop - d);
166
- if (dir === "down") el.scrollTop = Math.min(el.scrollHeight - el.clientHeight, el.scrollTop + d);
167
- scrollId = requestAnimationFrame(frame);
168
- };
169
- last = performance.now();
170
- frame();
171
- };
172
- const stop = () => (cancelAnimationFrame(scrollId ?? 0), scrollId = null);
173
- const addAssist = (dir) => {
174
- const div = createEl("div", { className: assistClassName }, { scrollDirection: dir }, { display: "none" });
175
- if (!div) return;
176
- ["pointerenter", "dragenter"].forEach((evt) => div.addEventListener(evt, () => scroll(dir)));
177
- ["pointerleave", "pointerup", "pointercancel", "dragleave", "dragend"].forEach((evt) => div.addEventListener(evt, stop));
178
- dir === "left" || dir === "up" ? parent.insertBefore(div, el) : parent.append(div);
179
- assist[dir] = div;
180
- };
181
- if (horizontal) ["left", "right"].forEach(addAssist);
182
- if (vertical) ["up", "down"].forEach(addAssist);
183
- el.addEventListener("scroll", update);
184
- t007._scroller_r_observer.observe(el);
185
- t007._scroller_m_observer.observe(el, { childList: true, subtree: true, characterData: true });
186
- t007._scrollers.set(el, {
187
- update,
188
- destroy() {
189
- stop();
190
- el.removeEventListener("scroll", update);
191
- t007._scroller_r_observer.unobserve(el);
192
- t007._scrollers.delete(el);
193
- Object.values(assist).forEach((a) => a.remove());
194
- }
195
- });
196
- return update(), t007._scrollers.get(el);
197
- }
198
- var removeScrollAssist = (el) => t007._scrollers.get(el)?.destroy();
199
-
200
- // src/index.ts
201
- if ("undefined" !== typeof window) {
202
- window.t007 ??= {};
203
- t007.VIRTUAL_RESOURCE = VIRTUAL_RESOURCE;
204
- window.T007_TOAST_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest`;
205
- window.T007_INPUT_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest`;
206
- window.T007_DIALOG_JS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest`;
207
- window.T007_TOAST_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/toast@latest/dist/index.min.css`;
208
- window.T007_INPUT_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/input@latest/dist/index.min.css`;
209
- window.T007_DIALOG_CSS_SRC ??= `https://cdn.jsdelivr.net/npm/@t007/dialog@latest/dist/index.min.css`;
210
- }
1
+ import {
2
+ INTERACTIVE_SELECTOR,
3
+ NIL,
4
+ NOOP,
5
+ VIRTUAL_RESOURCE,
6
+ assignEl,
7
+ bindAllMethods,
8
+ bindCleanupToSignal,
9
+ breath,
10
+ clamp,
11
+ cleanKeyCombo,
12
+ createEl,
13
+ deepBreath,
14
+ formatKeyForDisplay,
15
+ formatKeyShortcutsForDisplay,
16
+ formatSize,
17
+ getActiveEl,
18
+ getTermsForKey,
19
+ guardAllMethods,
20
+ guardMethod,
21
+ inBoolArrOpt,
22
+ isArr,
23
+ isBool,
24
+ isDef,
25
+ isFunc,
26
+ isInteractive,
27
+ isIter,
28
+ isNum,
29
+ isObj,
30
+ isPOJO,
31
+ isSameURL,
32
+ isStr,
33
+ isSym,
34
+ keyEventAllowed,
35
+ limited,
36
+ loadResource,
37
+ matchKeys,
38
+ mockAsync,
39
+ onAllMethods,
40
+ parseCSSSize,
41
+ parseCSSTime,
42
+ parseForARIAKS,
43
+ parseKeyCombo,
44
+ pxToRem,
45
+ remToPx,
46
+ requestAnimationFrame,
47
+ setInterval,
48
+ setTimeout,
49
+ stringifyKeyEvent,
50
+ uid
51
+ } from "./chunk-N5KX6IW4.js";
211
52
  export {
53
+ INTERACTIVE_SELECTOR,
54
+ NIL,
55
+ NOOP,
212
56
  VIRTUAL_RESOURCE,
213
57
  assignEl,
214
58
  bindAllMethods,
@@ -220,16 +64,17 @@ export {
220
64
  deepBreath,
221
65
  formatKeyForDisplay,
222
66
  formatKeyShortcutsForDisplay,
67
+ formatSize,
68
+ getActiveEl,
223
69
  getTermsForKey,
224
70
  guardAllMethods,
225
71
  guardMethod,
226
72
  inBoolArrOpt,
227
- initScrollAssist,
228
- initVScrollerator,
229
73
  isArr,
230
74
  isBool,
231
75
  isDef,
232
76
  isFunc,
77
+ isInteractive,
233
78
  isIter,
234
79
  isNum,
235
80
  isObj,
@@ -243,12 +88,15 @@ export {
243
88
  matchKeys,
244
89
  mockAsync,
245
90
  onAllMethods,
91
+ parseCSSSize,
92
+ parseCSSTime,
246
93
  parseForARIAKS,
247
94
  parseKeyCombo,
248
- removeScrollAssist,
249
- requestAnimationFrame2 as requestAnimationFrame,
95
+ pxToRem,
96
+ remToPx,
97
+ requestAnimationFrame,
250
98
  setInterval,
251
- setTimeout2 as setTimeout,
99
+ setTimeout,
252
100
  stringifyKeyEvent,
253
101
  uid
254
102
  };