sia-reactor 0.0.19 → 0.0.21

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.
Files changed (38) hide show
  1. package/README.md +102 -58
  2. package/dist/TimeTravelOverlay-CJv-S_Km.d.cts +41 -0
  3. package/dist/TimeTravelOverlay-DxqJL0Zk.d.ts +41 -0
  4. package/dist/adapters/react.cjs +308 -92
  5. package/dist/adapters/react.d.cts +68 -10
  6. package/dist/adapters/react.d.ts +68 -10
  7. package/dist/adapters/react.js +80 -29
  8. package/dist/adapters/vanilla.cjs +957 -10
  9. package/dist/adapters/vanilla.d.cts +4 -2
  10. package/dist/adapters/vanilla.d.ts +4 -2
  11. package/dist/adapters/vanilla.js +8 -12
  12. package/dist/{chunk-Q2AKMIHN.js → chunk-2WBPGSRL.js} +106 -48
  13. package/dist/chunk-5A44QFT6.js +93 -0
  14. package/dist/{chunk-4MJUBEI7.js → chunk-DP74DVRT.js} +4 -2
  15. package/dist/{chunk-UQIMMJTY.js → chunk-P37ADJMM.js} +3 -3
  16. package/dist/chunk-TFLYCXK4.js +251 -0
  17. package/dist/{index-C2hyIh0K.d.cts → index-Oie9hhE8.d.cts} +14 -10
  18. package/dist/{index-C2hyIh0K.d.ts → index-Oie9hhE8.d.ts} +14 -10
  19. package/dist/index.cjs +45 -52
  20. package/dist/index.d.cts +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.js +4 -6
  23. package/dist/plugins.cjs +72 -73
  24. package/dist/plugins.d.cts +4 -75
  25. package/dist/plugins.d.ts +4 -75
  26. package/dist/plugins.js +27 -22
  27. package/dist/styles/time-travel-overlay.css +189 -0
  28. package/dist/super.d.ts +79 -26
  29. package/dist/super.global.js +200 -105
  30. package/dist/timeTravel-B1vedDQc.d.ts +76 -0
  31. package/dist/timeTravel-WpgWmKu-.d.cts +76 -0
  32. package/dist/utils.cjs +34 -7
  33. package/dist/utils.d.cts +9 -2
  34. package/dist/utils.d.ts +9 -2
  35. package/dist/utils.js +17 -65
  36. package/package.json +3 -2
  37. package/dist/chunk-FGUCKMLH.js +0 -154
  38. package/dist/chunk-KIQP7G7W.js +0 -80
@@ -1,5 +1,7 @@
1
- import { E as EffectOptions } from '../index-C2hyIh0K.cjs';
2
- export { A as Autotracker, w as withTracker } from '../index-C2hyIh0K.cjs';
1
+ import { E as EffectOptions } from '../index-Oie9hhE8.cjs';
2
+ export { A as Autotracker, w as withTracker } from '../index-Oie9hhE8.cjs';
3
+ export { T as TimeTravelConfig, a as TimeTravelOverlay } from '../TimeTravelOverlay-CJv-S_Km.cjs';
4
+ import '../timeTravel-WpgWmKu-.cjs';
3
5
 
