@t007/utils 0.0.33 → 0.0.35
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/{arrowNavigation-DK8mqVOk.d.cts → arrowNavigation-B9bEdoqR.d.ts} +5 -2
- package/dist/{arrowNavigation-VenvPI4H.d.ts → arrowNavigation-zEJbo8Er.d.cts} +5 -2
- package/dist/{chunk-QJ72EQCJ.js → chunk-NX2LWYD6.js} +22 -17
- package/dist/chunk-ZALPHCSJ.js +317 -0
- package/dist/components/react.d.cts +1 -1
- package/dist/components/react.d.ts +1 -1
- package/dist/hooks/react.cjs +67 -53
- package/dist/hooks/react.d.cts +9 -6
- package/dist/hooks/react.d.ts +9 -6
- package/dist/hooks/react.js +34 -24
- package/dist/hooks/vanilla.cjs +58 -41
- package/dist/hooks/vanilla.d.cts +10 -10
- package/dist/hooks/vanilla.d.ts +10 -10
- package/dist/hooks/vanilla.js +25 -14
- package/dist/index.cjs +143 -22
- package/dist/index.d.cts +143 -16
- package/dist/index.d.ts +143 -16
- package/dist/index.js +23 -3
- package/dist/ripple-D1kGErTn.d.cts +55 -0
- package/dist/ripple-D1kGErTn.d.ts +55 -0
- package/dist/scrollAssist-BNvPnsJq.d.cts +97 -0
- package/dist/scrollAssist-BNvPnsJq.d.ts +97 -0
- package/dist/{useHighlight-DMpDCILK.d.cts → useHighlight-DYc_GF0R.d.cts} +2 -2
- package/dist/{useHighlight-DMpDCILK.d.ts → useHighlight-DYc_GF0R.d.ts} +2 -2
- package/package.json +4 -3
- package/dist/chunk-4O76EZJ4.js +0 -206
- package/dist/ripple-C5MfEErC.d.cts +0 -73
- package/dist/ripple-C5MfEErC.d.ts +0 -73
- package/dist/scrollAssist-y9wFmYgt.d.cts +0 -72
- package/dist/scrollAssist-y9wFmYgt.d.ts +0 -72
package/dist/index.cjs
CHANGED
|
@@ -21,17 +21,24 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
INTERACTIVE_SELECTOR: () => INTERACTIVE_SELECTOR,
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
KEYS_BLOCKS: () => import_utils6.KEYS_BLOCKS,
|
|
25
|
+
NIL: () => import_sia_reactor2.NIL,
|
|
26
|
+
NOOP: () => import_sia_reactor2.NOOP,
|
|
27
|
+
RAFLoop: () => RAFLoop,
|
|
26
28
|
VIRTUAL_RESOURCE: () => VIRTUAL_RESOURCE,
|
|
27
29
|
assignEl: () => import_utils.assignEl,
|
|
28
30
|
bindAllMethods: () => import_utils7.bindAllMethods,
|
|
29
31
|
bindCleanupToSignal: () => bindCleanupToSignal,
|
|
30
32
|
breath: () => breath,
|
|
33
|
+
camelize: () => camelize,
|
|
34
|
+
cancelRAFLoop: () => cancelRAFLoop,
|
|
35
|
+
capitalize: () => capitalize,
|
|
31
36
|
clamp: () => import_utils4.clamp,
|
|
32
37
|
cleanKeyCombo: () => import_utils6.cleanKeyCombo,
|
|
33
38
|
cleanURL: () => cleanURL,
|
|
34
39
|
createEl: () => import_utils.createEl,
|
|
40
|
+
createListRenderer: () => createListRenderer,
|
|
41
|
+
debounce: () => debounce,
|
|
35
42
|
deepBreath: () => deepBreath,
|
|
36
43
|
formatKeyForDisplay: () => import_utils6.formatKeyForDisplay,
|
|
37
44
|
formatKeyShortcutsForDisplay: () => import_utils6.formatKeyShortcutsForDisplay,
|
|
@@ -57,6 +64,7 @@ __export(index_exports, {
|
|
|
57
64
|
keyEventAllowed: () => import_utils6.keyEventAllowed,
|
|
58
65
|
limited: () => limited,
|
|
59
66
|
loadResource: () => loadResource,
|
|
67
|
+
longestIncreasingSubsequence: () => longestIncreasingSubsequence,
|
|
60
68
|
matchKeys: () => import_utils6.matchKeys,
|
|
61
69
|
mockAsync: () => mockAsync,
|
|
62
70
|
onAllMethods: () => import_utils7.onAllMethods,
|
|
@@ -70,49 +78,90 @@ __export(index_exports, {
|
|
|
70
78
|
setInterval: () => import_utils5.setInterval,
|
|
71
79
|
setTimeout: () => import_utils5.setTimeout,
|
|
72
80
|
stringifyKeyEvent: () => import_utils6.stringifyKeyEvent,
|
|
73
|
-
|
|
81
|
+
throttle: () => throttle,
|
|
82
|
+
uid: () => uid,
|
|
83
|
+
uncamelize: () => uncamelize
|
|
74
84
|
});
|
|
75
85
|
module.exports = __toCommonJS(index_exports);
|
|
76
86
|
|
|
77
87
|
// src/ts/core/dom.ts
|
|
78
88
|
var import_utils = require("sia-reactor/utils");
|
|
79
89
|
var import_utils2 = require("sia-reactor/utils");
|
|
80
|
-
var
|
|
90
|
+
var import_sia_reactor = require("sia-reactor");
|
|
91
|
+
var INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
81
92
|
var isInteractive = (target) => target instanceof HTMLElement && target.matches(INTERACTIVE_SELECTOR);
|
|
82
93
|
var VIRTUAL_RESOURCE = /* @__PURE__ */ Symbol.for("T007_VIRTUAL_RESOURCE");
|
|
83
|
-
function loadResource(req, type = "style", { module: module2, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {},
|
|
84
|
-
|
|
94
|
+
function loadResource(req, type = "style", { module: module2, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts = 3, retryKey = false } = {}, win = window) {
|
|
95
|
+
win.t007 ??= {}, win.t007._resourceCache ??= {};
|
|
85
96
|
if (req === VIRTUAL_RESOURCE || isSym(req)) return Promise.resolve();
|
|
86
97
|
const src = req;
|
|
87
|
-
if (
|
|
88
|
-
const existing = type === "script" ? Array.prototype.find.call(
|
|
89
|
-
if (existing) return
|
|
90
|
-
|
|
98
|
+
if (win.t007._resourceCache[src]) return win.t007._resourceCache[src];
|
|
99
|
+
const existing = type === "script" ? Array.prototype.find.call(win.document.scripts, (s) => isSameURL(s.src, src)) : type === "style" ? Array.prototype.find.call(win.document.styleSheets, (s) => isSameURL(s.href, src)) : null;
|
|
100
|
+
if (existing) return win.t007._resourceCache[src] = Promise.resolve(existing);
|
|
101
|
+
win.t007._resourceCache[src] = new Promise((resolve, reject) => {
|
|
91
102
|
(function tryLoad(remaining, el) {
|
|
92
103
|
const onerror = () => {
|
|
93
104
|
el?.remove?.();
|
|
94
105
|
if (remaining > 1) {
|
|
95
106
|
setTimeout(tryLoad, 1e3, remaining - 1);
|
|
96
|
-
console.warn(`Retrying ${type} load (${attempts - remaining + 1})
|
|
107
|
+
console.warn(`Retrying ${type} load for "${src}" (${attempts - remaining + 1})...`);
|
|
97
108
|
} else {
|
|
98
|
-
delete
|
|
99
|
-
reject(new Error(`${type} load failed
|
|
109
|
+
delete win.t007._resourceCache[src];
|
|
110
|
+
reject(new Error(`${capitalize(type)} load failed for "${src}" after ${attempts - 1} attempts`));
|
|
100
111
|
}
|
|
101
112
|
};
|
|
102
113
|
const url = retryKey && remaining < attempts ? `${src}${src.includes("?") ? "&" : "?"}_${retryKey}=${Date.now()}` : src;
|
|
103
|
-
if (type === "script")
|
|
104
|
-
else if (type === "style")
|
|
114
|
+
if (type === "script") win.document.body.append(el = (0, import_utils.createEl)("script", { src: url, type: module2 ? "module" : "text/javascript", crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
|
|
115
|
+
else if (type === "style") win.document.head.append(el = (0, import_utils.createEl)("link", { rel: "stylesheet", href: url, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, onload: () => resolve(el), onerror }) || "");
|
|
105
116
|
else reject(new Error(`Unsupported resource type: ${type}`));
|
|
106
117
|
})(attempts);
|
|
107
118
|
});
|
|
108
|
-
return
|
|
119
|
+
return win.t007._resourceCache[src];
|
|
109
120
|
}
|
|
110
121
|
function getWindow(el = window) {
|
|
111
|
-
return
|
|
122
|
+
return el?.ownerDocument?.defaultView ?? el?.defaultView ?? window;
|
|
123
|
+
}
|
|
124
|
+
function createListRenderer({ container, getKey, createNode, updateNode = import_sia_reactor.NOOP, destroyNode = import_sia_reactor.NOOP, initNode }) {
|
|
125
|
+
let nodeRegistry = /* @__PURE__ */ new Map();
|
|
126
|
+
if (initNode) {
|
|
127
|
+
const children = Array.from(container.children);
|
|
128
|
+
for (let i = 0, len = children.length; i < len; i++) initNode(children[i], (key) => nodeRegistry.set(key, children[i]));
|
|
129
|
+
}
|
|
130
|
+
return function syncDOM(array, strict = true) {
|
|
131
|
+
const newRegistry = /* @__PURE__ */ new Map(), seenKeys = /* @__PURE__ */ new Set(), oldPositions = /* @__PURE__ */ new WeakMap(), children = Array.from(container.children);
|
|
132
|
+
for (let i = 0, len = children.length; i < len; i++) oldPositions.set(children[i], i);
|
|
133
|
+
const futureNodes = [], oldIndices = [];
|
|
134
|
+
for (let i = 0, len = array.length; i < len; i++) {
|
|
135
|
+
const item = array[i], key = getKey(item);
|
|
136
|
+
if (seenKeys.has(key)) throw new Error(`[List Renderer] Duplicate key "${key}" detected`);
|
|
137
|
+
let node = nodeRegistry.get(key);
|
|
138
|
+
if (!node) {
|
|
139
|
+
node = createNode(item);
|
|
140
|
+
if (!node) {
|
|
141
|
+
if (strict) throw new Error(`[List Renderer] No HTMLElement for key "${key}"`);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
oldIndices.push(-1);
|
|
145
|
+
} else updateNode(node, item), oldIndices.push(oldPositions.get(node) ?? -1);
|
|
146
|
+
seenKeys.add(key), futureNodes.push(node), newRegistry.set(key, node);
|
|
147
|
+
}
|
|
148
|
+
for (const [key, node] of nodeRegistry.entries()) !seenKeys.has(key) && node.parentElement === container && (destroyNode(node, key), node.remove());
|
|
149
|
+
const sequence = longestIncreasingSubsequence(oldIndices), stable = new Set(sequence);
|
|
150
|
+
let anchor = null;
|
|
151
|
+
for (let i = futureNodes.length - 1; i >= 0; i--) {
|
|
152
|
+
const node = futureNodes[i];
|
|
153
|
+
if (oldIndices[i] !== -1 && stable.has(i)) {
|
|
154
|
+
anchor = node;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
container.insertBefore(node, anchor), anchor = node;
|
|
158
|
+
}
|
|
159
|
+
nodeRegistry = newRegistry;
|
|
160
|
+
};
|
|
112
161
|
}
|
|
113
162
|
|
|
114
163
|
// src/ts/index.ts
|
|
115
|
-
var
|
|
164
|
+
var import_sia_reactor2 = require("sia-reactor");
|
|
116
165
|
|
|
117
166
|
// src/ts/core/obj.ts
|
|
118
167
|
var import_utils3 = require("sia-reactor/utils");
|
|
@@ -149,11 +198,42 @@ function inBoolArrOpt(opt, str) {
|
|
|
149
198
|
|
|
150
199
|
// src/ts/core/num.ts
|
|
151
200
|
var import_utils4 = require("sia-reactor/utils");
|
|
201
|
+
function longestIncreasingSubsequence(array) {
|
|
202
|
+
const n = array.length, parent = new Array(n), tails = [];
|
|
203
|
+
for (let i = 0; i < n; i++) {
|
|
204
|
+
const value = array[i];
|
|
205
|
+
if (value === -1) continue;
|
|
206
|
+
let left = 0;
|
|
207
|
+
let right = tails.length;
|
|
208
|
+
while (left < right) {
|
|
209
|
+
const mid = left + right >> 1;
|
|
210
|
+
if (array[tails[mid]] < value) left = mid + 1;
|
|
211
|
+
else right = mid;
|
|
212
|
+
}
|
|
213
|
+
if (left > 0) parent[i] = tails[left - 1];
|
|
214
|
+
else parent[i] = -1;
|
|
215
|
+
tails[left] = i;
|
|
216
|
+
}
|
|
217
|
+
if (!tails.length) return [];
|
|
218
|
+
const result = [];
|
|
219
|
+
let k = tails[tails.length - 1];
|
|
220
|
+
while (k >= 0) result.push(k), k = parent[k];
|
|
221
|
+
return result.reverse(), result;
|
|
222
|
+
}
|
|
152
223
|
|
|
153
224
|
// src/ts/core/str.ts
|
|
154
225
|
function uid(prefix = "") {
|
|
155
226
|
return prefix + Date.now().toString(36) + "_" + performance.now().toString(36).replace(".", "") + "_" + Math.random().toString(36).slice(2);
|
|
156
227
|
}
|
|
228
|
+
function capitalize(word = "") {
|
|
229
|
+
return word.replace(/^(\s*)([a-z])/i, (_, s, l) => s + l.toUpperCase());
|
|
230
|
+
}
|
|
231
|
+
function camelize(str = "", { source } = /[\s_-]+/, { preserveInnerCase: pIC = true, upperFirst: uF = false } = {}) {
|
|
232
|
+
return (pIC ? str : str.toLowerCase()).replace(new RegExp(source + "(\\w)", "g"), (_, c) => c.toUpperCase()).replace(/^\w/, (c) => c[uF ? "toUpperCase" : "toLowerCase"]());
|
|
233
|
+
}
|
|
234
|
+
function uncamelize(str, separator = " ") {
|
|
235
|
+
return str.replace(/([a-z])([A-Z])/g, `$1${separator}$2`).toLowerCase();
|
|
236
|
+
}
|
|
157
237
|
function remToPx(rem, el = document.documentElement) {
|
|
158
238
|
return rem * parseFloat(getComputedStyle(el).fontSize);
|
|
159
239
|
}
|
|
@@ -175,26 +255,57 @@ function cleanURL(url) {
|
|
|
175
255
|
}
|
|
176
256
|
}
|
|
177
257
|
function isSameURL(url1, url2) {
|
|
258
|
+
if (url1 === url2) return true;
|
|
178
259
|
if (!isStr(url1) || !isStr(url2) || !url1 || !url2) return false;
|
|
179
260
|
return cleanURL(url1) === cleanURL(url2);
|
|
180
261
|
}
|
|
181
262
|
|
|
182
263
|
// src/ts/core/fn.ts
|
|
183
264
|
var import_utils5 = require("sia-reactor/utils");
|
|
265
|
+
function throttle(key, fn, delay = 30, strict = true, signal, win) {
|
|
266
|
+
const throttleMap = t007._throttlers ??= /* @__PURE__ */ new Map();
|
|
267
|
+
if (strict === true) {
|
|
268
|
+
const now = performance.now();
|
|
269
|
+
return now - (throttleMap.get(key) ?? 0) < delay ? void 0 : (throttleMap.set(key, now), fn());
|
|
270
|
+
}
|
|
271
|
+
if (throttleMap.has(key)) return;
|
|
272
|
+
const id = strict === false ? (0, import_utils5.setTimeout)(() => throttleMap.delete(key), delay, signal, win) : strict(() => throttleMap.delete(key));
|
|
273
|
+
return throttleMap.set(key, id), fn();
|
|
274
|
+
}
|
|
275
|
+
function debounce(key, fn, delay = 30, strict = true, signal, win) {
|
|
276
|
+
const debounceMap = t007._debouncers ??= /* @__PURE__ */ new Map();
|
|
277
|
+
if (strict) {
|
|
278
|
+
const now = performance.now(), prev = debounceMap.get(key) ?? 0;
|
|
279
|
+
return debounceMap.set(key, now), now - prev < delay ? void 0 : fn();
|
|
280
|
+
}
|
|
281
|
+
const prevId = debounceMap.get(key);
|
|
282
|
+
prevId !== void 0 && (win ?? window).clearTimeout(prevId);
|
|
283
|
+
const id = (0, import_utils5.setTimeout)(() => (debounceMap.delete(key), fn()), delay, signal, win);
|
|
284
|
+
return void debounceMap.set(key, id);
|
|
285
|
+
}
|
|
286
|
+
function RAFLoop(key, fn, signal, win) {
|
|
287
|
+
const rafLoopMap = t007._RAFLoopers ??= /* @__PURE__ */ new Map();
|
|
288
|
+
if (rafLoopMap.has(key)) return void rafLoopMap.set(key, fn);
|
|
289
|
+
rafLoopMap.set(key, fn);
|
|
290
|
+
const loop = (_ = 0, fn2 = rafLoopMap.get(key)) => fn2 && (fn2(), (0, import_utils5.requestAnimationFrame)(loop, signal, win));
|
|
291
|
+
loop();
|
|
292
|
+
}
|
|
293
|
+
var cancelRAFLoop = (key) => t007._RAFLoopers ? t007._RAFLoopers.delete(key) : false;
|
|
184
294
|
function limited(FN_KEY, fn, opts = {}) {
|
|
185
|
-
let count = 0, { key, maxTimes: max = 1 } = isStr(opts) ? { key: opts } : opts;
|
|
295
|
+
let count = 0, { key, maxTimes: max = 1, oncePerSession = true } = isStr(opts) ? { key: opts } : opts;
|
|
186
296
|
const getReg = () => JSON.parse(localStorage.getItem(FN_KEY) || "{}"), setReg = (r) => localStorage.setItem(FN_KEY, JSON.stringify(r));
|
|
187
297
|
const handle = (...args) => {
|
|
298
|
+
if (oncePerSession && count > 0) return void 0;
|
|
188
299
|
if (!key) return count++ < max ? fn(...args) : void 0;
|
|
189
300
|
const r = getReg(), c = r[key] || 0;
|
|
190
|
-
return c < max ? (r[key] = c + 1, setReg(r), fn(...args)) : void 0;
|
|
301
|
+
return c < max ? (count++, r[key] = c + 1, setReg(r), fn(...args)) : void 0;
|
|
191
302
|
};
|
|
192
303
|
handle.left = max - (handle.count = count);
|
|
193
304
|
handle.reset = () => (count = 0, key && ((r) => (delete r[key], setReg(r)))(getReg()));
|
|
194
305
|
handle.block = () => (count = max, key && ((r) => (r[key] = max, setReg(r)))(getReg()));
|
|
195
306
|
return handle;
|
|
196
307
|
}
|
|
197
|
-
var mockAsync = (timeout = 250) => new Promise((resolve) => setTimeout(resolve, timeout));
|
|
308
|
+
var mockAsync = (timeout = 250) => new Promise((resolve) => (0, import_utils5.setTimeout)(resolve, timeout));
|
|
198
309
|
var breath = (w = window) => new Promise((res) => w.requestAnimationFrame(res));
|
|
199
310
|
var deepBreath = (w = window) => new Promise((res) => w.requestAnimationFrame(() => w.requestAnimationFrame(res)));
|
|
200
311
|
function bindCleanupToSignal(cleanup, signal) {
|
|
@@ -229,17 +340,24 @@ if ("undefined" !== typeof window) {
|
|
|
229
340
|
// Annotate the CommonJS export names for ESM import in node:
|
|
230
341
|
0 && (module.exports = {
|
|
231
342
|
INTERACTIVE_SELECTOR,
|
|
343
|
+
KEYS_BLOCKS,
|
|
232
344
|
NIL,
|
|
233
345
|
NOOP,
|
|
346
|
+
RAFLoop,
|
|
234
347
|
VIRTUAL_RESOURCE,
|
|
235
348
|
assignEl,
|
|
236
349
|
bindAllMethods,
|
|
237
350
|
bindCleanupToSignal,
|
|
238
351
|
breath,
|
|
352
|
+
camelize,
|
|
353
|
+
cancelRAFLoop,
|
|
354
|
+
capitalize,
|
|
239
355
|
clamp,
|
|
240
356
|
cleanKeyCombo,
|
|
241
357
|
cleanURL,
|
|
242
358
|
createEl,
|
|
359
|
+
createListRenderer,
|
|
360
|
+
debounce,
|
|
243
361
|
deepBreath,
|
|
244
362
|
formatKeyForDisplay,
|
|
245
363
|
formatKeyShortcutsForDisplay,
|
|
@@ -265,6 +383,7 @@ if ("undefined" !== typeof window) {
|
|
|
265
383
|
keyEventAllowed,
|
|
266
384
|
limited,
|
|
267
385
|
loadResource,
|
|
386
|
+
longestIncreasingSubsequence,
|
|
268
387
|
matchKeys,
|
|
269
388
|
mockAsync,
|
|
270
389
|
onAllMethods,
|
|
@@ -278,5 +397,7 @@ if ("undefined" !== typeof window) {
|
|
|
278
397
|
setInterval,
|
|
279
398
|
setTimeout,
|
|
280
399
|
stringifyKeyEvent,
|
|
281
|
-
|
|
400
|
+
throttle,
|
|
401
|
+
uid,
|
|
402
|
+
uncamelize
|
|
282
403
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { A as ArrowNavigationHandle } from './arrowNavigation-
|
|
2
|
-
import { S as ScrollAssistHandle } from './scrollAssist-
|
|
1
|
+
import { A as ArrowNavigationHandle } from './arrowNavigation-zEJbo8Er.cjs';
|
|
2
|
+
import { F as FocusTrapHandle, S as ScrollAssistHandle } from './scrollAssist-BNvPnsJq.cjs';
|
|
3
3
|
export { NIL, NOOP } from 'sia-reactor';
|
|
4
|
-
export { KeyStruct, assignEl, bindAllMethods, clamp, cleanKeyCombo, createEl, formatKeyForDisplay, formatKeyShortcutsForDisplay, getActiveEl, getTermsForKey, guardAllMethods, guardMethod, isObj, keyEventAllowed,
|
|
4
|
+
export { KEYS_BLOCKS, KeyStruct, KeysSettings, assignEl, bindAllMethods, clamp, cleanKeyCombo, createEl, formatKeyForDisplay, formatKeyShortcutsForDisplay, getActiveEl, getTermsForKey, guardAllMethods, guardMethod, isObj, keyEventAllowed, matchKeys, onAllMethods, parseForARIAKS, parseKeyCombo, requestAnimationFrame, setInterval, setTimeout, stringifyKeyEvent } from 'sia-reactor/utils';
|
|
5
5
|
|
|
6
6
|
declare global {
|
|
7
7
|
interface T007Namespace {
|
|
8
8
|
/** Symbol used to mark virtual resources that should not load a real asset. */
|
|
9
9
|
VIRTUAL_RESOURCE: symbol;
|
|
10
10
|
_resourceCache: Partial<Record<string, Promise<HTMLElement | void>>>;
|
|
11
|
-
|
|
11
|
+
_throttlers?: Map<string, number>;
|
|
12
|
+
_debouncers?: Map<string, number>;
|
|
13
|
+
_RAFLoopers?: Map<string, Function>;
|
|
14
|
+
_ftrappers?: WeakMap<HTMLElement, FocusTrapHandle>;
|
|
12
15
|
_outsiders?: WeakMap<HTMLElement, () => void>;
|
|
13
16
|
_arrownavs?: WeakMap<HTMLElement, ArrowNavigationHandle>;
|
|
14
17
|
_scrollers?: WeakMap<HTMLElement, ScrollAssistHandle>;
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
_ftrappers_stack?: HTMLElement[];
|
|
19
|
+
_outsiders_stack?: HTMLElement[];
|
|
17
20
|
_scrollers_r_observer?: ResizeObserver;
|
|
18
21
|
_scrollers_m_observer?: MutationObserver;
|
|
19
22
|
}
|
|
@@ -37,6 +40,27 @@ declare global {
|
|
|
37
40
|
var t007: T007Namespace;
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
type TitleCase<S extends string> = S extends `${infer First}${infer Rest}`
|
|
44
|
+
? `${Uppercase<First>}${Rest}`
|
|
45
|
+
: S;
|
|
46
|
+
|
|
47
|
+
type CamelCase<S extends string> = S extends `${infer P1}_${infer P2}${infer P3}`
|
|
48
|
+
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
|
|
49
|
+
: S extends `${infer P1}-${infer P2}${infer P3}`
|
|
50
|
+
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
|
|
51
|
+
: S extends `${infer P1} ${infer P2}${infer P3}`
|
|
52
|
+
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
|
|
53
|
+
: Lowercase<S>;
|
|
54
|
+
|
|
55
|
+
type NoCamelCase<
|
|
56
|
+
S extends string,
|
|
57
|
+
Sep extends string = " "
|
|
58
|
+
> = S extends `${infer First}${infer Rest}`
|
|
59
|
+
? First extends Uppercase<First>
|
|
60
|
+
? `${Sep}${Lowercase<First>}${NoCamelCase<Rest, Sep>}`
|
|
61
|
+
: `${First}${NoCamelCase<Rest, Sep>}`
|
|
62
|
+
: S;
|
|
63
|
+
|
|
40
64
|
declare function isDef(val: any): boolean;
|
|
41
65
|
declare function isSym<T extends symbol = symbol>(val: any): val is T;
|
|
42
66
|
declare function isBool<T extends boolean = boolean>(val: any): val is T;
|
|
@@ -49,20 +73,52 @@ declare function isIter<T = unknown>(obj: any): obj is Iterable<T>;
|
|
|
49
73
|
declare function isFunc<T extends Function = Function>(val: any): val is T;
|
|
50
74
|
declare function inBoolArrOpt(opt: any, str: string): boolean;
|
|
51
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Finds the longest increasing subsequence in an array of numbers.
|
|
78
|
+
* @param array The input array of numbers
|
|
79
|
+
* @returns An array of indices representing the longest increasing subsequence
|
|
80
|
+
*/
|
|
81
|
+
declare function longestIncreasingSubsequence(array: number[]): number[];
|
|
82
|
+
|
|
52
83
|
/** Create a short unique string with an optional prefix.
|
|
53
84
|
* @param prefix Prefix added to the generated id.
|
|
54
85
|
* @returns A browser-safe unique id string.
|
|
55
86
|
*/
|
|
56
87
|
declare function uid(prefix?: string): string;
|
|
88
|
+
/** Capitalize the first letter of a string, leaving the rest unchanged.
|
|
89
|
+
* @param word The string to capitalize.
|
|
90
|
+
* @returns The input string with the first letter capitalized.
|
|
91
|
+
*/
|
|
92
|
+
declare function capitalize<T extends string>(word?: T): TitleCase<T>;
|
|
93
|
+
/** Convert a string to camelCase by removing separators and capitalizing subsequent words.
|
|
94
|
+
* @param str The input string to convert.
|
|
95
|
+
* @param options.source A regex or string defining word separators. @default whitespace, underscores, and hyphens (`[\s_-]+`).
|
|
96
|
+
* @param options.preserveInnerCase If true, preserves the original casing of letters; if false, converts the entire string to lowercase before processing. @default `true`.
|
|
97
|
+
* @param options.upperFirst If true, capitalizes the first letter of the resulting string (PascalCase); if false, lowercases the first letter (camelCase). @default `false`.
|
|
98
|
+
* @returns The camelCase version of the input string.
|
|
99
|
+
*/
|
|
100
|
+
declare function camelize<T extends string>(str?: T, { source }?: RegExp, { preserveInnerCase: pIC, upperFirst: uF }?: {
|
|
101
|
+
preserveInnerCase?: boolean | undefined;
|
|
102
|
+
upperFirst?: boolean | undefined;
|
|
103
|
+
}): CamelCase<T>;
|
|
104
|
+
/** Convert a camelCase or PascalCase string to a separator-based format (e.g. "helloWorld" to "hello-world").
|
|
105
|
+
* @param str The camelCase or PascalCase string to convert.
|
|
106
|
+
* @param separator The string to insert between words. @default a hyphen ("-").
|
|
107
|
+
* @returns The uncamelized version of the input string with separators.
|
|
108
|
+
* @example
|
|
109
|
+
* uncamelize("helloWorld") // "hello-world"
|
|
110
|
+
* uncamelize("HelloWorld", "_") // "hello_world"
|
|
111
|
+
*/
|
|
112
|
+
declare function uncamelize<T extends string, S extends string = " ">(str: T, separator?: S): NoCamelCase<T, S>;
|
|
57
113
|
/** Convert a rem value to pixels based on the font size of a given element.
|
|
58
114
|
* @param rem The rem value to convert.
|
|
59
|
-
* @param el The element to use for font size reference.
|
|
115
|
+
* @param el The element to use for font size reference. @default the root element.
|
|
60
116
|
* @returns The equivalent pixel value.
|
|
61
117
|
*/
|
|
62
118
|
declare function remToPx(rem: number, el?: HTMLElement): number;
|
|
63
119
|
/** Convert a pixel value to rem based on the font size of a given element.
|
|
64
120
|
* @param px The pixel value to convert.
|
|
65
|
-
* @param el The element to use for font size reference.
|
|
121
|
+
* @param el The element to use for font size reference. @default the root element.
|
|
66
122
|
* @returns The equivalent rem value.
|
|
67
123
|
*/
|
|
68
124
|
declare function pxToRem(px: number, el?: HTMLElement): number;
|
|
@@ -73,7 +129,7 @@ declare function pxToRem(px: number, el?: HTMLElement): number;
|
|
|
73
129
|
declare function parseCSSTime(time: any): number;
|
|
74
130
|
/** Parse a CSS size value (i.e. "16px" or "1.5rem") into pixels.
|
|
75
131
|
* @param size The CSS size string to parse.
|
|
76
|
-
* @param el The element to use for rem reference if needed.
|
|
132
|
+
* @param el The element to use for rem reference if needed. @default the root element.
|
|
77
133
|
* @returns The equivalent value in pixels.
|
|
78
134
|
*/
|
|
79
135
|
declare function parseCSSSize(size: any, el?: HTMLElement): number;
|
|
@@ -89,11 +145,45 @@ declare function cleanURL(url: string): string;
|
|
|
89
145
|
*/
|
|
90
146
|
declare function isSameURL(url1: unknown, url2: unknown): boolean;
|
|
91
147
|
|
|
148
|
+
/** Throttles a function, ensuring it's only called once within a specified delay period.
|
|
149
|
+
* @param key Unique identifier for the throttled function, used to track its last execution time.
|
|
150
|
+
* @param fn Function to be throttled.
|
|
151
|
+
* @param delay Time in milliseconds to wait before allowing the function to be called again. @default `30ms`.
|
|
152
|
+
* @param strict If `true`, exact timestamp difference between calls will be used else a `setTimeout()` will clear the throttle, allowing for more thread leniency. @default `true`.
|
|
153
|
+
* @param signal Optional `AbortSignal` to automatically clear the throttle when aborted.
|
|
154
|
+
* @param win Optional `Window` object for scheduling the throttle timeout, useful for testing or if running in a non-browser environment.
|
|
155
|
+
*/
|
|
156
|
+
declare function throttle(key: string, fn: Function, delay?: number, strict?: ((fn: Function) => number) | boolean, signal?: AbortSignal, win?: Window): void;
|
|
157
|
+
/** Debounces a function, ensuring it's only called after a quiet period of no further calls.
|
|
158
|
+
* @param key Unique identifier for the debounced function, used to track pending calls.
|
|
159
|
+
* @param fn Function to be debounced.
|
|
160
|
+
* @param delay Time in milliseconds to wait after the latest call before invoking the function. @default `30ms`.
|
|
161
|
+
* @param strict If `true`, exact timestamp difference between calls will be used else pending timeout is reset each call for practical thread leniency. @default `true`.
|
|
162
|
+
* @param signal Optional `AbortSignal` to automatically clear scheduled debounce execution when aborted.
|
|
163
|
+
* @param win Optional `Window` object for scheduling/clearing the debounce timeout, useful for testing or if running in a non-browser environment.
|
|
164
|
+
*/
|
|
165
|
+
declare function debounce(key: string, fn: Function, delay?: number, strict?: boolean, signal?: AbortSignal, win?: Window): void;
|
|
166
|
+
/** Creates a loop using `requestAnimationFrame`, allowing for efficient execution of a function on every frame.
|
|
167
|
+
* @param key Unique identifier for the loop, used to manage its execution and allow for updates or cancellation.
|
|
168
|
+
* @param fn Function to be executed on every frame.
|
|
169
|
+
* @param signal Optional `AbortSignal` to automatically cancel the loop when aborted.
|
|
170
|
+
* @param win Optional `Window` object for scheduling the animation frame, useful for testing or if running in a non-browser environment.
|
|
171
|
+
*
|
|
172
|
+
* Game-like loops will be our lil secret... ~ "The Smoooth Criminal" :)
|
|
173
|
+
*/
|
|
174
|
+
declare function RAFLoop(key: string, fn: Function, signal?: AbortSignal, win?: Window & typeof globalThis): void;
|
|
175
|
+
/** Cancels a loop created by `RAFLoop`.
|
|
176
|
+
* @param key Unique identifier for the loop to be cancelled.
|
|
177
|
+
* @returns True if the loop was successfully cancelled, false if no loop with the given key exists.
|
|
178
|
+
*/
|
|
179
|
+
declare const cancelRAFLoop: (key: string) => boolean;
|
|
92
180
|
interface LimitedOptions {
|
|
93
181
|
/** Storage key used to persist call counts. */
|
|
94
182
|
key?: string;
|
|
95
|
-
/** Maximum number of allowed calls. */
|
|
183
|
+
/** Maximum number of allowed calls. @default 1 */
|
|
96
184
|
maxTimes?: number;
|
|
185
|
+
/** Only allow calling once per session, regardless of maxTimes. @default true */
|
|
186
|
+
oncePerSession?: boolean;
|
|
97
187
|
}
|
|
98
188
|
interface LimitedHandle<T extends (...args: any[]) => any> {
|
|
99
189
|
/** Call the wrapped function with the original arguments. */
|
|
@@ -137,7 +227,7 @@ declare const deepBreath: (w?: Window & typeof globalThis) => Promise<unknown>;
|
|
|
137
227
|
declare function bindCleanupToSignal<Cb extends () => any>(cleanup: Cb, signal?: AbortSignal): Cb;
|
|
138
228
|
|
|
139
229
|
/** Exhaustive Selector used for interactive, tabbable UI controls. */
|
|
140
|
-
declare const INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable
|
|
230
|
+
declare const INTERACTIVE_SELECTOR = ":is(button,[href],input:not([type='hidden']),select,textarea,details>summary,[contenteditable],iframe,audio[controls],video[controls],[tabindex]):not([disabled],[tabindex='-1'],[data-focus-guard],[inert],[inert] *)";
|
|
141
231
|
/** Check whether an event target points to an interactive element. */
|
|
142
232
|
declare const isInteractive: (target: EventTarget | null) => boolean;
|
|
143
233
|
/** Resource type accepted by loadResource. */
|
|
@@ -169,16 +259,53 @@ declare const VIRTUAL_RESOURCE: symbol;
|
|
|
169
259
|
* @param req Resource URL or virtual resource symbol.
|
|
170
260
|
* @param type Resource type to load.
|
|
171
261
|
* @param options Resource loading options.
|
|
172
|
-
* @param
|
|
262
|
+
* @param win Window-like target used for DOM insertion.
|
|
173
263
|
* @returns Promise resolving to the created element or void.
|
|
174
264
|
*/
|
|
175
|
-
declare function loadResource(req: string | symbol, type?: ResourceType, { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts, retryKey }?: LoadResourceOptions,
|
|
265
|
+
declare function loadResource(req: string | symbol, type?: ResourceType, { module, media, crossOrigin, integrity, referrerPolicy, nonce, fetchPriority, attempts, retryKey }?: LoadResourceOptions, win?: Window & typeof globalThis): Promise<HTMLElement | void>;
|
|
176
266
|
|
|
177
267
|
/** Get the window object associated with a given element.
|
|
178
268
|
* @param el The element to get the window for, defaults to the main window.
|
|
179
|
-
* @returns The
|
|
269
|
+
* @returns The `Window` object or undefined if none found.
|
|
270
|
+
*/
|
|
271
|
+
declare function getWindow(el?: any): Window & typeof globalThis;
|
|
272
|
+
/** Options for configuring a list renderer */
|
|
273
|
+
type ListRendererOptions<T, El extends HTMLElement = HTMLElement> = {
|
|
274
|
+
/** The container element to render the list into */
|
|
275
|
+
container: HTMLElement;
|
|
276
|
+
/** Function to extract a unique key from each item.
|
|
277
|
+
* @param item The item to extract the key from
|
|
278
|
+
* @returns A unique string key for the item
|
|
279
|
+
*/
|
|
280
|
+
getKey: (item: T) => string;
|
|
281
|
+
/** Function to create a DOM node for an item.
|
|
282
|
+
* @param item The item to create a node for
|
|
283
|
+
* @returns An HTMLElement representing the item, or null/undefined to skip rendering
|
|
284
|
+
*/
|
|
285
|
+
createNode: (item: T) => El | null | undefined;
|
|
286
|
+
/** Optional function to update an existing node with new item data, called when an item is reused.
|
|
287
|
+
* @param node The existing DOM node for the item
|
|
288
|
+
* @param item The new item data to update the node with
|
|
289
|
+
*/
|
|
290
|
+
updateNode?: (node: El, item: T) => void;
|
|
291
|
+
/** Optional function to clean up a DOM node when an item is removed, called before the node is removed from the DOM.
|
|
292
|
+
* @param node The DOM node to be removed
|
|
293
|
+
* @param key The unique key of the item associated with the node
|
|
294
|
+
*/
|
|
295
|
+
destroyNode?: (node: El, key: string) => void;
|
|
296
|
+
/** Optional function called once during initialization for each existing child node in the container.
|
|
297
|
+
* Allows seeding the registry with pre-existing markup so nodes are reused instead of destroyed.
|
|
298
|
+
* @param node The pre-existing DOM node
|
|
299
|
+
* @param register A callback to register the node with its corresponding item key
|
|
300
|
+
*/
|
|
301
|
+
initNode?: (node: El, register: (key: string) => void) => void;
|
|
302
|
+
};
|
|
303
|
+
/**
|
|
304
|
+
* Creates a list renderer function for efficiently updating a DOM list based on a new array of items using the L.I.S(Longest Increasing Subsequence) algorithm.
|
|
305
|
+
* @param param0 The options for configuring the list renderer
|
|
306
|
+
* @returns A function that synchronizes the DOM with the new array of items
|
|
180
307
|
*/
|
|
181
|
-
declare function
|
|
308
|
+
declare function createListRenderer<T, El extends HTMLElement = HTMLElement>({ container, getKey, createNode, updateNode, destroyNode, initNode }: ListRendererOptions<T, El>): (array: T[], strict?: boolean) => void;
|
|
182
309
|
|
|
183
310
|
/** Format a file size for display.
|
|
184
311
|
* @param size Size in bytes.
|
|
@@ -188,4 +315,4 @@ declare function getWindow(el?: any): (Window & typeof globalThis) | undefined;
|
|
|
188
315
|
*/
|
|
189
316
|
declare function formatSize(bytes: number, decimals?: number, base?: number): string;
|
|
190
317
|
|
|
191
|
-
export { INTERACTIVE_SELECTOR, type LimitedHandle, type LimitedOptions, type LoadResourceOptions, type ResourceType, VIRTUAL_RESOURCE, bindCleanupToSignal, breath, cleanURL, deepBreath, formatSize, getWindow, inBoolArrOpt, isArr, isBool, isDef, isFunc, isInteractive, isIter, isNum, isPOJO, isSameURL, isStr, isSym, limited, loadResource, mockAsync, parseCSSSize, parseCSSTime, pxToRem, remToPx, uid };
|
|
318
|
+
export { type CamelCase, INTERACTIVE_SELECTOR, type LimitedHandle, type LimitedOptions, type ListRendererOptions, type LoadResourceOptions, type NoCamelCase, RAFLoop, type ResourceType, type TitleCase, VIRTUAL_RESOURCE, bindCleanupToSignal, breath, camelize, cancelRAFLoop, capitalize, cleanURL, createListRenderer, debounce, deepBreath, formatSize, getWindow, inBoolArrOpt, isArr, isBool, isDef, isFunc, isInteractive, isIter, isNum, isPOJO, isSameURL, isStr, isSym, limited, loadResource, longestIncreasingSubsequence, mockAsync, parseCSSSize, parseCSSTime, pxToRem, remToPx, throttle, uid, uncamelize };
|