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
@@ -18,7 +18,7 @@ var sia = (() => {
18
18
  };
19
19
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
20
 
21
- // src/super.ts
21
+ // src/ts/super.ts
22
22
  var super_exports = {};
23
23
  __export(super_exports, {
24
24
  CTX: () => CTX,
@@ -56,8 +56,10 @@ var sia = (() => {
56
56
  volatile: () => volatile
57
57
  });
58
58
 
59
- // src/core/consts.ts
59
+ // src/ts/core/consts.ts
60
60
  var CTX = {
61
+ /** Flag indicating whether the application is running in development mode. */
62
+ isDevEnv: "undefined" !== typeof process ? process.env.NODE_ENV !== "production" : true,
61
63
  /** active `Autotracker` instance, override for automatic dependency collection on `Reactor` traps. */
62
64
  autotracker: null
63
65
  };
@@ -76,7 +78,7 @@ var sia = (() => {
76
78
  var NOOP = () => {
77
79
  };
78
80
 
79
- // src/utils/obj.ts
81
+ // src/ts/utils/obj.ts
80
82
  var arrRx = /^([^\[\]]+)\[(\d+)\]$/;
81
83
  function isObj(obj, arraycheck = true) {
82
84
  return "object" === typeof obj && obj !== null && (arraycheck ? !Array.isArray(obj) : true);
@@ -93,10 +95,10 @@ var sia = (() => {
93
95
  function getAny(source, key, separator = ".", keyFunc) {
94
96
  if (key === "*") return source;
95
97
  if (!key.includes(separator)) return source[keyFunc ? keyFunc(key) : key];
96
- const keys = key.split(separator);
98
+ const keys2 = key.split(separator);
97
99
  let currObj = source;
98
- for (let i = 0, len = keys.length; i < len; i++) {
99
- const key2 = keyFunc ? keyFunc(keys[i]) : keys[i], match = key2.includes("[") && key2.match(arrRx);
100
+ for (let i = 0, len = keys2.length; i < len; i++) {
101
+ const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(arrRx);
100
102
  if (match) {
101
103
  const [, key3, iStr] = match;
102
104
  if (!Array.isArray(currObj[key3]) || !(key3 in currObj)) return void 0;
@@ -111,9 +113,9 @@ var sia = (() => {
111
113
  function setAny(target, key, value, separator = ".", keyFunc) {
112
114
  if (key === "*") return Object.assign(target, value);
113
115
  if (!key.includes(separator)) return void (target[keyFunc ? keyFunc(key) : key] = value);
114
- const keys = key.split(separator);
115
- for (let currObj = target, i = 0, len = keys.length; i < len; i++) {
116
- const key2 = keyFunc ? keyFunc(keys[i]) : keys[i], match = key2.includes("[") && key2.match(arrRx);
116
+ const keys2 = key.split(separator);
117
+ for (let currObj = target, i = 0, len = keys2.length; i < len; i++) {
118
+ const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(arrRx);
117
119
  if (match) {
118
120
  const [, key3, iStr] = match;
119
121
  if (!Array.isArray(currObj[key3])) currObj[key3] = [];
@@ -127,14 +129,14 @@ var sia = (() => {
127
129
  }
128
130
  function deleteAny(target, key, separator = ".", keyFunc) {
129
131
  if (key === "*") {
130
- const keys2 = Object.keys(target);
131
- for (let i = 0, len = keys2.length; i < len; i++) delete target[keys2[i]];
132
+ const keys3 = Object.keys(target);
133
+ for (let i = 0, len = keys3.length; i < len; i++) delete target[keys3[i]];
132
134
  return;
133
135
  }
134
136
  if (!key.includes(separator)) return void delete target[keyFunc ? keyFunc(key) : key];
135
- const keys = key.split(separator);
136
- for (let currObj = target, i = 0, len = keys.length; i < len; i++) {
137
- const key2 = keyFunc ? keyFunc(keys[i]) : keys[i], match = key2.includes("[") && key2.match(arrRx);
137
+ const keys2 = key.split(separator);
138
+ for (let currObj = target, i = 0, len = keys2.length; i < len; i++) {
139
+ const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(arrRx);
138
140
  if (match) {
139
141
  const [, key3, iStr] = match;
140
142
  if (!Array.isArray(currObj[key3]) || !(key3 in currObj)) return;
@@ -150,9 +152,9 @@ var sia = (() => {
150
152
  function inAny(source, key, separator = ".", keyFunc) {
151
153
  if (key === "*") return true;
152
154
  if (!key.includes(separator)) return key in source;
153
- const keys = key.split(separator);
154
- for (let currObj = source, i = 0, len = keys.length; i < len; i++) {
155
- const key2 = keyFunc ? keyFunc(keys[i]) : keys[i], match = key2.includes("[") && key2.match(arrRx);
155
+ const keys2 = key.split(separator);
156
+ for (let currObj = source, i = 0, len = keys2.length; i < len; i++) {
157
+ const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(arrRx);
156
158
  if (match) {
157
159
  const [, key3, iStr] = match;
158
160
  if (!Array.isArray(currObj[key3]) || !(key3 in currObj)) return false;
@@ -192,25 +194,25 @@ var sia = (() => {
192
194
  if (!canHandle(obj, config, false)) return obj;
193
195
  const clone = config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {};
194
196
  seen.set(obj, clone);
195
- const keys = config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
196
- for (let i = 0, len = keys.length; i < len; i++) clone[keys[i]] = deepClone(obj[keys[i]], config, seen);
197
+ const keys2 = config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
198
+ for (let i = 0, len = keys2.length; i < len; i++) clone[keys2[i]] = deepClone(obj[keys2[i]], config, seen);
197
199
  return clone;
198
200
  }
199
201
  function nuke(target) {
200
202
  let proto = target;
201
203
  while (proto && proto !== Object.prototype) {
202
- const keys = Object.getOwnPropertyNames(proto);
203
- for (let i = 0, len = keys.length; i < len; i++) {
204
- if (keys[i] === "constructor") continue;
205
- const desc = Object.getOwnPropertyDescriptor(proto, keys[i]);
204
+ const keys2 = Object.getOwnPropertyNames(proto);
205
+ for (let i = 0, len = keys2.length; i < len; i++) {
206
+ if (keys2[i] === "constructor") continue;
207
+ const desc = Object.getOwnPropertyDescriptor(proto, keys2[i]);
206
208
  if (desc && ("function" === typeof desc.value || desc.get || desc.set)) continue;
207
- proto[keys[i]] = null;
209
+ proto[keys2[i]] = null;
208
210
  }
209
211
  proto = Object.getPrototypeOf(proto);
210
212
  }
211
213
  }
212
214
 
213
- // src/core/event.ts
215
+ // src/ts/core/event.ts
214
216
  var ReactorEvent = class _ReactorEvent {
215
217
  /** No active propagation phase. */
216
218
  static NONE = 0;
@@ -333,7 +335,7 @@ var sia = (() => {
333
335
  }
334
336
  };
335
337
 
336
- // src/core/reactor.ts
338
+ // src/ts/core/reactor.ts
337
339
  var Reactor = class {
338
340
  log = NOOP;
339
341
  core;
@@ -361,27 +363,27 @@ var sia = (() => {
361
363
  listeners;
362
364
  /**
363
365
  * Creates a new Reactor instance.
364
- * @param object Initial state object.
366
+ * @param target Initial state target.
365
367
  * @param build Reactor bootstrap/build configuration.
366
368
  * @example
367
369
  * const rtr = new Reactor({ count: 0 });
368
370
  */
369
- constructor(object = {}, build) {
371
+ constructor(target = {}, build) {
370
372
  this[INERTIA] = true;
371
373
  this.config = { crossRealms: false, smartCloning: false, eventBubbling: true, lineageTracing: false, preserveContext: false, equalityFunction: Object.is, batchingFunction: RTR_BATCH, ...build };
372
- this.core = this.proxied(object);
374
+ this.core = this.proxied(target);
373
375
  if (build) this.canLog = !!build.debug;
374
376
  }
375
- proxied(obj, rejectable = false, indiffable = false, parent, key, path) {
376
- if (!obj || "object" !== typeof obj) return obj;
377
- obj = obj[RAW] || obj;
378
- if (this.config.referenceTracking && parent && key && !this.link(obj, parent, key, false)) return obj;
379
- const cached = this.proxyCache.get(obj);
377
+ proxied(target, rejectable = false, indiffable = false, parent, key, path) {
378
+ if (!target || "object" !== typeof target) return target;
379
+ target = target[RAW] || target;
380
+ if (this.config.referenceTracking && parent && key && !this.link(target, parent, key, false)) return target;
381
+ const cached = this.proxyCache.get(target);
380
382
  if (cached) return cached;
381
- if (obj[INERTIA] || !canHandle(obj, this.config, false)) return obj;
382
- rejectable ||= obj[REJECTABLE];
383
- indiffable ||= obj[INDIFFABLE];
384
- const proxy = new Proxy(obj, {
383
+ if (target[INERTIA] || !canHandle(target, this.config, false)) return target;
384
+ rejectable ||= target[REJECTABLE];
385
+ indiffable ||= target[INDIFFABLE];
386
+ const proxy = new Proxy(target, {
385
387
  // Robust Proxy handler
386
388
  get: (object, key2, receiver) => {
387
389
  if (key2 === RAW) return this.log(`\u{1F440} [Reactor \`get\` Trap] Peeked at ${object}`), object;
@@ -394,10 +396,10 @@ var sia = (() => {
394
396
  for (let i = 0, len = this.config.lineageTracing ? paths.length : 1; i < len; i++) {
395
397
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.getters.get(currPath);
396
398
  if (!cords && !wildcords) continue;
397
- const target = { path: currPath, value, key: keyStr, keyExisted: true, object: receiver }, payload = { type: "get", target, currentTarget: target, root: this.core, rejectable };
399
+ const target2 = { path: currPath, value, key: keyStr, hadKey: true, object: receiver }, payload = { type: "get", target: target2, currentTarget: target2, root: this.core, rejectable };
398
400
  if (cords) value = this.mediate(currPath, payload, "get", cords);
399
401
  if (!wildcords) continue;
400
- target.value = value;
402
+ target2.value = value;
401
403
  value = this.mediate("*", payload, "get", wildcords);
402
404
  }
403
405
  }
@@ -405,7 +407,7 @@ var sia = (() => {
405
407
  },
406
408
  set: (object, key2, value, receiver) => {
407
409
  let unchanged, safeValue, safeOldValue, terminated = false;
408
- 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);
410
+ 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);
409
411
  this.log(`\u270F\uFE0F [Reactor \`set\` Trap] Initiated for "${keyStr}" on "${paths}"`), CTX.autotracker?.track(fullPath, this, true);
410
412
  if (this.config.referenceTracking || !indiffable) {
411
413
  safeOldValue = oldValue?.[RAW] || oldValue;
@@ -419,13 +421,13 @@ var sia = (() => {
419
421
  for (let i = 0; i < loopLen; i++) {
420
422
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.setters.get(currPath);
421
423
  if (!cords && !wildcords) continue;
422
- const target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver }, payload = { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable };
424
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable };
423
425
  if (cords) {
424
426
  const result2 = this.mediate(currPath, payload, "set", cords);
425
427
  if (!(terminated ||= payload.terminated)) value = result2;
426
428
  }
427
429
  if (!wildcords) continue;
428
- target.value = value;
430
+ target2.value = value;
429
431
  const result = this.mediate("*", payload, "set", wildcords);
430
432
  if (!(terminated ||= payload.terminated)) value = result;
431
433
  }
@@ -436,14 +438,14 @@ var sia = (() => {
436
438
  if (this.config.referenceTracking && !unchanged) this.config.smartCloning && this.stamp(object), this.unlink(safeOldValue, object, keyStr), this.link(safeValue, object, keyStr);
437
439
  if (this.watchers || this.listeners)
438
440
  for (let i = 0; i < loopLen; i++) {
439
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver };
440
- this.notify(currPath, { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable });
441
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
442
+ this.notify(currPath, { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable });
441
443
  }
442
444
  return true;
443
445
  },
444
446
  deleteProperty: (object, key2) => {
445
447
  let value, receiver = this.proxyCache.get(object), terminated = false;
446
- 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);
448
+ 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);
447
449
  this.log(`\u{1F5D1}\uFE0F [Reactor \`deleteProperty\` Trap] Initiated for "${keyStr}" on "${paths}"`), CTX.autotracker?.track(fullPath, this, true);
448
450
  if (this.config.deleteProperty) terminated = (value = this.config.deleteProperty(object, key2, oldValue, receiver, paths)) === TERMINATOR;
449
451
  if (this.deleters) {
@@ -451,7 +453,7 @@ var sia = (() => {
451
453
  for (let i = 0; i < loopLen; i++) {
452
454
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.deleters.get(currPath);
453
455
  if (!cords && !wildcords) continue;
454
- const target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver }, payload = { type: "delete", target, currentTarget: target, root: this.core, rejectable };
456
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable };
455
457
  if (cords) {
456
458
  const result2 = this.mediate(currPath, payload, "delete", cords);
457
459
  if (!(terminated ||= payload.terminated)) value = result2;
@@ -467,8 +469,8 @@ var sia = (() => {
467
469
  if (this.config.referenceTracking) this.config.smartCloning && this.stamp(object), this.unlink(oldValue?.[RAW] || oldValue, object, keyStr);
468
470
  if (this.watchers || this.listeners)
469
471
  for (let i = 0; i < loopLen; i++) {
470
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, keyExisted, object: receiver };
471
- this.notify(currPath, { type: "delete", target, currentTarget: target, root: this.core, rejectable });
472
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
473
+ this.notify(currPath, { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable });
472
474
  }
473
475
  return true;
474
476
  },
@@ -494,7 +496,7 @@ var sia = (() => {
494
496
  return ownKeys;
495
497
  }
496
498
  });
497
- return this.proxyCache.set(obj, proxy), proxy;
499
+ return this.proxyCache.set(target, proxy), proxy;
498
500
  }
499
501
  trace(target, path, paths = [], seen = /* @__PURE__ */ new WeakSet()) {
500
502
  if (Object.is(target, this.core[RAW] || this.core)) return paths.push(path), paths;
@@ -586,7 +588,7 @@ var sia = (() => {
586
588
  fire([path, object, value], e, isCapture, cords = this.listeners.get(path)) {
587
589
  if (!cords) return;
588
590
  e.type = path !== e.target.path ? "update" : e.staticType;
589
- 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 };
591
+ 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 };
590
592
  for (let i = 0, len = cords.length, tDepth; i < len; i++) {
591
593
  if (e.immediatePropagationStopped) break;
592
594
  if (cords[i].capture !== isCapture) continue;
@@ -641,24 +643,23 @@ var sia = (() => {
641
643
  }
642
644
  getContext(path) {
643
645
  const lastDot = path.lastIndexOf("."), value = getAny(this.core, path), object = lastDot === -1 ? this.core : getAny(this.core, path.slice(0, lastDot));
644
- return { path, value, key: path.slice(lastDot + 1) || "", keyExisted: true, object };
646
+ return { path, value, key: path.slice(lastDot + 1) || "", hadKey: true, object };
645
647
  }
646
648
  bindSignal(cord, sig) {
647
649
  if (sig) sig.aborted ? cord.clup() : sig.addEventListener("abort", cord.clup, { once: true });
648
650
  return cord.sclup = !sig || sig.aborted ? NOOP : () => sig.removeEventListener("abort", cord.clup), cord.clup;
649
651
  }
650
- cloned(obj, raw, seen = /* @__PURE__ */ new WeakMap()) {
651
- if (!obj || "object" !== typeof obj) return obj;
652
- obj = obj[RAW] || obj;
653
- const cloned = seen.get(obj);
652
+ cloned(target, raw, seen = /* @__PURE__ */ new WeakMap()) {
653
+ if (!target || "object" !== typeof target) return target;
654
+ const obj = target[RAW] || target, cloned = seen.get(obj);
654
655
  if (cloned) return cloned;
655
656
  if (!canHandle(obj, this.config, false)) return obj;
656
657
  const version = obj[VERSION] || 0, cached = !raw && this.config.smartCloning && (this.snapCache ??= /* @__PURE__ */ new WeakMap()).get(obj);
657
658
  if (cached && obj[SSVERSION] === version) return cached;
658
- const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj[RAW] || obj;
659
+ const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj;
659
660
  seen.set(obj, clone);
660
- const keys = this.config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
661
- for (let i = 0, len = keys.length; i < len; i++) clone[keys[i]] = this.cloned(obj[keys[i]], raw, seen);
661
+ const keys2 = this.config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
662
+ for (let i = 0, len = keys2.length; i < len; i++) clone[keys2[i]] = this.cloned(obj[keys2[i]], raw, seen);
662
663
  if (!raw && this.config.smartCloning) this.snapCache.set(obj, clone), obj[SSVERSION] = version;
663
664
  return clone;
664
665
  }
@@ -839,19 +840,8 @@ var sia = (() => {
839
840
  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;
840
841
  return false;
841
842
  }
842
- /**
843
- * Creates a snapshot; possibly clone of state (or a state branch).
844
- * You could alternatively use or serialize your proxied state "as is" except the environment demands no proxies or new references.
845
- * @param raw Use raw (deep unproxied & uncloned) version of branch.
846
- * @param branch Branch to clone.
847
- * @returns Snapshot deep or smart (structurally shared) clone.
848
- * @example
849
- * const snap = rtr.snapshot();
850
- * @example
851
- * const snap = rtr.snapshot(false, rtr.core.history.past);
852
- */
853
- snapshot(raw = !this.config.smartCloning, branch = this.core) {
854
- return this.cloned(branch, raw);
843
+ snapshot(raw = !this.config.smartCloning, branch) {
844
+ return this.cloned(arguments.length < 2 ? this.core : branch, raw);
855
845
  }
856
846
  /**
857
847
  * Cascades object updates into direct child paths.
@@ -864,9 +854,9 @@ var sia = (() => {
864
854
  */
865
855
  cascade({ type, currentTarget: { path, value: news, oldValue: olds } }, objectSafe = true) {
866
856
  if (type !== "set" && type !== "delete" || !canHandle(news, this.config) || (objectSafe ? !canHandle(olds, this.config) : false)) return;
867
- const obj = objectSafe ? mergeObjs(olds, news) : news, keys = Object.keys(obj);
857
+ const obj = objectSafe ? mergeObjs(olds, news) : news, keys2 = Object.keys(obj);
868
858
  this.isCascading = true;
869
- for (let i = 0, len = keys.length; i < len; i++) setAny(this.core, path === "*" ? keys[i] : path + "." + keys[i], obj[keys[i]]);
859
+ for (let i = 0, len = keys2.length; i < len; i++) setAny(this.core, path === "*" ? keys2[i] : path + "." + keys2[i], obj[keys2[i]]);
870
860
  this.isCascading = false;
871
861
  }
872
862
  /**
@@ -902,11 +892,11 @@ var sia = (() => {
902
892
  }
903
893
  };
904
894
 
905
- // src/core/mixins.ts
906
- var methods = ["tick", "stall", "nostall", "get", "gonce", "noget", "set", "sonce", "noset", "delete", "donce", "nodelete", "watch", "wonce", "nowatch", "on", "once", "off", "cascade", "snapshot", "reset", "destroy"];
895
+ // src/ts/core/mixins.ts
896
+ 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"];
907
897
  function reactive(target, build, preferences = NIL) {
908
898
  if ("__Reactor__" in target) return target;
909
- const descriptors = {}, rtr = target instanceof Reactor ? target : new Reactor(target, build), locks = { enumerable: false, configurable: true, writable: false }, hasAffix = !!(preferences.prefix || preferences.suffix);
899
+ const descriptors = {}, rtr = getReactor(target, true, build), locks = { enumerable: false, configurable: true, writable: false }, hasAffix = !!(preferences.prefix || preferences.suffix);
910
900
  for (let i = 0, len = methods.length; i < len; i++) {
911
901
  let key = methods[i];
912
902
  if (hasAffix) (preferences.whitelist?.includes(key) ?? true) && (key = `${preferences.prefix || ""}${key}${preferences.suffix || ""}`);
@@ -943,6 +933,9 @@ var sia = (() => {
943
933
  function isVolatile(target) {
944
934
  return !!getRaw(target)[INDIFFABLE];
945
935
  }
936
+ function getReactor(target, create = false, build) {
937
+ return (target instanceof Reactor ? target : target.__Reactor__) || (create ? new Reactor(target, build) : void 0);
938
+ }
946
939
  function getRaw(target) {
947
940
  return target?.[RAW] || target;
948
941
  }
@@ -953,13 +946,15 @@ var sia = (() => {
953
946
  return getRaw(target)[SSVERSION] || 0;
954
947
  }
955
948
 
956
- // src/utils.ts
949
+ // src/ts/utils.ts
957
950
  var utils_exports = {};
958
951
  __export(utils_exports, {
952
+ assignEl: () => assignEl,
959
953
  bindAllMethods: () => bindAllMethods,
960
954
  canHandle: () => canHandle,
961
955
  clamp: () => clamp,
962
956
  cleanKeyCombo: () => cleanKeyCombo,
957
+ createEl: () => createEl,
963
958
  deepClone: () => deepClone,
964
959
  deleteAny: () => deleteAny,
965
960
  formatKeyForDisplay: () => formatKeyForDisplay,
@@ -988,12 +983,12 @@ var sia = (() => {
988
983
  stringifyKeyEvent: () => stringifyKeyEvent
989
984
  });
990
985
 
991
- // src/utils/num.ts
986
+ // src/ts/utils/num.ts
992
987
  function clamp(min = 0, val, max = Infinity) {
993
988
  return Math.min(Math.max(val, min), max);
994
989
  }
995
990
 
996
- // src/utils/fn.ts
991
+ // src/ts/utils/fn.ts
997
992
  function setTimeout2(handler, timeout, ...args) {
998
993
  const sig = args[0] instanceof AbortSignal ? args.shift() : void 0;
999
994
  if (sig?.aborted) return -1;
@@ -1015,7 +1010,7 @@ var sia = (() => {
1015
1010
  return sig.addEventListener("abort", kill, { once: true }), id;
1016
1011
  }
1017
1012
 
1018
- // src/utils/methd.ts
1013
+ // src/ts/utils/methd.ts
1019
1014
  function onAllMethods(owner, callback, skipOwn = true, nested = false) {
1020
1015
  let proto = owner;
1021
1016
  while (proto && proto !== Object.prototype) {
@@ -1048,7 +1043,7 @@ var sia = (() => {
1048
1043
  });
1049
1044
  }
1050
1045
 
1051
- // src/utils/keys.ts
1046
+ // src/ts/utils/keys.ts
1052
1047
  function parseKeyCombo(combo) {
1053
1048
  const parts = cleanKeyCombo(combo).toLowerCase().split("+");
1054
1049
  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)) || "" };
@@ -1111,7 +1106,24 @@ var sia = (() => {
1111
1106
  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();
1112
1107
  }
1113
1108
 
1114
- // src/plugins.ts
1109
+ // src/ts/utils/dom.ts
1110
+ function createEl(tag, props, dataset, styles, el = tag ? document?.createElement(tag) : null) {
1111
+ return assignEl(el, props, dataset, styles), el;
1112
+ }
1113
+ function assignEl(el, props, dataset, styles) {
1114
+ if (!el) return;
1115
+ if (props) {
1116
+ for (const k of Object.keys(props)) if (props[k] !== void 0) el[k] = props[k];
1117
+ }
1118
+ if (dataset) {
1119
+ for (const k of Object.keys(dataset)) if (dataset[k] !== void 0) el.dataset[k] = String(dataset[k]);
1120
+ }
1121
+ if (styles) {
1122
+ for (const k of Object.keys(styles)) if (styles[k] !== void 0) el.style[k] = styles[k];
1123
+ }
1124
+ }
1125
+
1126
+ // src/ts/plugins.ts
1115
1127
  var plugins_exports = {};
1116
1128
  __export(plugins_exports, {
1117
1129
  BaseReactorPlugin: () => BaseReactorPlugin,
@@ -1127,7 +1139,7 @@ var sia = (() => {
1127
1139
  TimeTravelPlugin: () => TimeTravelPlugin
1128
1140
  });
1129
1141
 
1130
- // src/plugins/base.ts
1142
+ // src/ts/plugins/base.ts
1131
1143
  var BaseReactorPlugin = class {
1132
1144
  static plugName;
1133
1145
  get name() {
@@ -1165,7 +1177,7 @@ var sia = (() => {
1165
1177
  // `()=>{}`: needs to be bounded even before initialization
1166
1178
  };
1167
1179
 
1168
- // src/utils/store.ts
1180
+ // src/ts/utils/store.ts
1169
1181
  var BaseStorageAdapter = class {
1170
1182
  static name;
1171
1183
  config;
@@ -1299,7 +1311,7 @@ var sia = (() => {
1299
1311
  };
1300
1312
  var INDEXED_DB_ADAPTER_BUILD = { dbName: "REACTOR_IDB", stores: ["VAULT"], version: 1, onidb: NOOP, onupgradeneeded: NOOP, onversionchange: NOOP, onsuccess: NOOP, onerror: NOOP, onblocked: NOOP };
1301
1313
 
1302
- // src/plugins/persist.ts
1314
+ // src/ts/plugins/persist.ts
1303
1315
  var PersistPlugin = class extends BaseReactorPlugin {
1304
1316
  static plugName = "persist";
1305
1317
  adapter;
@@ -1352,12 +1364,13 @@ var sia = (() => {
1352
1364
  };
1353
1365
  var PERSIST_PLUGIN_BUILD = { disabled: false, key: "REACTOR_STORE", throttle: 2500, useSnapshot: false };
1354
1366
 
1355
- // src/plugins/timeTravel.ts
1367
+ // src/ts/plugins/timeTravel.ts
1356
1368
  var TimeTravelPlugin = class extends BaseReactorPlugin {
1357
1369
  static plugName = "timeTravel";
1370
+ lastTimestamp = 0;
1358
1371
  playbackTimeoutId = -1;
1359
1372
  constructor(config, rtr) {
1360
- super({ ...TIME_TRAVEL_PLUGIN_BUILD, ...config }, rtr, { history: [], initialState: null, currentFrame: 0, paused: true });
1373
+ super({ ...TIME_TRAVEL_PLUGIN_BUILD, ...config }, rtr, { initialState: null, history: [], currentFrame: 0, paused: true });
1361
1374
  }
1362
1375
  // ===========================================================================
1363
1376
  // THE FOUNDATION & WIRETAP (Passive Recording)
@@ -1365,6 +1378,7 @@ var sia = (() => {
1365
1378
  wire() {
1366
1379
  this.rtr.config.referenceTracking = this.rtr.config.smartCloning = this.rtr.config.eventTimeStamps = true;
1367
1380
  if (!this.state.history.length || this.state.initialState == null) this.state.initialState = this.rtr.snapshot();
1381
+ this.lastTimestamp = performance.now();
1368
1382
  this.state.set("currentFrame", (v = 0) => clamp(0, v, this.state.history.length), { signal: this.signal, immediate: true });
1369
1383
  this.config.on("paths", this.handlePathsState, { signal: this.signal, immediate: true });
1370
1384
  !this.state.paused && this.play();
@@ -1378,16 +1392,17 @@ var sia = (() => {
1378
1392
  if (!this.state.paused) return;
1379
1393
  if (this.state.currentFrame < this.state.history.length) this.state.history = this.state.history.slice(0, this.state.currentFrame);
1380
1394
  if (this.state.history.length >= this.config.maxHistoryLength) this.state.history = this.state.history.slice(1);
1381
- this.state.history.push({ timestamp: e.timestamp ?? performance.now(), path: e.target.path, type: e.staticType, value: this.rtr.snapshot(false, e.target.value), oldValue: this.rtr.snapshot(false, e.target.oldValue), keyExisted: e.target.keyExisted, rejected: e.rejected });
1395
+ this.state.history.push({ path: e.target.path, value: this.rtr.snapshot(false, e.target.value), oldValue: this.rtr.snapshot(false, e.target.oldValue), type: e.staticType, rejected: e.rejected, timedelta: e.timestamp - this.lastTimestamp, hadKey: e.target.hadKey });
1382
1396
  this.state.currentFrame = this.state.history.length;
1397
+ this.lastTimestamp = e.timestamp;
1383
1398
  }
1384
1399
  /** Clears timeline history and resets playhead/genesis to the current reactor state. */
1385
1400
  clear() {
1386
1401
  this.pause();
1387
1402
  this.playbackTimeoutId = -1;
1388
- this.state.history = [];
1389
- this.state.currentFrame = 0;
1403
+ this.state.history.length = this.state.currentFrame = 0;
1390
1404
  this.state.initialState = this.rtr.snapshot();
1405
+ this.lastTimestamp = performance.now();
1391
1406
  }
1392
1407
  // ===========================================================================
1393
1408
  // THE TIME MACHINE (Manual Controls)
@@ -1400,7 +1415,7 @@ var sia = (() => {
1400
1415
  const e = this.state.history[forward ? this.state.currentFrame : this.state.currentFrame - 1];
1401
1416
  if (!e) break;
1402
1417
  if (forward) e.type === "delete" ? deleteAny(this.rtr.core, e.path) : setAny(this.rtr.core, e.path, deepClone(e.value, this.rtr.config));
1403
- else !e.keyExisted ? deleteAny(this.rtr.core, e.path) : setAny(this.rtr.core, e.path, deepClone(e.oldValue, this.rtr.config));
1418
+ else !e.hadKey ? deleteAny(this.rtr.core, e.path) : setAny(this.rtr.core, e.path, deepClone(e.oldValue, this.rtr.config));
1404
1419
  forward ? this.state.currentFrame++ : this.state.currentFrame--;
1405
1420
  if (e.rejected) this.rtr.log(`[Reactor ${this.name} Plug] ${forward ? "Replaying" : "Reversing"} REJECTED intent at "${e.path}"`);
1406
1421
  }
@@ -1423,9 +1438,9 @@ var sia = (() => {
1423
1438
  async automove(forward = true) {
1424
1439
  this.state.paused = false;
1425
1440
  while ((forward ? this.state.currentFrame < this.state.history.length : this.state.currentFrame > 0) && !this.state.paused) {
1426
- const currIndex = forward ? this.state.currentFrame : this.state.currentFrame - 1, e = this.state.history[currIndex], nextE = this.state.history[forward ? currIndex + 1 : currIndex - 1], delay = nextE && e ? Math.abs(nextE.timestamp - e.timestamp) : 0;
1441
+ const currIndex = forward ? this.state.currentFrame : this.state.currentFrame - 1, e = this.state.history[forward ? currIndex + 1 : currIndex - 1];
1427
1442
  this.jumpTo(this.state.currentFrame + (forward ? 1 : -1), true);
1428
- if (delay > 0) await new Promise((res) => this.playbackTimeoutId = setTimeout2(() => res(0), clamp(0, delay, this.config.maxPlaybackDelay), this.signal));
1443
+ if (e?.timedelta > 0) await new Promise((res) => this.playbackTimeoutId = setTimeout2(() => res(0), Math.min(e.timedelta, this.config.maxPlaybackDelay), this.signal));
1429
1444
  }
1430
1445
  this.state.paused = true;
1431
1446
  }
@@ -1439,35 +1454,39 @@ var sia = (() => {
1439
1454
  // TELEMETRY & I/O (Session Import/Export)
1440
1455
  // ===========================================================================
1441
1456
  /** Exports the current session as a JSON string. */
1442
- export() {
1443
- return JSON.stringify(this.state);
1457
+ export(replacer, space) {
1458
+ try {
1459
+ return JSON.stringify(this.state, replacer, space);
1460
+ } catch (e) {
1461
+ return this.rtr.log(`[Reactor ${this.name} Plug] Failed to export session`), "";
1462
+ }
1444
1463
  }
1445
1464
  /** Imports a session from a JSON string, allowing you to replay or analyze past states. */
1446
1465
  import(json) {
1447
1466
  try {
1448
1467
  setAny(this.state, "*", JSON.parse(json));
1468
+ this.lastTimestamp = performance.now();
1449
1469
  const resume = !this.state.paused, target = this.state.currentFrame;
1450
1470
  this.state.paused = false;
1451
- setAny(this.rtr.core, "*", deepClone(this.state.initialState, this.rtr.config));
1452
- this.rtr.tick();
1453
- this.state.currentFrame = 0;
1454
- this.jumpTo(target), resume && this.play();
1471
+ setAny(this.rtr.core, "*", deepClone(this.state.initialState, this.rtr.config)), this.rtr.tick();
1472
+ this.state.currentFrame = 0, this.jumpTo(target), resume && this.play();
1455
1473
  } catch (e) {
1456
- this.rtr.log(`[Reactor ${this.name} Plug] Failed to load session`, "error");
1474
+ this.rtr.log(`[Reactor ${this.name} Plug] Failed to load session`);
1457
1475
  }
1458
1476
  }
1459
1477
  };
1460
1478
  var TIME_TRAVEL_PLUGIN_BUILD = { maxPlaybackDelay: 2e3 };
1461
1479
 
1462
- // src/adapters/vanilla.ts
1480
+ // src/ts/adapters/vanilla.ts
1463
1481
  var vanilla_exports = {};
1464
1482
  __export(vanilla_exports, {
1465
1483
  Autotracker: () => Autotracker,
1484
+ TimeTravelOverlay: () => TimeTravelOverlay,
1466
1485
  effect: () => effect,
1467
1486
  withTracker: () => withTracker
1468
1487
  });
1469
1488
 
1470
- // src/adapters/autotracker.ts
1489
+ // src/ts/adapters/autotracker.ts
1471
1490
  var Autotracker = class {
1472
1491
  proxy;
1473
1492
  deps = /* @__PURE__ */ new Map();
@@ -1609,7 +1628,7 @@ var sia = (() => {
1609
1628
  }
1610
1629
  }
1611
1630
 
1612
- // src/adapters/vanilla/effect.ts
1631
+ // src/ts/adapters/vanilla/effect.ts
1613
1632
  function effect(callback, options) {
1614
1633
  const atrkr = new Autotracker();
1615
1634
  let destroyed = false;
@@ -1619,7 +1638,83 @@ var sia = (() => {
1619
1638
  return () => (destroyed = true, atrkr.destroy());
1620
1639
  }
1621
1640
 
1622
- // src/super.ts
1641
+ // src/ts/adapters/vanilla/TimeTravelOverlay.ts
1642
+ var keys = {
1643
+ overrides: ["Ctrl+z", "Cmd+z", "Ctrl+y", "Cmd+y", "Ctrl+Shift+z", "Cmd+Shift+z", "Ctrl+g", "Cmd+g", ",", ".", "ArrowLeft", "ArrowRight", "Space", "Alt+Space", "Escape", "Delete", "e", "i", "c"],
1644
+ shortcuts: { undo: ["Ctrl+z", "Cmd+z"], redo: ["Ctrl+y", "Cmd+y", "Ctrl+Shift+z", "Cmd+Shift+z"], genesis: ["Ctrl+g", "Cmd+g"], prevFrame: ",", nextFrame: ".", skipBwd: "ArrowLeft", skipFwd: "ArrowRight", playPause: "Space", rewind: "Alt+Space", closeOverlay: "Escape", clrHistory: "Delete", export: "e", import: "i", clear: "c" }
1645
+ };
1646
+ var TimeTravelOverlay = class _TimeTravelOverlay {
1647
+ static count = 0;
1648
+ index = _TimeTravelOverlay.count;
1649
+ config;
1650
+ state = reactive({ open: false, import: "" });
1651
+ time;
1652
+ els;
1653
+ clups = [];
1654
+ keyup;
1655
+ /** Creates a docked TimeTravel overlay bound to a plugin instance.
1656
+ * @param time TimeTravel plugin instance that owns timeline operations.
1657
+ * @param build Optional initial overlay config overrides.
1658
+ */
1659
+ constructor(time, build = {}) {
1660
+ this.time = time;
1661
+ this.config = reactive({ title: `Time Travel Overlay ${this.index = ++_TimeTravelOverlay.count}`, ...build });
1662
+ this.state.open = !!this.config.startOpen;
1663
+ const s = this.time.state, host = createEl("div", { className: "tt-overlay-host" }), toggle = createEl("button", { className: "tt-overlay-toggle", type: "button", onclick: () => this.state.open = !this.state.open }), panel = createEl("aside", { className: "tt-overlay", ariaLabel: "time travel overlay" }), title = createEl("div", { className: "title" }), frame = createEl("span", { className: "muted" }), clrHistory = createEl("button", { textContent: `Clear History${formatKeyForDisplay(keys.shortcuts.clrHistory)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.clrHistory, false), onclick: () => (this.time.clear(), this.state.import = "") }), undo = createEl("button", { textContent: `Undo${formatKeyForDisplay(keys.shortcuts.undo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.undo, false), onclick: this.time.undo }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: this.time.redo }), genesis = createEl("button", { textContent: `Genesis${formatKeyForDisplay(keys.shortcuts.genesis[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.genesis, false), onclick: () => this.time.jumpTo(0) }), playPause = createEl("button", { onclick: () => this.time[s.paused ? "play" : "pause"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.playPause, false) }), rewind = createEl("button", { textContent: `Rewind${formatKeyForDisplay(keys.shortcuts.rewind)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.rewind, false), onclick: this.time.rewind }), range = createEl("input", { type: "range", min: "0", max: "0", value: "0", title: "time travel frame", ariaLabel: "time travel frame", oninput: () => this.time.jumpTo(Number(range.value)) }), exp = createEl("button", { textContent: `Export${formatKeyForDisplay(keys.shortcuts.export)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.export, false), onclick: () => this.state.import = this.time.export(null, 2) }), imp = createEl("button", { textContent: `Import${formatKeyForDisplay(keys.shortcuts.import)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.import, false), onclick: () => this.state.import.trim().length && this.time.import(this.state.import) }), clr = createEl("button", { textContent: `Clear${formatKeyForDisplay(keys.shortcuts.clear)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.clear, false), onclick: () => this.state.import = "" }), payload = createEl("textarea", { className: "tt-io", readOnly: true, placeholder: "current payload json", title: "current payload" }), io = createEl("textarea", { className: "tt-io", placeholder: "timeline payload json", oninput: () => this.state.import = io.value }), foot = createEl("p", { className: "tt-footnote", textContent: "Want this in your app? " }), link = createEl("a", { target: "_blank", rel: "noreferrer noopener", textContent: "sia-reactor", href: "https://www.npmjs.com/package/sia-reactor" }), box = createEl("div", { className: "tt-status-box" }), status = createEl("div", { className: "tt-status-row" }), row1 = createEl("div", { className: "tt-row" }), row2 = createEl("div", { className: "tt-row" }), row3 = createEl("div", { className: "tt-row" });
1664
+ status.append((box.append(frame), box), clrHistory);
1665
+ panel.append(title, status, (row1.append(undo, redo, genesis), row1), (row2.append(playPause, rewind), row2), payload, range, (row3.append(exp, imp, clr), row3), io, (foot.appendChild(link), foot));
1666
+ host.append(toggle, panel);
1667
+ this.els = { host, toggle, panel, title, frame, clrHistory, undo, redo, genesis, playPause, rewind, range, exp, imp, clr, payload, io };
1668
+ this.keyup = (e) => {
1669
+ const a = this.state.open && keyEventAllowed(e, keys);
1670
+ a === "undo" ? this.time.undo() : a === "redo" ? this.time.redo() : a === "genesis" ? this.time.jumpTo(0) : a === "prevFrame" ? this.time.step(1, false) : a === "nextFrame" ? this.time.step(1, true) : a === "skipBwd" ? this.time.step(5, false) : a === "skipFwd" ? this.time.step(5, true) : a === "rewind" ? this.time.rewind() : a === "playPause" ? this.time[s.paused ? "play" : "pause"]() : a === "clrHistory" ? this.time.clear() : a === "closeOverlay" ? this.state.open = false : a === "export" ? this.state.import = this.time.export() : a === "import" ? this.state.import.trim().length && this.time.import(this.state.import) : a === "clear" && (this.state.import = "");
1671
+ };
1672
+ window.addEventListener("keydown", this.keyup);
1673
+ const sync = [
1674
+ effect(() => this.config.color ? host.style.setProperty("--sia-tt-color", this.config.color) : host.style.removeProperty("--sia-tt-color")),
1675
+ effect(() => {
1676
+ if (this.config.devOnly && !CTX.isDevEnv) return void host.remove();
1677
+ const dock = getDock(this.config.container);
1678
+ if (host.parentNode !== dock) dock.appendChild(host);
1679
+ }),
1680
+ effect(() => toggle.textContent = `${(panel.hidden = !this.state.open) ? "Show" : "Hide"} ${title.textContent = this.config.title ?? ""}`),
1681
+ effect(() => playPause.textContent = `${s.paused ? "Play" : "Pause"}${formatKeyForDisplay(keys.shortcuts.playPause)}`),
1682
+ effect(() => {
1683
+ frame.textContent = `Frame: ${s.currentFrame} / ${s.history.length}`;
1684
+ range.disabled = clrHistory.disabled = !s.history.length;
1685
+ genesis.disabled = rewind.disabled = undo.disabled = !s.currentFrame;
1686
+ playPause.disabled = redo.disabled = s.currentFrame >= s.history.length;
1687
+ range.max = String(s.history.length);
1688
+ range.value = String(Math.min(s.currentFrame, s.history.length));
1689
+ payload.value = JSON.stringify(s.currentFrame ? s.history[s.currentFrame - 1] : { type: "genesis", value: s.initialState }, null, 2);
1690
+ }),
1691
+ effect(() => {
1692
+ clr.disabled = imp.disabled = !this.state.import.trim().length;
1693
+ io.value !== this.state.import && (io.value = this.state.import);
1694
+ })
1695
+ ];
1696
+ this.clups.push(...sync);
1697
+ }
1698
+ destroy() {
1699
+ this.clups.forEach((fn) => fn());
1700
+ this.keyup && window.removeEventListener("keydown", this.keyup);
1701
+ this.els.host.remove();
1702
+ nuke(this), --_TimeTravelOverlay.count;
1703
+ }
1704
+ };
1705
+ function getDirChild(parent, className) {
1706
+ for (const child of parent.children) if (child instanceof HTMLElement && child.classList.contains(className)) return child;
1707
+ }
1708
+ function getDock(container) {
1709
+ const host = container && container !== document.documentElement ? container : document.body;
1710
+ if (host !== document.body && getComputedStyle(host).position === "static") host.style.position = "relative";
1711
+ const layer = getDirChild(host, "tt-overlay-layer") || createEl("div", { className: "tt-overlay-layer" }, void 0, { position: host === document.body ? "fixed" : "absolute" });
1712
+ if (layer.parentElement !== host) host.appendChild(layer);
1713
+ const dock = getDirChild(layer, "tt-overlay-dock") || createEl("div", { className: "tt-overlay-dock" });
1714
+ return dock.parentElement !== layer && layer.appendChild(dock), dock;
1715
+ }
1716
+
1717
+ // src/ts/super.ts
1623
1718
  var adapters = { vanilla: vanilla_exports };
1624
1719
  return __toCommonJS(super_exports);
1625
1720
  })();