4
6
  /**
5
7
  * Runs a reactive side effect in vanilla JavaScript.
@@ -1,5 +1,7 @@
1
- import { E as EffectOptions } from '../index-C2hyIh0K.js';
2
- export { A as Autotracker, w as withTracker } from '../index-C2hyIh0K.js';
1
+ import { E as EffectOptions } from '../index-Oie9hhE8.js';
2
+ export { A as Autotracker, w as withTracker } from '../index-Oie9hhE8.js';
3
+ export { T as TimeTravelConfig, a as TimeTravelOverlay } from '../TimeTravelOverlay-DxqJL0Zk.js';
4
+ import '../timeTravel-B1vedDQc.js';
3
5
 
4
6
  /**
5
7
  * Runs a reactive side effect in vanilla JavaScript.
@@ -1,20 +1,16 @@
1
1
  import {
2
2
  Autotracker,
3
+ TimeTravelOverlay,
4
+ effect,
3
5
  withTracker
4
- } from "../chunk-FGUCKMLH.js";
5
- import "../chunk-4MJUBEI7.js";
6
-
7
- // src/adapters/vanilla/effect.ts
8
- function effect(callback, options) {
9
- const atrkr = new Autotracker();
10
- let destroyed = false;
11
- (function execute() {
12
- if (!destroyed) withTracker(atrkr, () => callback()), atrkr.callback(execute, options);
13
- })();
14
- return () => (destroyed = true, atrkr.destroy());
15
- }
6
+ } from "../chunk-TFLYCXK4.js";
7
+ import "../chunk-2WBPGSRL.js";
8
+ import "../chunk-5A44QFT6.js";
9
+ import "../chunk-P37ADJMM.js";
10
+ import "../chunk-DP74DVRT.js";
16
11
  export {
17
12
  Autotracker,
13
+ TimeTravelOverlay,
18
14
  effect,
19
15
  withTracker
20
16
  };
@@ -4,6 +4,7 @@ import {
4
4
  EVT_WARN,
5
5
  INDIFFABLE,
6
6
  INERTIA,
7
+ NIL,
7
8
  NOOP,
8
9
  RAW,
9
10
  REJECTABLE,
@@ -21,9 +22,9 @@ import {
21
22
  nuke,
22
23
  parseEvtOpts,
23
24
  setAny
24
- } from "./chunk-4MJUBEI7.js";
25
+ } from "./chunk-DP74DVRT.js";
25
26
 
26
- // src/core/event.ts
27
+ // src/ts/core/event.ts
27
28
  var ReactorEvent = class _ReactorEvent {
28
29
  /** No active propagation phase. */
29
30
  static NONE = 0;
@@ -146,7 +147,7 @@ var ReactorEvent = class _ReactorEvent {
146
147
  }
147
148
  };
148
149
 
