sia-reactor 0.0.55 → 0.0.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -5
- package/dist/{TimeTravelConsole-BWRXxYp0.d.ts → TimeTravelConsole-Cof4tji7.d.ts} +11 -11
- package/dist/{TimeTravelConsole-Dt-W-sLq.d.cts → TimeTravelConsole-CrTYhT1B.d.cts} +11 -11
- package/dist/adapters/react.cjs +51 -65
- package/dist/adapters/react.cjs.map +1 -1
- package/dist/adapters/react.d.cts +3 -3
- package/dist/adapters/react.d.ts +3 -3
- package/dist/adapters/react.js +11 -23
- package/dist/adapters/react.js.map +1 -1
- package/dist/adapters/vanilla.cjs +44 -46
- package/dist/adapters/vanilla.cjs.map +1 -1
- package/dist/adapters/vanilla.d.cts +4 -4
- package/dist/adapters/vanilla.d.ts +4 -4
- package/dist/adapters/vanilla.js +4 -4
- package/dist/{chunk-YHGYHYEE.js → chunk-2XLSMY5N.js} +66 -62
- package/dist/chunk-2XLSMY5N.js.map +1 -0
- package/dist/{chunk-L7NMQHXQ.js → chunk-5E7VHA7E.js} +1 -1
- package/dist/chunk-5E7VHA7E.js.map +1 -0
- package/dist/{chunk-GG7PDKIM.js → chunk-EGNUVKWW.js} +1 -1
- package/dist/{chunk-TVXV5YVU.js → chunk-HW3EAWFJ.js} +20 -16
- package/dist/chunk-HW3EAWFJ.js.map +1 -0
- package/dist/{chunk-VS7CTLQH.js → chunk-TC2GUZRQ.js} +3 -3
- package/dist/{consts-CV83gskZ.d.ts → consts-RJWw9ugh.d.cts} +6 -29
- package/dist/{consts-CV83gskZ.d.cts → consts-RJWw9ugh.d.ts} +6 -29
- package/dist/{index-COpS7d1h.d.ts → index-Cc5CaM9q.d.cts} +42 -30
- package/dist/{index-CgFQ_rTz.d.cts → index-CwE3FzCU.d.ts} +42 -30
- package/dist/index.cjs +28 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/modules.cjs +125 -118
- package/dist/modules.cjs.map +1 -1
- package/dist/modules.d.cts +13 -7
- package/dist/modules.d.ts +13 -7
- package/dist/modules.js +72 -64
- package/dist/modules.js.map +1 -1
- package/dist/styles/time-travel-console.css +4 -4
- package/dist/super.d.ts +100 -71
- package/dist/super.global.js +144 -128
- package/dist/super.global.js.map +1 -1
- package/dist/utils.cjs +62 -57
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +35 -4
- package/dist/utils.d.ts +35 -4
- package/dist/utils.js +7 -3
- package/package.json +1 -1
- package/dist/chunk-G2WKPDNU.js +0 -3
- package/dist/chunk-G2WKPDNU.js.map +0 -1
- package/dist/chunk-L7NMQHXQ.js.map +0 -1
- package/dist/chunk-TVXV5YVU.js.map +0 -1
- package/dist/chunk-YHGYHYEE.js.map +0 -1
- /package/dist/{chunk-GG7PDKIM.js.map → chunk-EGNUVKWW.js.map} +0 -0
- /package/dist/{chunk-VS7CTLQH.js.map → chunk-TC2GUZRQ.js.map} +0 -0
package/README.md
CHANGED
|
@@ -167,7 +167,7 @@ All methods are available on `Reactor` instances or objects wrapped in `reactive
|
|
|
167
167
|
|
|
168
168
|
#### **Listeners (Asynchronous/Batched UI Observers)**
|
|
169
169
|
- **`on(path, callback, options)` <-> `off(path, callback, options)`**: Attach DOM-style event listeners that respect `depth`. Supports `{ capture: true, depth: 1, once: true, init: true }`.
|
|
170
|
-
- **`once(path, callback, options)`**: Fires once and self-destructs,
|
|
170
|
+
- **`once(path, callback, options)`**: Fires once and self-destructs, watch has too: `wonce(...)`.
|
|
171
171
|
|
|
172
172
|
#### **Lifecycle & Utilities**
|
|
173
173
|
- **`tick(path)`**: Forces a synchronous flush of the batch queue for a specific path.
|
|
@@ -419,7 +419,7 @@ The `target` and `currentTarget` objects give you absolute surgical awareness of
|
|
|
419
419
|
}
|
|
420
420
|
```
|
|
421
421
|
|
|
422
|
-
#### The Power of the `TERMINATOR` (Symbol.for("
|
|
422
|
+
#### The Power of the `TERMINATOR` (Symbol.for("SIA_TERMINATOR"))
|
|
423
423
|
Because `set` and `delete` mediators execute *before* the memory is written, you have the power to alter reality or stop it entirely using the `TERMINATOR` symbol.
|
|
424
424
|
|
|
425
425
|
```javascript
|
|
@@ -524,7 +524,7 @@ rtr.on("todos", (e: REvent<User, "todos", 1>) => {
|
|
|
524
524
|
#### 1. Transactions & Grouping
|
|
525
525
|
By default, every mutation is recorded as a single frame. For UI gestures like dragging a slider, you want to group hundreds of rapid mutations into a single Undo/Redo step for the `TimeTravelModule`.
|
|
526
526
|
|
|
527
|
-
Transactions natively support **deep nesting** and preserve your semantic labels. When paired with `createTxPathMerger`, duplicate paths inside these envelopes are compressed in-flight
|
|
527
|
+
Transactions natively support **deep nesting** and preserve your semantic labels. When paired with `createTxPathMerger`, duplicate paths inside these envelopes are compressed in-flight.
|
|
528
528
|
|
|
529
529
|
```javascript
|
|
530
530
|
import { transaction, startTx, endTx } from "sia-reactor/modules";
|
|
@@ -617,10 +617,15 @@ silence(() => {
|
|
|
617
617
|
player.state.volume = 100;
|
|
618
618
|
}); // Useful for internal side-effects that shouldn't ruin the undo/redo history.
|
|
619
619
|
|
|
620
|
-
// 2.
|
|
620
|
+
// 2. The Force Wrapper: Executes mutations that bypasses equality checks. same as withMeta({ forced: true }, () => ...)
|
|
621
|
+
force(() => {
|
|
622
|
+
player.state.volume = 100;
|
|
623
|
+
}); // Useful for internal side-effects that must force-sync.
|
|
624
|
+
|
|
625
|
+
// 3. Custom Meta Injection: Injects data seamlessly into the ReactorEvent payload for listeners to read.
|
|
621
626
|
withMeta({ customSource: "gamepad" }, () => {
|
|
622
627
|
player.intent.playing = true;
|
|
623
|
-
});
|
|
628
|
+
}); // startMeta & endMeta under the hood
|
|
624
629
|
|
|
625
630
|
player.on("intent.playing", (e) => {
|
|
626
631
|
console.log(e.customSource); // "gamepad"
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { W as Reactive } from './consts-
|
|
2
|
-
import {
|
|
1
|
+
import { W as Reactive } from './consts-RJWw9ugh.js';
|
|
2
|
+
import { h as TimeTravelModule } from './index-CwE3FzCU.js';
|
|
3
3
|
|
|
4
|
-
/** Reactive options for the TimeTravel
|
|
4
|
+
/** Reactive options for the TimeTravel console instance. */
|
|
5
5
|
interface TimeTravelConsoleConfig {
|
|
6
|
-
/** Header text shown at the top of the
|
|
6
|
+
/** Header text shown at the top of the console panel. */
|
|
7
7
|
title: string;
|
|
8
8
|
/** Accent color used to derive panel theme variables. */
|
|
9
9
|
color: string;
|
|
10
|
-
/** Shows the
|
|
10
|
+
/** Shows the console only in development when true. */
|
|
11
11
|
devOnly: boolean;
|
|
12
|
-
/** Initial open state applied when the
|
|
12
|
+
/** Initial open state applied when the console is created. */
|
|
13
13
|
startOpen: boolean;
|
|
14
|
-
/** Container element that owns the
|
|
14
|
+
/** Container element that owns the console layer and dock. */
|
|
15
15
|
container?: HTMLElement;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* - Vanilla
|
|
18
|
+
* - Vanilla console controller for visual time-travel controls and timeline I/O.
|
|
19
19
|
* - Mounts a docked HUD into the configured container, syncs its UI with module state, and forwards keyboard/button actions to the TimeTravelModule.
|
|
20
|
-
* Supports reactive `config` updates (title/color/container/devOnly) and maintains local
|
|
20
|
+
* Supports reactive `config` updates (title/color/container/devOnly) and maintains local console UI state (`open` and `import` payload text).
|
|
21
21
|
*/
|
|
22
22
|
declare class TimeTravelConsole {
|
|
23
23
|
static count: number;
|
|
@@ -32,9 +32,9 @@ declare class TimeTravelConsole {
|
|
|
32
32
|
readonly host: HTMLElement;
|
|
33
33
|
private clups;
|
|
34
34
|
private keydown;
|
|
35
|
-
/** Creates a docked TimeTravel overlay bound to a module instance.
|
|
35
|
+
/** Creates a docked TimeTravel console overlay bound to a module instance.
|
|
36
36
|
* @param time TimeTravel module instance that owns timeline operations.
|
|
37
|
-
* @param build Optional initial
|
|
37
|
+
* @param build Optional initial console config overrides.
|
|
38
38
|
*/
|
|
39
39
|
constructor(time: TimeTravelModule, build?: Partial<TimeTravelConsoleConfig>);
|
|
40
40
|
destroy(): void;
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { W as Reactive } from './consts-
|
|
2
|
-
import {
|
|
1
|
+
import { W as Reactive } from './consts-RJWw9ugh.cjs';
|
|
2
|
+
import { h as TimeTravelModule } from './index-Cc5CaM9q.cjs';
|
|
3
3
|
|
|
4
|
-
/** Reactive options for the TimeTravel
|
|
4
|
+
/** Reactive options for the TimeTravel console instance. */
|
|
5
5
|
interface TimeTravelConsoleConfig {
|
|
6
|
-
/** Header text shown at the top of the
|
|
6
|
+
/** Header text shown at the top of the console panel. */
|
|
7
7
|
title: string;
|
|
8
8
|
/** Accent color used to derive panel theme variables. */
|
|
9
9
|
color: string;
|
|
10
|
-
/** Shows the
|
|
10
|
+
/** Shows the console only in development when true. */
|
|
11
11
|
devOnly: boolean;
|
|
12
|
-
/** Initial open state applied when the
|
|
12
|
+
/** Initial open state applied when the console is created. */
|
|
13
13
|
startOpen: boolean;
|
|
14
|
-
/** Container element that owns the
|
|
14
|
+
/** Container element that owns the console layer and dock. */
|
|
15
15
|
container?: HTMLElement;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* - Vanilla
|
|
18
|
+
* - Vanilla console controller for visual time-travel controls and timeline I/O.
|
|
19
19
|
* - Mounts a docked HUD into the configured container, syncs its UI with module state, and forwards keyboard/button actions to the TimeTravelModule.
|
|
20
|
-
* Supports reactive `config` updates (title/color/container/devOnly) and maintains local
|
|
20
|
+
* Supports reactive `config` updates (title/color/container/devOnly) and maintains local console UI state (`open` and `import` payload text).
|
|
21
21
|
*/
|
|
22
22
|
declare class TimeTravelConsole {
|
|
23
23
|
static count: number;
|
|
@@ -32,9 +32,9 @@ declare class TimeTravelConsole {
|
|
|
32
32
|
readonly host: HTMLElement;
|
|
33
33
|
private clups;
|
|
34
34
|
private keydown;
|
|
35
|
-
/** Creates a docked TimeTravel overlay bound to a module instance.
|
|
35
|
+
/** Creates a docked TimeTravel console overlay bound to a module instance.
|
|
36
36
|
* @param time TimeTravel module instance that owns timeline operations.
|
|
37
|
-
* @param build Optional initial
|
|
37
|
+
* @param build Optional initial console config overrides.
|
|
38
38
|
*/
|
|
39
39
|
constructor(time: TimeTravelModule, build?: Partial<TimeTravelConsoleConfig>);
|
|
40
40
|
destroy(): void;
|
package/dist/adapters/react.cjs
CHANGED
|
@@ -40,15 +40,15 @@ var import_react = require("react");
|
|
|
40
40
|
var useISOLayoutEffect = "undefined" !== typeof window ? import_react.useLayoutEffect : import_react.useEffect;
|
|
41
41
|
|
|
42
42
|
// src/ts/core/consts.ts
|
|
43
|
-
var RAW = /* @__PURE__ */ Symbol.for("
|
|
44
|
-
var INERTIA = /* @__PURE__ */ Symbol.for("
|
|
45
|
-
var REJECTABLE = /* @__PURE__ */ Symbol.for("
|
|
46
|
-
var INDIFFABLE = /* @__PURE__ */ Symbol.for("
|
|
47
|
-
var TERMINATOR = /* @__PURE__ */ Symbol.for("
|
|
48
|
-
var VERSION = /* @__PURE__ */ Symbol.for("
|
|
49
|
-
var SSVERSION = /* @__PURE__ */ Symbol.for("
|
|
43
|
+
var RAW = /* @__PURE__ */ Symbol.for("SIA_RAW");
|
|
44
|
+
var INERTIA = /* @__PURE__ */ Symbol.for("SIA_INERTIA");
|
|
45
|
+
var REJECTABLE = /* @__PURE__ */ Symbol.for("SIA_REJECTABLE");
|
|
46
|
+
var INDIFFABLE = /* @__PURE__ */ Symbol.for("SIA_INDIFFABLE");
|
|
47
|
+
var TERMINATOR = /* @__PURE__ */ Symbol.for("SIA_TERMINATOR");
|
|
48
|
+
var VERSION = /* @__PURE__ */ Symbol.for("SIA_VERSION");
|
|
49
|
+
var SSVERSION = /* @__PURE__ */ Symbol.for("SIA_SNAPSHOT_VERSION");
|
|
50
50
|
var RTR_BATCH = "undefined" !== typeof window ? ("undefined" !== typeof queueMicrotask ? queueMicrotask : setTimeout).bind(window) : "undefined" !== typeof process && process.nextTick ? process.nextTick : setTimeout;
|
|
51
|
-
var RTR_LOG = console.log.bind(console, "[
|
|
51
|
+
var RTR_LOG = console.log.bind(console, "[SIA Reactor]");
|
|
52
52
|
var EVT_OPTS = { LISTENER: ["capture", "depth", "once", "signal", "init"], MEDIATOR: ["lazy", "signal", "init"] };
|
|
53
53
|
var NIL = Object.freeze({});
|
|
54
54
|
var NOOP = () => {
|
|
@@ -61,8 +61,6 @@ try {
|
|
|
61
61
|
var CTX_BUILD = {
|
|
62
62
|
/** Flag indicating whether the application is running in development mode. */
|
|
63
63
|
isDevEnv,
|
|
64
|
-
/** Flag indicating whether an operation is bypassing checks so reactors can allow all writes. */
|
|
65
|
-
usingForce: false,
|
|
66
64
|
/** Active `Autotracker` instance, override for automatic dependency collection on `Reactor` traps. */
|
|
67
65
|
autotracker: null,
|
|
68
66
|
/** Extensible meta context for payloads and cross-cutting concerns. */
|
|
@@ -79,7 +77,24 @@ var CTX_BUILD = {
|
|
|
79
77
|
batchingFunction: RTR_BATCH
|
|
80
78
|
}
|
|
81
79
|
};
|
|
82
|
-
var CTX = globalThis[/* @__PURE__ */ Symbol.for("
|
|
80
|
+
var CTX = globalThis[/* @__PURE__ */ Symbol.for("SIA_CTX")] ??= CTX_BUILD;
|
|
81
|
+
|
|
82
|
+
// src/ts/utils/meta.ts
|
|
83
|
+
function resetMeta(key) {
|
|
84
|
+
if (!CTX.meta) return;
|
|
85
|
+
delete CTX.meta[key];
|
|
86
|
+
for (const _ in CTX.meta) return;
|
|
87
|
+
CTX.meta = null;
|
|
88
|
+
}
|
|
89
|
+
function force(task, bool = true) {
|
|
90
|
+
const prev = CTX.meta?.forced;
|
|
91
|
+
(CTX.meta ??= {}).forced = bool;
|
|
92
|
+
try {
|
|
93
|
+
return task();
|
|
94
|
+
} finally {
|
|
95
|
+
prev !== void 0 ? CTX.meta.forced = prev : resetMeta("forced");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
83
98
|
|
|
84
99
|
// src/ts/utils/obj.ts
|
|
85
100
|
var arrRegex = /^([^\[\]]+)\[(\d+)\]$/;
|
|
@@ -174,15 +189,6 @@ function getDepth(path, depth = !path ? 0 : 1) {
|
|
|
174
189
|
function parseEvtOpts(options, opts, boolOpt = opts[0], result = {}) {
|
|
175
190
|
return Object.assign(result, "boolean" === typeof options ? { [boolOpt]: options } : options), result;
|
|
176
191
|
}
|
|
177
|
-
function force(task, bool = true) {
|
|
178
|
-
const prev = CTX.usingForce;
|
|
179
|
-
CTX.usingForce = bool;
|
|
180
|
-
try {
|
|
181
|
-
return task();
|
|
182
|
-
} finally {
|
|
183
|
-
CTX.usingForce = prev;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
192
|
function getTrailRecords(obj, path, reverse = false) {
|
|
187
193
|
const parts = path.split("."), chain = [["*", obj, obj]];
|
|
188
194
|
for (let acc = "", currObj = obj, i = 0, len = parts.length; i < len; i++) {
|
|
@@ -388,7 +394,7 @@ var Reactor = class {
|
|
|
388
394
|
safeValue = value?.[RAW] || value;
|
|
389
395
|
unchanged = this.config.equalityFunction(safeValue, safeOldValue);
|
|
390
396
|
}
|
|
391
|
-
if (!indiffable && unchanged && !CTX.
|
|
397
|
+
if (!indiffable && unchanged && !CTX.meta?.forced && keyStr !== "length") return this.log(`\u{1F504} [\`set\` Trap] Unchanged for "${keyStr}" on [${paths}]`), true;
|
|
392
398
|
if (this.config.set) terminated = (value = this.config.set(object, key2, value, oldValue, receiver, paths)) === TERMINATOR;
|
|
393
399
|
if (this.setters) {
|
|
394
400
|
const wildcords = this.setters.get("*");
|
|
@@ -712,10 +718,6 @@ var Reactor = class {
|
|
|
712
718
|
get(path, callback, options) {
|
|
713
719
|
return this.onSync("get", path, callback, options, () => getPath(this.core, path));
|
|
714
720
|
}
|
|
715
|
-
/** Registers a get mediator for a path that only triggers once. */
|
|
716
|
-
gonce(path, callback, options) {
|
|
717
|
-
return this.get(path, callback, { ...parseEvtOpts(options, EVT_OPTS.MEDIATOR), once: true });
|
|
718
|
-
}
|
|
719
721
|
/**
|
|
720
722
|
* Removes a get mediator for a path.
|
|
721
723
|
* @param path Path or wildcard path.
|
|
@@ -737,10 +739,6 @@ var Reactor = class {
|
|
|
737
739
|
set(path, callback, options) {
|
|
738
740
|
return this.onSync("set", path, callback, options, () => (force(() => setPath(this.core, path, getPath(this.core, path))), this.tick(path)));
|
|
739
741
|
}
|
|
740
|
-
/** Registers a set mediator for a path that only triggers once. */
|
|
741
|
-
sonce(path, callback, options) {
|
|
742
|
-
return this.set(path, callback, Object.assign(parseEvtOpts(options, EVT_OPTS.MEDIATOR), { once: true }));
|
|
743
|
-
}
|
|
744
742
|
/**
|
|
745
743
|
* Removes a set mediator for a path.
|
|
746
744
|
* @param path Path or wildcard path.
|
|
@@ -762,10 +760,6 @@ var Reactor = class {
|
|
|
762
760
|
delete(path, callback, options) {
|
|
763
761
|
return this.onSync("delete", path, callback, options, () => deletePath(this.core, path));
|
|
764
762
|
}
|
|
765
|
-
/** Registers a delete mediator for a path that only triggers once. */
|
|
766
|
-
donce(path, callback, options) {
|
|
767
|
-
return this.delete(path, callback, Object.assign(parseEvtOpts(options, EVT_OPTS.MEDIATOR), { once: true }));
|
|
768
|
-
}
|
|
769
763
|
/**
|
|
770
764
|
* Removes a delete mediator for a path.
|
|
771
765
|
* @param path Path or wildcard path.
|
|
@@ -890,7 +884,7 @@ var Reactor = class {
|
|
|
890
884
|
};
|
|
891
885
|
|
|
892
886
|
// src/ts/core/mixins.ts
|
|
893
|
-
var methods = ["tick", "stall", "nostall", "get", "
|
|
887
|
+
var methods = ["tick", "stall", "nostall", "get", "noget", "set", "noset", "delete", "nodelete", "watch", "wonce", "nowatch", "on", "once", "off", "snapshot", "use", "reset", "destroy"];
|
|
894
888
|
function reactive(target, build, preferences = NIL) {
|
|
895
889
|
if ("__Reactor__" in target) return target;
|
|
896
890
|
const descriptors = {}, rtr = getReactor(target, true, build), locks = { enumerable: false, configurable: true, writable: false }, hasAffix = !!(preferences.prefix || preferences.suffix);
|
|
@@ -1057,8 +1051,7 @@ function useReactor(target, options = NIL, build) {
|
|
|
1057
1051
|
const versionRef = (0, import_react2.useRef)(0), tgtRef = (0, import_react2.useRef)(), rtrRef = (0, import_react2.useRef)(), rtr = tgtRef.current !== target || !rtrRef.current ? (tgtRef.current = target, rtrRef.current = getReactor(target, true, build)) : rtrRef.current, atrkrRef = (0, import_react2.useRef)(), prevTrkr = CTX.autotracker, atrkr = CTX.autotracker = atrkrRef.current ||= new Autotracker(), optsRef = (0, import_react2.useRef)(options), notifyRef = (0, import_react2.useRef)(NOOP);
|
|
1058
1052
|
optsRef.current = options;
|
|
1059
1053
|
atrkr.unblock(rtr), queueMicrotask(() => CTX.autotracker === atrkr && (CTX.autotracker = prevTrkr));
|
|
1060
|
-
const subscribe = (0, import_react2.useCallback)((notify) => atrkr.callback(notifyRef.current = () => (versionRef.current++, notify())), [atrkr]);
|
|
1061
|
-
const getSnapshot = (0, import_react2.useCallback)(() => versionRef.current, []);
|
|
1054
|
+
const getSnapshot = (0, import_react2.useCallback)(() => versionRef.current, []), subscribe = (0, import_react2.useCallback)((notify) => atrkr.callback(notifyRef.current = () => (versionRef.current++, notify())), [atrkr]);
|
|
1062
1055
|
(0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1063
1056
|
return useISOLayoutEffect(() => (CTX.autotracker = prevTrkr, atrkr.callback(notifyRef.current, optsRef.current)), [atrkr]), rtr.core;
|
|
1064
1057
|
}
|
|
@@ -1066,8 +1059,7 @@ function useAnyReactor(options = NIL) {
|
|
|
1066
1059
|
const versionRef = (0, import_react2.useRef)(0), atrkrRef = (0, import_react2.useRef)(), prevTrkr = CTX.autotracker, atrkr = CTX.autotracker = atrkrRef.current ||= new Autotracker(), optsRef = (0, import_react2.useRef)(options), notifyRef = (0, import_react2.useRef)(NOOP);
|
|
1067
1060
|
optsRef.current = options;
|
|
1068
1061
|
atrkr.unblock(), queueMicrotask(() => CTX.autotracker === atrkr && (CTX.autotracker = prevTrkr));
|
|
1069
|
-
const subscribe = (0, import_react2.useCallback)((notify) => atrkr.callback(notifyRef.current = () => (versionRef.current++, notify())), [atrkr]);
|
|
1070
|
-
const getSnapshot = (0, import_react2.useCallback)(() => versionRef.current, []);
|
|
1062
|
+
const getSnapshot = (0, import_react2.useCallback)(() => versionRef.current, []), subscribe = (0, import_react2.useCallback)((notify) => atrkr.callback(notifyRef.current = () => (versionRef.current++, notify())), [atrkr]);
|
|
1071
1063
|
(0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1072
1064
|
useISOLayoutEffect(() => (CTX.autotracker = prevTrkr, atrkr.callback(notifyRef.current, optsRef.current)), [atrkr]);
|
|
1073
1065
|
}
|
|
@@ -1075,10 +1067,7 @@ function useReactorSnapshot(target, options, build = { referenceTracking: true,
|
|
|
1075
1067
|
const tgtRef = (0, import_react2.useRef)(), rtrRef = (0, import_react2.useRef)(), rtr = tgtRef.current !== target || !rtrRef.current ? (tgtRef.current = target, rtrRef.current = getReactor(target, true, build)) : rtrRef.current, atrkrRef = (0, import_react2.useRef)(), atrkrRtrRef = (0, import_react2.useRef)(), atrkr = atrkrRtrRef.current !== rtr || !atrkrRef.current ? (atrkrRtrRef.current = rtr, atrkrRef.current = new Autotracker(rtr)) : atrkrRef.current, notifyRef = (0, import_react2.useRef)(NOOP), optsRef = (0, import_react2.useRef)(options);
|
|
1076
1068
|
rtr.config.referenceTracking = rtr.config.smartCloning = true;
|
|
1077
1069
|
optsRef.current = options;
|
|
1078
|
-
const subscribe = (0, import_react2.useCallback)((notify) => (atrkr.callback(notifyRef.current = notify, optsRef.current), () => atrkr.cleanup()), [atrkr]);
|
|
1079
|
-
const getSnapshot = () => rtr.snapshot();
|
|
1080
|
-
const snapshot = (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1081
|
-
const proxy = (0, import_react2.useMemo)(() => atrkr.tracked(snapshot), [atrkr, snapshot]);
|
|
1070
|
+
const getSnapshot = () => rtr.snapshot(), subscribe = (0, import_react2.useCallback)((notify) => (atrkr.callback(notifyRef.current = notify, optsRef.current), () => atrkr.cleanup()), [atrkr]), snapshot = (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot), proxy = (0, import_react2.useMemo)(() => atrkr.tracked(snapshot), [atrkr, snapshot]);
|
|
1082
1071
|
return useISOLayoutEffect(() => atrkr.callback(notifyRef.current, optsRef.current), [atrkr, proxy]), proxy;
|
|
1083
1072
|
}
|
|
1084
1073
|
|
|
@@ -1087,35 +1076,29 @@ var import_react3 = require("react");
|
|
|
1087
1076
|
function useSelector(target, sel, eq = Object.is, options = NIL, build) {
|
|
1088
1077
|
const rtrRef = (0, import_react3.useRef)(), tgtRef = (0, import_react3.useRef)(), rtr = tgtRef.current !== target || !rtrRef.current ? (tgtRef.current = target, rtrRef.current = getReactor(target, true, build)) : rtrRef.current, atrkrRef = (0, import_react3.useRef)(), atrkr = atrkrRef.current ||= new Autotracker(), notifyRef = (0, import_react3.useRef)(NOOP), sliceRef = (0, import_react3.useRef)(), selRef = (0, import_react3.useRef)(sel), eqRef = (0, import_react3.useRef)(eq), optsRef = (0, import_react3.useRef)(options);
|
|
1089
1078
|
selRef.current = sel, eqRef.current = eq, optsRef.current = options;
|
|
1090
|
-
const subscribe = (0, import_react3.useCallback)((notify) => atrkr.callback(notifyRef.current = notify, optsRef.current), [atrkr]);
|
|
1091
1079
|
const getSnapshot = (0, import_react3.useCallback)(() => {
|
|
1092
1080
|
const next = withTracker(atrkr, () => selRef.current(rtr.core), rtr);
|
|
1093
1081
|
return eqRef.current(sliceRef.current, next) ? sliceRef.current : sliceRef.current = next;
|
|
1094
|
-
}, [atrkr, rtr]);
|
|
1095
|
-
const slice = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1082
|
+
}, [atrkr, rtr]), subscribe = (0, import_react3.useCallback)((notify) => atrkr.callback(notifyRef.current = notify, optsRef.current), [atrkr]), slice = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1096
1083
|
return useISOLayoutEffect(() => atrkr.callback(notifyRef.current, optsRef.current), [atrkr, slice]), slice;
|
|
1097
1084
|
}
|
|
1098
1085
|
function useAnySelector(sel, eq = Object.is, options = NIL) {
|
|
1099
1086
|
const atrkrRef = (0, import_react3.useRef)(), atrkr = atrkrRef.current ||= new Autotracker(), notifyRef = (0, import_react3.useRef)(NOOP), sliceRef = (0, import_react3.useRef)(), selRef = (0, import_react3.useRef)(sel), eqRef = (0, import_react3.useRef)(eq), optsRef = (0, import_react3.useRef)(options);
|
|
1100
1087
|
selRef.current = sel, eqRef.current = eq, optsRef.current = options;
|
|
1101
|
-
const subscribe = (0, import_react3.useCallback)((notify) => atrkr.callback(notifyRef.current = notify, optsRef.current), [atrkr]);
|
|
1102
1088
|
const getSnapshot = (0, import_react3.useCallback)(() => {
|
|
1103
1089
|
const next = withTracker(atrkr, () => selRef.current());
|
|
1104
1090
|
return eqRef.current(sliceRef.current, next) ? sliceRef.current : sliceRef.current = next;
|
|
1105
|
-
}, [atrkr]);
|
|
1106
|
-
const slice = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1091
|
+
}, [atrkr]), subscribe = (0, import_react3.useCallback)((notify) => atrkr.callback(notifyRef.current = notify, optsRef.current), [atrkr]), slice = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1107
1092
|
return useISOLayoutEffect(() => atrkr.callback(notifyRef.current, optsRef.current), [atrkr, slice]), slice;
|
|
1108
1093
|
}
|
|
1109
1094
|
function useSelectorSnapshot(target, sel, eq = Object.is, options, build = { referenceTracking: true, smartCloning: true }) {
|
|
1110
1095
|
const tgtRef = (0, import_react3.useRef)(), rtrRef = (0, import_react3.useRef)(), rtr = tgtRef.current !== target || !rtrRef.current ? (tgtRef.current = target, rtrRef.current = getReactor(target, true, build)) : rtrRef.current, atrkrRef = (0, import_react3.useRef)(), atrkrRtrRef = (0, import_react3.useRef)(), atrkr = atrkrRtrRef.current !== rtr || !atrkrRef.current ? (atrkrRtrRef.current = rtr, atrkrRef.current = new Autotracker(rtr)) : atrkrRef.current, notifyRef = (0, import_react3.useRef)(NOOP), sliceRef = (0, import_react3.useRef)(), selRef = (0, import_react3.useRef)(sel), eqRef = (0, import_react3.useRef)(eq), optsRef = (0, import_react3.useRef)(options);
|
|
1111
1096
|
rtr.config.referenceTracking = rtr.config.smartCloning = true;
|
|
1112
1097
|
optsRef.current = options, selRef.current = sel, eqRef.current = eq;
|
|
1113
|
-
const subscribe = (0, import_react3.useCallback)((notify) => (atrkr.callback(notifyRef.current = notify, optsRef.current), () => atrkr.cleanup()), [atrkr]);
|
|
1114
1098
|
const getSnapshot = (0, import_react3.useCallback)(() => {
|
|
1115
1099
|
const next = selRef.current(atrkr.tracked(rtr.snapshot()));
|
|
1116
1100
|
return eqRef.current(sliceRef.current, next) ? sliceRef.current : sliceRef.current = next;
|
|
1117
|
-
}, [atrkr]);
|
|
1118
|
-
const slice = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1101
|
+
}, [atrkr]), subscribe = (0, import_react3.useCallback)((notify) => (atrkr.callback(notifyRef.current = notify, optsRef.current), () => atrkr.cleanup()), [atrkr]), slice = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1119
1102
|
return useISOLayoutEffect(() => atrkr.callback(notifyRef.current, optsRef.current), [atrkr, slice]), slice;
|
|
1120
1103
|
}
|
|
1121
1104
|
|
|
@@ -1124,8 +1107,7 @@ var import_react4 = require("react");
|
|
|
1124
1107
|
function usePath(target, path, options = NIL, build) {
|
|
1125
1108
|
const versionRef = (0, import_react4.useRef)(0), tgtRef = (0, import_react4.useRef)(), rtrRef = (0, import_react4.useRef)(), rtr = tgtRef.current !== target || !rtrRef.current ? (tgtRef.current = target, rtrRef.current = getReactor(target, true, build)) : rtrRef.current, optsRef = (0, import_react4.useRef)(options);
|
|
1126
1109
|
optsRef.current = options;
|
|
1127
|
-
const subscribe = (0, import_react4.useCallback)((notify) => rtr[optsRef.current.sync ? "watch" : "on"](path, () => (versionRef.current++, notify()), optsRef.current), [rtr, path]);
|
|
1128
|
-
const getSnapshot = (0, import_react4.useCallback)(() => versionRef.current, []);
|
|
1110
|
+
const getSnapshot = (0, import_react4.useCallback)(() => versionRef.current, []), subscribe = (0, import_react4.useCallback)((notify) => rtr[optsRef.current.sync ? "watch" : "on"](path, () => (versionRef.current++, notify()), optsRef.current), [rtr, path]);
|
|
1129
1111
|
(0, import_react4.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1130
1112
|
return getPath(rtr.core, path);
|
|
1131
1113
|
}
|
|
@@ -1257,8 +1239,9 @@ function effect(callback, options = NIL) {
|
|
|
1257
1239
|
// src/ts/adapters/vanilla/TimeTravelConsole.ts
|
|
1258
1240
|
var keys = {
|
|
1259
1241
|
blocks: KEYS_BLOCKS,
|
|
1260
|
-
|
|
1261
|
-
|
|
1242
|
+
whitelist: ["Escape"],
|
|
1243
|
+
// overrides: ["Space", "Home", "End", "Escape", "Delete"], // Playing "God" now
|
|
1244
|
+
shortcuts: { undo: ["Ctrl+z", "Cmd+z"], redo: ["Ctrl+y", "Ctrl+Shift+z", "Cmd+Shift+z"], genesis: "Home", trackUntrack: "t", ending: "End", playPause: "Space", rewind: "Shift+Space", prune: "Insert", reset: "Delete", export: "e", import: "i", clear: "x", copy: "c", toggle: "Ctrl + `" }
|
|
1262
1245
|
};
|
|
1263
1246
|
var TimeTravelConsole = class _TimeTravelConsole {
|
|
1264
1247
|
static count = 0;
|
|
@@ -1269,22 +1252,24 @@ var TimeTravelConsole = class _TimeTravelConsole {
|
|
|
1269
1252
|
host;
|
|
1270
1253
|
clups = [];
|
|
1271
1254
|
keydown;
|
|
1272
|
-
/** Creates a docked TimeTravel overlay bound to a module instance.
|
|
1255
|
+
/** Creates a docked TimeTravel console overlay bound to a module instance.
|
|
1273
1256
|
* @param time TimeTravel module instance that owns timeline operations.
|
|
1274
|
-
* @param build Optional initial
|
|
1257
|
+
* @param build Optional initial console config overrides.
|
|
1275
1258
|
*/
|
|
1276
1259
|
constructor(time, build = { devOnly: true }) {
|
|
1277
1260
|
this.time = time;
|
|
1278
1261
|
this.config = reactive({ title: `Time Travel Console ${this.index = ++_TimeTravelConsole.count}`, ...build });
|
|
1279
1262
|
this.state.open = !!this.config.startOpen;
|
|
1280
1263
|
let wlLive = false, blLive = false;
|
|
1281
|
-
const s = this.time.state, host = this.host = createEl("div", { className: "sia-tt-console-host" }), toggle = createEl("button", { className: "sia-tt-console-toggle", type: "button", onclick: () => this.state.open = !this.state.open }), panel = createEl("aside", { className: "sia-tt-console", ariaLabel: "time travel
|
|
1264
|
+
const s = this.time.state, host = this.host = createEl("div", { className: "sia-tt-console-host" }), toggle = createEl("button", { className: "sia-tt-console-toggle", type: "button", title: `Toggle Overlay${formatKeyTooltip(keys.shortcuts.toggle)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.toggle), onclick: () => this.state.open = !this.state.open }), panel = createEl("aside", { className: "sia-tt-console", ariaLabel: "time travel console" }), title = createEl("div", { className: "title" }), frame = createEl("span", { className: "muted" }), prune = createEl("button", { textContent: `Prune${formatKeyTooltip(keys.shortcuts.prune)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.prune), onclick: () => this.time.prune() }), reset = createEl("button", { textContent: `Reset${formatKeyTooltip(keys.shortcuts.reset)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.reset), onclick: () => (this.time.reset(), this.state.import = "") }), undo = createEl("button", { textContent: `Undo${formatKeyTooltip(keys.shortcuts.undo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.undo), onclick: () => this.time.undo(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyTooltip(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo), onclick: () => this.time.redo(this.state.stride) }), genesis = createEl("button", { textContent: `Genesis${formatKeyTooltip(keys.shortcuts.genesis)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.genesis), onclick: () => this.time.jumpTo(0) }), playPause = createEl("button", { onclick: () => this.time[s.paused ? "play" : "pause"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.playPause) }), rewind = createEl("button", { textContent: `Rewind${formatKeyTooltip(keys.shortcuts.rewind)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.rewind), onclick: this.time.rewind }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack) }), range = createEl("input", { type: "range", min: "0", title: "time travel frame", ariaLabel: "time travel frame", oninput: () => this.time.jumpTo(Number(range.value)) }), exp = createEl("button", { textContent: `Export${formatKeyTooltip(keys.shortcuts.export)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.export), onclick: () => this.state.import = this.time.export(null, 2) }), imp = createEl("button", { textContent: `Import${formatKeyTooltip(keys.shortcuts.import)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.import), onclick: () => this.state.import.trim().length && this.time.import(this.state.import) }), clr = createEl("button", { textContent: `Clear${formatKeyTooltip(keys.shortcuts.clear)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.clear), onclick: () => this.state.import = "" }), copy = createEl("button", { textContent: `Copy${formatKeyTooltip(keys.shortcuts.copy)}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.copy), onclick: () => this.state.import.trim().length && navigator.clipboard?.writeText(this.state.import).catch?.(() => {
|
|
1265
|
+
}) }), payload = createEl("textarea", { className: "sia-tt-io", readOnly: true, placeholder: "current payload json", title: "Current History Entry" }), io = createEl("textarea", { className: "sia-tt-io", placeholder: "timeline payload json", title: "Time History", oninput: () => this.state.import = io.value }), foot = createEl("p", { className: "sia-tt-footnote", innerHTML: "<span>Try this in your app? </span>" }), link = createEl("a", { target: "_blank", rel: "noreferrer noopener", textContent: "sia-reactor", href: "https://www.npmjs.com/package/sia-reactor" }), box = createEl("div", { className: "sia-tt-status-box" }), status = createEl("div", { className: "sia-tt-status-row" }), filters = createEl("div", { className: "sia-tt-status-row" }), filterBox = createEl("div", { className: "sia-tt-status-box" }), whitelistLabel = createEl("span", { className: "muted", textContent: "Whitelist:" }), blacklistLabel = createEl("span", { className: "muted", textContent: "Blacklist:" }), whitelist = createEl("input", { className: "sia-tt-filter-input sia-tt-io", placeholder: 'a.b, c.d or {"0":["a.b"]}', title: "Whitelist paths", onfocus: () => wlLive = true, onblur: () => (wlLive = false, whitelist.value = formatPaths(this.time.config.whitelist, "*")), oninput: (_, parsed = parsePaths(whitelist.value)) => parsed !== null && (this.time.config.whitelist = parsed) }), blacklist = createEl("input", { className: "sia-tt-filter-input sia-tt-io", placeholder: 'a.b, c.d or {"0":["a.b"]}', title: "Blacklist paths", onfocus: () => blLive = true, onblur: () => (blLive = false, blacklist.value = formatPaths(this.time.config.blacklist, "")), oninput: (_, parsed = parsePaths(blacklist.value, true)) => parsed !== null && (this.time.config.blacklist = parsed) }), speed = createEl("select", { className: "sia-tt-speed", title: "Playback Speed", onchange: () => this.time.state.playbackRate = Number(speed.value) }), stride = createEl("input", { className: "sia-tt-stride sia-tt-button sia-tt-mini-input", type: "number", min: "1", title: "Skip Stride i.e. how many steps count as one unit", oninput: () => this.state.stride = Math.max(1, Number(stride.value) || 1) }), stats = createEl("span", { className: "sia-tt-stats" }), limit = createEl("input", { className: "sia-tt-limit sia-tt-mini-input sia-tt-button", type: "number", min: "1", title: "Maximum number of history entries kept in memory before older entries are discarded.", oninput: () => this.time.config.limit = Math.max(1, Number(limit.value) || 1) }), delay = createEl("input", { className: "sia-tt-delay sia-tt-mini-input sia-tt-button", type: "number", min: "0", step: "50", title: "Maximum playback delay between timeline frames in milliseconds.", oninput: () => this.time.config.maxPlaybackDelay = Math.max(0, Number(delay.value) || 0) }), read = createEl("label", { className: "sia-tt-check", title: "When recording intent mutations, read previous values from the matching state path instead of the intent path. Useful for accurate undo reconstruction of intent-driven flows." }), readBox = createEl("input", { type: "checkbox", checked: !!this.time.config.mirrorReads, onchange: () => this.time.config.mirrorReads = readBox.checked }), write = createEl("label", { className: "sia-tt-check", title: "During playback and teleportation, mirror state writes into matching intent paths to re-enact the recorded history. Useful for accurate reconstruction of the whole session." }), writeBox = createEl("input", { type: "checkbox", checked: !!this.time.config.mirrorWrites, onchange: () => this.time.config.mirrorWrites = writeBox.checked }), filterRow1 = createEl("div", { className: "sia-tt-filter-row" }), filterRow2 = createEl("div", { className: "sia-tt-filter-row" }), row1 = createEl("div", { className: "sia-tt-row" }), row2 = createEl("div", { className: "sia-tt-row" }), row3 = createEl("div", { className: "sia-tt-row" }), row4 = createEl("div", { className: "sia-tt-row" }), row5 = createEl("div", { className: "sia-tt-row sia-tt-config-row" });
|
|
1282
1266
|
speed.append(...[0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 4, 8, 16, 32].map((v) => createEl("option", { value: String(v), textContent: `${v}x` })));
|
|
1283
|
-
status.append((box.append(frame), box),
|
|
1267
|
+
status.append((box.append(frame), box), prune, reset);
|
|
1284
1268
|
filters.append((filterBox.append((filterRow1.append(whitelistLabel, whitelist), filterRow1), (filterRow2.append(blacklistLabel, blacklist), filterRow2)), filterBox));
|
|
1285
|
-
panel.append(title, status, (row1.append(playPause, rewind, genesis), row1), (row2.append(undo, redo, trackUntrack, stride), row2), payload, (row3.append(speed, range), row3), filters, (row4.append(exp, imp, clr), row4), io, (row5.append(delay, limit, (read.append(readBox, " Read Mirror"), read), (write.append(writeBox, " Write Mirror"), write)), row5), (foot.prepend(stats), foot.append(link), foot));
|
|
1269
|
+
panel.append(title, status, (row1.append(playPause, rewind, genesis), row1), (row2.append(undo, redo, trackUntrack, stride), row2), payload, (row3.append(speed, range), row3), filters, (row4.append(exp, imp, copy, clr), row4), io, (row5.append(delay, limit, (read.append(readBox, " Read Mirror"), read), (write.append(writeBox, " Write Mirror"), write)), row5), (foot.prepend(stats), foot.append(link), foot));
|
|
1286
1270
|
this.host.append(toggle, panel);
|
|
1287
|
-
this.keydown = (e, can = this.
|
|
1271
|
+
this.keydown = (e, can = this.config.devOnly ? CTX.isDevEnv : true, a = can && keyEventAllowed(e, keys), will = a === "toggle" || a && this.state.open) => will && (e.preventDefault(), e.stopImmediatePropagation(), a === "toggle" ? this.state.open = !this.state.open : a === "escape" ? this.state.open = false : a === "undo" ? this.time.undo(this.state.stride) : a === "redo" ? this.time.redo(this.state.stride) : a === "genesis" ? this.time.jumpTo(0) : a === "trackUntrack" ? this.time[s.tracking ? "untrack" : "track"]() : a === "ending" ? this.time.jumpTo(s.history.length) : a === "rewind" ? this.time.rewind() : a === "playPause" ? this.time[s.paused ? "play" : "pause"]() : a === "prune" ? this.time.prune() : a === "reset" ? this.time.reset() : a === "export" ? this.state.import = this.time.export(null, 2) : a === "import" ? this.state.import.trim().length && this.time.import(this.state.import) : a === "clear" ? this.state.import = "" : a === "copy" && this.state.import.trim().length && navigator.clipboard?.writeText(this.state.import).catch?.(() => {
|
|
1272
|
+
}));
|
|
1288
1273
|
window.addEventListener("keydown", this.keydown, { capture: true });
|
|
1289
1274
|
const sync = [
|
|
1290
1275
|
effect(() => this.config.color ? host.style.setProperty("--sia-tt-color", this.config.color) : host.style.removeProperty("--sia-tt-color")),
|
|
@@ -1298,7 +1283,7 @@ var TimeTravelConsole = class _TimeTravelConsole {
|
|
|
1298
1283
|
effect(() => trackUntrack.textContent = `${s.tracking ? "Untrack" : "Track"}${formatKeyTooltip(keys.shortcuts.trackUntrack)}`),
|
|
1299
1284
|
effect((sets = 0, txs = 0) => {
|
|
1300
1285
|
range.max = String(s.history.length);
|
|
1301
|
-
range.disabled =
|
|
1286
|
+
range.disabled = reset.disabled = !s.history.length;
|
|
1302
1287
|
for (let i = 0, len = s.history.length; i < len; i++) {
|
|
1303
1288
|
const frame2 = s.history[i];
|
|
1304
1289
|
"nodes" in frame2 ? txs++ : frame2.type === "set" && sets++;
|
|
@@ -1308,16 +1293,17 @@ var TimeTravelConsole = class _TimeTravelConsole {
|
|
|
1308
1293
|
effect(() => {
|
|
1309
1294
|
frame.textContent = `Frame: ${s.currentFrame} / ${s.history.length}`;
|
|
1310
1295
|
genesis.disabled = undo.disabled = !this.time.canUndo;
|
|
1296
|
+
redo.disabled = prune.disabled = !this.time.canRedo;
|
|
1297
|
+
playPause.disabled = s.paused && redo.disabled;
|
|
1311
1298
|
rewind.disabled = !s.paused || !s.currentFrame;
|
|
1312
|
-
playPause.disabled = redo.disabled = !this.time.canRedo;
|
|
1313
1299
|
range.value = String(Math.min(s.currentFrame, s.history.length));
|
|
1314
1300
|
payload.value = JSON.stringify(s.currentFrame ? s.history[s.currentFrame - 1] : { genesis: true, value: s.initialState }, null, 2);
|
|
1315
1301
|
}),
|
|
1316
1302
|
effect(() => {
|
|
1317
|
-
clr.disabled = imp.disabled = !this.state.import.trim().length;
|
|
1303
|
+
clr.disabled = copy.disabled = imp.disabled = !this.state.import.trim().length;
|
|
1318
1304
|
io.value !== this.state.import && (io.value = this.state.import);
|
|
1319
1305
|
}),
|
|
1320
|
-
effect((v = String(
|
|
1306
|
+
effect((v = String(s.playbackRate)) => v !== speed.value && (speed.value = v)),
|
|
1321
1307
|
effect((v = String(this.state.stride)) => v !== stride.value && (stride.value = v)),
|
|
1322
1308
|
effect((v = String(this.time.config.limit)) => v !== limit.value && (limit.value = v)),
|
|
1323
1309
|
effect((v = String(this.time.config.maxPlaybackDelay)) => v !== delay.value && (delay.value = v)),
|