sia-reactor 0.0.21 → 0.0.23
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 +115 -89
- package/dist/{TimeTravelOverlay-DxqJL0Zk.d.ts → TimeTravelOverlay-Dglcwpg-.d.ts} +9 -8
- package/dist/{TimeTravelOverlay-CJv-S_Km.d.cts → TimeTravelOverlay-OjklzuCD.d.cts} +9 -8
- package/dist/adapters/react.cjs +74 -91
- package/dist/adapters/react.d.cts +23 -22
- package/dist/adapters/react.d.ts +23 -22
- package/dist/adapters/react.js +3 -3
- package/dist/adapters/vanilla.cjs +74 -91
- package/dist/adapters/vanilla.d.cts +4 -4
- package/dist/adapters/vanilla.d.ts +4 -4
- package/dist/adapters/vanilla.js +3 -3
- package/dist/{chunk-TFLYCXK4.js → chunk-5JNWC7Z4.js} +14 -13
- package/dist/{chunk-DP74DVRT.js → chunk-MKL3JUPO.js} +55 -15
- package/dist/{chunk-2WBPGSRL.js → chunk-MSTHQVNK.js} +61 -78
- package/dist/{index-Oie9hhE8.d.cts → index-m0aAWxhX.d.cts} +330 -218
- package/dist/{index-Oie9hhE8.d.ts → index-m0aAWxhX.d.ts} +330 -218
- package/dist/index.cjs +69 -89
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -4
- package/dist/{plugins.cjs → modules.cjs} +464 -195
- package/dist/modules.d.cts +52 -0
- package/dist/modules.d.ts +52 -0
- package/dist/modules.js +619 -0
- package/dist/super.d.ts +642 -298
- package/dist/super.global.js +481 -210
- package/dist/timeTravel-DExvNb04.d.ts +352 -0
- package/dist/timeTravel-DctvcHVt.d.cts +352 -0
- package/dist/utils.cjs +59 -14
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +7 -1
- package/package.json +6 -6
- package/dist/plugins.d.cts +0 -112
- package/dist/plugins.d.ts +0 -112
- package/dist/plugins.js +0 -370
- package/dist/timeTravel-B1vedDQc.d.ts +0 -76
- package/dist/timeTravel-WpgWmKu-.d.cts +0 -76
package/dist/adapters/react.cjs
CHANGED
|
@@ -43,7 +43,9 @@ var useISOLayoutEffect = "undefined" !== typeof window ? import_react.useLayoutE
|
|
|
43
43
|
var CTX = {
|
|
44
44
|
/** Flag indicating whether the application is running in development mode. */
|
|
45
45
|
isDevEnv: "undefined" !== typeof process ? process.env.NODE_ENV !== "production" : true,
|
|
46
|
-
/**
|
|
46
|
+
/** Flag indicating whether a cascade is currently ongoing so reactors can allow all writes. */
|
|
47
|
+
isCascading: false,
|
|
48
|
+
/** Active `Autotracker` instance, override for automatic dependency collection on `Reactor` traps. */
|
|
47
49
|
autotracker: null
|
|
48
50
|
};
|
|
49
51
|
var RAW = /* @__PURE__ */ Symbol.for("S.I.A_RAW");
|
|
@@ -55,14 +57,13 @@ var VERSION = /* @__PURE__ */ Symbol.for("S.I.A_VERSION");
|
|
|
55
57
|
var SSVERSION = /* @__PURE__ */ Symbol.for("S.I.A_SNAPSHOT_VERSION");
|
|
56
58
|
var RTR_BATCH = "undefined" !== typeof window ? ("undefined" !== typeof queueMicrotask ? queueMicrotask : setTimeout).bind(window) : "undefined" !== typeof process && process.nextTick ? process.nextTick : setTimeout;
|
|
57
59
|
var RTR_LOG = console.log.bind(console, "[S.I.A Reactor]");
|
|
58
|
-
var EVT_WARN = console.warn.bind(console, "[S.I.A Event]");
|
|
59
60
|
var EVT_OPTS = { LISTENER: ["capture", "depth", "once", "signal", "immediate"], MEDIATOR: ["lazy", "signal", "immediate"] };
|
|
60
61
|
var NIL = Object.freeze({});
|
|
61
62
|
var NOOP = () => {
|
|
62
63
|
};
|
|
63
64
|
|
|
64
65
|
// src/ts/utils/obj.ts
|
|
65
|
-
var
|
|
66
|
+
var arrRegex = /^([^\[\]]+)\[(\d+)\]$/;
|
|
66
67
|
function isObj(obj, arraycheck = true) {
|
|
67
68
|
return "object" === typeof obj && obj !== null && (arraycheck ? !Array.isArray(obj) : true);
|
|
68
69
|
}
|
|
@@ -70,7 +71,7 @@ function isPOJO(obj, config = NIL, typecheck = true) {
|
|
|
70
71
|
return (typecheck ? isObj(obj, false) : true) && (config.crossRealms ? Object.prototype.toString.call(obj) === "[object Object]" : obj.constructor === Object);
|
|
71
72
|
}
|
|
72
73
|
function canHandle(obj, config = NIL, typecheck = true) {
|
|
73
|
-
if (typecheck && !isObj(obj, false)) return false;
|
|
74
|
+
if (typecheck && !isObj(obj, false) || obj[INERTIA]) return false;
|
|
74
75
|
if (Array.isArray(obj) || !config.preserveContext && isPOJO(obj, config, false)) return true;
|
|
75
76
|
if (config.preserveContext) return !(obj instanceof Map) && !(obj instanceof Set) && !(obj instanceof WeakMap) && !(obj instanceof WeakSet) && !(obj instanceof Error) && !(obj instanceof Number) && !(obj instanceof Date) && !(obj instanceof String) && !(obj instanceof RegExp) && !(obj instanceof ArrayBuffer) && !(obj instanceof Promise);
|
|
76
77
|
return false;
|
|
@@ -81,7 +82,7 @@ function getAny(source, key, separator = ".", keyFunc) {
|
|
|
81
82
|
const keys2 = key.split(separator);
|
|
82
83
|
let currObj = source;
|
|
83
84
|
for (let i = 0, len = keys2.length; i < len; i++) {
|
|
84
|
-
const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(
|
|
85
|
+
const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(arrRegex);
|
|
85
86
|
if (match) {
|
|
86
87
|
const [, key3, iStr] = match;
|
|
87
88
|
if (!Array.isArray(currObj[key3]) || !(key3 in currObj)) return void 0;
|
|
@@ -98,7 +99,7 @@ function setAny(target, key, value, separator = ".", keyFunc) {
|
|
|
98
99
|
if (!key.includes(separator)) return void (target[keyFunc ? keyFunc(key) : key] = value);
|
|
99
100
|
const keys2 = key.split(separator);
|
|
100
101
|
for (let currObj = target, i = 0, len = keys2.length; i < len; i++) {
|
|
101
|
-
const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(
|
|
102
|
+
const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(arrRegex);
|
|
102
103
|
if (match) {
|
|
103
104
|
const [, key3, iStr] = match;
|
|
104
105
|
if (!Array.isArray(currObj[key3])) currObj[key3] = [];
|
|
@@ -119,7 +120,7 @@ function deleteAny(target, key, separator = ".", keyFunc) {
|
|
|
119
120
|
if (!key.includes(separator)) return void delete target[keyFunc ? keyFunc(key) : key];
|
|
120
121
|
const keys2 = key.split(separator);
|
|
121
122
|
for (let currObj = target, i = 0, len = keys2.length; i < len; i++) {
|
|
122
|
-
const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(
|
|
123
|
+
const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(arrRegex);
|
|
123
124
|
if (match) {
|
|
124
125
|
const [, key3, iStr] = match;
|
|
125
126
|
if (!Array.isArray(currObj[key3]) || !(key3 in currObj)) return;
|
|
@@ -137,7 +138,7 @@ function inAny(source, key, separator = ".", keyFunc) {
|
|
|
137
138
|
if (!key.includes(separator)) return key in source;
|
|
138
139
|
const keys2 = key.split(separator);
|
|
139
140
|
for (let currObj = source, i = 0, len = keys2.length; i < len; i++) {
|
|
140
|
-
const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(
|
|
141
|
+
const key2 = keyFunc ? keyFunc(keys2[i]) : keys2[i], match = key2.includes("[") && key2.match(arrRegex);
|
|
141
142
|
if (match) {
|
|
142
143
|
const [, key3, iStr] = match;
|
|
143
144
|
if (!Array.isArray(currObj[key3]) || !(key3 in currObj)) return false;
|
|
@@ -154,10 +155,6 @@ function inAny(source, key, separator = ".", keyFunc) {
|
|
|
154
155
|
function parseEvtOpts(options, opts, boolOpt = opts[0], result = {}) {
|
|
155
156
|
return Object.assign(result, "boolean" === typeof options ? { [boolOpt]: options } : options), result;
|
|
156
157
|
}
|
|
157
|
-
function mergeObjs(o1 = {}, o2 = {}) {
|
|
158
|
-
const merged = { ...o1 || {}, ...o2 || {} };
|
|
159
|
-
return Object.keys(merged).forEach((k) => isObj(o1?.[k]) && isObj(o2?.[k]) && (merged[k] = mergeObjs(o1[k], o2[k]))), merged;
|
|
160
|
-
}
|
|
161
158
|
function getTrailRecords(obj, path, reverse = false) {
|
|
162
159
|
const parts = path.split("."), chain = [["*", obj, obj]];
|
|
163
160
|
for (let acc = "", currObj = obj, i = 0, len = parts.length; i < len; i++) chain.push([acc += (i ? "." : "") + parts[i], currObj, currObj = currObj?.[parts[i]]]);
|
|
@@ -200,35 +197,34 @@ var ReactorEvent = class _ReactorEvent {
|
|
|
200
197
|
staticType;
|
|
201
198
|
/** Original event target context. */
|
|
202
199
|
target;
|
|
203
|
-
/** Root reactive object for this event wave. */
|
|
200
|
+
/** Root reactive object for this event instance wave. */
|
|
204
201
|
root;
|
|
205
|
-
/** Original target path for this event wave. */
|
|
202
|
+
/** Original target path for this event instance wave. */
|
|
206
203
|
path;
|
|
207
204
|
/** Current value at the event target path. */
|
|
208
205
|
value;
|
|
209
206
|
/** Previous value at the event target path. */
|
|
210
207
|
oldValue;
|
|
211
|
-
/** Whether resolve/reject intent semantics are allowed for this event. */
|
|
208
|
+
/** Whether resolve/reject intent semantics are allowed for this event instance. */
|
|
212
209
|
rejectable;
|
|
213
|
-
/** Whether this event wave can bubble back up to ancestors or just capture down. */
|
|
210
|
+
/** Whether this event instance wave can bubble back up to ancestors or just capture down. */
|
|
214
211
|
bubbles;
|
|
215
212
|
/**
|
|
216
|
-
* `DOMHighResTimeStamp` for this event payload for native event parity and accuracy.
|
|
213
|
+
* `DOMHighResTimeStamp` for this event instance payload for native event parity and accuracy.
|
|
217
214
|
* Enable `eventTimeStamps` option, then use this over custom timestamps in listeners for accuracy.
|
|
218
215
|
* */
|
|
219
216
|
timestamp;
|
|
220
|
-
|
|
217
|
+
/** The `Reactor` instance that dispatched this event instance. */
|
|
218
|
+
reactor;
|
|
221
219
|
_resolved = "";
|
|
222
220
|
_rejected = "";
|
|
223
221
|
_propagationStopped = false;
|
|
224
222
|
_immediatePropagationStopped = false;
|
|
225
223
|
/**
|
|
226
224
|
* @param payload Source payload for this event instance.
|
|
227
|
-
* @param
|
|
228
|
-
* @param canWarn Whether warning output is enabled.
|
|
229
|
-
* @param canStamp Whether timestamping is enabled.
|
|
225
|
+
* @param reactor The `Reactor` instance creating this event instance.
|
|
230
226
|
*/
|
|
231
|
-
constructor(payload,
|
|
227
|
+
constructor(payload, reactor) {
|
|
232
228
|
this.staticType = this.type = payload.type;
|
|
233
229
|
this.target = payload.target;
|
|
234
230
|
this.currentTarget = payload.currentTarget;
|
|
@@ -237,9 +233,9 @@ var ReactorEvent = class _ReactorEvent {
|
|
|
237
233
|
this.value = payload.target.value;
|
|
238
234
|
this.oldValue = payload.target.oldValue;
|
|
239
235
|
this.rejectable = payload.rejectable;
|
|
240
|
-
this.bubbles =
|
|
241
|
-
if (
|
|
242
|
-
|
|
236
|
+
this.bubbles = !!reactor.config.eventBubbling;
|
|
237
|
+
if (reactor.config.eventTimeStamps) this.timestamp = performance.now();
|
|
238
|
+
this.reactor = reactor;
|
|
243
239
|
}
|
|
244
240
|
/** Whether propagation has been stopped. */
|
|
245
241
|
get propagationStopped() {
|
|
@@ -269,9 +265,9 @@ var ReactorEvent = class _ReactorEvent {
|
|
|
269
265
|
* @example e.resolve("API Load successful"); // message
|
|
270
266
|
*/
|
|
271
267
|
resolve(message) {
|
|
272
|
-
if (!this.rejectable) return this.
|
|
273
|
-
if (this.eventPhase !== _ReactorEvent.CAPTURING_PHASE) this.
|
|
274
|
-
if (this.rejectable) this._resolved = message || `Could ${this.staticType} intended value at "${this.path}"
|
|
268
|
+
if (!this.rejectable) return this.reactor.log(`[ReactorEvent] Ignored \`resolve()\` call on a non-rejectable ${this.staticType} at "${this.path}"`);
|
|
269
|
+
if (this.eventPhase !== _ReactorEvent.CAPTURING_PHASE) this.reactor.log(`[ReactorEvent] Resolving an intent on ${this.staticType} at "${this.path}" outside of the capture phase is unadvised.`);
|
|
270
|
+
if (this.rejectable) this.reactor.log(`[ReactorEvent] ${this._resolved = message || `Could ${this.staticType} intended value at "${this.path}"`}`);
|
|
275
271
|
}
|
|
276
272
|
/** Rejection reason for rejectable events. */
|
|
277
273
|
get rejected() {
|
|
@@ -284,9 +280,9 @@ var ReactorEvent = class _ReactorEvent {
|
|
|
284
280
|
* @example e.resolve("User is not logged in"); // reason
|
|
285
281
|
*/
|
|
286
282
|
reject(reason) {
|
|
287
|
-
if (!this.rejectable) return this.
|
|
288
|
-
if (this.eventPhase !== _ReactorEvent.CAPTURING_PHASE) this.
|
|
289
|
-
if (this.rejectable) this._rejected = reason || `Couldn't ${this.staticType} intended value at "${this.path}"
|
|
283
|
+
if (!this.rejectable) return this.reactor.log(`[ReactorEvent] Ignored \`reject()\` call on a non-rejectable ${this.staticType} at "${this.path}"`);
|
|
284
|
+
if (this.eventPhase !== _ReactorEvent.CAPTURING_PHASE) this.reactor.log(`[ReactorEvent] Rejecting an intent on ${this.staticType} at "${this.path}" outside of the capture phase is unadvised.`);
|
|
285
|
+
if (this.rejectable) this.reactor.log(`[ReactorEvent] ${this._rejected = reason || `Couldn't ${this.staticType} intended value at "${this.path}"`}`);
|
|
290
286
|
}
|
|
291
287
|
/**
|
|
292
288
|
* Returns event path values from target to root.
|
|
@@ -295,24 +291,22 @@ var ReactorEvent = class _ReactorEvent {
|
|
|
295
291
|
composedPath() {
|
|
296
292
|
return getTrailRecords(this.root, this.path, true).map((r) => r[2]);
|
|
297
293
|
}
|
|
298
|
-
get canWarn() {
|
|
299
|
-
return this._warn !== NOOP;
|
|
300
|
-
}
|
|
301
294
|
};
|
|
302
295
|
|
|
303
296
|
// src/ts/core/reactor.ts
|
|
304
297
|
var Reactor = class {
|
|
298
|
+
/** Logger function for this reactor instance, override if desired, `this.canLog = false` resets. */
|
|
305
299
|
log = NOOP;
|
|
300
|
+
/** The core state object for this reactor instance. */
|
|
306
301
|
core;
|
|
307
302
|
// `?:`s | pay the ~800 byte price upfront for what u might never use
|
|
308
|
-
|
|
303
|
+
/** The modules being used by this reactor. */
|
|
304
|
+
modules;
|
|
305
|
+
/** Configuration options for this reactor instance. */
|
|
309
306
|
config;
|
|
307
|
+
/** Whether this reactor instance is currently batching updates, a window view into the engine timing */
|
|
310
308
|
isBatching = false;
|
|
311
309
|
// Async Batching
|
|
312
|
-
isCascading = false;
|
|
313
|
-
// Setter Cascading
|
|
314
|
-
isLogging = false;
|
|
315
|
-
// keeping track so API getter doesn't slow down internal iterations in any way
|
|
316
310
|
queue;
|
|
317
311
|
// Tasks to run after flush
|
|
318
312
|
batch;
|
|
@@ -345,7 +339,7 @@ var Reactor = class {
|
|
|
345
339
|
if (this.config.referenceTracking && parent && key && !this.link(target, parent, key, false)) return target;
|
|
346
340
|
const cached = this.proxyCache.get(target);
|
|
347
341
|
if (cached) return cached;
|
|
348
|
-
if (
|
|
342
|
+
if (!canHandle(target, this.config, false)) return target;
|
|
349
343
|
rejectable ||= target[REJECTABLE];
|
|
350
344
|
indiffable ||= target[INDIFFABLE];
|
|
351
345
|
const proxy = new Proxy(target, {
|
|
@@ -379,7 +373,7 @@ var Reactor = class {
|
|
|
379
373
|
safeValue = value?.[RAW] || value;
|
|
380
374
|
unchanged = this.config.equalityFunction(safeValue, safeOldValue);
|
|
381
375
|
}
|
|
382
|
-
if (!indiffable && unchanged && !
|
|
376
|
+
if (!indiffable && unchanged && !CTX.isCascading) return this.log(`\u{1F504} [Reactor \`set\` Trap] Unchanged for "${keyStr}" on "${paths}"`), true;
|
|
383
377
|
if (this.config.set) terminated = (value = this.config.set(object, key2, value, oldValue, receiver, paths)) === TERMINATOR;
|
|
384
378
|
if (this.setters) {
|
|
385
379
|
const wildcords = this.setters.get("*");
|
|
@@ -533,7 +527,7 @@ var Reactor = class {
|
|
|
533
527
|
if (this.queue?.size) for (const task of this.queue) task(), this.queue.delete(task);
|
|
534
528
|
}
|
|
535
529
|
wave(path, payload) {
|
|
536
|
-
const e = new ReactorEvent(payload, this
|
|
530
|
+
const e = new ReactorEvent(payload, this), chain = getTrailRecords(this.core, path);
|
|
537
531
|
e.eventPhase = ReactorEvent.CAPTURING_PHASE;
|
|
538
532
|
for (let i = 0; i <= chain.length - 2; i++) {
|
|
539
533
|
if (e.propagationStopped) break;
|
|
@@ -607,8 +601,8 @@ var Reactor = class {
|
|
|
607
601
|
return depth;
|
|
608
602
|
}
|
|
609
603
|
getContext(path) {
|
|
610
|
-
const
|
|
611
|
-
return { path, value, key: path.slice(
|
|
604
|
+
const last = path.lastIndexOf("."), value = getAny(this.core, path), object = last === -1 ? this.core : getAny(this.core, path.slice(0, last));
|
|
605
|
+
return { path, value, key: path.slice(last + 1) || "", hadKey: true, object };
|
|
612
606
|
}
|
|
613
607
|
bindSignal(cord, sig) {
|
|
614
608
|
if (sig) sig.aborted ? cord.clup() : sig.addEventListener("abort", cord.clup, { once: true });
|
|
@@ -624,7 +618,12 @@ var Reactor = class {
|
|
|
624
618
|
const clone = !raw ? this.config.preserveContext ? Object.create(Object.getPrototypeOf(obj)) : Array.isArray(obj) ? [] : {} : obj;
|
|
625
619
|
seen.set(obj, clone);
|
|
626
620
|
const keys2 = this.config.preserveContext ? Reflect.ownKeys(obj) : Object.keys(obj);
|
|
627
|
-
for (let i = 0, len = keys2.length; i < len; i++)
|
|
621
|
+
for (let i = 0, len = keys2.length; i < len; i++)
|
|
622
|
+
try {
|
|
623
|
+
clone[keys2[i]] = this.cloned(obj[keys2[i]], raw, seen);
|
|
624
|
+
} catch (e) {
|
|
625
|
+
if (e instanceof RangeError) throw e;
|
|
626
|
+
}
|
|
628
627
|
if (!raw && this.config.smartCloning) this.snapCache.set(obj, clone), obj[SSVERSION] = version;
|
|
629
628
|
return clone;
|
|
630
629
|
}
|
|
@@ -712,7 +711,7 @@ var Reactor = class {
|
|
|
712
711
|
* rtr.delete("cache.temp", () => TERMINATOR);
|
|
713
712
|
*/
|
|
714
713
|
delete(path, callback, options) {
|
|
715
|
-
return this.syncAdd("delete", path, callback, options, (imm) => (imm !== "auto" || inAny(this.core, path)) && deleteAny(this.core, path
|
|
714
|
+
return this.syncAdd("delete", path, callback, options, (imm) => (imm !== "auto" || inAny(this.core, path)) && deleteAny(this.core, path));
|
|
716
715
|
}
|
|
717
716
|
/** Registers a delete mediator for a path that only triggers once. */
|
|
718
717
|
donce(path, callback, options) {
|
|
@@ -729,7 +728,7 @@ var Reactor = class {
|
|
|
729
728
|
}
|
|
730
729
|
/**
|
|
731
730
|
* Registers a watcher for a path.
|
|
732
|
-
* Watch callbacks run synchronously with the operation.
|
|
731
|
+
* Watch callbacks run synchronously with the operation, use leaf paths for reliability as it sees exact sets; no bubbling here.
|
|
733
732
|
* @param path Path or wildcard path.
|
|
734
733
|
* @param callback Watch callback.
|
|
735
734
|
* @param options Sync options.
|
|
@@ -778,7 +777,7 @@ var Reactor = class {
|
|
|
778
777
|
cord = { cb: callback, capture, depth, once, clup: () => this.off(path, callback, options), lDepth: depth !== void 0 ? this.getDepth(path) : depth };
|
|
779
778
|
if (immediate && (immediate !== "auto" || inAny(this.core, path))) {
|
|
780
779
|
const target = this.getContext(path);
|
|
781
|
-
callback(new ReactorEvent({ type: "init", target, currentTarget: target, root: this.core, rejectable: false }, this
|
|
780
|
+
callback(new ReactorEvent({ type: "init", target, currentTarget: target, root: this.core, rejectable: false }, this));
|
|
782
781
|
}
|
|
783
782
|
(cords ?? (this.listeners.set(path, cords = []), cords)).push(cord);
|
|
784
783
|
return this.bindSignal(cord, signal);
|
|
@@ -809,56 +808,39 @@ var Reactor = class {
|
|
|
809
808
|
return this.cloned(arguments.length < 2 ? this.core : branch, raw);
|
|
810
809
|
}
|
|
811
810
|
/**
|
|
812
|
-
*
|
|
813
|
-
* @param
|
|
814
|
-
* @param
|
|
815
|
-
* @
|
|
816
|
-
* rtr.on("user", (event) => rtr.cascade(event));
|
|
817
|
-
* @example
|
|
818
|
-
* rtr.watch("user", (_value, payload) => rtr.cascade(payload));
|
|
819
|
-
*/
|
|
820
|
-
cascade({ type, currentTarget: { path, value: news, oldValue: olds } }, objectSafe = true) {
|
|
821
|
-
if (type !== "set" && type !== "delete" || !canHandle(news, this.config) || (objectSafe ? !canHandle(olds, this.config) : false)) return;
|
|
822
|
-
const obj = objectSafe ? mergeObjs(olds, news) : news, keys2 = Object.keys(obj);
|
|
823
|
-
this.isCascading = true;
|
|
824
|
-
for (let i = 0, len = keys2.length; i < len; i++) setAny(this.core, path === "*" ? keys2[i] : path + "." + keys2[i], obj[keys2[i]]);
|
|
825
|
-
this.isCascading = false;
|
|
826
|
-
}
|
|
827
|
-
/**
|
|
828
|
-
* Installs a plugin instance.
|
|
829
|
-
* @param plugin Plugin instance.
|
|
830
|
-
* @returns Current reactor for fluent chaining.
|
|
811
|
+
* Installs a module instance.
|
|
812
|
+
* @param target Module instance.
|
|
813
|
+
* @param id Optional identification tag for this instance in the module.
|
|
814
|
+
* @returns Current `Reactor` instance for fluent chaining.
|
|
831
815
|
*/
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
this.plugins?.get(name)?.destroy();
|
|
835
|
-
return (this.plugins ??= /* @__PURE__ */ new Map()).set(name, (plugin.setup(this), plugin)), this;
|
|
816
|
+
use(target, id) {
|
|
817
|
+
return (this.modules ??= /* @__PURE__ */ new Set()).add(target.setup(this, id)), this;
|
|
836
818
|
}
|
|
837
|
-
/** Resets
|
|
819
|
+
/** Resets this reactor instance to its initial state. */
|
|
838
820
|
reset() {
|
|
839
821
|
this.getters?.clear(), this.setters?.clear(), this.deleters?.clear(), this.watchers?.clear(), this.listeners?.clear();
|
|
840
822
|
this.batch?.clear(), this.queue?.clear(), this.isBatching = false;
|
|
841
823
|
}
|
|
842
824
|
destroy() {
|
|
843
|
-
if (this.
|
|
825
|
+
if (this.modules) for (const mdle of this.modules) mdle.destroy();
|
|
844
826
|
this.reset(), nuke(this);
|
|
845
827
|
}
|
|
846
828
|
get canLog() {
|
|
847
|
-
return this.
|
|
829
|
+
return this.log !== NOOP;
|
|
848
830
|
}
|
|
849
831
|
set canLog(value) {
|
|
850
|
-
this.log =
|
|
832
|
+
this.log = value ? RTR_LOG : NOOP;
|
|
851
833
|
}
|
|
852
|
-
get
|
|
853
|
-
return this.config.
|
|
834
|
+
get canLineageTrace() {
|
|
835
|
+
return this.config.lineageTracing && this.config.referenceTracking;
|
|
854
836
|
}
|
|
855
837
|
get canSmartClone() {
|
|
856
|
-
return this.config.
|
|
838
|
+
return this.config.smartCloning && this.config.referenceTracking;
|
|
857
839
|
}
|
|
858
840
|
};
|
|
859
841
|
|
|
860
842
|
// src/ts/core/mixins.ts
|
|
861
|
-
var methods = ["tick", "stall", "nostall", "get", "gonce", "noget", "set", "sonce", "noset", "delete", "donce", "nodelete", "watch", "wonce", "nowatch", "on", "once", "off", "snapshot", "
|
|
843
|
+
var methods = ["tick", "stall", "nostall", "get", "gonce", "noget", "set", "sonce", "noset", "delete", "donce", "nodelete", "watch", "wonce", "nowatch", "on", "once", "off", "snapshot", "use", "reset", "destroy"];
|
|
862
844
|
function reactive(target, build, preferences = NIL) {
|
|
863
845
|
if ("__Reactor__" in target) return target;
|
|
864
846
|
const descriptors = {}, rtr = getReactor(target, true, build), locks = { enumerable: false, configurable: true, writable: false }, hasAffix = !!(preferences.prefix || preferences.suffix);
|
|
@@ -866,7 +848,7 @@ function reactive(target, build, preferences = NIL) {
|
|
|
866
848
|
let key = methods[i];
|
|
867
849
|
if (hasAffix) (preferences.whitelist?.includes(key) ?? true) && (key = `${preferences.prefix || ""}${key}${preferences.suffix || ""}`);
|
|
868
850
|
else if (preferences.whitelist?.includes(key)) continue;
|
|
869
|
-
descriptors[key] = { value: rtr[
|
|
851
|
+
descriptors[key] = { value: rtr[methods[i]].bind(rtr), ...locks };
|
|
870
852
|
}
|
|
871
853
|
descriptors["__Reactor__"] = { value: rtr, ...locks };
|
|
872
854
|
return Object.defineProperties(rtr.core, descriptors), rtr.core;
|
|
@@ -979,9 +961,9 @@ var Autotracker = class {
|
|
|
979
961
|
* const stop = atrkr.callback(() => console.log("changed")); // re-run after when ".user.name" changes
|
|
980
962
|
* @example Packaged Customization
|
|
981
963
|
* const atrkr = new Autotracker(); // no reactor passed
|
|
982
|
-
* withTracker(atrkr, () => state.user.name); // import `withTracker`
|
|
964
|
+
* withTracker(atrkr, () => state.user.name); // import `withTracker` too
|
|
983
965
|
* const stop = atrkr.callback(() => console.log("sync"), { sync: true }); // re-run immediately when ".user.name" changes, works on any path used from any reactor state
|
|
984
|
-
* @example Extensive
|
|
966
|
+
* @example Extensive Customization
|
|
985
967
|
* atrkr.unblock();
|
|
986
968
|
* const prev = CTX.autotracker;
|
|
987
969
|
* CTX.autotracker = atrkr; // import CTX first
|
|
@@ -1181,8 +1163,8 @@ function effect(callback, options) {
|
|
|
1181
1163
|
|
|
1182
1164
|
// src/ts/adapters/vanilla/TimeTravelOverlay.ts
|
|
1183
1165
|
var keys = {
|
|
1184
|
-
overrides: ["Ctrl+z", "Cmd+z", "Ctrl+y", "Cmd+y", "Ctrl+Shift+z", "Cmd+Shift+z", "
|
|
1185
|
-
shortcuts: { undo: ["Ctrl+z", "Cmd+z"], redo: ["Ctrl+y", "Cmd+y", "Ctrl+Shift+z", "Cmd+Shift+z"], genesis:
|
|
1166
|
+
overrides: ["Ctrl+z", "Cmd+z", "Ctrl+y", "Cmd+y", "Ctrl+Shift+z", "Cmd+Shift+z", "Home", "End", ",", ".", "ArrowLeft", "ArrowRight", "Space", "Alt+Space", "Escape", "Delete", "e", "i", "c"],
|
|
1167
|
+
shortcuts: { undo: ["Ctrl+z", "Cmd+z"], redo: ["Ctrl+y", "Cmd+y", "Ctrl+Shift+z", "Cmd+Shift+z"], genesis: "Home", ending: "End", prevFrame: ",", nextFrame: ".", skipBwd: "ArrowLeft", skipFwd: "ArrowRight", playPause: "Space", rewind: "Alt+Space", closeOverlay: "Escape", clrHistory: "Delete", export: "e", import: "i", clear: "c" }
|
|
1186
1168
|
};
|
|
1187
1169
|
var TimeTravelOverlay = class _TimeTravelOverlay {
|
|
1188
1170
|
static count = 0;
|
|
@@ -1193,22 +1175,22 @@ var TimeTravelOverlay = class _TimeTravelOverlay {
|
|
|
1193
1175
|
els;
|
|
1194
1176
|
clups = [];
|
|
1195
1177
|
keyup;
|
|
1196
|
-
/** Creates a docked TimeTravel overlay bound to a
|
|
1197
|
-
* @param time TimeTravel
|
|
1178
|
+
/** Creates a docked TimeTravel overlay bound to a module instance.
|
|
1179
|
+
* @param time TimeTravel module instance that owns timeline operations.
|
|
1198
1180
|
* @param build Optional initial overlay config overrides.
|
|
1199
1181
|
*/
|
|
1200
1182
|
constructor(time, build = {}) {
|
|
1201
1183
|
this.time = time;
|
|
1202
1184
|
this.config = reactive({ title: `Time Travel Overlay ${this.index = ++_TimeTravelOverlay.count}`, ...build });
|
|
1203
1185
|
this.state.open = !!this.config.startOpen;
|
|
1204
|
-
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
|
|
1186
|
+
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)}`, 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" });
|
|
1205
1187
|
status.append((box.append(frame), box), clrHistory);
|
|
1206
1188
|
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));
|
|
1207
1189
|
host.append(toggle, panel);
|
|
1208
1190
|
this.els = { host, toggle, panel, title, frame, clrHistory, undo, redo, genesis, playPause, rewind, range, exp, imp, clr, payload, io };
|
|
1209
1191
|
this.keyup = (e) => {
|
|
1210
|
-
const a = this.state.open && keyEventAllowed(e, keys);
|
|
1211
|
-
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 = "");
|
|
1192
|
+
const a = this.state.open && (this.config.devOnly ? CTX.isDevEnv : true) && keyEventAllowed(e, keys);
|
|
1193
|
+
a === "undo" ? this.time.undo() : a === "redo" ? this.time.redo() : a === "genesis" ? this.time.jumpTo(0) : a === "ending" ? this.time.jumpTo(s.history.length) : 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 = "");
|
|
1212
1194
|
};
|
|
1213
1195
|
window.addEventListener("keydown", this.keyup);
|
|
1214
1196
|
const sync = [
|
|
@@ -1223,7 +1205,8 @@ var TimeTravelOverlay = class _TimeTravelOverlay {
|
|
|
1223
1205
|
effect(() => {
|
|
1224
1206
|
frame.textContent = `Frame: ${s.currentFrame} / ${s.history.length}`;
|
|
1225
1207
|
range.disabled = clrHistory.disabled = !s.history.length;
|
|
1226
|
-
genesis.disabled =
|
|
1208
|
+
genesis.disabled = undo.disabled = !s.currentFrame;
|
|
1209
|
+
rewind.disabled = !s.paused || !s.currentFrame;
|
|
1227
1210
|
playPause.disabled = redo.disabled = s.currentFrame >= s.history.length;
|
|
1228
1211
|
range.max = String(s.history.length);
|
|
1229
1212
|
range.value = String(Math.min(s.currentFrame, s.history.length));
|
|
@@ -1237,7 +1220,7 @@ var TimeTravelOverlay = class _TimeTravelOverlay {
|
|
|
1237
1220
|
this.clups.push(...sync);
|
|
1238
1221
|
}
|
|
1239
1222
|
destroy() {
|
|
1240
|
-
this.clups
|
|
1223
|
+
for (const clup of this.clups) clup();
|
|
1241
1224
|
this.keyup && window.removeEventListener("keydown", this.keyup);
|
|
1242
1225
|
this.els.host.remove();
|
|
1243
1226
|
nuke(this), --_TimeTravelOverlay.count;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions,
|
|
1
|
+
import { E as EffectOptions, R as Reactor, d as Reactive, u as ReactorBuild, W as WildPaths, v as PathValue } from '../index-m0aAWxhX.cjs';
|
|
2
2
|
import { useLayoutEffect } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import { T as TimeTravelConfig } from '../TimeTravelOverlay-
|
|
3
|
+
import { m as TimeTravelModule } from '../timeTravel-DctvcHVt.cjs';
|
|
4
|
+
import { T as TimeTravelConfig } from '../TimeTravelOverlay-OjklzuCD.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Subscribes a component to desired Reactor state and returns it.
|
|
@@ -12,12 +12,12 @@ import { T as TimeTravelConfig } from '../TimeTravelOverlay-CJv-S_Km.cjs';
|
|
|
12
12
|
* @param build Optional Reactor build options used when creating a scoped Reactor for plain objects.
|
|
13
13
|
* @returns State for render usage if state is scoped locally or just desired.
|
|
14
14
|
* @example
|
|
15
|
-
* const a = useReactor({ user: { name: "
|
|
15
|
+
* const a = useReactor({ user: { name: "Kosi" } }); // per-component scoped
|
|
16
16
|
* @example
|
|
17
|
-
* const state = reactive({ user: { name: "
|
|
17
|
+
* const state = reactive({ user: { name: "Kosi" } });
|
|
18
18
|
* const b = useReactor(state);
|
|
19
19
|
* @example
|
|
20
|
-
* const rtr = new Reactor({ user: { name: "
|
|
20
|
+
* const rtr = new Reactor({ user: { name: "Kosi" } });
|
|
21
21
|
* const c = useReactor(rtr);
|
|
22
22
|
*/
|
|
23
23
|
declare function useReactor<T extends object>(target: T | Reactor<T> | Reactive<T>, options?: EffectOptions, build?: ReactorBuild<T>): T;
|
|
@@ -39,12 +39,12 @@ declare function useAnyReactor(options?: EffectOptions): void;
|
|
|
39
39
|
* @param build Optional Reactor build options used when creating a scoped Reactor for plain objects.
|
|
40
40
|
* @returns Tracked snapshot snap for render usage.
|
|
41
41
|
* @example
|
|
42
|
-
* const a = useReactorSnapshot({ user: { name: "
|
|
42
|
+
* const a = useReactorSnapshot({ user: { name: "Kosi" } }); // per-component scoped
|
|
43
43
|
* @example
|
|
44
|
-
* const state = reactive({ user: { name: "
|
|
44
|
+
* const state = reactive({ user: { name: "Kosi" } });
|
|
45
45
|
* const b = useReactorSnapshot(state);
|
|
46
46
|
* @example
|
|
47
|
-
* const rtr = new Reactor({ user: { name: "
|
|
47
|
+
* const rtr = new Reactor({ user: { name: "Kosi" } });
|
|
48
48
|
* const c = useReactorSnapshot(rtr);
|
|
49
49
|
*/
|
|
50
50
|
declare function useReactorSnapshot<T extends object>(target: T | Reactor<T> | Reactive<T>, options?: EffectOptions, build?: ReactorBuild<T>): T;
|
|
@@ -62,12 +62,12 @@ declare function useReactorSnapshot<T extends object>(target: T | Reactor<T> | R
|
|
|
62
62
|
* @param build Optional Reactor build options used when creating a scoped Reactor for plain objects.
|
|
63
63
|
* @returns The selected slice.
|
|
64
64
|
* @example
|
|
65
|
-
* const a = useSelector({ user: { name: "
|
|
65
|
+
* const a = useSelector({ user: { name: "Kosi" } }, (s) => s.user.name); // per-component scoped
|
|
66
66
|
* @example
|
|
67
|
-
* const state = reactive({ user: { name: "
|
|
67
|
+
* const state = reactive({ user: { name: "Kosi" } });
|
|
68
68
|
* const b = useSelector(state, (s) => s.user.name);
|
|
69
69
|
* @example
|
|
70
|
-
* const rtr = new Reactor({ user: { name: "
|
|
70
|
+
* const rtr = new Reactor({ user: { name: "Kosi" } });
|
|
71
71
|
* const c = useSelector(rtr, (s) => s.user.name);
|
|
72
72
|
*/
|
|
73
73
|
declare function useSelector<T extends object, R>(target: T | Reactor<T> | Reactive<T>, sel: (state: T) => R, eq?: (prev: R | undefined, next: R) => boolean, options?: EffectOptions, build?: ReactorBuild<T>): R;
|
|
@@ -95,12 +95,12 @@ declare function useAnySelector<R>(sel: () => R, eq?: (value1: any, value2: any)
|
|
|
95
95
|
* @param build Optional Reactor build options used when creating a scoped Reactor for plain objects.
|
|
96
96
|
* @returns The selected slice.
|
|
97
97
|
* @example
|
|
98
|
-
* const a = useSelectorSnapshot({ user: { name: "
|
|
98
|
+
* const a = useSelectorSnapshot({ user: { name: "Kosi" } }, (s) => s.user.name); // per-component scoped
|
|
99
99
|
* @example
|
|
100
|
-
* const state = reactive({ user: { name: "
|
|
100
|
+
* const state = reactive({ user: { name: "Kosi" } });
|
|
101
101
|
* const b = useSelectorSnapshot(state, (s) => s.user.name);
|
|
102
102
|
* @example
|
|
103
|
-
* const rtr = new Reactor({ user: { name: "
|
|
103
|
+
* const rtr = new Reactor({ user: { name: "Kosi" } });
|
|
104
104
|
* const c = useSelectorSnapshot(rtr, (s) => s.user.name);
|
|
105
105
|
*/
|
|
106
106
|
declare function useSelectorSnapshot<T extends object, R>(target: T | Reactor<T> | Reactive<T>, sel: (state: T) => R, eq?: (value1: any, value2: any) => boolean, options?: EffectOptions, build?: ReactorBuild<T>): R;
|
|
@@ -116,12 +116,12 @@ declare function useSelectorSnapshot<T extends object, R>(target: T | Reactor<T>
|
|
|
116
116
|
* @param build Optional Reactor build options used when creating a scoped Reactor for plain objects.
|
|
117
117
|
* @returns Current value at the requested path.
|
|
118
118
|
* @example
|
|
119
|
-
* const a = usePath({ user: { profile: { name: "
|
|
119
|
+
* const a = usePath({ user: { profile: { name: "Kosi" } } }, "user.profile.name");
|
|
120
120
|
* @example
|
|
121
|
-
* const state = reactive({ user: { profile: { name: "
|
|
121
|
+
* const state = reactive({ user: { profile: { name: "Kosi" } } });
|
|
122
122
|
* const b = usePath(state, "user.profile.name");
|
|
123
123
|
* @example
|
|
124
|
-
* const rtr = new Reactor({ user: { profile: { name: "
|
|
124
|
+
* const rtr = new Reactor({ user: { profile: { name: "Kosi" } } });
|
|
125
125
|
* const c = usePath(rtr, "user.profile.name");
|
|
126
126
|
* @example
|
|
127
127
|
* const wholeState = usePath(state, "*");
|
|
@@ -133,11 +133,12 @@ declare const useISOLayoutEffect: typeof useLayoutEffect;
|
|
|
133
133
|
|
|
134
134
|
/** React props for controlling the vanilla TimeTravel overlay. */
|
|
135
135
|
interface TimeTravelOverlayProps extends Partial<TimeTravelConfig> {
|
|
136
|
-
/**
|
|
137
|
-
time:
|
|
136
|
+
/** Module instance controlled by this overlay bridge. */
|
|
137
|
+
time: TimeTravelModule;
|
|
138
138
|
}
|
|
139
|
-
/**
|
|
140
|
-
|
|
139
|
+
/**
|
|
140
|
+
- React bridge for mounting and controlling a vanilla TimeTravelOverlay instance.
|
|
141
|
+
- Instantiates a `TimeTravelOverlay` for the provided module, tears it down on unmount, and syncs prop changes into reactive `config`.
|
|
141
142
|
* Use this when your app is React but you want the overlay behavior with react-safe instance lifecycle management.
|
|
142
143
|
* @param props Overlay bridge props.
|
|
143
144
|
*/
|