149
- // src/core/reactor.ts
150
+ // src/ts/core/reactor.ts
150
151
  var Reactor = class {
151
152
  log = NOOP;
152
153
  core;
@@ -174,27 +175,27 @@ var Reactor = class {
174
175
  listeners;
175
176
  /**
176
177
  * Creates a new Reactor instance.
177
- * @param object Initial state object.
178
+ * @param target Initial state target.
178
179
  * @param build Reactor bootstrap/build configuration.
179
180
  * @example
180
181
  * const rtr = new Reactor({ count: 0 });
181
182
  */
182
- constructor(object = {}, build) {
183
+ constructor(target = {}, build) {
183
184
  this[INERTIA] = true;
184
185
  this.config = { crossRealms: false, smartCloning: false, eventBubbling: true, lineageTracing: false, preserveContext: false, equalityFunction: Object.is, batchingFunction: RTR_BATCH, ...build };
185
- this.core = this.proxied(object);
186
+ this.core = this.proxied(target);
186
187
  if (build) this.canLog = !!build.debug;
187
188
  }
188
- proxied(obj, rejectable = false, indiffable = false, parent, key, path) {
189
- if (!obj || "object" !== typeof obj) return obj;
190
- obj = obj[RAW] || obj;
191
- if (this.config.referenceTracking && parent && key && !this.link(obj, parent, key, false)) return obj;
192
- const cached = this.proxyCache.get(obj);
189
+ proxied(target, rejectable = false, indiffable = false, parent, key, path) {
190
+ if (!target || "object" !== typeof target) return target;
191
+ target = target[RAW] || target;
192
+ if (this.config.referenceTracking && parent && key && !this.link(target, parent, key, false)) return target;
193
+ const cached = this.proxyCache.get(target);
193
194
  if (cached) return cached;
194
- if (obj[INERTIA] || !canHandle(obj, this.config, false)) return obj;
195
- rejectable ||= obj[REJECTABLE];
196
- indiffable ||= obj[INDIFFABLE];
197
- const proxy = new Proxy(obj, {
195
+ if (target[INERTIA] || !canHandle(target, this.config, false)) return target;
196
+ rejectable ||= target[REJECTABLE];
197
+ indiffable ||= target[INDIFFABLE];
198
+ const proxy = new Proxy(target, {
198
199
  // Robust Proxy handler
199
200
  get: (object, key2, receiver) => {
200
201
  if (key2 === RAW) return this.log(`\u{1F440} [Reactor \`get\` Trap] Peeked at ${object}`), object;
@@ -207,10 +208,10 @@ var Reactor = class {
207
208
  for (let i = 0, len = this.config.lineageTracing ? paths.length : 1; i < len; i++) {
208
209
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.getters.get(currPath);
209
210
  if (!cords && !wildcords) continue;
210
- const target = { path: currPath, value, key: keyStr, keyExisted: true, object: receiver }, payload = { type: "get", target, currentTarget: target, root: this.core, rejectable };
211
+ const target2 = { path: currPath, value, key: keyStr, hadKey: true, object: receiver }, payload = { type: "get", target: target2, currentTarget: target2, root: this.core, rejectable };
211
212
  if (cords) value = this.mediate(currPath, payload, "get", cords);
212
213
  if (!wildcords) continue;
213
- target.value = value;
214
+ target2.value = value;
214
215
  value = this.mediate("*", payload, "get", wildcords);
215
216
  }
216
217
  }
@@ -218,7 +219,7 @@ var Reactor = class {
218
219
  },
219
220
  set: (object, key2, value, receiver) => {
220
221
  let unchanged, safeValue, safeOldValue, terminated = false;
221
- const keyStr = String(key2), fullPath = path ? path + "." + keyStr : keyStr, paths = this.config.lineageTracing ? this.trace(object, keyStr) : fullPath, loopLen = this.config.lineageTracing ? paths.length : 1, oldValue = !this.config.preserveContext ? object[key2] : Reflect.get(object, key2, receiver), keyExisted = !this.config.preserveContext ? key2 in object : Reflect.has(object, key2);
222
+ const keyStr = String(key2), fullPath = path ? path + "." + keyStr : keyStr, paths = this.config.lineageTracing ? this.trace(object, keyStr) : fullPath, loopLen = this.config.lineageTracing ? paths.length : 1, oldValue = !this.config.preserveContext ? object[key2] : Reflect.get(object, key2, receiver), hadKey = !this.config.preserveContext ? key2 in object : Reflect.has(object, key2);
222
223
  this.log(`\u270F\uFE0F [Reactor \`set\` Trap] Initiated for "${keyStr}" on "${paths}"`), CTX.autotracker?.track(fullPath, this, true);
223
224
  if (this.config.referenceTracking || !indiffable) {
224
225
  safeOldValue = oldValue?.[RAW] || oldValue;
@@ -232,13 +233,13 @@ var Reactor = class {
232
233
  for (let i = 0; i < loopLen; i++) {
233
234
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.setters.get(currPath);
234
235
  if (!cords && !wildcords) continue;
235
- const target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver }, payload = { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable };
236
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable };
236
237
  if (cords) {
237
238
  const result2 = this.mediate(currPath, payload, "set", cords);
238
239
  if (!(terminated ||= payload.terminated)) value = result2;
239
240
  }
240
241
  if (!wildcords) continue;
241
- target.value = value;
242
+ target2.value = value;
242
243
  const result = this.mediate("*", payload, "set", wildcords);
243
244
  if (!(terminated ||= payload.terminated)) value = result;
244
245
  }
@@ -249,14 +250,14 @@ var Reactor = class {
249
250
  if (this.config.referenceTracking && !unchanged) this.config.smartCloning && this.stamp(object), this.unlink(safeOldValue, object, keyStr), this.link(safeValue, object, keyStr);
250
251
  if (this.watchers || this.listeners)
251
252
  for (let i = 0; i < loopLen; i++) {
252
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver };
253
- this.notify(currPath, { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable });
253
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
254
+ this.notify(currPath, { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable });
254
255
  }
255
256
  return true;
256
257
  },
257
258
  deleteProperty: (object, key2) => {
258
259
  let value, receiver = this.proxyCache.get(object), terminated = false;
259
- const keyStr = String(key2), fullPath = path ? path + "." + keyStr : keyStr, paths = this.config.lineageTracing ? this.trace(object, keyStr) : fullPath, loopLen = this.config.lineageTracing ? paths.length : 1, oldValue = !this.config.preserveContext ? object[key2] : Reflect.get(object, key2, receiver), keyExisted = !this.config.preserveContext ? key2 in object : Reflect.has(object, key2);
260
+ const keyStr = String(key2), fullPath = path ? path + "." + keyStr : keyStr, paths = this.config.lineageTracing ? this.trace(object, keyStr) : fullPath, loopLen = this.config.lineageTracing ? paths.length : 1, oldValue = !this.config.preserveContext ? object[key2] : Reflect.get(object, key2, receiver), hadKey = !this.config.preserveContext ? key2 in object : Reflect.has(object, key2);
260
261
  this.log(`\u{1F5D1}\uFE0F [Reactor \`deleteProperty\` Trap] Initiated for "${keyStr}" on "${paths}"`), CTX.autotracker?.track(fullPath, this, true);
261
262
  if (this.config.deleteProperty) terminated = (value = this.config.deleteProperty(object, key2, oldValue, receiver, paths)) === TERMINATOR;
262
263
  if (this.deleters) {
@@ -264,7 +265,7 @@ var Reactor = class {
264
265
  for (let i = 0; i < loopLen; i++) {
265
266
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.deleters.get(currPath);
266
267
  if (!cords && !wildcords) continue;
267
- const target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver }, payload = { type: "delete", target, currentTarget: target, root: this.core, rejectable };
268
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable };
268
269
  if (cords) {
269
270
  const result2 = this.mediate(currPath, payload, "delete", cords);
270
271
  if (!(terminated ||= payload.terminated)) value = result2;
@@ -280,8 +281,8 @@ var Reactor = class {
280
281
  if (this.config.referenceTracking) this.config.smartCloning && this.stamp(object), this.unlink(oldValue?.[RAW] || oldValue, object, keyStr);
281
282
  if (this.watchers || this.listeners)
282
283
  for (let i = 0; i < loopLen; i++) {
283
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver };
284
- this.notify(currPath, { type: "delete", target, currentTarget: target, root: this.core, rejectable });
284
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
285
+ this.notify(currPath, { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable });
285
286
  }
286
287
  return true;
287
288
  },
@@ -307,7 +308,7 @@ var Reactor = class {
307
308
  return ownKeys;
308
309
  }
309
310
  });
310
- return this.proxyCache.set(obj, proxy), proxy;
311
+ return this.proxyCache.set(target, proxy), proxy;
311
312
  }
312
313
  trace(target, path, paths = [], seen = /* @__PURE__ */ new WeakSet()) {
313
314
  if (Object.is(target, this.core[RAW] || this.core)) return paths.push(path), paths;
@@ -399,7 +400,7 @@ var Reactor = class {
399
400
  fire([path, object, value], e, isCapture, cords = this.listeners.get(path)) {
400
401
  if (!cords) return;
401
402
  e.type = path !== e.target.path ? "update" : e.staticType;
402
- e.currentTarget = { path, value, oldValue: e.type !== "update" ? e.target.oldValue : void 0, key: e.type !== "update" ? path : path.slice(path.lastIndexOf(".") + 1) || "", keyExisted: e.type !== "update" ? e.target.keyExisted : true, object };
403
+ e.currentTarget = { path, value, oldValue: e.type !== "update" ? e.target.oldValue : void 0, key: e.type !== "update" ? path : path.slice(path.lastIndexOf(".") + 1) || "", hadKey: e.type !== "update" ? e.target.hadKey : true, object };
403
404
  for (let i = 0, len = cords.length, tDepth; i < len; i++) {
404
405
  if (e.immediatePropagationStopped) break;
405
406
  if (cords[i].capture !== isCapture) continue;
@@ -454,21 +455,20 @@ var Reactor = class {
454
455
  }
455
456
  getContext(path) {
456
457
  const lastDot = path.lastIndexOf("."), value = getAny(this.core, path), object = lastDot === -1 ? this.core : getAny(this.core, path.slice(0, lastDot));
457
- return { path, value, key: path.slice(lastDot + 1) || "", keyExisted: true, object };
458
+ return { path, value, key: path.slice(lastDot + 1) || "", hadKey: true, object };
458
459
  }
459
460
  bindSignal(cord, sig) {
460
461
  if (sig) sig.aborted ? cord.clup() : sig.addEventListener("abort", cord.clup, { once: true });
461
462
  return cord.sclup = !sig || sig.aborted ? NOOP : () => sig.removeEventListener("abort", cord.clup), cord.clup;
462
463
  }
463
- cloned(obj, raw, seen = /* @__PURE__ */ new WeakMap()) {
464
- if (!obj || "object" !== typeof obj) return obj;
465
- obj = obj[RAW] || obj;
466
- const cloned = seen.get(obj);
464
+ cloned(target, raw, seen = /* @__PURE__ */ new WeakMap()) {
465
+ if (!target || "object" !== typeof target) return target;
466
+ const obj = target[RAW] || target, cloned = seen.get(obj);
467
467
  if (cloned) return cloned;
468
468
  if (!canHandle(obj, this.config, false)) return obj;
469
469
  const version = obj[VERSION] || 0, cached = !raw && this.config.smartCloning && (this.snapCache ??= /* @__PURE__ */ new WeakMap()).get(obj);
470
470
  if (cached && obj[SSVERSION] === version) return cached;
471
- const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj[RAW] || obj;
471
+ const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj;
472
472
  seen.set(obj, clone);
473
473
  const keys = this.config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
474
474
  for (let i = 0, len = keys.length; i < len; i++) clone[keys[i]] = this.cloned(obj[keys[i]], raw, seen);
@@ -652,19 +652,8 @@ var Reactor = class {
652
652
  for (let i = 0, len = cords.length; i < len; i++) if (Object.is(cords[i].cb, callback) && cords[i].capture === capture) return cords[i].sclup(), cords.splice((len--, i--), 1), !cords.length && this.listeners.delete(path), true;
653
653
  return false;
654
654
  }
655
- /**
656
- * Creates a snapshot; possibly clone of state (or a state branch).
657
- * You could alternatively use or serialize your proxied state "as is" except the environment demands no proxies or new references.
658
- * @param raw Use raw (deep unproxied & uncloned) version of branch.
659
- * @param branch Branch to clone.
660
- * @returns Snapshot deep or smart (structurally shared) clone.
661
- * @example
662
- * const snap = rtr.snapshot();
663
- * @example
664
- * const snap = rtr.snapshot(false, rtr.core.history.past);
665
- */
666
- snapshot(raw = !this.config.smartCloning, branch = this.core) {
667
- return this.cloned(branch, raw);
655
+ snapshot(raw = !this.config.smartCloning, branch) {
656
+ return this.cloned(arguments.length < 2 ? this.core : branch, raw);
668
657
  }
669
658
  /**
670
659
  * Cascades object updates into direct child paths.
@@ -715,7 +704,76 @@ var Reactor = class {
715
704
  }
716
705
  };
717
706
 
707
+ // src/ts/core/mixins.ts
708
+ var methods = ["tick", "stall", "nostall", "get", "gonce", "noget", "set", "sonce", "noset", "delete", "donce", "nodelete", "watch", "wonce", "nowatch", "on", "once", "off", "snapshot", "cascade", "plugIn", "reset", "destroy"];
709
+ function reactive(target, build, preferences = NIL) {
710
+ if ("__Reactor__" in target) return target;
711
+ const descriptors = {}, rtr = getReactor(target, true, build), locks = { enumerable: false, configurable: true, writable: false }, hasAffix = !!(preferences.prefix || preferences.suffix);
712
+ for (let i = 0, len = methods.length; i < len; i++) {
713
+ let key = methods[i];
714
+ if (hasAffix) (preferences.whitelist?.includes(key) ?? true) && (key = `${preferences.prefix || ""}${key}${preferences.suffix || ""}`);
715
+ else if (preferences.whitelist?.includes(key)) continue;
716
+ descriptors[key] = { value: rtr[key].bind(rtr), ...locks };
717
+ }
718
+ descriptors["__Reactor__"] = { value: rtr, ...locks };
719
+ return Object.defineProperties(rtr.core, descriptors), rtr.core;
720
+ }
721
+ function inert(target) {
722
+ return getRaw(target)[INERTIA] = true, target;
723
+ }
724
+ function live(target) {
725
+ return delete getRaw(target)[INERTIA], target;
726
+ }
727
+ function isInert(target) {
728
+ return !!getRaw(target)[INERTIA];
729
+ }
730
+ function intent(target) {
731
+ return getRaw(target)[REJECTABLE] = true, target;
732
+ }
733
+ function state(target) {
734
+ return delete getRaw(target)[REJECTABLE], target;
735
+ }
736
+ function isIntent(target) {
737
+ return !!getRaw(target)[REJECTABLE];
738
+ }
739
+ function volatile(target) {
740
+ return getRaw(target)[INDIFFABLE] = true, target;
741
+ }
742
+ function stable(target) {
743
+ return delete getRaw(target)[INDIFFABLE], target;
744
+ }
745
+ function isVolatile(target) {
746
+ return !!getRaw(target)[INDIFFABLE];
747
+ }
748
+ function getReactor(target, create = false, build) {
749
+ return (target instanceof Reactor ? target : target.__Reactor__) || (create ? new Reactor(target, build) : void 0);
750
+ }
751
+ function getRaw(target) {
752
+ return target?.[RAW] || target;
753
+ }
754
+ function getVersion(target) {
755
+ return getRaw(target)[VERSION] || 0;
756
+ }
757
+ function getSnapshotVersion(target) {
758
+ return getRaw(target)[SSVERSION] || 0;
759
+ }
760
+
718
761
  export {
719
762
  ReactorEvent,
720
- Reactor
763
+ Reactor,
764
+ methods,
765
+ reactive,
766
+ inert,
767
+ live,
768
+ isInert,
769
+ intent,
770
+ state,
771
+ isIntent,
772
+ volatile,
773
+ stable,
774
+ isVolatile,
775
+ getReactor,
776
+ getRaw,
777
+ getVersion,
778
+ getSnapshotVersion
721
779
  };
@@ -0,0 +1,93 @@
1
+ // src/ts/utils/keys.ts
2
+ function parseKeyCombo(combo) {
3
+ const parts = cleanKeyCombo(combo).toLowerCase().split("+");
4
+ return { ctrlKey: parts.includes("ctrl"), shiftKey: parts.includes("shift"), altKey: parts.includes("alt"), metaKey: parts.includes("meta") || parts.includes("cmd"), key: parts.find((p) => !["ctrl", "shift", "alt", "meta", "cmd"].includes(p)) || "" };
5
+ }
6
+ function stringifyKeyEvent(e) {
7
+ const parts = [];
8
+ if (e.ctrlKey) parts.push("ctrl");
9
+ if (e.altKey) parts.push("alt");
10
+ if (e.shiftKey) parts.push("shift");
11
+ if (e.metaKey) parts.push("meta");
12
+ parts.push(e.key?.toLowerCase() ?? "");
13
+ return parts.join("+");
14
+ }
15
+ function cleanKeyCombo(combo) {
16
+ const clean = (combo2) => {
17
+ const m = ["ctrl", "alt", "shift", "meta"], alias = { cmd: "meta", space: " " };
18
+ if (combo2 === " " || combo2 === "+") return combo2;
19
+ combo2 = combo2.replace(/\+\s*\+$/, "+plus");
20
+ const p = combo2.toLowerCase().split("+").filter((k) => k !== "").map((k) => alias[k] || (k === "plus" ? "+" : k.trim() || " "));
21
+ return [...p.filter((k) => m.includes(k)).sort((a, b) => m.indexOf(a) - m.indexOf(b)), ...p.filter((k) => !m.includes(k)) || ""].join("+");
22
+ };
23
+ return Array.isArray(combo) ? combo.map(clean) : clean(combo);
24
+ }
25
+ function matchKeys(required, actual, strict = false) {
26
+ actual = cleanKeyCombo(actual);
27
+ const match = (required2, actual2) => {
28
+ required2 = cleanKeyCombo(required2);
29
+ if (strict) return required2 === actual2;
30
+ const reqKeys = required2.split("+"), actKeys = actual2.split("+");
31
+ return reqKeys.every((k) => actKeys.includes(k));
32
+ };
33
+ return Array.isArray(required) ? required.some((req) => match(req, actual)) : match(required, actual);
34
+ }
35
+ function getTermsForKey(combo, settings) {
36
+ const terms = { override: false, block: false, whitelisted: false, action: null }, { overrides = [], shortcuts = {}, blocks = [], strictMatches: s = false, whitelist = [] } = settings || {};
37
+ combo = cleanKeyCombo(combo);
38
+ if (matchKeys(overrides, combo, s)) terms.override = true;
39
+ if (matchKeys(blocks, combo, s)) terms.block = true;
40
+ if (matchKeys(whitelist, combo)) terms.whitelisted = true;
41
+ terms.action = Object.keys(shortcuts).find((key) => matchKeys(shortcuts[key], combo, s)) || null;
42
+ return terms;
43
+ }
44
+ function keyEventAllowed(e, settings) {
45
+ if (settings.disabled || (e.key === " " || e.key === "Enter") && (e.target?.ownerDocument || document).activeElement?.tagName === "BUTTON" || (e.target?.ownerDocument || document).activeElement?.matches("input,textarea,[contenteditable='true']")) return false;
46
+ const combo = stringifyKeyEvent(e), { override, block, action, whitelisted } = getTermsForKey(combo, settings);
47
+ if (block) return false;
48
+ if (override) e.preventDefault();
49
+ if (action) return action;
50
+ if (whitelisted) return e.key.toLowerCase();
51
+ return false;
52
+ }
53
+ var formatKeyForDisplay = (combo) => ` ${(Array.isArray(combo) ? combo : [combo]).map((c) => `(${cleanKeyCombo(c).replace(" ", "space")})`).join(" or ")}`;
54
+ function formatKeyShortcutsForDisplay(keyShortcuts) {
55
+ const shortcuts = {};
56
+ for (const action of Object.keys(keyShortcuts)) shortcuts[action] = formatKeyForDisplay(keyShortcuts[action]);
57
+ return shortcuts;
58
+ }
59
+ function parseForARIAKS(s, formatted = true) {
60
+ const m = { ctrl: "Control", cmd: "Meta", space: "Space", plus: "+" };
61
+ return (formatted && !Array.isArray(s) ? s : formatKeyForDisplay(s)).toLowerCase().replace(/[()]/g, "").replace(/\bor\b/g, " ").replace(/\w+/g, (k) => m[k] || k).replace(/\s+/g, " ").trim();
62
+ }
63
+
64
+ // src/ts/utils/dom.ts
65
+ function createEl(tag, props, dataset, styles, el = tag ? document?.createElement(tag) : null) {
66
+ return assignEl(el, props, dataset, styles), el;
67
+ }
68
+ function assignEl(el, props, dataset, styles) {
69
+ if (!el) return;
70
+ if (props) {
71
+ for (const k of Object.keys(props)) if (props[k] !== void 0) el[k] = props[k];
72
+ }
73
+ if (dataset) {
74
+ for (const k of Object.keys(dataset)) if (dataset[k] !== void 0) el.dataset[k] = String(dataset[k]);
75
+ }
76
+ if (styles) {
77
+ for (const k of Object.keys(styles)) if (styles[k] !== void 0) el.style[k] = styles[k];
78
+ }
79
+ }
80
+
81
+ export {
82
+ parseKeyCombo,
83
+ stringifyKeyEvent,
84
+ cleanKeyCombo,
85
+ matchKeys,
86
+ getTermsForKey,
87
+ keyEventAllowed,
88
+ formatKeyForDisplay,
89
+ formatKeyShortcutsForDisplay,
90
+ parseForARIAKS,
91
+ createEl,
92
+ assignEl
93
+ };
@@ -1,5 +1,7 @@
1
- // src/core/consts.ts
1
+ // src/ts/core/consts.ts
2
2
  var CTX = {
3
+ /** Flag indicating whether the application is running in development mode. */
4
+ isDevEnv: "undefined" !== typeof process ? process.env.NODE_ENV !== "production" : true,
3
5
  /** active `Autotracker` instance, override for automatic dependency collection on `Reactor` traps. */
4
6
  autotracker: null
5
7
  };
@@ -18,7 +20,7 @@ var NIL = Object.freeze({});
18
20
  var NOOP = () => {
19
21
  };
20
22
 
21
- // src/utils/obj.ts
23
+ // src/ts/utils/obj.ts
22
24
  var arrRx = /^([^\[\]]+)\[(\d+)\]$/;
23
25
  function isObj(obj, arraycheck = true) {
24
26
  return "object" === typeof obj && obj !== null && (arraycheck ? !Array.isArray(obj) : true);
@@ -1,4 +1,4 @@
1
- // src/utils/methd.ts
1
+ // src/ts/utils/methd.ts
2
2
  function onAllMethods(owner, callback, skipOwn = true, nested = false) {
3
3
  let proto = owner;
4
4
  while (proto && proto !== Object.prototype) {
@@ -31,7 +31,7 @@ function guardMethod(fn, onError = (e) => console.error(e)) {
31
31
  });
32
32
  }
33
33
 
34
- // src/utils/fn.ts
34
+ // src/ts/utils/fn.ts
35
35
  function setTimeout(handler, timeout, ...args) {
36
36
  const sig = args[0] instanceof AbortSignal ? args.shift() : void 0;
37
37
  if (sig?.aborted) return -1;
@@ -53,7 +53,7 @@ function requestAnimationFrame(callback, sig, win = window) {
53
53
  return sig.addEventListener("abort", kill, { once: true }), id;
54
54
  }
55
55
 
56
- // src/utils/num.ts
56
+ // src/ts/utils/num.ts
57
57
  function clamp(min = 0, val, max = Infinity) {
58
58
  return Math.min(Math.max(val, min), max);
59
59
  }