sia-reactor 0.0.39 → 0.0.41
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/dist/{TimeTravelConsole-DSifvt2z.d.ts → TimeTravelConsole-BjDL0JjZ.d.ts} +2 -2
- package/dist/{TimeTravelConsole-nYAqg57U.d.cts → TimeTravelConsole-Dt8txKnt.d.cts} +2 -2
- package/dist/adapters/react.cjs +3 -3
- package/dist/adapters/react.d.cts +3 -3
- package/dist/adapters/react.d.ts +3 -3
- package/dist/adapters/react.js +4 -4
- package/dist/adapters/vanilla.cjs +3 -3
- 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-56H5BKHJ.js → chunk-A2SOELR6.js} +4 -4
- package/dist/{chunk-FOD32N6J.js → chunk-AW22CQWE.js} +2 -2
- package/dist/{chunk-DCUPDG7B.js → chunk-LZJYX2LE.js} +20 -21
- package/dist/{chunk-ORK3EGB6.js → chunk-PJTPFVEG.js} +3 -3
- package/dist/{index-BsH8KkqG.d.cts → index-BtHNGnRR.d.cts} +8 -6
- package/dist/{index-BsH8KkqG.d.ts → index-BtHNGnRR.d.ts} +8 -6
- package/dist/{index-D4DGBS2N.d.ts → index-CKHoDs6x.d.ts} +1 -1
- package/dist/{index-DBx4TIVW.d.cts → index-C_djeddc.d.cts} +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/modules.cjs +12 -11
- package/dist/modules.d.cts +5 -5
- package/dist/modules.d.ts +5 -5
- package/dist/modules.js +5 -5
- package/dist/super.d.ts +11 -8
- package/dist/super.global.js +26 -27
- package/dist/utils.cjs +23 -24
- package/dist/utils.d.cts +3 -2
- package/dist/utils.d.ts +3 -2
- package/dist/utils.js +2 -2
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as Reactive } from './index-
|
|
2
|
-
import { T as TimeTravelModule } from './index-
|
|
1
|
+
import { R as Reactive } from './index-BtHNGnRR.js';
|
|
2
|
+
import { T as TimeTravelModule } from './index-CKHoDs6x.js';
|
|
3
3
|
|
|
4
4
|
/** Reactive options for the TimeTravel overlay instance. */
|
|
5
5
|
interface TimeTravelConsoleConfig {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as Reactive } from './index-
|
|
2
|
-
import { T as TimeTravelModule } from './index-
|
|
1
|
+
import { R as Reactive } from './index-BtHNGnRR.cjs';
|
|
2
|
+
import { T as TimeTravelModule } from './index-C_djeddc.cjs';
|
|
3
3
|
|
|
4
4
|
/** Reactive options for the TimeTravel overlay instance. */
|
|
5
5
|
interface TimeTravelConsoleConfig {
|
package/dist/adapters/react.cjs
CHANGED
|
@@ -1159,9 +1159,9 @@ function assignEl(el, props, dataset, styles, nodiff = true) {
|
|
|
1159
1159
|
}
|
|
1160
1160
|
return el;
|
|
1161
1161
|
}
|
|
1162
|
-
function getActiveEl(root) {
|
|
1162
|
+
function getActiveEl(root, noBody = true) {
|
|
1163
1163
|
const activeEl = (root ?? document).activeElement;
|
|
1164
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
1164
|
+
return !activeEl || noBody && activeEl === document.body ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
1165
1165
|
}
|
|
1166
1166
|
|
|
1167
1167
|
// src/ts/utils/keys.ts
|
|
@@ -1260,7 +1260,7 @@ var TimeTravelConsole = class _TimeTravelConsole {
|
|
|
1260
1260
|
this.config = reactive({ title: `Time Travel Console ${this.index = ++_TimeTravelConsole.count}`, ...build });
|
|
1261
1261
|
this.state.open = !!this.config.startOpen;
|
|
1262
1262
|
let wlLive = false, blLive = false;
|
|
1263
|
-
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 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(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: () => this.time.redo(this.state.stride) }), 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 }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack, false) }), 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${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: "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>
|
|
1263
|
+
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 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(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: () => this.time.redo(this.state.stride) }), 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 }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack, false) }), 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${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: "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.config.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" });
|
|
1264
1264
|
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` })));
|
|
1265
1265
|
status.append((box.append(frame), box), clrHistory);
|
|
1266
1266
|
filters.append((filterBox.append((filterRow1.append(whitelistLabel, whitelist), filterRow1), (filterRow2.append(blacklistLabel, blacklist), filterRow2)), filterBox));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions, d as Reactor, R as Reactive, J as ReactorBuild, K as DeepReadonly, W as WildPaths, a as PathValue } from '../index-
|
|
1
|
+
import { E as EffectOptions, d as Reactor, R as Reactive, J as ReactorBuild, K as DeepReadonly, W as WildPaths, a as PathValue } from '../index-BtHNGnRR.cjs';
|
|
2
2
|
import { useLayoutEffect } from 'react';
|
|
3
|
-
import { T as TimeTravelModule } from '../index-
|
|
4
|
-
import { a as TimeTravelConsoleConfig } from '../TimeTravelConsole-
|
|
3
|
+
import { T as TimeTravelModule } from '../index-C_djeddc.cjs';
|
|
4
|
+
import { a as TimeTravelConsoleConfig } from '../TimeTravelConsole-Dt8txKnt.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Subscribes a component to desired Reactor state and returns it.
|
package/dist/adapters/react.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions, d as Reactor, R as Reactive, J as ReactorBuild, K as DeepReadonly, W as WildPaths, a as PathValue } from '../index-
|
|
1
|
+
import { E as EffectOptions, d as Reactor, R as Reactive, J as ReactorBuild, K as DeepReadonly, W as WildPaths, a as PathValue } from '../index-BtHNGnRR.js';
|
|
2
2
|
import { useLayoutEffect } from 'react';
|
|
3
|
-
import { T as TimeTravelModule } from '../index-
|
|
4
|
-
import { a as TimeTravelConsoleConfig } from '../TimeTravelConsole-
|
|
3
|
+
import { T as TimeTravelModule } from '../index-CKHoDs6x.js';
|
|
4
|
+
import { a as TimeTravelConsoleConfig } from '../TimeTravelConsole-BjDL0JjZ.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Subscribes a component to desired Reactor state and returns it.
|
package/dist/adapters/react.js
CHANGED
|
@@ -2,16 +2,16 @@ import {
|
|
|
2
2
|
Autotracker,
|
|
3
3
|
TimeTravelConsole,
|
|
4
4
|
withTracker
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-A2SOELR6.js";
|
|
6
|
+
import "../chunk-AW22CQWE.js";
|
|
7
|
+
import "../chunk-PJTPFVEG.js";
|
|
8
8
|
import {
|
|
9
9
|
CTX,
|
|
10
10
|
NIL,
|
|
11
11
|
NOOP,
|
|
12
12
|
getPath,
|
|
13
13
|
getReactor
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-LZJYX2LE.js";
|
|
15
15
|
|
|
16
16
|
// src/ts/adapters/react/hooks/useReactor.ts
|
|
17
17
|
import { useRef, useCallback, useSyncExternalStore, useMemo } from "react";
|
|
@@ -1079,9 +1079,9 @@ function assignEl(el, props, dataset, styles, nodiff = true) {
|
|
|
1079
1079
|
}
|
|
1080
1080
|
return el;
|
|
1081
1081
|
}
|
|
1082
|
-
function getActiveEl(root) {
|
|
1082
|
+
function getActiveEl(root, noBody = true) {
|
|
1083
1083
|
const activeEl = (root ?? document).activeElement;
|
|
1084
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
1084
|
+
return !activeEl || noBody && activeEl === document.body ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
1085
1085
|
}
|
|
1086
1086
|
|
|
1087
1087
|
// src/ts/utils/keys.ts
|
|
@@ -1167,7 +1167,7 @@ var TimeTravelConsole = class _TimeTravelConsole {
|
|
|
1167
1167
|
this.config = reactive({ title: `Time Travel Console ${this.index = ++_TimeTravelConsole.count}`, ...build });
|
|
1168
1168
|
this.state.open = !!this.config.startOpen;
|
|
1169
1169
|
let wlLive = false, blLive = false;
|
|
1170
|
-
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 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(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: () => this.time.redo(this.state.stride) }), 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 }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack, false) }), 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${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: "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>
|
|
1170
|
+
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 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(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: () => this.time.redo(this.state.stride) }), 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 }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack, false) }), 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${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: "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.config.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" });
|
|
1171
1171
|
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` })));
|
|
1172
1172
|
status.append((box.append(frame), box), clrHistory);
|
|
1173
1173
|
filters.append((filterBox.append((filterRow1.append(whitelistLabel, whitelist), filterRow1), (filterRow2.append(blacklistLabel, blacklist), filterRow2)), filterBox));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions } from '../index-
|
|
2
|
-
export { A as Autotracker, w as withTracker } from '../index-
|
|
3
|
-
export { T as TimeTravelConsole, a as TimeTravelConsoleConfig } from '../TimeTravelConsole-
|
|
4
|
-
import '../index-
|
|
1
|
+
import { E as EffectOptions } from '../index-BtHNGnRR.cjs';
|
|
2
|
+
export { A as Autotracker, w as withTracker } from '../index-BtHNGnRR.cjs';
|
|
3
|
+
export { T as TimeTravelConsole, a as TimeTravelConsoleConfig } from '../TimeTravelConsole-Dt8txKnt.cjs';
|
|
4
|
+
import '../index-C_djeddc.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Runs a reactive side effect in vanilla JavaScript.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { E as EffectOptions } from '../index-
|
|
2
|
-
export { A as Autotracker, w as withTracker } from '../index-
|
|
3
|
-
export { T as TimeTravelConsole, a as TimeTravelConsoleConfig } from '../TimeTravelConsole-
|
|
4
|
-
import '../index-
|
|
1
|
+
import { E as EffectOptions } from '../index-BtHNGnRR.js';
|
|
2
|
+
export { A as Autotracker, w as withTracker } from '../index-BtHNGnRR.js';
|
|
3
|
+
export { T as TimeTravelConsole, a as TimeTravelConsoleConfig } from '../TimeTravelConsole-BjDL0JjZ.js';
|
|
4
|
+
import '../index-CKHoDs6x.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Runs a reactive side effect in vanilla JavaScript.
|
package/dist/adapters/vanilla.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
TimeTravelConsole,
|
|
4
4
|
effect,
|
|
5
5
|
withTracker
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-A2SOELR6.js";
|
|
7
|
+
import "../chunk-AW22CQWE.js";
|
|
8
|
+
import "../chunk-PJTPFVEG.js";
|
|
9
|
+
import "../chunk-LZJYX2LE.js";
|
|
10
10
|
export {
|
|
11
11
|
Autotracker,
|
|
12
12
|
TimeTravelConsole,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
wpArr
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AW22CQWE.js";
|
|
4
4
|
import {
|
|
5
5
|
KEYS_BLOCKS,
|
|
6
6
|
createEl,
|
|
7
7
|
formatKeyForDisplay,
|
|
8
8
|
keyEventAllowed,
|
|
9
9
|
parseForARIAKS
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PJTPFVEG.js";
|
|
11
11
|
import {
|
|
12
12
|
CTX,
|
|
13
13
|
NIL,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
canHandle,
|
|
16
16
|
nuke,
|
|
17
17
|
reactive
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-LZJYX2LE.js";
|
|
19
19
|
|
|
20
20
|
// src/ts/adapters/autotracker.ts
|
|
21
21
|
var Autotracker = class {
|
|
@@ -200,7 +200,7 @@ var TimeTravelConsole = class _TimeTravelConsole {
|
|
|
200
200
|
this.config = reactive({ title: `Time Travel Console ${this.index = ++_TimeTravelConsole.count}`, ...build });
|
|
201
201
|
this.state.open = !!this.config.startOpen;
|
|
202
202
|
let wlLive = false, blLive = false;
|
|
203
|
-
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 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(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: () => this.time.redo(this.state.stride) }), 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 }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack, false) }), 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${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: "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>
|
|
203
|
+
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 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(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: () => this.time.redo(this.state.stride) }), 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 }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack, false) }), 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${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: "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.config.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" });
|
|
204
204
|
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` })));
|
|
205
205
|
status.append((box.append(frame), box), clrHistory);
|
|
206
206
|
filters.append((filterBox.append((filterRow1.append(whitelistLabel, whitelist), filterRow1), (filterRow2.append(blacklistLabel, blacklist), filterRow2)), filterBox));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
guardAllMethods,
|
|
3
3
|
guardMethod
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PJTPFVEG.js";
|
|
5
5
|
import {
|
|
6
6
|
getPath,
|
|
7
7
|
getReactor,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
nuke,
|
|
11
11
|
reactive,
|
|
12
12
|
setPath
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-LZJYX2LE.js";
|
|
14
14
|
|
|
15
15
|
// src/ts/modules/base/index.ts
|
|
16
16
|
var BaseReactorModule = class {
|
|
@@ -176,24 +176,25 @@ function parseEvtOpts(options, opts, boolOpt = opts[0], result = {}) {
|
|
|
176
176
|
function fanout(a, b, c, d) {
|
|
177
177
|
const isEvPd = !!a?.target, isPath = !isEvPd && "string" === typeof b, [state2, path, olds, news, opts, type] = isEvPd ? [a.root, a.currentTarget.path, a.currentTarget.oldValue, a.currentTarget.value, b || NIL, a.type] : isPath ? [a, b, getPath(a, b), c, d || NIL, void 0] : [void 0, void 0, a, b, c || NIL, void 0], target = isEvPd ? getPath(a.root, a.currentTarget.path) : isPath ? getPath(state2, path) : olds;
|
|
178
178
|
if (isEvPd && type !== "set" && type !== "delete" || !target || !canHandle(news, opts)) return;
|
|
179
|
+
const { merge = false, depth, atomic = true, skipUndef = false, cloneSets = false, txLabel } = opts;
|
|
179
180
|
const func = () => {
|
|
180
|
-
const walk = (target2, obj,
|
|
181
|
+
const walk = (target2, obj, depth2 = isEvPd ? 1 : Infinity, keys = Object.keys(obj)) => {
|
|
181
182
|
for (let i = 0, len = keys.length; i < len; i++) {
|
|
182
183
|
const key = keys[i], val = obj[key];
|
|
183
184
|
try {
|
|
184
|
-
if (
|
|
185
|
-
else
|
|
185
|
+
if (atomic && Array.isArray(val)) target2[key] = cloneSets ? deepClone(val) : val, target2[key].length = target2[key].length;
|
|
186
|
+
else depth2 > 1 && canHandle(val, opts) ? walk(target2[key] ||= {}, val, depth2 - 1) : (!skipUndef || val !== void 0) && (target2[key] = cloneSets ? deepClone(val) : val);
|
|
186
187
|
} catch (e) {
|
|
187
188
|
if (e instanceof RangeError) throw e;
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
191
|
};
|
|
191
|
-
if (
|
|
192
|
-
else walk(target,
|
|
192
|
+
if (atomic && Array.isArray(news) && isPath) setPath(state2, path, cloneSets ? deepClone(news) : news), getPath(state2, path).length = news.length;
|
|
193
|
+
else walk(target, merge ? mergeObjs(olds, news, opts) : news, depth === true ? Infinity : depth);
|
|
193
194
|
};
|
|
194
|
-
force(() => transaction(func,
|
|
195
|
+
force(() => transaction(func, txLabel ?? `${path ? `Fanout -> '${path}'` : `Fanout`} (Tx ${txId + 1})`), CTX.usingForce || isEvPd);
|
|
195
196
|
}
|
|
196
|
-
var fanoutOptsArr = ["merge", "depth", "atomic", "
|
|
197
|
+
var fanoutOptsArr = ["merge", "depth", "atomic", "skipUndef"];
|
|
197
198
|
function force(task, bool = true) {
|
|
198
199
|
const prev = CTX.usingForce;
|
|
199
200
|
CTX.usingForce = bool;
|
|
@@ -206,8 +207,8 @@ function force(task, bool = true) {
|
|
|
206
207
|
function mergeObjs(o1, o2, config = NIL, pojocheck = true) {
|
|
207
208
|
if (pojocheck && (!isPOJO(o1 || NIL, config) || !isPOJO(o2 || NIL, config))) return o2;
|
|
208
209
|
o1 ||= {}, o2 ||= {};
|
|
209
|
-
const merged = config.
|
|
210
|
-
if (config.
|
|
210
|
+
const merged = config.skipUndef ? { ...o1 } : { ...o1, ...o2 };
|
|
211
|
+
if (config.skipUndef) {
|
|
211
212
|
const keys2 = Object.keys(o1);
|
|
212
213
|
for (let i = 0, len = keys2.length; i < len; i++) {
|
|
213
214
|
const key = keys2[i], val = o2[key];
|
|
@@ -300,20 +301,18 @@ function isLeafPath(obj, path, config = CTX.defaults, value = getPath(obj, path,
|
|
|
300
301
|
return path !== "*" && !canHandle(value, config);
|
|
301
302
|
}
|
|
302
303
|
function createReactorSync(rA, rB, prefixA, prefixB = "", signal) {
|
|
303
|
-
const
|
|
304
|
+
const rtrA = getReactor(rA, true), rtrB = getReactor(rB, true);
|
|
304
305
|
let origin = null;
|
|
305
|
-
const sync = (
|
|
306
|
-
if (origin === (
|
|
307
|
-
const { path, object, key } = payload.target;
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
setPath(destCore, pDest ? stripped ? `${pDest}.${stripped}` : pDest : stripped || "*", Array.isArray(object) ? object : val);
|
|
312
|
-
origin = null;
|
|
306
|
+
const sync = (src, dest, srcP, destP) => (val, payload) => {
|
|
307
|
+
if (origin === (src ^ 1)) return;
|
|
308
|
+
const { path, object: obj, key } = payload.target;
|
|
309
|
+
if (srcP && path !== srcP && !path.startsWith(srcP + ".")) return;
|
|
310
|
+
const isArr = Array.isArray(obj), origP = isArr ? path.slice(0, -(key.length + 1)) : path, syncP = origP === srcP ? "" : srcP ? origP.slice(srcP.length + 1) : origP;
|
|
311
|
+
origin = src, setPath(dest, destP ? syncP ? `${destP}.${syncP}` : destP : syncP || "*", isArr ? deepClone(obj) : val), origin = null;
|
|
313
312
|
};
|
|
314
|
-
const
|
|
315
|
-
if (
|
|
316
|
-
const clupA =
|
|
313
|
+
const initA = prefixA ? getPath(rtrA.core, prefixA) : rtrA.core;
|
|
314
|
+
if (initA !== void 0) fanout(rtrB.core, prefixB || "*", initA, { depth: 1, cloneSets: true, txLabel: `ReactorSync: ${prefixA}^ <-> ${prefixB}` });
|
|
315
|
+
const clupA = rtrA.watch("*", sync(0, rtrB.core, prefixA, prefixB), { signal }), clupB = rtrB.watch("*", sync(1, rtrA.core, prefixB, prefixA), { signal });
|
|
317
316
|
return () => (clupA(), clupB());
|
|
318
317
|
}
|
|
319
318
|
|
|
@@ -54,16 +54,16 @@ function assignEl(el, props, dataset, styles, nodiff = true) {
|
|
|
54
54
|
}
|
|
55
55
|
return el;
|
|
56
56
|
}
|
|
57
|
-
function getActiveEl(root) {
|
|
57
|
+
function getActiveEl(root, noBody = true) {
|
|
58
58
|
const activeEl = (root ?? document).activeElement;
|
|
59
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
59
|
+
return !activeEl || noBody && activeEl === document.body ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// src/ts/utils/keys.ts
|
|
63
63
|
var KEYS_BLOCKS = ["Ctrl+Tab", "Ctrl+Shift+Tab", "Ctrl+PageUp", "Ctrl+PageDown", "Cmd+Option+ArrowRight", "Cmd+Option+ArrowLeft", "Ctrl+1", "Ctrl+2", "Ctrl+3", "Ctrl+4", "Ctrl+5", "Ctrl+6", "Ctrl+7", "Ctrl+8", "Ctrl+9", "Cmd+1", "Cmd+2", "Cmd+3", "Cmd+4", "Cmd+5", "Cmd+6", "Cmd+7", "Cmd+8", "Cmd+9", "Alt+ArrowLeft", "Alt+ArrowRight", "Cmd+ArrowLeft", "Cmd+ArrowRight", "Ctrl+r", "Ctrl+Shift+r", "F5", "Shift+F5", "Cmd+r", "Cmd+Shift+r", "Ctrl+h", "Ctrl+j", "Ctrl+d", "Ctrl+f", "Cmd+y", "Cmd+Option+b", "Cmd+d", "Cmd+f", "Ctrl+Shift+i", "Ctrl+Shift+j", "Ctrl+Shift+c", "Ctrl+u", "F12", "Cmd+Option+i", "Cmd+Option+j", "Cmd+Option+c", "Cmd+Option+u", "Ctrl+=", "Ctrl+-", "Ctrl+0", "Cmd+=", "Cmd+-", "Cmd+0", "Ctrl+p", "Ctrl+s", "Ctrl+o", "Cmd+p", "Cmd+s", "Cmd+o"];
|
|
64
64
|
function parseKeyCombo(combo) {
|
|
65
65
|
const parts = cleanKeyCombo(combo).toLowerCase().split("+");
|
|
66
|
-
return { ctrlKey: parts.includes("ctrl"), shiftKey: parts.includes("shift"), altKey: parts.includes("alt"), metaKey: parts.includes("meta") || parts.includes("cmd"), key: parts.find((p) =>
|
|
66
|
+
return { ctrlKey: parts.includes("ctrl"), shiftKey: parts.includes("shift"), altKey: parts.includes("alt"), metaKey: parts.includes("meta") || parts.includes("cmd"), key: parts.find((p) => !/^(ctrl|shift|alt|meta|cmd)$/.test(p)) || "" };
|
|
67
67
|
}
|
|
68
68
|
function stringifyKeyEvent(e) {
|
|
69
69
|
const parts = [];
|
|
@@ -509,10 +509,12 @@ interface FanoutOptionsTuple extends Partial<Record<(typeof fanoutOptsArr)[numbe
|
|
|
509
509
|
depth?: number | boolean;
|
|
510
510
|
/** Whether to assign arrays as a whole and only touch `.length` for common cases. Only works with the `path` parameter overload or in nested levels.
|
|
511
511
|
* Arrays can lead to unnecessary work as more often than not, you won't be watching index paths but waiting on the parent bubble instead.
|
|
512
|
-
* If you happen to be watching, it might be more optimal to re-set it yourself if it's only a few indexes or just
|
|
512
|
+
* If you happen to be watching, it might be more optimal to re-set it yourself if it's only a few indexes or just set this to `false`. @default `true` */
|
|
513
513
|
atomic?: boolean;
|
|
514
514
|
/** Whether to skip `undefined` values during fanout. @default `false`. */
|
|
515
|
-
|
|
515
|
+
skipUndef?: boolean;
|
|
516
|
+
/** Whether to clone before setting any final values, prevents unintended reference sharing across the state tree. @default `false`. */
|
|
517
|
+
cloneSets?: boolean;
|
|
516
518
|
/** A label for the transaction that will be started, useful for debugging and tracking. @default `Fanout -> "${path}"` : `Fanout`} (Tx ${CTX.txId})`. */
|
|
517
519
|
txLabel?: string;
|
|
518
520
|
}
|
|
@@ -536,7 +538,7 @@ declare function fanout<T extends object>(target: T, value: Partial<T> | Partial
|
|
|
536
538
|
declare function fanout<T extends object, P extends WildPaths<T> = WildPaths<T>>(state: T, path: P, value: Partial<PathValue<T, P>>, options?: {
|
|
537
539
|
crossRealms?: boolean;
|
|
538
540
|
} & FanoutOptionsTuple): void;
|
|
539
|
-
declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "
|
|
541
|
+
declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "skipUndef"];
|
|
540
542
|
/**
|
|
541
543
|
* Executes a task while forcing all reactive writes to bypass equality checks.
|
|
542
544
|
* @param task The mutation logic to execute.
|
|
@@ -545,13 +547,13 @@ declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "skipUndefine
|
|
|
545
547
|
*/
|
|
546
548
|
declare function force<T>(task: () => T, bool?: boolean): T;
|
|
547
549
|
/**
|
|
548
|
-
* Deep-merges object-like values, does necessary checks so use without doubts. Only `o2` keys are checked when `
|
|
550
|
+
* Deep-merges object-like values, does necessary checks so use without doubts. Only `o2` keys are checked when `skipUndef` is true.
|
|
549
551
|
* @example
|
|
550
552
|
* const next = mergeObjs({ user: { name: "Kosi" } }, { user: { role: "admin" } }); // { ...o1, ...o2 } // o2 over o1 and deep!
|
|
551
553
|
*/
|
|
552
554
|
declare function mergeObjs<T1 extends object, T2 extends object>(o1?: T1 | null, o2?: T2 | null, config?: {
|
|
553
555
|
crossRealms?: boolean;
|
|
554
|
-
|
|
556
|
+
skipUndef?: boolean;
|
|
555
557
|
}, pojocheck?: boolean): DeepMerge<T1, T2>;
|
|
556
558
|
/** Returns [path, parent, value] records from root to the target path. */
|
|
557
559
|
declare function getTrailRecords<T extends object>(obj: T, path: WildPaths<T>, reverse?: boolean): [WildPaths<T>, PathBranchValue<T, WildPaths<T>>, PathValue<T, WildPaths<T>>][];
|
|
@@ -592,7 +594,7 @@ declare function isLeafPath<T extends object, const S extends string = ".", P ex
|
|
|
592
594
|
separator?: S;
|
|
593
595
|
} & typeof CTX.defaults, value?: PathValue<T, P, S>): boolean;
|
|
594
596
|
/**
|
|
595
|
-
* Creates a two-way, array-
|
|
597
|
+
* Creates a two-way, array-atomic, echo-proof sync bridge between two S.I.A Reactors. Uses a synchronous origin lock to prevent infinite echo loops.
|
|
596
598
|
* On setup, `rA` hydrates `rB` at `prefixB` with a deep clone of its current state at `prefixA` (primary drives initial truth).
|
|
597
599
|
* @param rA Primary reactor — source of truth. Its `prefixA` slice seeds `rB.prefixB` on setup.
|
|
598
600
|
* @param rB Secondary reactor — the wider store (e.g. `ctlr.config`). Holds the primary at a named path.
|
|
@@ -509,10 +509,12 @@ interface FanoutOptionsTuple extends Partial<Record<(typeof fanoutOptsArr)[numbe
|
|
|
509
509
|
depth?: number | boolean;
|
|
510
510
|
/** Whether to assign arrays as a whole and only touch `.length` for common cases. Only works with the `path` parameter overload or in nested levels.
|
|
511
511
|
* Arrays can lead to unnecessary work as more often than not, you won't be watching index paths but waiting on the parent bubble instead.
|
|
512
|
-
* If you happen to be watching, it might be more optimal to re-set it yourself if it's only a few indexes or just
|
|
512
|
+
* If you happen to be watching, it might be more optimal to re-set it yourself if it's only a few indexes or just set this to `false`. @default `true` */
|
|
513
513
|
atomic?: boolean;
|
|
514
514
|
/** Whether to skip `undefined` values during fanout. @default `false`. */
|
|
515
|
-
|
|
515
|
+
skipUndef?: boolean;
|
|
516
|
+
/** Whether to clone before setting any final values, prevents unintended reference sharing across the state tree. @default `false`. */
|
|
517
|
+
cloneSets?: boolean;
|
|
516
518
|
/** A label for the transaction that will be started, useful for debugging and tracking. @default `Fanout -> "${path}"` : `Fanout`} (Tx ${CTX.txId})`. */
|
|
517
519
|
txLabel?: string;
|
|
518
520
|
}
|
|
@@ -536,7 +538,7 @@ declare function fanout<T extends object>(target: T, value: Partial<T> | Partial
|
|
|
536
538
|
declare function fanout<T extends object, P extends WildPaths<T> = WildPaths<T>>(state: T, path: P, value: Partial<PathValue<T, P>>, options?: {
|
|
537
539
|
crossRealms?: boolean;
|
|
538
540
|
} & FanoutOptionsTuple): void;
|
|
539
|
-
declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "
|
|
541
|
+
declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "skipUndef"];
|
|
540
542
|
/**
|
|
541
543
|
* Executes a task while forcing all reactive writes to bypass equality checks.
|
|
542
544
|
* @param task The mutation logic to execute.
|
|
@@ -545,13 +547,13 @@ declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "skipUndefine
|
|
|
545
547
|
*/
|
|
546
548
|
declare function force<T>(task: () => T, bool?: boolean): T;
|
|
547
549
|
/**
|
|
548
|
-
* Deep-merges object-like values, does necessary checks so use without doubts. Only `o2` keys are checked when `
|
|
550
|
+
* Deep-merges object-like values, does necessary checks so use without doubts. Only `o2` keys are checked when `skipUndef` is true.
|
|
549
551
|
* @example
|
|
550
552
|
* const next = mergeObjs({ user: { name: "Kosi" } }, { user: { role: "admin" } }); // { ...o1, ...o2 } // o2 over o1 and deep!
|
|
551
553
|
*/
|
|
552
554
|
declare function mergeObjs<T1 extends object, T2 extends object>(o1?: T1 | null, o2?: T2 | null, config?: {
|
|
553
555
|
crossRealms?: boolean;
|
|
554
|
-
|
|
556
|
+
skipUndef?: boolean;
|
|
555
557
|
}, pojocheck?: boolean): DeepMerge<T1, T2>;
|
|
556
558
|
/** Returns [path, parent, value] records from root to the target path. */
|
|
557
559
|
declare function getTrailRecords<T extends object>(obj: T, path: WildPaths<T>, reverse?: boolean): [WildPaths<T>, PathBranchValue<T, WildPaths<T>>, PathValue<T, WildPaths<T>>][];
|
|
@@ -592,7 +594,7 @@ declare function isLeafPath<T extends object, const S extends string = ".", P ex
|
|
|
592
594
|
separator?: S;
|
|
593
595
|
} & typeof CTX.defaults, value?: PathValue<T, P, S>): boolean;
|
|
594
596
|
/**
|
|
595
|
-
* Creates a two-way, array-
|
|
597
|
+
* Creates a two-way, array-atomic, echo-proof sync bridge between two S.I.A Reactors. Uses a synchronous origin lock to prevent infinite echo loops.
|
|
596
598
|
* On setup, `rA` hydrates `rB` at `prefixB` with a deep clone of its current state at `prefixA` (primary drives initial truth).
|
|
597
599
|
* @param rA Primary reactor — source of truth. Its `prefixA` slice seeds `rB.prefixB` on setup.
|
|
598
600
|
* @param rB Secondary reactor — the wider store (e.g. `ctlr.config`). Holds the primary at a named path.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Paths, a as PathValue, b as ReactorModuleId, c as ReactorModulePathConfig, B as BaseReactorModule, T as Transaction, d as Reactor, e as REvent, f as Payload } from './index-
|
|
1
|
+
import { P as Paths, a as PathValue, b as ReactorModuleId, c as ReactorModulePathConfig, B as BaseReactorModule, T as Transaction, d as Reactor, e as REvent, f as Payload } from './index-BtHNGnRR.js';
|
|
2
2
|
|
|
3
3
|
interface StorageAdapterConstructor<Config extends StorageAdapterConfig = StorageAdapterConfig> {
|
|
4
4
|
new (config?: Partial<Config>): StorageAdapter<any, Config>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Paths, a as PathValue, b as ReactorModuleId, c as ReactorModulePathConfig, B as BaseReactorModule, T as Transaction, d as Reactor, e as REvent, f as Payload } from './index-
|
|
1
|
+
import { P as Paths, a as PathValue, b as ReactorModuleId, c as ReactorModulePathConfig, B as BaseReactorModule, T as Transaction, d as Reactor, e as REvent, f as Payload } from './index-BtHNGnRR.cjs';
|
|
2
2
|
|
|
3
3
|
interface StorageAdapterConstructor<Config extends StorageAdapterConfig = StorageAdapterConfig> {
|
|
4
4
|
new (config?: Partial<Config>): StorageAdapter<any, Config>;
|
package/dist/index.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { V as APIKey, X as AddDepth, Y as CTX, Z as ChildPaths, _ as DeepKeys, $ as DeepMerge, a0 as DeepPartial, K as DeepReadonly, a1 as DeepRequired, a2 as Deleter, a3 as DeleterRecord, a4 as DepthConfig, a5 as DirectPayload, a6 as EVT_OPTS, E as EffectOptions, a7 as Getter, a8 as GetterRecord, a9 as INDIFFABLE, aa as INERTIA, L as Inert, ab as Intent, ac as Listener, ad as ListenerOptions, ae as ListenerOptionsTuple, af as ListenerRecord, ag as Live, ah as MaxDepth, ai as NIL, aj as NOOP, ak as NextDepth, al as NoTraverse, am as PathBranch, an as PathBranchValue, ao as PathDepth, ap as PathKey, aq as PathLeaf, a as PathValue, P as Paths, f as Payload, ar as PrevDepth, as as Primitive, at as Pure, au as RAW, av as REJECTABLE, e as REvent, aw as RTR_BATCH, ax as RTR_LOG, R as Reactive, ay as ReactivePreferences, d as Reactor, J as ReactorBuild, az as ReactorEvent, aA as SSVERSION, aB as Setter, aC as SetterRecord, aD as Stable, aE as State, aF as StrictPathKey, aG as SubtractDepth, aH as SyncOptions, aI as SyncOptionsTuple, aJ as TERMINATOR, aK as Target, aL as Unflatten, aM as UnionToIntersection, aN as UpdatePayload, aO as VERSION, aP as Volatile, aQ as Watcher, aR as WatcherRecord, W as WildPaths, aS as getRaw, aT as getReactor, aU as getSnapshotVersion, aV as getVersion, aW as inert, aX as intent, aY as isInert, aZ as isIntent, a_ as isVolatile, a$ as live, b0 as methods, b1 as reactive, b2 as stable, b3 as state, b4 as volatile } from './index-
|
|
1
|
+
export { V as APIKey, X as AddDepth, Y as CTX, Z as ChildPaths, _ as DeepKeys, $ as DeepMerge, a0 as DeepPartial, K as DeepReadonly, a1 as DeepRequired, a2 as Deleter, a3 as DeleterRecord, a4 as DepthConfig, a5 as DirectPayload, a6 as EVT_OPTS, E as EffectOptions, a7 as Getter, a8 as GetterRecord, a9 as INDIFFABLE, aa as INERTIA, L as Inert, ab as Intent, ac as Listener, ad as ListenerOptions, ae as ListenerOptionsTuple, af as ListenerRecord, ag as Live, ah as MaxDepth, ai as NIL, aj as NOOP, ak as NextDepth, al as NoTraverse, am as PathBranch, an as PathBranchValue, ao as PathDepth, ap as PathKey, aq as PathLeaf, a as PathValue, P as Paths, f as Payload, ar as PrevDepth, as as Primitive, at as Pure, au as RAW, av as REJECTABLE, e as REvent, aw as RTR_BATCH, ax as RTR_LOG, R as Reactive, ay as ReactivePreferences, d as Reactor, J as ReactorBuild, az as ReactorEvent, aA as SSVERSION, aB as Setter, aC as SetterRecord, aD as Stable, aE as State, aF as StrictPathKey, aG as SubtractDepth, aH as SyncOptions, aI as SyncOptionsTuple, aJ as TERMINATOR, aK as Target, aL as Unflatten, aM as UnionToIntersection, aN as UpdatePayload, aO as VERSION, aP as Volatile, aQ as Watcher, aR as WatcherRecord, W as WildPaths, aS as getRaw, aT as getReactor, aU as getSnapshotVersion, aV as getVersion, aW as inert, aX as intent, aY as isInert, aZ as isIntent, a_ as isVolatile, a$ as live, b0 as methods, b1 as reactive, b2 as stable, b3 as state, b4 as volatile } from './index-BtHNGnRR.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { V as APIKey, X as AddDepth, Y as CTX, Z as ChildPaths, _ as DeepKeys, $ as DeepMerge, a0 as DeepPartial, K as DeepReadonly, a1 as DeepRequired, a2 as Deleter, a3 as DeleterRecord, a4 as DepthConfig, a5 as DirectPayload, a6 as EVT_OPTS, E as EffectOptions, a7 as Getter, a8 as GetterRecord, a9 as INDIFFABLE, aa as INERTIA, L as Inert, ab as Intent, ac as Listener, ad as ListenerOptions, ae as ListenerOptionsTuple, af as ListenerRecord, ag as Live, ah as MaxDepth, ai as NIL, aj as NOOP, ak as NextDepth, al as NoTraverse, am as PathBranch, an as PathBranchValue, ao as PathDepth, ap as PathKey, aq as PathLeaf, a as PathValue, P as Paths, f as Payload, ar as PrevDepth, as as Primitive, at as Pure, au as RAW, av as REJECTABLE, e as REvent, aw as RTR_BATCH, ax as RTR_LOG, R as Reactive, ay as ReactivePreferences, d as Reactor, J as ReactorBuild, az as ReactorEvent, aA as SSVERSION, aB as Setter, aC as SetterRecord, aD as Stable, aE as State, aF as StrictPathKey, aG as SubtractDepth, aH as SyncOptions, aI as SyncOptionsTuple, aJ as TERMINATOR, aK as Target, aL as Unflatten, aM as UnionToIntersection, aN as UpdatePayload, aO as VERSION, aP as Volatile, aQ as Watcher, aR as WatcherRecord, W as WildPaths, aS as getRaw, aT as getReactor, aU as getSnapshotVersion, aV as getVersion, aW as inert, aX as intent, aY as isInert, aZ as isIntent, a_ as isVolatile, a$ as live, b0 as methods, b1 as reactive, b2 as stable, b3 as state, b4 as volatile } from './index-
|
|
1
|
+
export { V as APIKey, X as AddDepth, Y as CTX, Z as ChildPaths, _ as DeepKeys, $ as DeepMerge, a0 as DeepPartial, K as DeepReadonly, a1 as DeepRequired, a2 as Deleter, a3 as DeleterRecord, a4 as DepthConfig, a5 as DirectPayload, a6 as EVT_OPTS, E as EffectOptions, a7 as Getter, a8 as GetterRecord, a9 as INDIFFABLE, aa as INERTIA, L as Inert, ab as Intent, ac as Listener, ad as ListenerOptions, ae as ListenerOptionsTuple, af as ListenerRecord, ag as Live, ah as MaxDepth, ai as NIL, aj as NOOP, ak as NextDepth, al as NoTraverse, am as PathBranch, an as PathBranchValue, ao as PathDepth, ap as PathKey, aq as PathLeaf, a as PathValue, P as Paths, f as Payload, ar as PrevDepth, as as Primitive, at as Pure, au as RAW, av as REJECTABLE, e as REvent, aw as RTR_BATCH, ax as RTR_LOG, R as Reactive, ay as ReactivePreferences, d as Reactor, J as ReactorBuild, az as ReactorEvent, aA as SSVERSION, aB as Setter, aC as SetterRecord, aD as Stable, aE as State, aF as StrictPathKey, aG as SubtractDepth, aH as SyncOptions, aI as SyncOptionsTuple, aJ as TERMINATOR, aK as Target, aL as Unflatten, aM as UnionToIntersection, aN as UpdatePayload, aO as VERSION, aP as Volatile, aQ as Watcher, aR as WatcherRecord, W as WildPaths, aS as getRaw, aT as getReactor, aU as getSnapshotVersion, aV as getVersion, aW as inert, aX as intent, aY as isInert, aZ as isIntent, a_ as isVolatile, a$ as live, b0 as methods, b1 as reactive, b2 as stable, b3 as state, b4 as volatile } from './index-BtHNGnRR.js';
|
package/dist/index.js
CHANGED
package/dist/modules.cjs
CHANGED
|
@@ -215,24 +215,25 @@ function parseEvtOpts(options, opts, boolOpt = opts[0], result = {}) {
|
|
|
215
215
|
function fanout(a, b, c, d) {
|
|
216
216
|
const isEvPd = !!a?.target, isPath = !isEvPd && "string" === typeof b, [state, path, olds, news, opts, type] = isEvPd ? [a.root, a.currentTarget.path, a.currentTarget.oldValue, a.currentTarget.value, b || NIL, a.type] : isPath ? [a, b, getPath(a, b), c, d || NIL, void 0] : [void 0, void 0, a, b, c || NIL, void 0], target = isEvPd ? getPath(a.root, a.currentTarget.path) : isPath ? getPath(state, path) : olds;
|
|
217
217
|
if (isEvPd && type !== "set" && type !== "delete" || !target || !canHandle(news, opts)) return;
|
|
218
|
+
const { merge = false, depth, atomic = true, skipUndef = false, cloneSets = false, txLabel } = opts;
|
|
218
219
|
const func = () => {
|
|
219
|
-
const walk = (target2, obj,
|
|
220
|
+
const walk = (target2, obj, depth2 = isEvPd ? 1 : Infinity, keys = Object.keys(obj)) => {
|
|
220
221
|
for (let i = 0, len = keys.length; i < len; i++) {
|
|
221
222
|
const key = keys[i], val = obj[key];
|
|
222
223
|
try {
|
|
223
|
-
if (
|
|
224
|
-
else
|
|
224
|
+
if (atomic && Array.isArray(val)) target2[key] = cloneSets ? deepClone(val) : val, target2[key].length = target2[key].length;
|
|
225
|
+
else depth2 > 1 && canHandle(val, opts) ? walk(target2[key] ||= {}, val, depth2 - 1) : (!skipUndef || val !== void 0) && (target2[key] = cloneSets ? deepClone(val) : val);
|
|
225
226
|
} catch (e) {
|
|
226
227
|
if (e instanceof RangeError) throw e;
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
230
|
};
|
|
230
|
-
if (
|
|
231
|
-
else walk(target,
|
|
231
|
+
if (atomic && Array.isArray(news) && isPath) setPath(state, path, cloneSets ? deepClone(news) : news), getPath(state, path).length = news.length;
|
|
232
|
+
else walk(target, merge ? mergeObjs(olds, news, opts) : news, depth === true ? Infinity : depth);
|
|
232
233
|
};
|
|
233
|
-
force(() => transaction(func,
|
|
234
|
+
force(() => transaction(func, txLabel ?? `${path ? `Fanout -> '${path}'` : `Fanout`} (Tx ${txId + 1})`), CTX.usingForce || isEvPd);
|
|
234
235
|
}
|
|
235
|
-
var fanoutOptsArr = ["merge", "depth", "atomic", "
|
|
236
|
+
var fanoutOptsArr = ["merge", "depth", "atomic", "skipUndef"];
|
|
236
237
|
function force(task, bool = true) {
|
|
237
238
|
const prev = CTX.usingForce;
|
|
238
239
|
CTX.usingForce = bool;
|
|
@@ -245,8 +246,8 @@ function force(task, bool = true) {
|
|
|
245
246
|
function mergeObjs(o1, o2, config = NIL, pojocheck = true) {
|
|
246
247
|
if (pojocheck && (!isPOJO(o1 || NIL, config) || !isPOJO(o2 || NIL, config))) return o2;
|
|
247
248
|
o1 ||= {}, o2 ||= {};
|
|
248
|
-
const merged = config.
|
|
249
|
-
if (config.
|
|
249
|
+
const merged = config.skipUndef ? { ...o1 } : { ...o1, ...o2 };
|
|
250
|
+
if (config.skipUndef) {
|
|
250
251
|
const keys2 = Object.keys(o1);
|
|
251
252
|
for (let i = 0, len = keys2.length; i < len; i++) {
|
|
252
253
|
const key = keys2[i], val = o2[key];
|
|
@@ -1650,9 +1651,9 @@ var PersistModule = class extends BaseReactorModule {
|
|
|
1650
1651
|
for (const [rid, rtr] of this.deps) this.attachPaths(rtr, rid);
|
|
1651
1652
|
value && this.adapter?.remove(this.config.key);
|
|
1652
1653
|
}
|
|
1653
|
-
hydrate(entry, rtr, rid = this.rids.get(rtr), { depth, merge = true, atomic,
|
|
1654
|
+
hydrate(entry, rtr, rid = this.rids.get(rtr), { depth, merge = true, atomic, skipUndef } = parseEvtOpts(this.config.fanout, fanoutOptsArr, "depth"), tick = true) {
|
|
1654
1655
|
if (!entry) return;
|
|
1655
|
-
const whites = this.getPaths(rid), blacks = this.getPaths(rid, this.config.blacklist, true), set = (p, curr, prev) => (depth ? fanout : setPath)(rtr.core, p, merge ? mergeObjs(curr, prev, rtr.config) : prev, depth ? { depth, atomic,
|
|
1656
|
+
const whites = this.getPaths(rid), blacks = this.getPaths(rid, this.config.blacklist, true), set = (p, curr, prev) => (depth ? fanout : setPath)(rtr.core, p, merge ? mergeObjs(curr, prev, rtr.config) : prev, depth ? { depth, atomic, skipUndef, crossRealms: rtr.config.crossRealms } : void 0);
|
|
1656
1657
|
let ticks = this.tickMap.get(rid);
|
|
1657
1658
|
for (let i = 0, len = blacks.length; i < len; i++) deletePath(entry, blacks[i]);
|
|
1658
1659
|
for (let i = 0, len = whites.length; i < len; i++) {
|
package/dist/modules.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as Paths, c as ReactorModulePathConfig, L as Inert, F as FanoutOptionsTuple, B as BaseReactorModule, b as ReactorModuleId, d as Reactor, e as REvent } from './index-
|
|
2
|
-
export { M as ModulePaths, N as ReactorModuleConstructor, T as Transaction, O as endTx, Q as startTx, S as transaction, U as txId } from './index-
|
|
3
|
-
import { S as StorageAdapterConfig, a as StorageAdapter, J as JSONReviver, b as JSONReplacer, A as AsyncStorageAdapter, c as StorageAdapterConstructor, d as AsyncStorageAdapterConstructor, e as TimeTravelConfig, H as HistoryEntry, f as HistoryNode } from './index-
|
|
4
|
-
export { B as BaseStorageAdapter, g as HistoryTransaction, T as TimeTravelModule, h as TimeTravelState } from './index-
|
|
1
|
+
import { P as Paths, c as ReactorModulePathConfig, L as Inert, F as FanoutOptionsTuple, B as BaseReactorModule, b as ReactorModuleId, d as Reactor, e as REvent } from './index-BtHNGnRR.cjs';
|
|
2
|
+
export { M as ModulePaths, N as ReactorModuleConstructor, T as Transaction, O as endTx, Q as startTx, S as transaction, U as txId } from './index-BtHNGnRR.cjs';
|
|
3
|
+
import { S as StorageAdapterConfig, a as StorageAdapter, J as JSONReviver, b as JSONReplacer, A as AsyncStorageAdapter, c as StorageAdapterConstructor, d as AsyncStorageAdapterConstructor, e as TimeTravelConfig, H as HistoryEntry, f as HistoryNode } from './index-C_djeddc.cjs';
|
|
4
|
+
export { B as BaseStorageAdapter, g as HistoryTransaction, T as TimeTravelModule, h as TimeTravelState } from './index-C_djeddc.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* - The LocalStorage Adapter (~5MB per origin, browser-dependent).
|
|
@@ -291,7 +291,7 @@ declare class PersistModule<T extends object = any, P extends Paths<T> = Paths<T
|
|
|
291
291
|
protected persist(): Promise<void>;
|
|
292
292
|
protected handleAdapter({ value }: REvent<PersistConfig<T, P>, "adapter">): Promise<void>;
|
|
293
293
|
protected handleDisabled({ value }: REvent<PersistConfig<T, P>, "disabled">): void;
|
|
294
|
-
protected hydrate(entry: any, rtr: Reactor<any>, rid?: ReactorModuleId, { depth, merge, atomic,
|
|
294
|
+
protected hydrate(entry: any, rtr: Reactor<any>, rid?: ReactorModuleId, { depth, merge, atomic, skipUndef }?: FanoutOptionsTuple & {
|
|
295
295
|
depth: number | boolean | undefined;
|
|
296
296
|
}, tick?: boolean): void;
|
|
297
297
|
/** Clears persisted payload for this module instance by removing the stored key from the adapter and drops any pending save. */
|
package/dist/modules.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as Paths, c as ReactorModulePathConfig, L as Inert, F as FanoutOptionsTuple, B as BaseReactorModule, b as ReactorModuleId, d as Reactor, e as REvent } from './index-
|
|
2
|
-
export { M as ModulePaths, N as ReactorModuleConstructor, T as Transaction, O as endTx, Q as startTx, S as transaction, U as txId } from './index-
|
|
3
|
-
import { S as StorageAdapterConfig, a as StorageAdapter, J as JSONReviver, b as JSONReplacer, A as AsyncStorageAdapter, c as StorageAdapterConstructor, d as AsyncStorageAdapterConstructor, e as TimeTravelConfig, H as HistoryEntry, f as HistoryNode } from './index-
|
|
4
|
-
export { B as BaseStorageAdapter, g as HistoryTransaction, T as TimeTravelModule, h as TimeTravelState } from './index-
|
|
1
|
+
import { P as Paths, c as ReactorModulePathConfig, L as Inert, F as FanoutOptionsTuple, B as BaseReactorModule, b as ReactorModuleId, d as Reactor, e as REvent } from './index-BtHNGnRR.js';
|
|
2
|
+
export { M as ModulePaths, N as ReactorModuleConstructor, T as Transaction, O as endTx, Q as startTx, S as transaction, U as txId } from './index-BtHNGnRR.js';
|
|
3
|
+
import { S as StorageAdapterConfig, a as StorageAdapter, J as JSONReviver, b as JSONReplacer, A as AsyncStorageAdapter, c as StorageAdapterConstructor, d as AsyncStorageAdapterConstructor, e as TimeTravelConfig, H as HistoryEntry, f as HistoryNode } from './index-CKHoDs6x.js';
|
|
4
|
+
export { B as BaseStorageAdapter, g as HistoryTransaction, T as TimeTravelModule, h as TimeTravelState } from './index-CKHoDs6x.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* - The LocalStorage Adapter (~5MB per origin, browser-dependent).
|
|
@@ -291,7 +291,7 @@ declare class PersistModule<T extends object = any, P extends Paths<T> = Paths<T
|
|
|
291
291
|
protected persist(): Promise<void>;
|
|
292
292
|
protected handleAdapter({ value }: REvent<PersistConfig<T, P>, "adapter">): Promise<void>;
|
|
293
293
|
protected handleDisabled({ value }: REvent<PersistConfig<T, P>, "disabled">): void;
|
|
294
|
-
protected hydrate(entry: any, rtr: Reactor<any>, rid?: ReactorModuleId, { depth, merge, atomic,
|
|
294
|
+
protected hydrate(entry: any, rtr: Reactor<any>, rid?: ReactorModuleId, { depth, merge, atomic, skipUndef }?: FanoutOptionsTuple & {
|
|
295
295
|
depth: number | boolean | undefined;
|
|
296
296
|
}, tick?: boolean): void;
|
|
297
297
|
/** Clears persisted payload for this module instance by removing the stored key from the adapter and drops any pending save. */
|
package/dist/modules.js
CHANGED
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
} from "./chunk-JGEI2Q4M.js";
|
|
6
6
|
import {
|
|
7
7
|
BaseReactorModule
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-AW22CQWE.js";
|
|
9
|
+
import "./chunk-PJTPFVEG.js";
|
|
10
10
|
import {
|
|
11
11
|
CTX,
|
|
12
12
|
NIL,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
transaction,
|
|
28
28
|
txId,
|
|
29
29
|
withMeta
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-LZJYX2LE.js";
|
|
31
31
|
|
|
32
32
|
// src/ts/modules/persist/storage/base/index.ts
|
|
33
33
|
var BaseStorageAdapter = class {
|
|
@@ -489,9 +489,9 @@ var PersistModule = class extends BaseReactorModule {
|
|
|
489
489
|
for (const [rid, rtr] of this.deps) this.attachPaths(rtr, rid);
|
|
490
490
|
value && this.adapter?.remove(this.config.key);
|
|
491
491
|
}
|
|
492
|
-
hydrate(entry, rtr, rid = this.rids.get(rtr), { depth, merge = true, atomic,
|
|
492
|
+
hydrate(entry, rtr, rid = this.rids.get(rtr), { depth, merge = true, atomic, skipUndef } = parseEvtOpts(this.config.fanout, fanoutOptsArr, "depth"), tick = true) {
|
|
493
493
|
if (!entry) return;
|
|
494
|
-
const whites = this.getPaths(rid), blacks = this.getPaths(rid, this.config.blacklist, true), set = (p, curr, prev) => (depth ? fanout : setPath)(rtr.core, p, merge ? mergeObjs(curr, prev, rtr.config) : prev, depth ? { depth, atomic,
|
|
494
|
+
const whites = this.getPaths(rid), blacks = this.getPaths(rid, this.config.blacklist, true), set = (p, curr, prev) => (depth ? fanout : setPath)(rtr.core, p, merge ? mergeObjs(curr, prev, rtr.config) : prev, depth ? { depth, atomic, skipUndef, crossRealms: rtr.config.crossRealms } : void 0);
|
|
495
495
|
let ticks = this.tickMap.get(rid);
|
|
496
496
|
for (let i = 0, len = blacks.length; i < len; i++) deletePath(entry, blacks[i]);
|
|
497
497
|
for (let i = 0, len = whites.length; i < len; i++) {
|
package/dist/super.d.ts
CHANGED
|
@@ -509,10 +509,12 @@ interface FanoutOptionsTuple extends Partial<Record<(typeof fanoutOptsArr)[numbe
|
|
|
509
509
|
depth?: number | boolean;
|
|
510
510
|
/** Whether to assign arrays as a whole and only touch `.length` for common cases. Only works with the `path` parameter overload or in nested levels.
|
|
511
511
|
* Arrays can lead to unnecessary work as more often than not, you won't be watching index paths but waiting on the parent bubble instead.
|
|
512
|
-
* If you happen to be watching, it might be more optimal to re-set it yourself if it's only a few indexes or just
|
|
512
|
+
* If you happen to be watching, it might be more optimal to re-set it yourself if it's only a few indexes or just set this to `false`. @default `true` */
|
|
513
513
|
atomic?: boolean;
|
|
514
514
|
/** Whether to skip `undefined` values during fanout. @default `false`. */
|
|
515
|
-
|
|
515
|
+
skipUndef?: boolean;
|
|
516
|
+
/** Whether to clone before setting any final values, prevents unintended reference sharing across the state tree. @default `false`. */
|
|
517
|
+
cloneSets?: boolean;
|
|
516
518
|
/** A label for the transaction that will be started, useful for debugging and tracking. @default `Fanout -> "${path}"` : `Fanout`} (Tx ${CTX.txId})`. */
|
|
517
519
|
txLabel?: string;
|
|
518
520
|
}
|
|
@@ -536,7 +538,7 @@ declare function fanout<T extends object>(target: T, value: Partial<T> | Partial
|
|
|
536
538
|
declare function fanout<T extends object, P extends WildPaths<T> = WildPaths<T>>(state: T, path: P, value: Partial<PathValue<T, P>>, options?: {
|
|
537
539
|
crossRealms?: boolean;
|
|
538
540
|
} & FanoutOptionsTuple): void;
|
|
539
|
-
declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "
|
|
541
|
+
declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "skipUndef"];
|
|
540
542
|
/**
|
|
541
543
|
* Executes a task while forcing all reactive writes to bypass equality checks.
|
|
542
544
|
* @param task The mutation logic to execute.
|
|
@@ -545,13 +547,13 @@ declare const fanoutOptsArr: readonly ["merge", "depth", "atomic", "skipUndefine
|
|
|
545
547
|
*/
|
|
546
548
|
declare function force<T>(task: () => T, bool?: boolean): T;
|
|
547
549
|
/**
|
|
548
|
-
* Deep-merges object-like values, does necessary checks so use without doubts. Only `o2` keys are checked when `
|
|
550
|
+
* Deep-merges object-like values, does necessary checks so use without doubts. Only `o2` keys are checked when `skipUndef` is true.
|
|
549
551
|
* @example
|
|
550
552
|
* const next = mergeObjs({ user: { name: "Kosi" } }, { user: { role: "admin" } }); // { ...o1, ...o2 } // o2 over o1 and deep!
|
|
551
553
|
*/
|
|
552
554
|
declare function mergeObjs<T1 extends object, T2 extends object>(o1?: T1 | null, o2?: T2 | null, config?: {
|
|
553
555
|
crossRealms?: boolean;
|
|
554
|
-
|
|
556
|
+
skipUndef?: boolean;
|
|
555
557
|
}, pojocheck?: boolean): DeepMerge<T1, T2>;
|
|
556
558
|
/** Returns [path, parent, value] records from root to the target path. */
|
|
557
559
|
declare function getTrailRecords<T extends object>(obj: T, path: WildPaths<T>, reverse?: boolean): [WildPaths<T>, PathBranchValue<T, WildPaths<T>>, PathValue<T, WildPaths<T>>][];
|
|
@@ -592,7 +594,7 @@ declare function isLeafPath<T extends object, const S extends string = ".", P ex
|
|
|
592
594
|
separator?: S;
|
|
593
595
|
} & typeof CTX.defaults, value?: PathValue<T, P, S>): boolean;
|
|
594
596
|
/**
|
|
595
|
-
* Creates a two-way, array-
|
|
597
|
+
* Creates a two-way, array-atomic, echo-proof sync bridge between two S.I.A Reactors. Uses a synchronous origin lock to prevent infinite echo loops.
|
|
596
598
|
* On setup, `rA` hydrates `rB` at `prefixB` with a deep clone of its current state at `prefixA` (primary drives initial truth).
|
|
597
599
|
* @param rA Primary reactor — source of truth. Its `prefixA` slice seeds `rB.prefixB` on setup.
|
|
598
600
|
* @param rB Secondary reactor — the wider store (e.g. `ctlr.config`). Holds the primary at a named path.
|
|
@@ -1556,9 +1558,10 @@ declare function assignEl<El extends HTMLElement>(el?: El | null, props?: Partia
|
|
|
1556
1558
|
declare function assignEl<El extends HTMLElement>(el?: El | null, props?: Partial<El>, dataset?: Dataset, styles?: Style, nodiff?: boolean): El | null;
|
|
1557
1559
|
/** Get the currently active element, traversing into shadow roots if necessary.
|
|
1558
1560
|
* @param root Root node to start searching from, defaults to the main document.
|
|
1561
|
+
* @param noBody If `true`, will return `null` if the active element is the body element.
|
|
1559
1562
|
* @returns The active element or null if none found.
|
|
1560
1563
|
*/
|
|
1561
|
-
declare function getActiveEl(root?: Document | ShadowRoot | null): Element | null;
|
|
1564
|
+
declare function getActiveEl(root?: Document | ShadowRoot | null, noBody?: boolean): Element | null;
|
|
1562
1565
|
|
|
1563
1566
|
type utils_FanoutOptionsTuple = FanoutOptionsTuple;
|
|
1564
1567
|
declare const utils_KEYS_BLOCKS: typeof KEYS_BLOCKS;
|
|
@@ -1956,7 +1959,7 @@ declare class PersistModule<T extends object = any, P extends Paths<T> = Paths<T
|
|
|
1956
1959
|
protected persist(): Promise<void>;
|
|
1957
1960
|
protected handleAdapter({ value }: REvent<PersistConfig<T, P>, "adapter">): Promise<void>;
|
|
1958
1961
|
protected handleDisabled({ value }: REvent<PersistConfig<T, P>, "disabled">): void;
|
|
1959
|
-
protected hydrate(entry: any, rtr: Reactor<any>, rid?: ReactorModuleId, { depth, merge, atomic,
|
|
1962
|
+
protected hydrate(entry: any, rtr: Reactor<any>, rid?: ReactorModuleId, { depth, merge, atomic, skipUndef }?: FanoutOptionsTuple & {
|
|
1960
1963
|
depth: number | boolean | undefined;
|
|
1961
1964
|
}, tick?: boolean): void;
|
|
1962
1965
|
/** Clears persisted payload for this module instance by removing the stored key from the adapter and drops any pending save. */
|
package/dist/super.global.js
CHANGED
|
@@ -288,24 +288,25 @@ var sia = (() => {
|
|
|
288
288
|
function fanout(a, b, c, d) {
|
|
289
289
|
const isEvPd = !!a?.target, isPath = !isEvPd && "string" === typeof b, [state2, path, olds, news, opts, type] = isEvPd ? [a.root, a.currentTarget.path, a.currentTarget.oldValue, a.currentTarget.value, b || NIL, a.type] : isPath ? [a, b, getPath(a, b), c, d || NIL, void 0] : [void 0, void 0, a, b, c || NIL, void 0], target = isEvPd ? getPath(a.root, a.currentTarget.path) : isPath ? getPath(state2, path) : olds;
|
|
290
290
|
if (isEvPd && type !== "set" && type !== "delete" || !target || !canHandle(news, opts)) return;
|
|
291
|
+
const { merge = false, depth, atomic = true, skipUndef = false, cloneSets = false, txLabel } = opts;
|
|
291
292
|
const func = () => {
|
|
292
|
-
const walk = (target2, obj,
|
|
293
|
+
const walk = (target2, obj, depth2 = isEvPd ? 1 : Infinity, keys2 = Object.keys(obj)) => {
|
|
293
294
|
for (let i = 0, len = keys2.length; i < len; i++) {
|
|
294
295
|
const key = keys2[i], val = obj[key];
|
|
295
296
|
try {
|
|
296
|
-
if (
|
|
297
|
-
else
|
|
297
|
+
if (atomic && Array.isArray(val)) target2[key] = cloneSets ? deepClone(val) : val, target2[key].length = target2[key].length;
|
|
298
|
+
else depth2 > 1 && canHandle(val, opts) ? walk(target2[key] ||= {}, val, depth2 - 1) : (!skipUndef || val !== void 0) && (target2[key] = cloneSets ? deepClone(val) : val);
|
|
298
299
|
} catch (e) {
|
|
299
300
|
if (e instanceof RangeError) throw e;
|
|
300
301
|
}
|
|
301
302
|
}
|
|
302
303
|
};
|
|
303
|
-
if (
|
|
304
|
-
else walk(target,
|
|
304
|
+
if (atomic && Array.isArray(news) && isPath) setPath(state2, path, cloneSets ? deepClone(news) : news), getPath(state2, path).length = news.length;
|
|
305
|
+
else walk(target, merge ? mergeObjs(olds, news, opts) : news, depth === true ? Infinity : depth);
|
|
305
306
|
};
|
|
306
|
-
force(() => transaction(func,
|
|
307
|
+
force(() => transaction(func, txLabel ?? `${path ? `Fanout -> '${path}'` : `Fanout`} (Tx ${txId + 1})`), CTX.usingForce || isEvPd);
|
|
307
308
|
}
|
|
308
|
-
var fanoutOptsArr = ["merge", "depth", "atomic", "
|
|
309
|
+
var fanoutOptsArr = ["merge", "depth", "atomic", "skipUndef"];
|
|
309
310
|
function force(task, bool = true) {
|
|
310
311
|
const prev = CTX.usingForce;
|
|
311
312
|
CTX.usingForce = bool;
|
|
@@ -318,8 +319,8 @@ var sia = (() => {
|
|
|
318
319
|
function mergeObjs(o1, o2, config = NIL, pojocheck = true) {
|
|
319
320
|
if (pojocheck && (!isPOJO(o1 || NIL, config) || !isPOJO(o2 || NIL, config))) return o2;
|
|
320
321
|
o1 ||= {}, o2 ||= {};
|
|
321
|
-
const merged = config.
|
|
322
|
-
if (config.
|
|
322
|
+
const merged = config.skipUndef ? { ...o1 } : { ...o1, ...o2 };
|
|
323
|
+
if (config.skipUndef) {
|
|
323
324
|
const keys3 = Object.keys(o1);
|
|
324
325
|
for (let i = 0, len = keys3.length; i < len; i++) {
|
|
325
326
|
const key = keys3[i], val = o2[key];
|
|
@@ -412,20 +413,18 @@ var sia = (() => {
|
|
|
412
413
|
return path !== "*" && !canHandle(value, config);
|
|
413
414
|
}
|
|
414
415
|
function createReactorSync(rA, rB, prefixA, prefixB = "", signal) {
|
|
415
|
-
const
|
|
416
|
+
const rtrA = getReactor(rA, true), rtrB = getReactor(rB, true);
|
|
416
417
|
let origin = null;
|
|
417
|
-
const sync = (
|
|
418
|
-
if (origin === (
|
|
419
|
-
const { path, object, key } = payload.target;
|
|
420
|
-
if (
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
setPath(destCore, pDest ? stripped ? `${pDest}.${stripped}` : pDest : stripped || "*", Array.isArray(object) ? object : val);
|
|
424
|
-
origin = null;
|
|
418
|
+
const sync = (src, dest, srcP, destP) => (val, payload) => {
|
|
419
|
+
if (origin === (src ^ 1)) return;
|
|
420
|
+
const { path, object: obj, key } = payload.target;
|
|
421
|
+
if (srcP && path !== srcP && !path.startsWith(srcP + ".")) return;
|
|
422
|
+
const isArr = Array.isArray(obj), origP = isArr ? path.slice(0, -(key.length + 1)) : path, syncP = origP === srcP ? "" : srcP ? origP.slice(srcP.length + 1) : origP;
|
|
423
|
+
origin = src, setPath(dest, destP ? syncP ? `${destP}.${syncP}` : destP : syncP || "*", isArr ? deepClone(obj) : val), origin = null;
|
|
425
424
|
};
|
|
426
|
-
const
|
|
427
|
-
if (
|
|
428
|
-
const clupA =
|
|
425
|
+
const initA = prefixA ? getPath(rtrA.core, prefixA) : rtrA.core;
|
|
426
|
+
if (initA !== void 0) fanout(rtrB.core, prefixB || "*", initA, { depth: 1, cloneSets: true, txLabel: `ReactorSync: ${prefixA}^ <-> ${prefixB}` });
|
|
427
|
+
const clupA = rtrA.watch("*", sync(0, rtrB.core, prefixA, prefixB), { signal }), clupB = rtrB.watch("*", sync(1, rtrA.core, prefixB, prefixA), { signal });
|
|
429
428
|
return () => (clupA(), clupB());
|
|
430
429
|
}
|
|
431
430
|
|
|
@@ -1252,16 +1251,16 @@ var sia = (() => {
|
|
|
1252
1251
|
}
|
|
1253
1252
|
return el;
|
|
1254
1253
|
}
|
|
1255
|
-
function getActiveEl(root) {
|
|
1254
|
+
function getActiveEl(root, noBody = true) {
|
|
1256
1255
|
const activeEl = (root ?? document).activeElement;
|
|
1257
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
1256
|
+
return !activeEl || noBody && activeEl === document.body ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
1258
1257
|
}
|
|
1259
1258
|
|
|
1260
1259
|
// src/ts/utils/keys.ts
|
|
1261
1260
|
var KEYS_BLOCKS = ["Ctrl+Tab", "Ctrl+Shift+Tab", "Ctrl+PageUp", "Ctrl+PageDown", "Cmd+Option+ArrowRight", "Cmd+Option+ArrowLeft", "Ctrl+1", "Ctrl+2", "Ctrl+3", "Ctrl+4", "Ctrl+5", "Ctrl+6", "Ctrl+7", "Ctrl+8", "Ctrl+9", "Cmd+1", "Cmd+2", "Cmd+3", "Cmd+4", "Cmd+5", "Cmd+6", "Cmd+7", "Cmd+8", "Cmd+9", "Alt+ArrowLeft", "Alt+ArrowRight", "Cmd+ArrowLeft", "Cmd+ArrowRight", "Ctrl+r", "Ctrl+Shift+r", "F5", "Shift+F5", "Cmd+r", "Cmd+Shift+r", "Ctrl+h", "Ctrl+j", "Ctrl+d", "Ctrl+f", "Cmd+y", "Cmd+Option+b", "Cmd+d", "Cmd+f", "Ctrl+Shift+i", "Ctrl+Shift+j", "Ctrl+Shift+c", "Ctrl+u", "F12", "Cmd+Option+i", "Cmd+Option+j", "Cmd+Option+c", "Cmd+Option+u", "Ctrl+=", "Ctrl+-", "Ctrl+0", "Cmd+=", "Cmd+-", "Cmd+0", "Ctrl+p", "Ctrl+s", "Ctrl+o", "Cmd+p", "Cmd+s", "Cmd+o"];
|
|
1262
1261
|
function parseKeyCombo(combo) {
|
|
1263
1262
|
const parts = cleanKeyCombo(combo).toLowerCase().split("+");
|
|
1264
|
-
return { ctrlKey: parts.includes("ctrl"), shiftKey: parts.includes("shift"), altKey: parts.includes("alt"), metaKey: parts.includes("meta") || parts.includes("cmd"), key: parts.find((p) =>
|
|
1263
|
+
return { ctrlKey: parts.includes("ctrl"), shiftKey: parts.includes("shift"), altKey: parts.includes("alt"), metaKey: parts.includes("meta") || parts.includes("cmd"), key: parts.find((p) => !/^(ctrl|shift|alt|meta|cmd)$/.test(p)) || "" };
|
|
1265
1264
|
}
|
|
1266
1265
|
function stringifyKeyEvent(e) {
|
|
1267
1266
|
const parts = [];
|
|
@@ -1941,9 +1940,9 @@ var sia = (() => {
|
|
|
1941
1940
|
for (const [rid, rtr] of this.deps) this.attachPaths(rtr, rid);
|
|
1942
1941
|
value && this.adapter?.remove(this.config.key);
|
|
1943
1942
|
}
|
|
1944
|
-
hydrate(entry, rtr, rid = this.rids.get(rtr), { depth, merge = true, atomic,
|
|
1943
|
+
hydrate(entry, rtr, rid = this.rids.get(rtr), { depth, merge = true, atomic, skipUndef } = parseEvtOpts(this.config.fanout, fanoutOptsArr, "depth"), tick = true) {
|
|
1945
1944
|
if (!entry) return;
|
|
1946
|
-
const whites = this.getPaths(rid), blacks = this.getPaths(rid, this.config.blacklist, true), set = (p, curr, prev) => (depth ? fanout : setPath)(rtr.core, p, merge ? mergeObjs(curr, prev, rtr.config) : prev, depth ? { depth, atomic,
|
|
1945
|
+
const whites = this.getPaths(rid), blacks = this.getPaths(rid, this.config.blacklist, true), set = (p, curr, prev) => (depth ? fanout : setPath)(rtr.core, p, merge ? mergeObjs(curr, prev, rtr.config) : prev, depth ? { depth, atomic, skipUndef, crossRealms: rtr.config.crossRealms } : void 0);
|
|
1947
1946
|
let ticks = this.tickMap.get(rid);
|
|
1948
1947
|
for (let i = 0, len = blacks.length; i < len; i++) deletePath(entry, blacks[i]);
|
|
1949
1948
|
for (let i = 0, len = whites.length; i < len; i++) {
|
|
@@ -2437,7 +2436,7 @@ var sia = (() => {
|
|
|
2437
2436
|
this.config = reactive({ title: `Time Travel Console ${this.index = ++_TimeTravelConsole.count}`, ...build });
|
|
2438
2437
|
this.state.open = !!this.config.startOpen;
|
|
2439
2438
|
let wlLive = false, blLive = false;
|
|
2440
|
-
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 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(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: () => this.time.redo(this.state.stride) }), 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 }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack, false) }), 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${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: "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>
|
|
2439
|
+
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 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(this.state.stride) }), redo = createEl("button", { textContent: `Redo${formatKeyForDisplay(keys.shortcuts.redo[0])}`, ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.redo, false), onclick: () => this.time.redo(this.state.stride) }), 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 }), trackUntrack = createEl("button", { onclick: () => this.time[s.tracking ? "untrack" : "track"](), ariaKeyShortcuts: parseForARIAKS(keys.shortcuts.trackUntrack, false) }), 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${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: "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.config.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" });
|
|
2441
2440
|
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` })));
|
|
2442
2441
|
status.append((box.append(frame), box), clrHistory);
|
|
2443
2442
|
filters.append((filterBox.append((filterRow1.append(whitelistLabel, whitelist), filterRow1), (filterRow2.append(blacklistLabel, blacklist), filterRow2)), filterBox));
|
package/dist/utils.cjs
CHANGED
|
@@ -941,24 +941,25 @@ function parseEvtOpts(options, opts, boolOpt = opts[0], result = {}) {
|
|
|
941
941
|
function fanout(a, b, c, d) {
|
|
942
942
|
const isEvPd = !!a?.target, isPath = !isEvPd && "string" === typeof b, [state, path, olds, news, opts, type] = isEvPd ? [a.root, a.currentTarget.path, a.currentTarget.oldValue, a.currentTarget.value, b || NIL, a.type] : isPath ? [a, b, getPath(a, b), c, d || NIL, void 0] : [void 0, void 0, a, b, c || NIL, void 0], target = isEvPd ? getPath(a.root, a.currentTarget.path) : isPath ? getPath(state, path) : olds;
|
|
943
943
|
if (isEvPd && type !== "set" && type !== "delete" || !target || !canHandle(news, opts)) return;
|
|
944
|
+
const { merge = false, depth, atomic = true, skipUndef = false, cloneSets = false, txLabel } = opts;
|
|
944
945
|
const func = () => {
|
|
945
|
-
const walk = (target2, obj,
|
|
946
|
+
const walk = (target2, obj, depth2 = isEvPd ? 1 : Infinity, keys = Object.keys(obj)) => {
|
|
946
947
|
for (let i = 0, len = keys.length; i < len; i++) {
|
|
947
948
|
const key = keys[i], val = obj[key];
|
|
948
949
|
try {
|
|
949
|
-
if (
|
|
950
|
-
else
|
|
950
|
+
if (atomic && Array.isArray(val)) target2[key] = cloneSets ? deepClone(val) : val, target2[key].length = target2[key].length;
|
|
951
|
+
else depth2 > 1 && canHandle(val, opts) ? walk(target2[key] ||= {}, val, depth2 - 1) : (!skipUndef || val !== void 0) && (target2[key] = cloneSets ? deepClone(val) : val);
|
|
951
952
|
} catch (e) {
|
|
952
953
|
if (e instanceof RangeError) throw e;
|
|
953
954
|
}
|
|
954
955
|
}
|
|
955
956
|
};
|
|
956
|
-
if (
|
|
957
|
-
else walk(target,
|
|
957
|
+
if (atomic && Array.isArray(news) && isPath) setPath(state, path, cloneSets ? deepClone(news) : news), getPath(state, path).length = news.length;
|
|
958
|
+
else walk(target, merge ? mergeObjs(olds, news, opts) : news, depth === true ? Infinity : depth);
|
|
958
959
|
};
|
|
959
|
-
force(() => transaction(func,
|
|
960
|
+
force(() => transaction(func, txLabel ?? `${path ? `Fanout -> '${path}'` : `Fanout`} (Tx ${txId + 1})`), CTX.usingForce || isEvPd);
|
|
960
961
|
}
|
|
961
|
-
var fanoutOptsArr = ["merge", "depth", "atomic", "
|
|
962
|
+
var fanoutOptsArr = ["merge", "depth", "atomic", "skipUndef"];
|
|
962
963
|
function force(task, bool = true) {
|
|
963
964
|
const prev = CTX.usingForce;
|
|
964
965
|
CTX.usingForce = bool;
|
|
@@ -971,8 +972,8 @@ function force(task, bool = true) {
|
|
|
971
972
|
function mergeObjs(o1, o2, config = NIL, pojocheck = true) {
|
|
972
973
|
if (pojocheck && (!isPOJO(o1 || NIL, config) || !isPOJO(o2 || NIL, config))) return o2;
|
|
973
974
|
o1 ||= {}, o2 ||= {};
|
|
974
|
-
const merged = config.
|
|
975
|
-
if (config.
|
|
975
|
+
const merged = config.skipUndef ? { ...o1 } : { ...o1, ...o2 };
|
|
976
|
+
if (config.skipUndef) {
|
|
976
977
|
const keys2 = Object.keys(o1);
|
|
977
978
|
for (let i = 0, len = keys2.length; i < len; i++) {
|
|
978
979
|
const key = keys2[i], val = o2[key];
|
|
@@ -1065,20 +1066,18 @@ function isLeafPath(obj, path, config = CTX.defaults, value = getPath(obj, path,
|
|
|
1065
1066
|
return path !== "*" && !canHandle(value, config);
|
|
1066
1067
|
}
|
|
1067
1068
|
function createReactorSync(rA, rB, prefixA, prefixB = "", signal) {
|
|
1068
|
-
const
|
|
1069
|
+
const rtrA = getReactor(rA, true), rtrB = getReactor(rB, true);
|
|
1069
1070
|
let origin = null;
|
|
1070
|
-
const sync = (
|
|
1071
|
-
if (origin === (
|
|
1072
|
-
const { path, object, key } = payload.target;
|
|
1073
|
-
if (
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
setPath(destCore, pDest ? stripped ? `${pDest}.${stripped}` : pDest : stripped || "*", Array.isArray(object) ? object : val);
|
|
1077
|
-
origin = null;
|
|
1071
|
+
const sync = (src, dest, srcP, destP) => (val, payload) => {
|
|
1072
|
+
if (origin === (src ^ 1)) return;
|
|
1073
|
+
const { path, object: obj, key } = payload.target;
|
|
1074
|
+
if (srcP && path !== srcP && !path.startsWith(srcP + ".")) return;
|
|
1075
|
+
const isArr = Array.isArray(obj), origP = isArr ? path.slice(0, -(key.length + 1)) : path, syncP = origP === srcP ? "" : srcP ? origP.slice(srcP.length + 1) : origP;
|
|
1076
|
+
origin = src, setPath(dest, destP ? syncP ? `${destP}.${syncP}` : destP : syncP || "*", isArr ? deepClone(obj) : val), origin = null;
|
|
1078
1077
|
};
|
|
1079
|
-
const
|
|
1080
|
-
if (
|
|
1081
|
-
const clupA =
|
|
1078
|
+
const initA = prefixA ? getPath(rtrA.core, prefixA) : rtrA.core;
|
|
1079
|
+
if (initA !== void 0) fanout(rtrB.core, prefixB || "*", initA, { depth: 1, cloneSets: true, txLabel: `ReactorSync: ${prefixA}^ <-> ${prefixB}` });
|
|
1080
|
+
const clupA = rtrA.watch("*", sync(0, rtrB.core, prefixA, prefixB), { signal }), clupB = rtrB.watch("*", sync(1, rtrA.core, prefixB, prefixA), { signal });
|
|
1082
1081
|
return () => (clupA(), clupB());
|
|
1083
1082
|
}
|
|
1084
1083
|
|
|
@@ -1165,16 +1164,16 @@ function assignEl(el, props, dataset, styles, nodiff = true) {
|
|
|
1165
1164
|
}
|
|
1166
1165
|
return el;
|
|
1167
1166
|
}
|
|
1168
|
-
function getActiveEl(root) {
|
|
1167
|
+
function getActiveEl(root, noBody = true) {
|
|
1169
1168
|
const activeEl = (root ?? document).activeElement;
|
|
1170
|
-
return !activeEl ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
1169
|
+
return !activeEl || noBody && activeEl === document.body ? null : activeEl.shadowRoot ? getActiveEl(activeEl.shadowRoot) : activeEl;
|
|
1171
1170
|
}
|
|
1172
1171
|
|
|
1173
1172
|
// src/ts/utils/keys.ts
|
|
1174
1173
|
var KEYS_BLOCKS = ["Ctrl+Tab", "Ctrl+Shift+Tab", "Ctrl+PageUp", "Ctrl+PageDown", "Cmd+Option+ArrowRight", "Cmd+Option+ArrowLeft", "Ctrl+1", "Ctrl+2", "Ctrl+3", "Ctrl+4", "Ctrl+5", "Ctrl+6", "Ctrl+7", "Ctrl+8", "Ctrl+9", "Cmd+1", "Cmd+2", "Cmd+3", "Cmd+4", "Cmd+5", "Cmd+6", "Cmd+7", "Cmd+8", "Cmd+9", "Alt+ArrowLeft", "Alt+ArrowRight", "Cmd+ArrowLeft", "Cmd+ArrowRight", "Ctrl+r", "Ctrl+Shift+r", "F5", "Shift+F5", "Cmd+r", "Cmd+Shift+r", "Ctrl+h", "Ctrl+j", "Ctrl+d", "Ctrl+f", "Cmd+y", "Cmd+Option+b", "Cmd+d", "Cmd+f", "Ctrl+Shift+i", "Ctrl+Shift+j", "Ctrl+Shift+c", "Ctrl+u", "F12", "Cmd+Option+i", "Cmd+Option+j", "Cmd+Option+c", "Cmd+Option+u", "Ctrl+=", "Ctrl+-", "Ctrl+0", "Cmd+=", "Cmd+-", "Cmd+0", "Ctrl+p", "Ctrl+s", "Ctrl+o", "Cmd+p", "Cmd+s", "Cmd+o"];
|
|
1175
1174
|
function parseKeyCombo(combo) {
|
|
1176
1175
|
const parts = cleanKeyCombo(combo).toLowerCase().split("+");
|
|
1177
|
-
return { ctrlKey: parts.includes("ctrl"), shiftKey: parts.includes("shift"), altKey: parts.includes("alt"), metaKey: parts.includes("meta") || parts.includes("cmd"), key: parts.find((p) =>
|
|
1176
|
+
return { ctrlKey: parts.includes("ctrl"), shiftKey: parts.includes("shift"), altKey: parts.includes("alt"), metaKey: parts.includes("meta") || parts.includes("cmd"), key: parts.find((p) => !/^(ctrl|shift|alt|meta|cmd)$/.test(p)) || "" };
|
|
1178
1177
|
}
|
|
1179
1178
|
function stringifyKeyEvent(e) {
|
|
1180
1179
|
const parts = [];
|
package/dist/utils.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { F as FanoutOptionsTuple, g as arrRegex, h as canHandle, i as createReactorSync, j as deepClone, k as deletePath, l as fanout, m as fanoutOptsArr, n as force, o as getDepth, p as getPath, q as getPaths, r as getTrailRecords, s as hasPath, t as isLeafPath, u as isObj, v as isPOJO, x as matchPaths, y as mergeObjs, z as nuke, C as parseEvtOpts, D as parsePathObj, G as resetMeta, H as setPath, I as withMeta } from './index-
|
|
1
|
+
export { F as FanoutOptionsTuple, g as arrRegex, h as canHandle, i as createReactorSync, j as deepClone, k as deletePath, l as fanout, m as fanoutOptsArr, n as force, o as getDepth, p as getPath, q as getPaths, r as getTrailRecords, s as hasPath, t as isLeafPath, u as isObj, v as isPOJO, x as matchPaths, y as mergeObjs, z as nuke, C as parseEvtOpts, D as parsePathObj, G as resetMeta, H as setPath, I as withMeta } from './index-BtHNGnRR.cjs';
|
|
2
2
|
|
|
3
3
|
declare function clamp(min: number | undefined, val: number, max?: number): number;
|
|
4
4
|
|
|
@@ -197,8 +197,9 @@ declare function assignEl<El extends HTMLElement>(el?: El | null, props?: Partia
|
|
|
197
197
|
declare function assignEl<El extends HTMLElement>(el?: El | null, props?: Partial<El>, dataset?: Dataset, styles?: Style, nodiff?: boolean): El | null;
|
|
198
198
|
/** Get the currently active element, traversing into shadow roots if necessary.
|
|
199
199
|
* @param root Root node to start searching from, defaults to the main document.
|
|
200
|
+
* @param noBody If `true`, will return `null` if the active element is the body element.
|
|
200
201
|
* @returns The active element or null if none found.
|
|
201
202
|
*/
|
|
202
|
-
declare function getActiveEl(root?: Document | ShadowRoot | null): Element | null;
|
|
203
|
+
declare function getActiveEl(root?: Document | ShadowRoot | null, noBody?: boolean): Element | null;
|
|
203
204
|
|
|
204
205
|
export { KEYS_BLOCKS, type KeyStruct, type KeysSettings, assignEl, bindAllMethods, clamp, cleanKeyCombo, createEl, formatKeyForDisplay, formatKeyShortcutsForDisplay, getActiveEl, getTermsForKey, guardAllMethods, guardMethod, keyEventAllowed, matchKeys, onAllMethods, parseForARIAKS, parseKeyCombo, requestAnimationFrame, setInterval, setTimeout, stringifyKeyEvent };
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { F as FanoutOptionsTuple, g as arrRegex, h as canHandle, i as createReactorSync, j as deepClone, k as deletePath, l as fanout, m as fanoutOptsArr, n as force, o as getDepth, p as getPath, q as getPaths, r as getTrailRecords, s as hasPath, t as isLeafPath, u as isObj, v as isPOJO, x as matchPaths, y as mergeObjs, z as nuke, C as parseEvtOpts, D as parsePathObj, G as resetMeta, H as setPath, I as withMeta } from './index-
|
|
1
|
+
export { F as FanoutOptionsTuple, g as arrRegex, h as canHandle, i as createReactorSync, j as deepClone, k as deletePath, l as fanout, m as fanoutOptsArr, n as force, o as getDepth, p as getPath, q as getPaths, r as getTrailRecords, s as hasPath, t as isLeafPath, u as isObj, v as isPOJO, x as matchPaths, y as mergeObjs, z as nuke, C as parseEvtOpts, D as parsePathObj, G as resetMeta, H as setPath, I as withMeta } from './index-BtHNGnRR.js';
|
|
2
2
|
|
|
3
3
|
declare function clamp(min: number | undefined, val: number, max?: number): number;
|
|
4
4
|
|
|
@@ -197,8 +197,9 @@ declare function assignEl<El extends HTMLElement>(el?: El | null, props?: Partia
|
|
|
197
197
|
declare function assignEl<El extends HTMLElement>(el?: El | null, props?: Partial<El>, dataset?: Dataset, styles?: Style, nodiff?: boolean): El | null;
|
|
198
198
|
/** Get the currently active element, traversing into shadow roots if necessary.
|
|
199
199
|
* @param root Root node to start searching from, defaults to the main document.
|
|
200
|
+
* @param noBody If `true`, will return `null` if the active element is the body element.
|
|
200
201
|
* @returns The active element or null if none found.
|
|
201
202
|
*/
|
|
202
|
-
declare function getActiveEl(root?: Document | ShadowRoot | null): Element | null;
|
|
203
|
+
declare function getActiveEl(root?: Document | ShadowRoot | null, noBody?: boolean): Element | null;
|
|
203
204
|
|
|
204
205
|
export { KEYS_BLOCKS, type KeyStruct, type KeysSettings, assignEl, bindAllMethods, clamp, cleanKeyCombo, createEl, formatKeyForDisplay, formatKeyShortcutsForDisplay, getActiveEl, getTermsForKey, guardAllMethods, guardMethod, keyEventAllowed, matchKeys, onAllMethods, parseForARIAKS, parseKeyCombo, requestAnimationFrame, setInterval, setTimeout, stringifyKeyEvent };
|
package/dist/utils.js
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
parseForARIAKS,
|
|
23
23
|
parseKeyCombo,
|
|
24
24
|
stringifyKeyEvent
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-PJTPFVEG.js";
|
|
26
26
|
import {
|
|
27
27
|
arrRegex,
|
|
28
28
|
canHandle,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
resetMeta,
|
|
49
49
|
setPath,
|
|
50
50
|
withMeta
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-LZJYX2LE.js";
|
|
52
52
|
export {
|
|
53
53
|
KEYS_BLOCKS,
|
|
54
54
|
arrRegex,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sia-reactor",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.41",
|
|
4
4
|
"description": "The Programmable Data DOM. A high-performance State & Intent Architecture (S.I.A.) engine that gives your data transactional mutation routing and multi-phase state observation.",
|
|
5
5
|
"author": "Oketade Oluwatobiloba <tobioketade007@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsup",
|
|
63
|
+
"build:demo": "vite build --config demo/vite.config.ts",
|
|
63
64
|
"test": "vitest --reporter=verbose",
|
|
64
65
|
"test:run": "vitest run --reporter=verbose",
|
|
65
66
|
"demo": "vite --config demo/vite.config.ts",
|
|
66
|
-
"demo:build": "vite build --config demo/vite.config.ts",
|
|
67
67
|
"demo:preview": "vite preview --config demo/vite.config.ts",
|
|
68
68
|
"change": "changeset",
|
|
69
69
|
"bump": "changeset version",
|