sia-reactor 0.0.20 → 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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  reactive
3
- } from "./chunk-VPR5SP3E.js";
3
+ } from "./chunk-2WBPGSRL.js";
4
4
  import {
5
5
  createEl,
6
6
  formatKeyForDisplay,
@@ -187,41 +187,16 @@ var TimeTravelOverlay = class _TimeTravelOverlay {
187
187
  */
188
188
  constructor(time, build = {}) {
189
189
  this.time = time;
190
- this.config = reactive({ container: document.body, color: "", startOpen: false, devOnly: true, title: `Time Travel Overlay ${this.index = ++_TimeTravelOverlay.count}`, ...build });
190
+ this.config = reactive({ title: `Time Travel Overlay ${this.index = ++_TimeTravelOverlay.count}`, ...build });
191
191
  this.state.open = !!this.config.startOpen;
192
- const host = createEl("div", { className: "tt-overlay-host" });
193
- const toggle = createEl("button", { className: "tt-overlay-toggle", type: "button", onclick: () => this.state.open = !this.state.open });
194
- const panel = createEl("aside", { className: "tt-overlay", ariaLabel: "time travel overlay" });
195
- const title = createEl("div", { className: "title" });
196
- const frame = createEl("span", { className: "muted" });
197
- const history = createEl("span", { className: "muted" });
198
- const paused = createEl("span", { className: "muted" });
199
- const clrHistory = createEl("button", { textContent: `Clear History${formatKeyForDisplay(keys.shortcuts.clrHistory)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.clrHistory, false), onclick: () => (this.time.clear(), this.state.import = "") });
200
- const undo = createEl("button", { textContent: `Undo${formatKeyForDisplay(keys.shortcuts.undo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.undo, false), onclick: this.time.undo });
201
- const redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: this.time.redo });
202
- const genesis = createEl("button", { textContent: `Genesis${formatKeyForDisplay(keys.shortcuts.genesis[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.genesis, false), onclick: () => this.time.jumpTo(0) });
203
- const playPause = createEl("button", { onclick: () => this.time[this.time.state.paused ? "play" : "pause"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.playPause, false) });
204
- const rewind = createEl("button", { textContent: `Rewind${formatKeyForDisplay(keys.shortcuts.rewind)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.rewind, false), onclick: this.time.rewind });
205
- const 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)) });
206
- const exp = createEl("button", { textContent: `Export${formatKeyForDisplay(keys.shortcuts.export)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.export, false), onclick: () => this.state.import = this.time.export() });
207
- const 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) });
208
- const clr = createEl("button", { textContent: `Clear${formatKeyForDisplay(keys.shortcuts.clear)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.clear, false), onclick: () => this.state.import = "" });
209
- const io = createEl("textarea", { className: "tt-io", placeholder: "timeline payload json", oninput: () => this.state.import = io.value });
210
- const foot = createEl("p", { className: "tt-footnote", textContent: "Want this in your app? " });
211
- const link = createEl("a", { target: "_blank", rel: "noreferrer noopener", textContent: "sia-reactor", href: "https://www.npmjs.com/package/sia-reactor" });
212
- const box = createEl("div", { className: "tt-status-box" });
213
- const status = createEl("div", { className: "tt-status-row" });
214
- const row1 = createEl("div", { className: "tt-row" });
215
- const row2 = createEl("div", { className: "tt-row" });
216
- const row3 = createEl("div", { className: "tt-row" });
217
- status.append((box.append(frame, history, paused), box), clrHistory);
218
- panel.append(title, status, (row1.append(undo, redo, genesis), row1), (row2.append(playPause, rewind), row2), range, (row3.append(exp, imp, clr), row3), io, (foot.appendChild(link), foot));
192
+ 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" });
193
+ status.append((box.append(frame), box), clrHistory);
194
+ 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));
219
195
  host.append(toggle, panel);
220
- this.els = { host, toggle, panel, title, frame, history, paused, clrHistory, undo, redo, genesis, playPause, rewind, range, exp, imp, clr, io };
196
+ this.els = { host, toggle, panel, title, frame, clrHistory, undo, redo, genesis, playPause, rewind, range, exp, imp, clr, payload, io };
221
197
  this.keyup = (e) => {
222
- if (!this.state.open) return;
223
- const a = keyEventAllowed(e, keys);
224
- 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[this.time.state.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 = "");
198
+ const a = this.state.open && keyEventAllowed(e, keys);
199
+ 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 = "");
225
200
  };
226
201
  window.addEventListener("keydown", this.keyup);
227
202
  const sync = [
@@ -231,26 +206,19 @@ var TimeTravelOverlay = class _TimeTravelOverlay {
231
206
  const dock = getDock(this.config.container);
232
207
  if (host.parentNode !== dock) dock.appendChild(host);
233
208
  }),
234
- effect(() => (toggle.textContent = `${this.state.open ? "Hide" : "Show"} ${this.config.title ?? ""}`, panel.hidden = !this.state.open)),
209
+ effect(() => toggle.textContent = `${(panel.hidden = !this.state.open) ? "Show" : "Hide"} ${title.textContent = this.config.title ?? ""}`),
210
+ effect(() => playPause.textContent = `${s.paused ? "Play" : "Pause"}${formatKeyForDisplay(keys.shortcuts.playPause)}`),
235
211
  effect(() => {
236
- title.textContent = this.config.title ?? "";
237
- frame.textContent = `Frame: ${this.time.state.currentFrame} / ${this.time.state.history.length}`;
238
- history.textContent = `History: ${this.time.state.history.length}`;
239
- paused.textContent = `Paused: ${this.time.state.paused ? "Yes" : "No"}`;
240
- playPause.textContent = `${this.time.state.paused ? "Play" : "Pause"}${formatKeyForDisplay(keys.shortcuts.playPause)}`;
212
+ frame.textContent = `Frame: ${s.currentFrame} / ${s.history.length}`;
213
+ range.disabled = clrHistory.disabled = !s.history.length;
214
+ genesis.disabled = rewind.disabled = undo.disabled = !s.currentFrame;
215
+ playPause.disabled = redo.disabled = s.currentFrame >= s.history.length;
216
+ range.max = String(s.history.length);
217
+ range.value = String(Math.min(s.currentFrame, s.history.length));
218
+ payload.value = JSON.stringify(s.currentFrame ? s.history[s.currentFrame - 1] : { type: "genesis", value: s.initialState }, null, 2);
241
219
  }),
