sia-reactor 0.0.21 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +115 -89
  2. package/dist/{TimeTravelOverlay-CJv-S_Km.d.cts → TimeTravelOverlay-DiXUgbUU.d.cts} +9 -8
  3. package/dist/{TimeTravelOverlay-DxqJL0Zk.d.ts → TimeTravelOverlay-eWjAy0yr.d.ts} +9 -8
  4. package/dist/adapters/react.cjs +66 -84
  5. package/dist/adapters/react.d.cts +23 -22
  6. package/dist/adapters/react.d.ts +23 -22
  7. package/dist/adapters/react.js +3 -3
  8. package/dist/adapters/vanilla.cjs +66 -84
  9. package/dist/adapters/vanilla.d.cts +4 -4
  10. package/dist/adapters/vanilla.d.ts +4 -4
  11. package/dist/adapters/vanilla.js +3 -3
  12. package/dist/{chunk-2WBPGSRL.js → chunk-3SKLWTEA.js} +52 -70
  13. package/dist/{chunk-DP74DVRT.js → chunk-BTA6MIQ6.js} +40 -8
  14. package/dist/{chunk-TFLYCXK4.js → chunk-CS3FOV6J.js} +14 -13
  15. package/dist/{index-Oie9hhE8.d.cts → index-BgbbNXTW.d.cts} +306 -207
  16. package/dist/{index-Oie9hhE8.d.ts → index-BgbbNXTW.d.ts} +306 -207
  17. package/dist/index.cjs +54 -75
  18. package/dist/index.d.cts +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +2 -4
  21. package/dist/{plugins.cjs → modules.cjs} +437 -166
  22. package/dist/modules.d.cts +53 -0
  23. package/dist/modules.d.ts +53 -0
  24. package/dist/modules.js +627 -0
  25. package/dist/super.d.ts +610 -281
  26. package/dist/super.global.js +445 -174
  27. package/dist/timeTravel-CraHdbXZ.d.cts +352 -0
  28. package/dist/timeTravel-YUxRHRgh.d.ts +352 -0
  29. package/dist/utils.cjs +41 -7
  30. package/dist/utils.d.cts +1 -1
  31. package/dist/utils.d.ts +1 -1
  32. package/dist/utils.js +3 -1
  33. package/package.json +6 -6
  34. package/dist/plugins.d.cts +0 -112
  35. package/dist/plugins.d.ts +0 -112
  36. package/dist/plugins.js +0 -370
  37. package/dist/timeTravel-B1vedDQc.d.ts +0 -76
  38. package/dist/timeTravel-WpgWmKu-.d.cts +0 -76
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  - [sia-reactor](#sia-reactor)
18
18
  - [Table of contents](#table-of-contents)
19
- - [Reading Paths](#reading-paths)
19
+ - [Why sia-reactor?](#why-sia-reactor)
20
20
  - [Getting Started](#getting-started)
21
21
  - [Usage](#usage)
22
22
  - [API Reference](#api-reference)
@@ -30,41 +30,45 @@
30
30
 
31
31
  ---
32
32
 
33
- ## Reading Paths
33
+ ## Why sia-reactor?
34
34
 
35
- Choose your reading mode:
35
+ Most state libraries react to changes.
36
36
 
37
- - **I want to understand the architecture shift first**:
38
- Read [Chronicles](https://github.com/Tobi007-del/tmg-media-player/blob/main/CHRONICLES.md) and [Interaction Folklore](https://github.com/Tobi007-del/tmg-media-player/blob/main/FOLKLORE.md), then continue here.
39
- - **I just need to use this fast**:
40
- Jump directly to [Getting Started](#getting-started) and [API Reference](#api-reference).
37
+ `sia-reactor` lets you:
41
38
 
42
- ### Quick Overview
39
+ - intercept changes BEFORE they happen
40
+ - approve or reject user intent
41
+ - observe changes AFTER they settle
42
+ - treat your state like a programmable event system
43
43
 
44
- `sia-reactor` treats nested data like a programmable evented tree.
45
-
46
- - **State** = factual reality.
47
- - **Intent** = requested reality.
48
- - **Mediators** (`get|set|delete`) = synchronous gatekeepers.
49
- - **Watchers** (`watch`) = synchronous post-mutation observers.
50
- - **Listeners** (`on`) = microtask-batched event observers.
51
-
52
- Semantic split recommendation:
53
- - `intent`: async/delayed requests.
54
- - `state`: granted facts.
55
- - `settings/config (custom)`: immediate user prefs.
56
- - `status (custom)`: read-only system facts.
44
+ ```js
45
+ const player = reactive({
46
+ intent: intent({ playing: false }),
47
+ state: { playing: false }
48
+ });
57
49
 
58
- ```javascript
59
- import { reactive, intent } from 'sia-reactor';
50
+ // Logic layer (capture phase)
51
+ player.on("intent.playing", (e) => {
52
+ if (!ready) return e.reject();
53
+ player.state.playing = true;
54
+ }, { capture: true });
60
55
 
61
- const player = reactive({
62
- intent: intent({ playing: false, fullscreen: false }),
63
- state: { playing: false, fullscreen: false },
64
- settings: { theme: "dark", defaultPlaybackRate: 1 },
65
- status: { buffering: false, duration: 120 }
56
+ // UI layer
57
+ player.on("state.playing", (e) => {
58
+ console.log("Now playing:", e.value);
66
59
  });
60
+
61
+ // User action
62
+ player.intent.playing = true;
67
63
  ```
64
+ ***"This is the entire system."***
65
+
66
+ Choose your reading mode:
67
+
68
+ - **I want to understand the architecture shift first**:
69
+ Read [Chronicles](https://github.com/Tobi007-del/tmg-media-player/blob/main/CHRONICLES.md) and [Interaction Folklore](https://github.com/Tobi007-del/tmg-media-player/blob/main/FOLKLORE.md), then continue here.
70
+ - **I just need to use this fast**:
71
+ Jump directly to [Getting Started](#getting-started) and [API Reference](#api-reference).
68
72
 
69
73
  ---
70
74
 
@@ -84,10 +88,10 @@ pnpm add sia-reactor
84
88
 
85
89
  ```javascript
86
90
  // 1. Core Engine
87
- import { reactive, Reactor, TERMINATOR } from 'sia-reactor';
91
+ import { reactive, Reactor, TERMINATOR } from "sia-reactor";
88
92
 
89
93
  // 2. Deep Object Utilities
90
- import { setAny, getAny, mergeObjs } from 'sia-reactor/utils';
94
+ import { setAny, getAny, mergeObjs } from "sia-reactor/utils";
91
95
  ```
92
96
 
93
97
  ---
@@ -97,12 +101,12 @@ import { setAny, getAny, mergeObjs } from 'sia-reactor/utils';
97
101
  ### Modern Bundlers (ESM)
98
102
 
99
103
  ```javascript
100
- import { reactive, Reactor } from 'sia-reactor';
101
- import 'sia-reactor/utils'; // deep object helpers (setAny/getAny/mergeObjs/...)
102
- import 'sia-reactor/plugins'; // built-in plugins + storage adapters
103
- import 'sia-reactor/adapters/vanilla'; // Autotracker + effect API + TimeTravelOverlay class
104
- import 'sia-reactor/adapters/vanilla/time-travel-overlay.css'; // TimeTravelOverlay CSS
105
- import 'sia-reactor/adapters/react'; // useReactor/useSelector/usePath hooks
104
+ import { reactive, Reactor } from "sia-reactor";
105
+ import "sia-reactor/utils"; // deep object helpers (setAny/getAny/deleteAny/inAny/parseAnyObj/fanout/mergeObjs/deepClone/nuke...)
106
+ import "sia-reactor/modules"; // built-in modules + storage adapters
107
+ import "sia-reactor/adapters/vanilla"; // Autotracker + effect API + TimeTravelOverlay class
108
+ import "sia-reactor/adapters/react"; // useReactor/useSelector/usePath hooks
109
+ import "sia-reactor/styles/time-travel-overlay.css"; // TimeTravelOverlay CSS
106
110
  ```
107
111
 
108
112
  ### CDN / Browser (Global)
@@ -115,7 +119,7 @@ import 'sia-reactor/adapters/react'; // useReactor/useSelector/usePath hooks
115
119
  <script>
116
120
  const { reactive, Reactor } = window.sia;
117
121
  window.sia.utils;
118
- window.sia.plugins;
122
+ window.sia.modules;
119
123
  window.sia.adapters.vanilla;
120
124
  </script>
121
125
  </body>
@@ -157,10 +161,10 @@ All methods are available on `Reactor` instances or objects wrapped in `reactive
157
161
  - **`delete(path, callback, options)`**: Intercept property deletion.
158
162
 
159
163
  #### **Watchers (Synchronous Observers)**
160
- - **`watch(path, callback, options)`**: Fires instantly after a mutation. Use strictly for critical internal engine syncing.
164
+ - **`watch(path, callback, options)`**: Fires instantly after a mutation. Use strictly for critical internal engine syncing on leaf paths preferably, sees only direct operations.
161
165
 
162
166
  #### **Listeners (Asynchronous/Batched UI Observers)**
163
- - **`on(path, callback, options)`**: Attach DOM-style event listeners. Supports `{ capture: true, depth: 1, once: true, immediate: true }`.
167
+ - **`on(path, callback, options)`**: Attach DOM-style event listeners that respect `depth`. Supports `{ capture: true, depth: 1, once: true, immediate: true }`.
164
168
  - **`once(path, callback, options)`**: Fires once and self-destructs.
165
169
  - **`off(path, callback, options)`**: Removes a listener.
166
170
 
@@ -168,8 +172,7 @@ All methods are available on `Reactor` instances or objects wrapped in `reactive
168
172
  - **`tick(path)`**: Forces a synchronous flush of the batch queue for a specific path.
169
173
  - **`stall(task)` / `nostall(task)`**: Manually stall the queue to wait for calculations before rendering.
170
174
  - **`snapshot(raw)`**: Generates a strict, structurally-shared, un-proxied clone of the current state tree.
171
- - **`cascade(eventOrPayload, objectSafe)`**: Manually trigger direct object values event waves, bypassing strict unchanged-proxy traps, `objectSafe` merges `value` with `oldValue`.
172
- - **`plugIn(new ReactorPlugin(config))`**: Allows extended behaviour with external logic.
175
+ - **`use(new ReactorModule(config), id)`**: Allows extended behaviour with external logic.
173
176
  - **`reset()`**: Clears all records bringing everything back to a clean slate.
174
177
  - **`destroy()`**: Last resort destruction, nukes everything by nullifying it's properties for full disposal, lives on every class.
175
178
 
@@ -182,7 +185,7 @@ You can wrap properties in special flags *before* initializing the reactor to di
182
185
  - **`volatile(obj)` / `stable(obj)`**: Forces the reactor to fire event waves even if the new value is identical to the old value (bypassing the Proxy's unchanged performance check).
183
186
 
184
187
  ```javascript
185
- import { reactive, intent, volatile, inert } from 'sia-reactor';
188
+ import { reactive, intent, volatile, inert } from "sia-reactor";
186
189
 
187
190
  const data = reactive({
188
191
  apiResponse: inert({ heavy: "data" }), // Proxy won't traverse this
@@ -193,18 +196,18 @@ const data = reactive({
193
196
 
194
197
  ### React Hooks & Effects
195
198
 
196
- The engine provides native React bindings utilizing `useSyncExternalStore` and an internal `Autotracker` for concurrent-safe, surgically precise component re-renders. All hooks natively accept a `Reactor` instance, a `reactive()` proxy, or a plain object (which will be auto-wrapped on the fly).
199
+ The engine provides native React bindings utilizing `useSyncExternalStore` and an internal `Autotracker` for concurrent-safe, surgically precise component re-renders. All hooks natively accept a `Reactor` instance, a `reactive()` proxy, or a plain object (which will be auto-wrapped on the fly). Just import, your editor will reveal more details.
197
200
 
198
201
  ```javascript
199
- import { reactive } from 'sia-reactor';
200
- import { useReactor, useAnyReactor, useSelector, useAnySelector, usePath, effect } from 'sia-reactor/react';
202
+ import { reactive } from "sia-reactor";
203
+ import { useReactor, useAnyReactor, useSelector, useAnySelector, usePath, effect } from "sia-reactor/adapters/react";
201
204
 
202
- const state = reactive({ user: { name: "Ada", age: 25 }, theme: "dark" });
205
+ const state = reactive({ user: { name: "Kosi", age: 25 }, theme: "dark" });
203
206
 
204
207
  // 1. The Tracked State (Valtio-style)
205
208
  function Profile() {
206
209
  const sameState = useReactor(state); // `useReactorSnapshot()` if mutable issues arise
207
- useAnyReactor(); // use this when you just want to use any state from any reactor
210
+ useAnyReactor(); // when you just want state from any reactor
208
211
  // Only re-renders if state.user.name mutates. Completely ignores age and theme!
209
212
  return <div>{sameState.user.name + otherState.user.name}</div>;
210
213
  } // no snapshots like Valtio, you can read or write to anything
@@ -212,7 +215,7 @@ function Profile() {
212
215
  // 2. The Slice Selector (Zustand-style)
213
216
  function Theme() {
214
217
  const theme = useSelector(state, (s) => s.theme); // `useSelectorSnapshot()` if mutable issues arise
215
- const newName = useAnySelector(() => state.user.name + spouseState.user.name); // use this when you just want to derive any state from any reactor
218
+ const newName = useAnySelector(() => state.user.name + spouseState.user.name); // when you just want to derive any state from any reactor
216
219
  return <div>Theme: {theme}</div>;
217
220
  }
218
221
 
@@ -226,51 +229,56 @@ function AgeObserver() {
226
229
  const stopTracking = effect(() => console.log("User name changed to:", state.user.name)); // read or write as you wish
227
230
  ```
228
231
 
229
- ### Plugins: The Extension Port
232
+ ### Modules: The Extension Port
230
233
 
231
- The `Reactor` is designed to be a lightweight core. Extended capabilities are attached via Plugins. It ships with a suite of built-in plugins for common architectural needs.
234
+ The `Reactor` is designed to be a lightweight core. Extended capabilities are attached via Modules. It ships with a suite of powerful modules for common architectural needs.
232
235
 
233
- #### The Persistence Plugin
234
- Automatically syncs your State to LocalStorage, SessionStorage, Memory or IndexedDB. It respects the async nature of any adapter while keeping your app synchronous.
236
+ #### The Persistence Module
237
+ Automatically syncs your State to LocalStorage, SessionStorage, Memory or IndexedDB. Always use this module first to avoid re-initialization issues.
235
238
 
236
239
  ```javascript
237
- import { reactive, Reactor, getReactor } from 'sia-reactor';
238
- import { PersistPlugin, LocalStorageAdapter, IndexedDBAdapter } from 'sia-reactor/plugins';
240
+ import { reactive, Reactor, getReactor } from "sia-reactor";
241
+ import { PersistModule, LocalStorageAdapter, IndexedDBAdapter, SessionStorageAdapter, CookieAdapter, MemoryAdapter } from "sia-reactor/modules";
239
242
 
240
243
  const state = reactive({ theme: "dark", settings: { volume: 50, brightness: 30 } });
241
- state.plugIn(new PersistPlugin({ // Plug it in. State is now automatically hydrated and throttled-saved.
244
+ const persist = new PersistModule({ // Plug it in. State is now automatically hydrated and throttled-saved.
242
245
  key: "APP_PREFS",
243
246
  paths: ["theme", "settings.brightness"],
244
247
  throttle: 5000,
245
- adapter: new IndexedDBAdapter({ dbName: "Session", version: 1, onversionchange: () => location.reload() }) // or `LocalStorageAdapter` (instance or signature)
246
- }, getReactor(state))); // Put Reactor as second arg if you want type inference, e.g. for the paths in the array.
248
+ fanout: true, // async hydration should use leaf writes incase UI listeners already initialized.
249
+ adapter: new IndexedDBAdapter({ dbName: "Session", version: 1, onversionchange: () => location.reload(), useSnapshot: true }) // or `LocalStorageAdapter` (instance or signature)
250
+ };
251
+ state.use(persist, getReactor(state))); // Put `Reactor` as second constructor arg if you want type inference, e.g. for the paths in the array.
247
252
  ```
248
253
 
249
- #### The Time Travel Plugin
254
+ #### The Time Travel Module
250
255
  Record state frames, step through history, and optionally attach a ready-to-use vanilla debug overlay.
251
256
 
252
257
  ```javascript
253
- import { reactive } from 'sia-reactor';
254
- import { TimeTravelPlugin } from 'sia-reactor/plugins';
255
- import { TimeTravelOverlay } from 'sia-reactor/adapters/vanilla';
256
- import 'sia-reactor/css/time-travel-overlay.css';
257
-
258
- const state = reactive({ count: 0, filter: "all" });
259
- const time = new TimeTravelPlugin({ maxHistory: 300, loop: false, rate: 150 });
260
- state.plugIn(time);
258
+ import { TimeTravelModule } from "sia-reactor/modules";
259
+ import { effect, TimeTravelOverlay } from "sia-reactor/adapters/vanilla";
260
+ import "sia-reactor/css/time-travel-overlay.css";
261
+
262
+ const time = new TimeTravelModule({ maxHistory: 300, loop: false, rate: 150 });
263
+ state.use(time);
264
+
265
+ // If persist uses an async adapter (e.g. IndexedDB), wait till after hydration:
266
+ persist.state.once("hydrated", () => state.use(time)); // starts `false`, one-time stall until it flips
267
+ effect(() => persist.state.hydrated && state.use(time), { once: true }) // same logic, different look :)
268
+
261
269
  const overlay = new TimeTravelOverlay(time, { color: "#e26e02", startOpen: false, devOnly: true, container: document.body }); // optional debug interface for visulazation
262
270
  ```
263
271
  ```jsx
264
- import { TimeTravelOverlay } from 'sia-reactor/adapters/react';
272
+ import { TimeTravelOverlay } from "sia-reactor/adapters/react";
265
273
 
266
274
  <TimeTravelOverlay time={time} color="#e26e02" startOpen devOnly /> // react-safe instance lifecycle management, e.g. for HMR predictability.
267
275
  ```
268
276
 
269
- Useful plugin methods: `play()`, `pause()`, `rewind()`, `clear()`, `undo()`, `redo()`, `step(n, forward)`, `jumpTo(frame)`, `export()`, `import(serialized)`.
277
+ Useful methods: `play()`, `pause()`, `rewind()`, `clear()`, `undo()`, `redo()`, `step(n, forward)`, `jumpTo(frame)`, `export(replacer)`, `import(json, reviver)`.
270
278
 
271
279
  ### Reactor Build Options
272
280
 
273
- These are some core build options accepted by `new Reactor(core, build)` and `reactive(core, build, preferences)`.
281
+ These are some core build options accepted by `new Reactor(core, build)` and `reactive(core, build, preferences)` configurable via `Reactor.config`.
274
282
 
275
283
  - **`debug?`**: 1-time set. Enables debug logging and diagnostics of core operations. (default: `false`)
276
284
  - **`crossRealms?`**: Enables cross-realm object detection support by using slower but safer type checks. (e.g. iframes) (default: `false`).
@@ -281,8 +289,6 @@ These are some core build options accepted by `new Reactor(core, build)` and `re
281
289
  - **`equalityFunction?`**: Custom equality used by setters and adapter comparisons (default: `Object.is`).
282
290
  - **`batchingFunction?`**: Custom batching scheduler for listener notification flushes (default: `queueMicrotask`)
283
291
  - **`referenceTracking?`**: Enables identity/reference tracking features in the runtime. (default: `false`).
284
-
285
- *NOTE: those not marked as 1-time set are configurable via `Reactor.config`. Also, plugs and hooks turn on whatever they need automatically.*
286
292
 
287
293
  ### Reactive Preferences (Method Naming)
288
294
 
@@ -293,7 +299,7 @@ These are some core build options accepted by `new Reactor(core, build)` and `re
293
299
  - **`whitelist?`**: Keeps specific methods on their original names while others get affixed.
294
300
 
295
301
  ```javascript
296
- import { reactive } from 'sia-reactor';
302
+ import { reactive } from "sia-reactor";
297
303
 
298
304
  const state = reactive(
299
305
  { count: 0 },
@@ -339,9 +345,10 @@ player.on("intent.playing", (e) => {
339
345
 
340
346
  ### Troubleshooting
341
347
 
342
- - Listener timing feels late: `on` is microtask-batched by design; use `watch` only for strict immediate engine sync.
343
- - `reject()` appears ignored: call it in capture phase and ensure branch is wrapped in `intent(...)`, remember it's the listener's choice to listen also.
344
- - Snapshot behavior feels stale: enable `referenceTracking: true` with `smartCloning: true`.
348
+ - Listener timing feels late: `on(path, ...)` is microtask-batched by design; use `watch(path, ...)` only for strict immediate engine sync on leaf paths preferably.
349
+ - Listeners don't react to changes: use `fanout(state, path, object, { depth: n })` instead of direct object sets to keep immutable semantics.
350
+ - `reject()` appears ignored: call it in capture phase and ensure branch is wrapped in `intent(...)`, also remember it's the listener's choice to comply.
351
+ - Snapshot behavior feels stale: enable `referenceTracking: true` with `smartCloning: true`, also use these when persisting to environments that don't take proxies, e.g. IndexedDB.
345
352
  - Cross-frame data is skipped: enable `crossRealms: true` for iframe/other realm objects.
346
353
  - Class/prototype behavior is odd: enable `preserveContext: true` (tradeoff: slower hot paths).
347
354
  - Working with symbol keys and you want blind writes/reads: unwrap first with `getRaw` or `RAW` and operate on the raw object.
@@ -353,9 +360,9 @@ player.on("intent.playing", (e) => {
353
360
  The S.I.A. Reactor operates in two distinct dimensions: **The Synchronous Dimension** (Gatekeepers & Watchers) and **The Asynchronous Dimension** (Listeners). Because they intercept data at entirely different points in time, they receive different objects and possess different capabilities.
354
361
 
355
362
  ### 1. The Synchronous Dimension: The `Payload`
356
- When you use `get`, `set`, `delete`, or `watch`, you are sitting *directly inside the Javascript Proxy Trap*. The memory has not been written yet (or is being written right at that exact millisecond).
363
+ When you use `.get()`, `.set()`, `.delete()`, or `.watch()`, you are sitting *directly inside the Javascript Proxy Trap*. The memory has not been written yet (or is being written right at that exact millisecond).
357
364
 
358
- Because there is no "bubbling" or "event wave" yet, these methods do not receive a complex event object. They receive a lightweight, factual `Payload`.
365
+ Because there is no "bubbling" or "event wave" yet, these methods do not receive an event object. They receive a lightweight, factual `Payload`.
359
366
 
360
367
  #### The `Payload` Anatomy
361
368
  ```javascript
@@ -388,7 +395,7 @@ The `target` and `currentTarget` objects give you absolute surgical awareness of
388
395
  Because `set` and `delete` mediators execute *before* the memory is written, you have the power to alter reality or stop it entirely using the `TERMINATOR` symbol.
389
396
 
390
397
  ```javascript
391
- import { TERMINATOR } from 'sia-reactor';
398
+ import { TERMINATOR } from "sia-reactor";
392
399
 
393
400
  // Example: Data Sanitization & Blocking
394
401
  rtr.set("user.age", (value) => {
@@ -398,14 +405,14 @@ rtr.set("user.age", (value) => {
398
405
  ```
399
406
 
400
407
  ### 2. The Asynchronous Dimension: The S.I.A. Event Loop
401
- When you use `on` or `once` (Listeners), you are sitting in the **Microtask Queue**. The memory has already been safely written, the Proxy traps have closed, and the engine is now broadcasting a DOM-Style "Mutation Wave" across the state tree.
408
+ When you use `.on()` or `.once()` (Listeners), you are sitting in the **Microtask Queue**. The memory has already been safely written, the Proxy traps have closed, and the engine is now broadcasting a DOM-Style "Mutation Wave" across the state tree.
402
409
 
403
- If you mutate `state.user.profile.name = "Ada"`, the event wave travels like this:
410
+ If you mutate `state.user.profile.name = "Kosi"`, the event wave travels like this:
404
411
  1. **Capture Phase:** `*` (Root) ➔ `user` ➔ `user.profile`
405
412
  2. **Target Phase:** `user.profile.name`
406
413
  3. **Bubble Phase:** `user.profile` ➔ `user` ➔ `*` (Root)
407
414
 
408
- *NOTE: Only `on` does this since it is batched tree walking to stay within recursive limits.*
415
+ *NOTE: Only `on` does this since it is batched to stay within recursive limits.*
409
416
 
410
417
  #### The Event Anatomy (`REvent` type)
411
418
  Listeners receive a `ReactorEvent` (`REvent`). This object *inherits* everything from the `Payload`, but adds **Political Event Routing**, providing absolute surgical awareness of what is happening in the tree.
@@ -417,13 +424,13 @@ rtr.on("user.profile", (e) => {
417
424
  console.log(e.staticType); // "set" (The original action)
418
425
  console.log(e.path); // "user.profile.name" (The actual property changed)
419
426
  console.log(e.currentTarget); // { path: "user.profile", value: {...} } (Where we are listening)
420
- console.log(e.value); // "Ada" (The new value)
427
+ console.log(e.value); // "Kosi" (The new value)
421
428
  console.log(e.oldValue); // "John" (The previous value)
422
429
  // 2. Political Routing
423
430
  console.log(e.eventPhase); // 3 (Bubbling Phase)
424
431
  console.log(e.bubbles); // true/false
425
432
  // 3. Misc
426
- console.log(e.composedPath()); // ["Ada", { name: "Ada", age: 26 }, { profile: { name: "Ada", age: 26 } }, { user: { profile: { name: "Ada", age: 26 } } }] (refs, target -> root)
433
+ console.log(e.composedPath()); // ["Kosi", { name: "Kosi", age: 26 }, { profile: { name: "Kosi", age: 26 } }, { user: { profile: { name: "Kosi", age: 26 } } }] (refs, target -> root)
427
434
  }); // you could use external callbacks but typed with `REvent<T, "user.age">`
428
435
  ```
429
436
 
@@ -452,9 +459,29 @@ When you listen to a parent object (like `"user.profile"`), you will naturally c
452
459
 
453
460
  To help you instantly differentiate between the object *itself* being replaced, versus a *child* property mutating deep inside of it, the Reactor intelligently morphs the `e.type`:
454
461
  * If `state.user.profile = {}` happens, the listener receives `e.type === "set"`.
455
- * If `state.user.profile.name = "Ada"` happens, the parent listener receives `e.type === "update"`.
462
+ * If `state.user.profile.name = "Kosi"` happens, the parent listener receives `e.type === "update"`.
456
463
 
457
- This allows for highly fine-grained syncing bridges across your application without writing heavy, manual for-loop diffing algorithms!
464
+ This allows for highly fine-grained syncing bridges across your application without writing heavy for-loop diffing algorithms! Use `{ depth: n }` to control how deep the path bubbles you see are, i.e.
465
+
466
+ ```javascript
467
+ rtr.on("todos", (e) => console.log(e), { depth : 1 }); // only sees updates on direct children
468
+ ```
469
+
470
+ Typing tip (for depth-aware `update` narrowing): `depth` mainly affects inferred `target.key` unions. To preserve type narrowing where desired, avoid destructuring in the callback signature. Types can be too accurate thereby causing issues, cast where necessary. e.g. `e.value as any`.
471
+
472
+ ```javascript
473
+ // Less reliable inference for depth-aware unions
474
+ rtr.on("todos", ({ type, target: { path, key } }) => {
475
+ if (type === "update") console.log(path, key);
476
+ }, { depth: 1 });
477
+ // Better: narrow first, then destructure inside
478
+ rtr.on("todos", (e: REvent<user, "todos", 1>) => {
479
+ if (e.type === "update") {
480
+ const { path, key } = e.target;
481
+ console.log(path, key); // or e.target.path, e.target.key
482
+ }
483
+ }, { depth: 1 }); // you need the generic for external callbacks only
484
+ ```
458
485
 
459
486
  ---
460
487
 
@@ -462,7 +489,7 @@ This allows for highly fine-grained syncing bridges across your application with
462
489
 
463
490
  ### The CSS Black Box
464
491
 
465
- Imagine you have 50 different CSS variables in your state (`settings.css.containerWidth`, `settings.css.themeColor`, etc.). Registering 50 individual `watch()` or `on()` listeners would need manual css crawling that will be blind dynamically added variables.
492
+ Imagine you have 50 different CSS variables in your state (`settings.css.containerWidth`, `settings.css.themeColor`, etc.). Registering 50 individual `watch()` or `on()` listeners would need manual css crawling that will be blind to dynamically added variables.
466
493
 
467
494
  Instead, we use the **Root Wildcard** (`"*"`) for both Reading (`get`) and Writing (`watch`).
468
495
 
@@ -484,8 +511,8 @@ this.ctlr.config.get("*", (val, { target: { key, path } }) => {
484
511
  });
485
512
  ```
486
513
  #### Why this pattern is elite:
487
- 1. **Synchronous Execution (`watch`):** CSSOM needs immediate updates. If you used an asynchronous `.on()` listener, the browser might paint the old frame before the microtask resolves, causing UI flicker. `.watch()` executes synchronously during the proxy trap.
488
- 2. **The Wildcard Tradeoff:** By listening to `*`, this callback runs synchronously on *every single mutation* in the entire reactor.
514
+ 1. **Synchronous Execution (`watch`):** CSSOM needs immediate updates. If you used an `.on()` listener, a slow browser might paint the old frame before the microtask resolves, causing UI flicker. `.watch()` executes synchronously during the proxy trap.
515
+ 2. **The Wildcard Tradeoff:** By listening to `*`, this callback runs synchronously on *every single mutation* in the entire reactor. This is the only synchronous way to catch deep nested updates.
489
516
  3. **The Ultimate Illusion:** A developer writes `console.log(state.settings.css.themeColor)`. To them, it looks like a standard plain object property access. In reality, the Reactor just executed a surgical DOM read. It is a true black box.
490
517
 
491
518
  ---
@@ -497,7 +524,6 @@ S.I.A. Reactor synthesizes core concepts from the heavyweights of web and media
497
524
  * **The Native JavaScript Proxy API:** Arguably the most powerful, slept-on feature in the ECMAScript specification. The Reactor is essentially a love letter to the Proxy API, packaging its raw, interception-level power into a structured and safe Data DOM so the community can finally use what it's truly capable of.
498
525
  * **Video.js (VJS):** The philosophy of "Intent vs. State" MEDIATION, ensuring UI actions only commit when the underlying engine allows it.
499
526
  * **The Browser DOM:** Treating a raw JSON state tree like HTML nodes, complete with deep, path-based event bubbling.
500
- * **The JavaScript Event Loop:** Utilizing `queueMicrotask` to batch thousands of synchronous state mutations into a single, noiseless render tick.
501
527
  * **Vue, MobX & Valtio:** Leveraging native ES6 Proxies for instant, deep reactivity without forcing clunky `get()` or `set()` wrapper functions.
502
528
 
503
529
  ---
@@ -1,5 +1,5 @@
1
- import { R as Reactive } from './index-Oie9hhE8.cjs';
2
- import { T as TimeTravelPlugin } from './timeTravel-WpgWmKu-.cjs';
1
+ import { d as Reactive } from './index-BgbbNXTW.cjs';
2
+ import { m as TimeTravelModule } from './timeTravel-CraHdbXZ.cjs';
3
3
 
4
4
  /** Reactive options for the TimeTravel overlay instance. */
5
5
  interface TimeTravelConfig {
@@ -14,8 +14,9 @@ interface TimeTravelConfig {
14
14
  /** Container element that owns the overlay layer and dock. */
15
15
  container: HTMLElement;
16
16
  }
17
- /** Vanilla overlay controller for visual time-travel controls and timeline I/O.
18
- * Mounts a docked HUD into the configured container, syncs its UI with plugin state, and forwards keyboard/button actions to the TimeTravelPlugin.
17
+ /**
18
+ * - Vanilla overlay controller for visual time-travel controls and timeline I/O.
19
+ * - Mounts a docked HUD into the configured container, syncs its UI with module state, and forwards keyboard/button actions to the TimeTravelModule.
19
20
  * Supports reactive `config` updates (title/color/container/devOnly) and maintains local overlay UI state (`open` and `import` payload text).
20
21
  */
21
22
  declare class TimeTravelOverlay {
@@ -26,15 +27,15 @@ declare class TimeTravelOverlay {
26
27
  open: boolean;
27
28
  import: string;
28
29
  }, undefined>;
29
- readonly time: TimeTravelPlugin;
30
+ readonly time: TimeTravelModule;
30
31
  readonly els: Record<string, HTMLElement>;
31
32
  private clups;
32
33
  private keyup?;
33
- /** Creates a docked TimeTravel overlay bound to a plugin instance.
34
- * @param time TimeTravel plugin instance that owns timeline operations.
34
+ /** Creates a docked TimeTravel overlay bound to a module instance.
35
+ * @param time TimeTravel module instance that owns timeline operations.
35
36
  * @param build Optional initial overlay config overrides.
36
37
  */
37
- constructor(time: TimeTravelPlugin, build?: Partial<TimeTravelConfig>);
38
+ constructor(time: TimeTravelModule, build?: Partial<TimeTravelConfig>);
38
39
  destroy(): void;
39
40
  }
40
41
 
@@ -1,5 +1,5 @@
1
- import { R as Reactive } from './index-Oie9hhE8.js';
2
- import { T as TimeTravelPlugin } from './timeTravel-B1vedDQc.js';
1
+ import { d as Reactive } from './index-BgbbNXTW.js';
2
+ import { m as TimeTravelModule } from './timeTravel-YUxRHRgh.js';
3
3
 
4
4
  /** Reactive options for the TimeTravel overlay instance. */
5
5
  interface TimeTravelConfig {
@@ -14,8 +14,9 @@ interface TimeTravelConfig {
14
14
  /** Container element that owns the overlay layer and dock. */
15
15
  container: HTMLElement;
16
16
  }
17
- /** Vanilla overlay controller for visual time-travel controls and timeline I/O.
18
- * Mounts a docked HUD into the configured container, syncs its UI with plugin state, and forwards keyboard/button actions to the TimeTravelPlugin.
17
+ /**
18
+ * - Vanilla overlay controller for visual time-travel controls and timeline I/O.
19
+ * - Mounts a docked HUD into the configured container, syncs its UI with module state, and forwards keyboard/button actions to the TimeTravelModule.
19
20
  * Supports reactive `config` updates (title/color/container/devOnly) and maintains local overlay UI state (`open` and `import` payload text).
20
21
  */
21
22
  declare class TimeTravelOverlay {
@@ -26,15 +27,15 @@ declare class TimeTravelOverlay {
26
27
  open: boolean;
27
28
  import: string;
28
29
  }, undefined>;
29
- readonly time: TimeTravelPlugin;
30
+ readonly time: TimeTravelModule;
30
31
  readonly els: Record<string, HTMLElement>;
31
32
  private clups;
32
33
  private keyup?;
33
- /** Creates a docked TimeTravel overlay bound to a plugin instance.
34
- * @param time TimeTravel plugin instance that owns timeline operations.
34
+ /** Creates a docked TimeTravel overlay bound to a module instance.
35
+ * @param time TimeTravel module instance that owns timeline operations.
35
36
  * @param build Optional initial overlay config overrides.
36
37
  */
37
- constructor(time: TimeTravelPlugin, build?: Partial<TimeTravelConfig>);
38
+ constructor(time: TimeTravelModule, build?: Partial<TimeTravelConfig>);
38
39
  destroy(): void;
39
40
  }
40
41