242
220
  effect(() => {
243
- clrHistory.disabled = !this.time.state.history.length;
244
- undo.disabled = this.time.state.currentFrame <= 0;
245
- redo.disabled = this.time.state.currentFrame >= this.time.state.history.length;
246
- genesis.disabled = this.time.state.currentFrame <= 0;
247
- playPause.disabled = this.time.state.currentFrame === this.time.state.history.length;
248
- rewind.disabled = !this.time.state.currentFrame;
249
- range.max = String(this.time.state.history.length);
250
- range.value = String(Math.min(this.time.state.currentFrame, this.time.state.history.length));
251
- range.disabled = !this.time.state.history.length;
252
- imp.disabled = !this.state.import.trim().length;
253
- clr.disabled = !this.state.import.trim().length;
221
+ clr.disabled = imp.disabled = !this.state.import.trim().length;
254
222
  io.value !== this.state.import && (io.value = this.state.import);
255
223
  })
256
224
  ];
@@ -769,13 +769,13 @@ declare class Reactor<T extends object> {
769
769
  protected listeners?: Map<WildPaths<T>, Array<ListenerRecord<T>>>;
770
770
  /**
771
771
  * Creates a new Reactor instance.
772
- * @param object Initial state object.
772
+ * @param target Initial state target.
773
773
  * @param build Reactor bootstrap/build configuration.
774
774
  * @example
775
775
  * const rtr = new Reactor({ count: 0 });
776
776
  */
777
- constructor(object?: T, build?: ReactorBuild<T>);
778
- proxied<O extends object>(obj: O, rejectable?: boolean, indiffable?: boolean, parent?: object, key?: string, path?: string): O;
777
+ constructor(target?: T, build?: ReactorBuild<T>);
778
+ proxied<O extends object>(target: O, rejectable?: boolean, indiffable?: boolean, parent?: object, key?: string, path?: string): O;
779
779
  trace(target: object, path: string, paths?: string[], seen?: WeakSet<object>): Paths<T>[];
780
780
  protected link(target: any, parent: object, key: string, typecheck?: boolean, es?: (object | string)[]): boolean;
781
781
  protected unlink(target: any, parent: object, key: string): void;
@@ -815,7 +815,7 @@ declare class Reactor<T extends object> {
815
815
  getDepth(path: string, depth?: number): number;
816
816
  protected getContext<P extends WildPaths<T>>(path: P): Target<T, P>;
817
817
  protected bindSignal<Cb>(cord: GetterRecord<T> | SetterRecord<T> | DeleterRecord<T> | WatcherRecord<T> | ListenerRecord<T>, sig?: AbortSignal): Cb;
818
- protected cloned(obj: any, raw: boolean, seen?: WeakMap<WeakKey, any>): any;
818
+ protected cloned<O>(target: O, raw: boolean, seen?: WeakMap<WeakKey, any>): O;
819
819
  protected syncAdd<P extends WildPaths<T>>(key: "get" | "set" | "delete" | "watch", path: P, cb: any, opts: SyncOptions | undefined, onImmediate?: (immediate: boolean | "auto") => void): () => boolean | undefined;
820
820
  protected syncDrop<P extends WildPaths<T>>(store: Map<WildPaths<T>, any[]> | undefined, path: P, cb: any): boolean | undefined;
821
821
  /**
@@ -931,7 +931,8 @@ declare class Reactor<T extends object> {
931
931
  * @example
932
932
  * const snap = rtr.snapshot(false, rtr.core.history.past);
933
933
  */
934
- snapshot(raw?: boolean, branch?: T): T;
934
+ snapshot(raw?: boolean): T;
935
+ snapshot<B>(raw?: boolean, branch?: B): B;
935
936
  /**
936
937
  * Cascades object updates into direct child paths.
937
938
  * @param payload Event or payload source.
@@ -769,13 +769,13 @@ declare class Reactor<T extends object> {
769
769
  protected listeners?: Map<WildPaths<T>, Array<ListenerRecord<T>>>;
770
770
  /**
771
771
  * Creates a new Reactor instance.
772
- * @param object Initial state object.
772
+ * @param target Initial state target.
773
773
  * @param build Reactor bootstrap/build configuration.
774
774
  * @example
775
775
  * const rtr = new Reactor({ count: 0 });
776
776
  */
777
- constructor(object?: T, build?: ReactorBuild<T>);
778
- proxied<O extends object>(obj: O, rejectable?: boolean, indiffable?: boolean, parent?: object, key?: string, path?: string): O;
777
+ constructor(target?: T, build?: ReactorBuild<T>);
778
+ proxied<O extends object>(target: O, rejectable?: boolean, indiffable?: boolean, parent?: object, key?: string, path?: string): O;
779
779
  trace(target: object, path: string, paths?: string[], seen?: WeakSet<object>): Paths<T>[];
780
780
  protected link(target: any, parent: object, key: string, typecheck?: boolean, es?: (object | string)[]): boolean;
781
781
  protected unlink(target: any, parent: object, key: string): void;
@@ -815,7 +815,7 @@ declare class Reactor<T extends object> {
815
815
  getDepth(path: string, depth?: number): number;
816
816
  protected getContext<P extends WildPaths<T>>(path: P): Target<T, P>;
817
817
  protected bindSignal<Cb>(cord: GetterRecord<T> | SetterRecord<T> | DeleterRecord<T> | WatcherRecord<T> | ListenerRecord<T>, sig?: AbortSignal): Cb;
818
- protected cloned(obj: any, raw: boolean, seen?: WeakMap<WeakKey, any>): any;
818
+ protected cloned<O>(target: O, raw: boolean, seen?: WeakMap<WeakKey, any>): O;
819
819
  protected syncAdd<P extends WildPaths<T>>(key: "get" | "set" | "delete" | "watch", path: P, cb: any, opts: SyncOptions | undefined, onImmediate?: (immediate: boolean | "auto") => void): () => boolean | undefined;
820
820
  protected syncDrop<P extends WildPaths<T>>(store: Map<WildPaths<T>, any[]> | undefined, path: P, cb: any): boolean | undefined;
821
821
  /**
@@ -931,7 +931,8 @@ declare class Reactor<T extends object> {
931
931
  * @example
932
932
  * const snap = rtr.snapshot(false, rtr.core.history.past);
933
933
  */
934
- snapshot(raw?: boolean, branch?: T): T;
934
+ snapshot(raw?: boolean): T;
935
+ snapshot<B>(raw?: boolean, branch?: B): B;
935
936
  /**
936
937
  * Cascades object updates into direct child paths.
937
938
  * @param payload Event or payload source.
package/dist/index.cjs CHANGED
@@ -342,27 +342,27 @@ var Reactor = class {
342
342
  listeners;
343
343
  /**
344
344
  * Creates a new Reactor instance.
345
- * @param object Initial state object.
345
+ * @param target Initial state target.
346
346
  * @param build Reactor bootstrap/build configuration.
347
347
  * @example
348
348
  * const rtr = new Reactor({ count: 0 });
349
349
  */
350
- constructor(object = {}, build) {
350
+ constructor(target = {}, build) {
351
351
  this[INERTIA] = true;
352
352
  this.config = { crossRealms: false, smartCloning: false, eventBubbling: true, lineageTracing: false, preserveContext: false, equalityFunction: Object.is, batchingFunction: RTR_BATCH, ...build };
353
- this.core = this.proxied(object);
353
+ this.core = this.proxied(target);
354
354
  if (build) this.canLog = !!build.debug;
355
355
  }
356
- proxied(obj, rejectable = false, indiffable = false, parent, key, path) {
357
- if (!obj || "object" !== typeof obj) return obj;
358
- obj = obj[RAW] || obj;
359
- if (this.config.referenceTracking && parent && key && !this.link(obj, parent, key, false)) return obj;
360
- const cached = this.proxyCache.get(obj);
356
+ proxied(target, rejectable = false, indiffable = false, parent, key, path) {
357
+ if (!target || "object" !== typeof target) return target;
358
+ target = target[RAW] || target;
359
+ if (this.config.referenceTracking && parent && key && !this.link(target, parent, key, false)) return target;
360
+ const cached = this.proxyCache.get(target);
361
361
  if (cached) return cached;
362
- if (obj[INERTIA] || !canHandle(obj, this.config, false)) return obj;
363
- rejectable ||= obj[REJECTABLE];
364
- indiffable ||= obj[INDIFFABLE];
365
- const proxy = new Proxy(obj, {
362
+ if (target[INERTIA] || !canHandle(target, this.config, false)) return target;
363
+ rejectable ||= target[REJECTABLE];
364
+ indiffable ||= target[INDIFFABLE];
365
+ const proxy = new Proxy(target, {
366
366
  // Robust Proxy handler
367
367
  get: (object, key2, receiver) => {
368
368
  if (key2 === RAW) return this.log(`\u{1F440} [Reactor \`get\` Trap] Peeked at ${object}`), object;
@@ -375,10 +375,10 @@ var Reactor = class {
375
375
  for (let i = 0, len = this.config.lineageTracing ? paths.length : 1; i < len; i++) {
376
376
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.getters.get(currPath);
377
377
  if (!cords && !wildcords) continue;
378
- const target = { path: currPath, value, key: keyStr, hadKey: true, object: receiver }, payload = { type: "get", target, currentTarget: target, root: this.core, rejectable };
378
+ const target2 = { path: currPath, value, key: keyStr, hadKey: true, object: receiver }, payload = { type: "get", target: target2, currentTarget: target2, root: this.core, rejectable };
379
379
  if (cords) value = this.mediate(currPath, payload, "get", cords);
380
380
  if (!wildcords) continue;
381
- target.value = value;
381
+ target2.value = value;
382
382
  value = this.mediate("*", payload, "get", wildcords);
383
383
  }
384
384
  }
@@ -400,13 +400,13 @@ var Reactor = class {
400
400
  for (let i = 0; i < loopLen; i++) {
401
401
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.setters.get(currPath);
402
402
  if (!cords && !wildcords) continue;
403
- const target = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable };
403
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable };
404
404
  if (cords) {
405
405
  const result2 = this.mediate(currPath, payload, "set", cords);
406
406
  if (!(terminated ||= payload.terminated)) value = result2;
407
407
  }
408
408
  if (!wildcords) continue;
409
- target.value = value;
409
+ target2.value = value;
410
410
  const result = this.mediate("*", payload, "set", wildcords);
411
411
  if (!(terminated ||= payload.terminated)) value = result;
412
412
  }
@@ -417,8 +417,8 @@ var Reactor = class {
417
417
  if (this.config.referenceTracking && !unchanged) this.config.smartCloning && this.stamp(object), this.unlink(safeOldValue, object, keyStr), this.link(safeValue, object, keyStr);
418
418
  if (this.watchers || this.listeners)
419
419
  for (let i = 0; i < loopLen; i++) {
420
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
421
- this.notify(currPath, { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable });
420
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
421
+ this.notify(currPath, { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable });
422
422
  }
423
423
  return true;
424
424
  },
@@ -432,7 +432,7 @@ var Reactor = class {
432
432
  for (let i = 0; i < loopLen; i++) {
433
433
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.deleters.get(currPath);
434
434
  if (!cords && !wildcords) continue;
435
- const target = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "delete", target, currentTarget: target, root: this.core, rejectable };
435
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable };
436
436
  if (cords) {
437
437
  const result2 = this.mediate(currPath, payload, "delete", cords);
438
438
  if (!(terminated ||= payload.terminated)) value = result2;
@@ -448,8 +448,8 @@ var Reactor = class {
448
448
  if (this.config.referenceTracking) this.config.smartCloning && this.stamp(object), this.unlink(oldValue?.[RAW] || oldValue, object, keyStr);
449
449
  if (this.watchers || this.listeners)
450
450
  for (let i = 0; i < loopLen; i++) {
451
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
452
- this.notify(currPath, { type: "delete", target, currentTarget: target, root: this.core, rejectable });
451
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
452
+ this.notify(currPath, { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable });
453
453
  }
454
454
  return true;
455
455
  },
@@ -475,7 +475,7 @@ var Reactor = class {
475
475
  return ownKeys;
476
476
  }
477
477
  });
478
- return this.proxyCache.set(obj, proxy), proxy;
478
+ return this.proxyCache.set(target, proxy), proxy;
479
479
  }
480
480
  trace(target, path, paths = [], seen = /* @__PURE__ */ new WeakSet()) {
481
481
  if (Object.is(target, this.core[RAW] || this.core)) return paths.push(path), paths;
@@ -628,15 +628,14 @@ var Reactor = class {
628
628
  if (sig) sig.aborted ? cord.clup() : sig.addEventListener("abort", cord.clup, { once: true });
629
629
  return cord.sclup = !sig || sig.aborted ? NOOP : () => sig.removeEventListener("abort", cord.clup), cord.clup;
630
630
  }
631
- cloned(obj, raw, seen = /* @__PURE__ */ new WeakMap()) {
632
- if (!obj || "object" !== typeof obj) return obj;
633
- obj = obj[RAW] || obj;
634
- const cloned = seen.get(obj);
631
+ cloned(target, raw, seen = /* @__PURE__ */ new WeakMap()) {
632
+ if (!target || "object" !== typeof target) return target;
633
+ const obj = target[RAW] || target, cloned = seen.get(obj);
635
634
  if (cloned) return cloned;
636
635
  if (!canHandle(obj, this.config, false)) return obj;
637
636
  const version = obj[VERSION] || 0, cached = !raw && this.config.smartCloning && (this.snapCache ??= /* @__PURE__ */ new WeakMap()).get(obj);
638
637
  if (cached && obj[SSVERSION] === version) return cached;
639
- const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj[RAW] || obj;
638
+ const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj;
640
639
  seen.set(obj, clone);
641
640
  const keys = this.config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
642
641
  for (let i = 0, len = keys.length; i < len; i++) clone[keys[i]] = this.cloned(obj[keys[i]], raw, seen);
@@ -820,19 +819,8 @@ var Reactor = class {
820
819
  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;
821
820
  return false;
822
821
  }
823
- /**
824
- * Creates a snapshot; possibly clone of state (or a state branch).
825
- * You could alternatively use or serialize your proxied state "as is" except the environment demands no proxies or new references.
826
- * @param raw Use raw (deep unproxied & uncloned) version of branch.
827
- * @param branch Branch to clone.
828
- * @returns Snapshot deep or smart (structurally shared) clone.
829
- * @example
830
- * const snap = rtr.snapshot();
831
- * @example
832
- * const snap = rtr.snapshot(false, rtr.core.history.past);
833
- */
834
- snapshot(raw = !this.config.smartCloning, branch = this.core) {
835
- return this.cloned(branch, raw);
822
+ snapshot(raw = !this.config.smartCloning, branch) {
823
+ return this.cloned(arguments.length < 2 ? this.core : branch, raw);
836
824
  }
837
825
  /**
838
826
  * Cascades object updates into direct child paths.
package/dist/index.d.cts CHANGED
@@ -1 +1 @@
1
- export { C as CTX, r as ChildPaths, D as DeepKeys, t as DeepMerge, u as DeepPartial, v as DeepRequired, x as Deleter, y as DeleterRecord, z as DirectPayload, F as EVT_OPTS, G as EVT_WARN, E as EffectOptions, H as Getter, J as GetterRecord, K as INDIFFABLE, L as INERTIA, I as Inert, M as Intent, N as Listener, O as ListenerOptions, Q as ListenerOptionsTuple, S as ListenerRecord, T as Live, U as NIL, V as NOOP, X as NoTraverse, Y as PathBranch, Z as PathBranchValue, _ as PathKey, $ as PathLeaf, q as PathValue, P as Paths, a0 as Payload, a1 as Primitive, a2 as RAW, a3 as REJECTABLE, a as REvent, a4 as RTR_BATCH, a5 as RTR_LOG, R as Reactive, a6 as ReactivePreferences, b as Reactor, o as ReactorBuild, a7 as ReactorEvent, a8 as SSVERSION, a9 as Setter, aa as SetterRecord, ab as Stable, ac as State, ad as StrictPathKey, ae as SyncOptions, af as SyncOptionsTuple, ag as TERMINATOR, ah as Target, ai as Unflatten, aj as UnionToIntersection, ak as UpdatePayload, al as VERSION, am as Volatile, an as Watcher, ao as WatcherRecord, W as WildPaths, ap as getRaw, aq as getSnapshotVersion, ar as getVersion, as as inert, at as intent, au as isInert, av as isIntent, aw as isVolatile, ax as live, ay as methods, az as reactive, aA as stable, aB as state, aC as volatile } from './index-DCG3sacH.cjs';
1
+ export { C as CTX, r as ChildPaths, D as DeepKeys, t as DeepMerge, u as DeepPartial, v as DeepRequired, x as Deleter, y as DeleterRecord, z as DirectPayload, F as EVT_OPTS, G as EVT_WARN, E as EffectOptions, H as Getter, J as GetterRecord, K as INDIFFABLE, L as INERTIA, I as Inert, M as Intent, N as Listener, O as ListenerOptions, Q as ListenerOptionsTuple, S as ListenerRecord, T as Live, U as NIL, V as NOOP, X as NoTraverse, Y as PathBranch, Z as PathBranchValue, _ as PathKey, $ as PathLeaf, q as PathValue, P as Paths, a0 as Payload, a1 as Primitive, a2 as RAW, a3 as REJECTABLE, a as REvent, a4 as RTR_BATCH, a5 as RTR_LOG, R as Reactive, a6 as ReactivePreferences, b as Reactor, o as ReactorBuild, a7 as ReactorEvent, a8 as SSVERSION, a9 as Setter, aa as SetterRecord, ab as Stable, ac as State, ad as StrictPathKey, ae as SyncOptions, af as SyncOptionsTuple, ag as TERMINATOR, ah as Target, ai as Unflatten, aj as UnionToIntersection, ak as UpdatePayload, al as VERSION, am as Volatile, an as Watcher, ao as WatcherRecord, W as WildPaths, ap as getRaw, aq as getSnapshotVersion, ar as getVersion, as as inert, at as intent, au as isInert, av as isIntent, aw as isVolatile, ax as live, ay as methods, az as reactive, aA as stable, aB as state, aC as volatile } from './index-Oie9hhE8.cjs';
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { C as CTX, r as ChildPaths, D as DeepKeys, t as DeepMerge, u as DeepPartial, v as DeepRequired, x as Deleter, y as DeleterRecord, z as DirectPayload, F as EVT_OPTS, G as EVT_WARN, E as EffectOptions, H as Getter, J as GetterRecord, K as INDIFFABLE, L as INERTIA, I as Inert, M as Intent, N as Listener, O as ListenerOptions, Q as ListenerOptionsTuple, S as ListenerRecord, T as Live, U as NIL, V as NOOP, X as NoTraverse, Y as PathBranch, Z as PathBranchValue, _ as PathKey, $ as PathLeaf, q as PathValue, P as Paths, a0 as Payload, a1 as Primitive, a2 as RAW, a3 as REJECTABLE, a as REvent, a4 as RTR_BATCH, a5 as RTR_LOG, R as Reactive, a6 as ReactivePreferences, b as Reactor, o as ReactorBuild, a7 as ReactorEvent, a8 as SSVERSION, a9 as Setter, aa as SetterRecord, ab as Stable, ac as State, ad as StrictPathKey, ae as SyncOptions, af as SyncOptionsTuple, ag as TERMINATOR, ah as Target, ai as Unflatten, aj as UnionToIntersection, ak as UpdatePayload, al as VERSION, am as Volatile, an as Watcher, ao as WatcherRecord, W as WildPaths, ap as getRaw, aq as getSnapshotVersion, ar as getVersion, as as inert, at as intent, au as isInert, av as isIntent, aw as isVolatile, ax as live, ay as methods, az as reactive, aA as stable, aB as state, aC as volatile } from './index-DCG3sacH.js';
1
+ export { C as CTX, r as ChildPaths, D as DeepKeys, t as DeepMerge, u as DeepPartial, v as DeepRequired, x as Deleter, y as DeleterRecord, z as DirectPayload, F as EVT_OPTS, G as EVT_WARN, E as EffectOptions, H as Getter, J as GetterRecord, K as INDIFFABLE, L as INERTIA, I as Inert, M as Intent, N as Listener, O as ListenerOptions, Q as ListenerOptionsTuple, S as ListenerRecord, T as Live, U as NIL, V as NOOP, X as NoTraverse, Y as PathBranch, Z as PathBranchValue, _ as PathKey, $ as PathLeaf, q as PathValue, P as Paths, a0 as Payload, a1 as Primitive, a2 as RAW, a3 as REJECTABLE, a as REvent, a4 as RTR_BATCH, a5 as RTR_LOG, R as Reactive, a6 as ReactivePreferences, b as Reactor, o as ReactorBuild, a7 as ReactorEvent, a8 as SSVERSION, a9 as Setter, aa as SetterRecord, ab as Stable, ac as State, ad as StrictPathKey, ae as SyncOptions, af as SyncOptionsTuple, ag as TERMINATOR, ah as Target, ai as Unflatten, aj as UnionToIntersection, ak as UpdatePayload, al as VERSION, am as Volatile, an as Watcher, ao as WatcherRecord, W as WildPaths, ap as getRaw, aq as getSnapshotVersion, ar as getVersion, as as inert, at as intent, au as isInert, av as isIntent, aw as isVolatile, ax as live, ay as methods, az as reactive, aA as stable, aB as state, aC as volatile } from './index-Oie9hhE8.js';
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  stable,
16
16
  state,
17
17
  volatile
18
- } from "./chunk-VPR5SP3E.js";
18
+ } from "./chunk-2WBPGSRL.js";
19
19
  import {
20
20
  CTX,
21
21
  EVT_OPTS,
package/dist/plugins.cjs CHANGED
@@ -334,27 +334,27 @@ var Reactor = class {
334
334
  listeners;
335
335
  /**
336
336
  * Creates a new Reactor instance.
337
- * @param object Initial state object.
337
+ * @param target Initial state target.
338
338
  * @param build Reactor bootstrap/build configuration.
339
339
  * @example
340
340
  * const rtr = new Reactor({ count: 0 });
341
341
  */
342
- constructor(object = {}, build) {
342
+ constructor(target = {}, build) {
343
343
  this[INERTIA] = true;
344
344
  this.config = { crossRealms: false, smartCloning: false, eventBubbling: true, lineageTracing: false, preserveContext: false, equalityFunction: Object.is, batchingFunction: RTR_BATCH, ...build };
345
- this.core = this.proxied(object);
345
+ this.core = this.proxied(target);
346
346
  if (build) this.canLog = !!build.debug;
347
347
  }
348
- proxied(obj, rejectable = false, indiffable = false, parent, key, path) {
349
- if (!obj || "object" !== typeof obj) return obj;
350
- obj = obj[RAW] || obj;
351
- if (this.config.referenceTracking && parent && key && !this.link(obj, parent, key, false)) return obj;
352
- const cached = this.proxyCache.get(obj);
348
+ proxied(target, rejectable = false, indiffable = false, parent, key, path) {
349
+ if (!target || "object" !== typeof target) return target;
350
+ target = target[RAW] || target;
351
+ if (this.config.referenceTracking && parent && key && !this.link(target, parent, key, false)) return target;
352
+ const cached = this.proxyCache.get(target);
353
353
  if (cached) return cached;
354
- if (obj[INERTIA] || !canHandle(obj, this.config, false)) return obj;
355
- rejectable ||= obj[REJECTABLE];
356
- indiffable ||= obj[INDIFFABLE];
357
- const proxy = new Proxy(obj, {
354
+ if (target[INERTIA] || !canHandle(target, this.config, false)) return target;
355
+ rejectable ||= target[REJECTABLE];
356
+ indiffable ||= target[INDIFFABLE];
357
+ const proxy = new Proxy(target, {
358
358
  // Robust Proxy handler
359
359
  get: (object, key2, receiver) => {
360
360
  if (key2 === RAW) return this.log(`\u{1F440} [Reactor \`get\` Trap] Peeked at ${object}`), object;
@@ -367,10 +367,10 @@ var Reactor = class {
367
367
  for (let i = 0, len = this.config.lineageTracing ? paths.length : 1; i < len; i++) {
368
368
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.getters.get(currPath);
369
369
  if (!cords && !wildcords) continue;
370
- const target = { path: currPath, value, key: keyStr, hadKey: true, object: receiver }, payload = { type: "get", target, currentTarget: target, root: this.core, rejectable };
370
+ const target2 = { path: currPath, value, key: keyStr, hadKey: true, object: receiver }, payload = { type: "get", target: target2, currentTarget: target2, root: this.core, rejectable };
371
371
  if (cords) value = this.mediate(currPath, payload, "get", cords);
372
372
  if (!wildcords) continue;
373
- target.value = value;
373
+ target2.value = value;
374
374
  value = this.mediate("*", payload, "get", wildcords);
375
375
  }
376
376
  }
@@ -392,13 +392,13 @@ var Reactor = class {
392
392
  for (let i = 0; i < loopLen; i++) {
393
393
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.setters.get(currPath);
394
394
  if (!cords && !wildcords) continue;
395
- const target = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable };
395
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable };
396
396
  if (cords) {
397
397
  const result2 = this.mediate(currPath, payload, "set", cords);
398
398
  if (!(terminated ||= payload.terminated)) value = result2;
399
399
  }
400
400
  if (!wildcords) continue;
401
- target.value = value;
401
+ target2.value = value;
402
402
  const result = this.mediate("*", payload, "set", wildcords);
403
403
  if (!(terminated ||= payload.terminated)) value = result;
404
404
  }
@@ -409,8 +409,8 @@ var Reactor = class {
409
409
  if (this.config.referenceTracking && !unchanged) this.config.smartCloning && this.stamp(object), this.unlink(safeOldValue, object, keyStr), this.link(safeValue, object, keyStr);
410
410
  if (this.watchers || this.listeners)
411
411
  for (let i = 0; i < loopLen; i++) {
412
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
413
- this.notify(currPath, { type: "set", target, currentTarget: target, root: this.core, terminated, rejectable });
412
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
413
+ this.notify(currPath, { type: "set", target: target2, currentTarget: target2, root: this.core, terminated, rejectable });
414
414
  }
415
415
  return true;
416
416
  },
@@ -424,7 +424,7 @@ var Reactor = class {
424
424
  for (let i = 0; i < loopLen; i++) {
425
425
  const currPath = this.config.lineageTracing ? paths[i] : fullPath, cords = this.deleters.get(currPath);
426
426
  if (!cords && !wildcords) continue;
427
- const target = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "delete", target, currentTarget: target, root: this.core, rejectable };
427
+ const target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver }, payload = { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable };
428
428
  if (cords) {
429
429
  const result2 = this.mediate(currPath, payload, "delete", cords);
430
430
  if (!(terminated ||= payload.terminated)) value = result2;
@@ -440,8 +440,8 @@ var Reactor = class {
440
440
  if (this.config.referenceTracking) this.config.smartCloning && this.stamp(object), this.unlink(oldValue?.[RAW] || oldValue, object, keyStr);
441
441
  if (this.watchers || this.listeners)
442
442
  for (let i = 0; i < loopLen; i++) {
443
- const currPath = this.config.lineageTracing ? paths[i] : fullPath, target = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
444
- this.notify(currPath, { type: "delete", target, currentTarget: target, root: this.core, rejectable });
443
+ const currPath = this.config.lineageTracing ? paths[i] : fullPath, target2 = { path: currPath, value, oldValue, key: keyStr, hadKey, object: receiver };
444
+ this.notify(currPath, { type: "delete", target: target2, currentTarget: target2, root: this.core, rejectable });
445
445
  }
446
446
  return true;
447
447
  },
@@ -467,7 +467,7 @@ var Reactor = class {
467
467
  return ownKeys;
468
468
  }
469
469
  });
470
- return this.proxyCache.set(obj, proxy), proxy;
470
+ return this.proxyCache.set(target, proxy), proxy;
471
471
  }
472
472
  trace(target, path, paths = [], seen = /* @__PURE__ */ new WeakSet()) {
473
473
  if (Object.is(target, this.core[RAW] || this.core)) return paths.push(path), paths;
@@ -620,15 +620,14 @@ var Reactor = class {
620
620
  if (sig) sig.aborted ? cord.clup() : sig.addEventListener("abort", cord.clup, { once: true });
621
621
  return cord.sclup = !sig || sig.aborted ? NOOP : () => sig.removeEventListener("abort", cord.clup), cord.clup;
622
622
  }
623
- cloned(obj, raw, seen = /* @__PURE__ */ new WeakMap()) {
624
- if (!obj || "object" !== typeof obj) return obj;
625
- obj = obj[RAW] || obj;
626
- const cloned = seen.get(obj);
623
+ cloned(target, raw, seen = /* @__PURE__ */ new WeakMap()) {
624
+ if (!target || "object" !== typeof target) return target;
625
+ const obj = target[RAW] || target, cloned = seen.get(obj);
627
626
  if (cloned) return cloned;
628
627
  if (!canHandle(obj, this.config, false)) return obj;
629
628
  const version = obj[VERSION] || 0, cached = !raw && this.config.smartCloning && (this.snapCache ??= /* @__PURE__ */ new WeakMap()).get(obj);
630
629
  if (cached && obj[SSVERSION] === version) return cached;
631
- const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj[RAW] || obj;
630
+ const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj;
632
631
  seen.set(obj, clone);
633
632
  const keys = this.config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
634
633
  for (let i = 0, len = keys.length; i < len; i++) clone[keys[i]] = this.cloned(obj[keys[i]], raw, seen);
@@ -812,19 +811,8 @@ var Reactor = class {
812
811
  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;
813
812
  return false;
814
813
  }
815
- /**
816
- * Creates a snapshot; possibly clone of state (or a state branch).
817
- * You could alternatively use or serialize your proxied state "as is" except the environment demands no proxies or new references.
818
- * @param raw Use raw (deep unproxied & uncloned) version of branch.
819
- * @param branch Branch to clone.
820
- * @returns Snapshot deep or smart (structurally shared) clone.
821
- * @example
822
- * const snap = rtr.snapshot();
823
- * @example
824
- * const snap = rtr.snapshot(false, rtr.core.history.past);
825
- */
826
- snapshot(raw = !this.config.smartCloning, branch = this.core) {
827
- return this.cloned(branch, raw);
814
+ snapshot(raw = !this.config.smartCloning, branch) {
815
+ return this.cloned(arguments.length < 2 ? this.core : branch, raw);
828
816
  }
829
817
  /**
830
818
  * Cascades object updates into direct child paths.
@@ -1164,9 +1152,10 @@ function clamp(min = 0, val, max = Infinity) {
1164
1152
  // src/ts/plugins/timeTravel.ts
1165
1153
  var TimeTravelPlugin = class extends BaseReactorPlugin {
1166
1154
  static plugName = "timeTravel";
1155
+ lastTimestamp = 0;
1167
1156
  playbackTimeoutId = -1;
1168
1157
  constructor(config, rtr) {
1169
- super({ ...TIME_TRAVEL_PLUGIN_BUILD, ...config }, rtr, { history: [], initialState: null, currentFrame: 0, paused: true });
1158
+ super({ ...TIME_TRAVEL_PLUGIN_BUILD, ...config }, rtr, { initialState: null, history: [], currentFrame: 0, paused: true });
1170
1159
  }
1171
1160
  // ===========================================================================
1172
1161
  // THE FOUNDATION & WIRETAP (Passive Recording)
@@ -1174,6 +1163,7 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1174
1163
  wire() {
1175
1164
  this.rtr.config.referenceTracking = this.rtr.config.smartCloning = this.rtr.config.eventTimeStamps = true;
1176
1165
  if (!this.state.history.length || this.state.initialState == null) this.state.initialState = this.rtr.snapshot();
1166
+ this.lastTimestamp = performance.now();
1177
1167
  this.state.set("currentFrame", (v = 0) => clamp(0, v, this.state.history.length), { signal: this.signal, immediate: true });
1178
1168
  this.config.on("paths", this.handlePathsState, { signal: this.signal, immediate: true });
1179
1169
  !this.state.paused && this.play();
@@ -1187,8 +1177,9 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1187
1177
  if (!this.state.paused) return;
1188
1178
  if (this.state.currentFrame < this.state.history.length) this.state.history = this.state.history.slice(0, this.state.currentFrame);
1189
1179
  if (this.state.history.length >= this.config.maxHistoryLength) this.state.history = this.state.history.slice(1);
1190
- 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), hadKey: e.target.hadKey, rejected: e.rejected });
1180
+ 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 });
1191
1181
  this.state.currentFrame = this.state.history.length;
1182
+ this.lastTimestamp = e.timestamp;
1192
1183
  }
1193
1184
  /** Clears timeline history and resets playhead/genesis to the current reactor state. */
1194
1185
  clear() {
@@ -1196,6 +1187,7 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1196
1187
  this.playbackTimeoutId = -1;
1197
1188
  this.state.history.length = this.state.currentFrame = 0;
1198
1189
  this.state.initialState = this.rtr.snapshot();
1190
+ this.lastTimestamp = performance.now();
1199
1191
  }
1200
1192
  // ===========================================================================
1201
1193
  // THE TIME MACHINE (Manual Controls)
@@ -1231,9 +1223,9 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1231
1223
  async automove(forward = true) {
1232
1224
  this.state.paused = false;
1233
1225
  while ((forward ? this.state.currentFrame < this.state.history.length : this.state.currentFrame > 0) && !this.state.paused) {
1234
- 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;
1226
+ const currIndex = forward ? this.state.currentFrame : this.state.currentFrame - 1, e = this.state.history[forward ? currIndex + 1 : currIndex - 1];
1235
1227
  this.jumpTo(this.state.currentFrame + (forward ? 1 : -1), true);
1236
- if (delay > 0) await new Promise((res) => this.playbackTimeoutId = setTimeout2(() => res(0), clamp(0, delay, this.config.maxPlaybackDelay), this.signal));
1228
+ if (e?.timedelta > 0) await new Promise((res) => this.playbackTimeoutId = setTimeout2(() => res(0), Math.min(e.timedelta, this.config.maxPlaybackDelay), this.signal));
1237
1229
  }
1238
1230
  this.state.paused = true;
1239
1231
  }
@@ -1247,21 +1239,24 @@ var TimeTravelPlugin = class extends BaseReactorPlugin {
1247
1239
  // TELEMETRY & I/O (Session Import/Export)
1248
1240
  // ===========================================================================
1249
1241
  /** Exports the current session as a JSON string. */
1250
- export() {
1251
- return JSON.stringify(this.state);
1242
+ export(replacer, space) {
1243
+ try {
1244
+ return JSON.stringify(this.state, replacer, space);
1245
+ } catch (e) {
1246
+ return this.rtr.log(`[Reactor ${this.name} Plug] Failed to export session`), "";
1247
+ }
1252
1248
  }
1253
1249
  /** Imports a session from a JSON string, allowing you to replay or analyze past states. */
1254
1250
  import(json) {
1255
1251
  try {
1256
1252
  setAny(this.state, "*", JSON.parse(json));
1253
+ this.lastTimestamp = performance.now();
1257
1254
  const resume = !this.state.paused, target = this.state.currentFrame;
1258
1255
  this.state.paused = false;
1259
- setAny(this.rtr.core, "*", deepClone(this.state.initialState, this.rtr.config));
1260
- this.rtr.tick();
1261
- this.state.currentFrame = 0;
1262
- this.jumpTo(target), resume && this.play();
1256
+ setAny(this.rtr.core, "*", deepClone(this.state.initialState, this.rtr.config)), this.rtr.tick();
1257
+ this.state.currentFrame = 0, this.jumpTo(target), resume && this.play();
1263
1258
  } catch (e) {
1264
- this.rtr.log(`[Reactor ${this.name} Plug] Failed to load session`, "error");
1259
+ this.rtr.log(`[Reactor ${this.name} Plug] Failed to load session`);
1265
1260
  }
1266
1261
  }
1267
1262
  };
@@ -1,6 +1,6 @@
1
- import { P as Paths, I as Inert, B as BaseReactorPlugin, b as Reactor, a as REvent } from './index-DCG3sacH.cjs';
2
- export { c as ReactorPluginConstructor } from './index-DCG3sacH.cjs';
3
- export { H as HistoryEntry, a as TIME_TRAVEL_PLUGIN_BUILD, b as TimeTravelConfig, T as TimeTravelPlugin, c as TimeTravelState } from './timeTravel-L8CEhHIo.cjs';
1
+ import { P as Paths, I as Inert, B as BaseReactorPlugin, b as Reactor, a as REvent } from './index-Oie9hhE8.cjs';
2
+ export { c as ReactorPluginConstructor } from './index-Oie9hhE8.cjs';
3
+ export { H as HistoryEntry, a as TIME_TRAVEL_PLUGIN_BUILD, b as TimeTravelConfig, T as TimeTravelPlugin, c as TimeTravelState } from './timeTravel-WpgWmKu-.cjs';
4
4
 
5
5
  interface StorageAdapterConfig {
6
6
  debug: boolean;
package/dist/plugins.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { P as Paths, I as Inert, B as BaseReactorPlugin, b as Reactor, a as REvent } from './index-DCG3sacH.js';
2
- export { c as ReactorPluginConstructor } from './index-DCG3sacH.js';
3
- export { H as HistoryEntry, a as TIME_TRAVEL_PLUGIN_BUILD, b as TimeTravelConfig, T as TimeTravelPlugin, c as TimeTravelState } from './timeTravel-Bv_u5M1D.js';
1
+ import { P as Paths, I as Inert, B as BaseReactorPlugin, b as Reactor, a as REvent } from './index-Oie9hhE8.js';
2
+ export { c as ReactorPluginConstructor } from './index-Oie9hhE8.js';
3
+ export { H as HistoryEntry, a as TIME_TRAVEL_PLUGIN_BUILD, b as TimeTravelConfig, T as TimeTravelPlugin, c as TimeTravelState } from './timeTravel-B1vedDQc.js';
4
4
 
5
5
  interface StorageAdapterConfig {
6
6
  debug: boolean;