mutts 1.0.8 → 1.0.9

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 (226) hide show
  1. package/README.md +19 -2
  2. package/dist/browser.cjs +1030 -4406
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.ts +310 -573
  5. package/dist/browser.esm.js +18 -24
  6. package/dist/browser.esm.js.map +1 -1
  7. package/dist/chunks/{async-browser-CA0jPWIi.cjs → async-browser-lvzLOCgk.cjs} +17 -24
  8. package/dist/chunks/async-browser-lvzLOCgk.cjs.map +1 -0
  9. package/dist/chunks/{async-core-UqHzvJ-S.cjs → async-core-CRLKP3l-.cjs} +8 -4
  10. package/dist/chunks/async-core-CRLKP3l-.cjs.map +1 -0
  11. package/dist/chunks/{async-node-BYHuGTni.cjs → async-node-C3DeIb0y.cjs} +5 -12
  12. package/dist/chunks/async-node-C3DeIb0y.cjs.map +1 -0
  13. package/dist/chunks/index-2vea86wD.esm.js +3011 -0
  14. package/dist/chunks/index-2vea86wD.esm.js.map +1 -0
  15. package/dist/chunks/index-CtA2AWl3.esm.js +4376 -0
  16. package/dist/chunks/index-CtA2AWl3.esm.js.map +1 -0
  17. package/dist/chunks/index-VTO-b2vR.cjs +4461 -0
  18. package/dist/chunks/index-VTO-b2vR.cjs.map +1 -0
  19. package/dist/{reactive → debug}/debug.d.ts +19 -8
  20. package/dist/debug/debug.d.ts.map +1 -0
  21. package/dist/debug/index.d.ts +4 -0
  22. package/dist/debug/index.d.ts.map +1 -0
  23. package/dist/debug/lineage-panel.d.ts +5 -0
  24. package/dist/debug/lineage-panel.d.ts.map +1 -0
  25. package/dist/debug/lineage.d.ts +79 -0
  26. package/dist/debug/lineage.d.ts.map +1 -0
  27. package/dist/debug.cjs +35 -0
  28. package/dist/debug.cjs.map +1 -0
  29. package/dist/debug.d.ts +209 -0
  30. package/dist/debug.esm.js +2 -0
  31. package/dist/debug.esm.js.map +1 -0
  32. package/dist/index.d.ts +1 -13
  33. package/dist/mutts.umd.js +1 -1
  34. package/dist/mutts.umd.js.map +1 -1
  35. package/dist/mutts.umd.min.js +1 -1
  36. package/dist/mutts.umd.min.js.map +1 -1
  37. package/dist/node.cjs +65 -63
  38. package/dist/node.cjs.map +1 -1
  39. package/dist/node.d.ts +2 -1
  40. package/dist/node.esm.js +5 -11
  41. package/dist/node.esm.js.map +1 -1
  42. package/dist/{async → src/async}/browser.d.ts.map +1 -1
  43. package/dist/{async → src/async}/index.d.ts +2 -1
  44. package/dist/src/async/index.d.ts.map +1 -0
  45. package/dist/{async → src/async}/node.d.ts.map +1 -1
  46. package/dist/src/decorator.d.ts.map +1 -0
  47. package/dist/src/destroyable.d.ts.map +1 -0
  48. package/dist/src/entry-browser.d.ts.map +1 -0
  49. package/dist/src/entry-node.d.ts.map +1 -0
  50. package/dist/src/eventful.d.ts +20 -0
  51. package/dist/src/eventful.d.ts.map +1 -0
  52. package/dist/src/flavored.d.ts +33 -0
  53. package/dist/src/flavored.d.ts.map +1 -0
  54. package/dist/src/index.d.ts +14 -0
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/indexable.d.ts.map +1 -0
  57. package/dist/{introspection.d.ts → src/introspection.d.ts} +1 -1
  58. package/dist/src/introspection.d.ts.map +1 -0
  59. package/dist/src/iterableWeak.d.ts.map +1 -0
  60. package/dist/src/mixins.d.ts.map +1 -0
  61. package/dist/src/promiseChain.d.ts.map +1 -0
  62. package/dist/{reactive → src/reactive}/array.d.ts +9 -10
  63. package/dist/src/reactive/array.d.ts.map +1 -0
  64. package/dist/src/reactive/buffer.d.ts +120 -0
  65. package/dist/src/reactive/buffer.d.ts.map +1 -0
  66. package/dist/{reactive → src/reactive}/change.d.ts +2 -2
  67. package/dist/src/reactive/change.d.ts.map +1 -0
  68. package/dist/src/reactive/deep-touch.d.ts.map +1 -0
  69. package/dist/{reactive → src/reactive}/deep-watch-state.d.ts +3 -3
  70. package/dist/src/reactive/deep-watch-state.d.ts.map +1 -0
  71. package/dist/{reactive → src/reactive}/deep-watch.d.ts +2 -1
  72. package/dist/src/reactive/deep-watch.d.ts.map +1 -0
  73. package/dist/src/reactive/describe.d.ts +12 -0
  74. package/dist/src/reactive/describe.d.ts.map +1 -0
  75. package/dist/src/reactive/effect-context.d.ts +34 -0
  76. package/dist/src/reactive/effect-context.d.ts.map +1 -0
  77. package/dist/{reactive → src/reactive}/effects.d.ts +31 -18
  78. package/dist/src/reactive/effects.d.ts.map +1 -0
  79. package/dist/src/reactive/index.d.ts +19 -0
  80. package/dist/src/reactive/index.d.ts.map +1 -0
  81. package/dist/{reactive → src/reactive}/map.d.ts +0 -2
  82. package/dist/src/reactive/map.d.ts.map +1 -0
  83. package/dist/src/reactive/memoize.d.ts +28 -0
  84. package/dist/src/reactive/memoize.d.ts.map +1 -0
  85. package/dist/src/reactive/non-reactive-state.d.ts.map +1 -0
  86. package/dist/src/reactive/non-reactive.d.ts.map +1 -0
  87. package/dist/{reactive → src/reactive}/project.d.ts +1 -2
  88. package/dist/src/reactive/project.d.ts.map +1 -0
  89. package/dist/src/reactive/proxy-state.d.ts.map +1 -0
  90. package/dist/src/reactive/proxy.d.ts.map +1 -0
  91. package/dist/{reactive → src/reactive}/record.d.ts +2 -3
  92. package/dist/src/reactive/record.d.ts.map +1 -0
  93. package/dist/{reactive → src/reactive}/register.d.ts +61 -0
  94. package/dist/src/reactive/register.d.ts.map +1 -0
  95. package/dist/{reactive → src/reactive}/registry.d.ts +6 -5
  96. package/dist/src/reactive/registry.d.ts.map +1 -0
  97. package/dist/{reactive → src/reactive}/set.d.ts +0 -2
  98. package/dist/src/reactive/set.d.ts.map +1 -0
  99. package/dist/src/reactive/tracking.d.ts.map +1 -0
  100. package/dist/{reactive → src/reactive}/types.d.ts +69 -21
  101. package/dist/src/reactive/types.d.ts.map +1 -0
  102. package/dist/{reactive/interface.d.ts → src/reactive/watch.d.ts} +7 -23
  103. package/dist/src/reactive/watch.d.ts.map +1 -0
  104. package/dist/{std-decorators.d.ts → src/std-decorators.d.ts} +1 -6
  105. package/dist/src/std-decorators.d.ts.map +1 -0
  106. package/dist/src/utils.d.ts.map +1 -0
  107. package/dist/{zone.d.ts → src/zone.d.ts} +2 -2
  108. package/dist/src/zone.d.ts.map +1 -0
  109. package/dist/types-DaHFfhlN.d.ts +414 -0
  110. package/docs/ai/api-reference.md +1 -1
  111. package/docs/ai/manual.md +443 -17
  112. package/docs/events.md +57 -2
  113. package/docs/flavored.md +210 -0
  114. package/docs/reactive/advanced.md +2 -3
  115. package/docs/reactive/attend.md +143 -0
  116. package/docs/reactive/collections.md +55 -0
  117. package/docs/reactive/core.md +120 -4
  118. package/docs/reactive/debugging.md +8 -10
  119. package/docs/reactive/describe.md +85 -0
  120. package/docs/reactive/error-handling.md +121 -0
  121. package/docs/reactive/project.md +1 -1
  122. package/docs/reactive/scan.md +215 -0
  123. package/docs/reactive.md +2 -0
  124. package/docs/std-decorators.md +102 -51
  125. package/docs/zone.md +3 -7
  126. package/package.json +6 -1
  127. package/src/async/browser.ts +110 -106
  128. package/src/async/index.ts +15 -11
  129. package/src/async/node.ts +5 -17
  130. package/src/eventful.ts +82 -49
  131. package/src/flavored.ts +106 -0
  132. package/src/index.d.ts +12 -12
  133. package/src/index.ts +2 -2
  134. package/src/introspection.ts +1 -1
  135. package/src/reactive/array.ts +29 -36
  136. package/src/reactive/buffer.ts +187 -27
  137. package/src/reactive/change.ts +16 -23
  138. package/src/reactive/deep-touch.ts +19 -14
  139. package/src/reactive/deep-watch-state.ts +3 -3
  140. package/src/reactive/deep-watch.ts +7 -4
  141. package/src/reactive/describe.ts +39 -0
  142. package/src/reactive/effect-context.ts +69 -4
  143. package/src/reactive/effects.ts +445 -393
  144. package/src/reactive/index.ts +12 -15
  145. package/src/reactive/map.ts +9 -25
  146. package/src/reactive/memoize.ts +26 -3
  147. package/src/reactive/project.md +107 -0
  148. package/src/reactive/project.ts +48 -71
  149. package/src/reactive/proxy.ts +21 -3
  150. package/src/reactive/record.ts +30 -45
  151. package/src/reactive/register.ts +138 -19
  152. package/src/reactive/registry.ts +22 -9
  153. package/src/reactive/set.ts +8 -21
  154. package/src/reactive/tracking.ts +9 -12
  155. package/src/reactive/types.ts +104 -24
  156. package/src/reactive/{interface.ts → watch.ts} +29 -59
  157. package/src/std-decorators.ts +56 -17
  158. package/src/utils.ts +2 -3
  159. package/src/zone.ts +28 -24
  160. package/dist/async/index.d.ts.map +0 -1
  161. package/dist/chunks/async-browser-CA0jPWIi.cjs.map +0 -1
  162. package/dist/chunks/async-core-UqHzvJ-S.cjs.map +0 -1
  163. package/dist/chunks/async-node-BYHuGTni.cjs.map +0 -1
  164. package/dist/chunks/index-DhaOVusv.esm.js +0 -6411
  165. package/dist/chunks/index-DhaOVusv.esm.js.map +0 -1
  166. package/dist/decorator.d.ts.map +0 -1
  167. package/dist/destroyable.d.ts.map +0 -1
  168. package/dist/entry-browser.d.ts.map +0 -1
  169. package/dist/entry-node.d.ts.map +0 -1
  170. package/dist/eventful.d.ts +0 -18
  171. package/dist/eventful.d.ts.map +0 -1
  172. package/dist/index.d.ts.map +0 -1
  173. package/dist/indexable.d.ts.map +0 -1
  174. package/dist/introspection.d.ts.map +0 -1
  175. package/dist/iterableWeak.d.ts.map +0 -1
  176. package/dist/mixins.d.ts.map +0 -1
  177. package/dist/promiseChain.d.ts.map +0 -1
  178. package/dist/reactive/array.d.ts.map +0 -1
  179. package/dist/reactive/buffer.d.ts +0 -44
  180. package/dist/reactive/buffer.d.ts.map +0 -1
  181. package/dist/reactive/change.d.ts.map +0 -1
  182. package/dist/reactive/debug.d.ts.map +0 -1
  183. package/dist/reactive/deep-touch.d.ts.map +0 -1
  184. package/dist/reactive/deep-watch-state.d.ts.map +0 -1
  185. package/dist/reactive/deep-watch.d.ts.map +0 -1
  186. package/dist/reactive/effect-context.d.ts +0 -7
  187. package/dist/reactive/effect-context.d.ts.map +0 -1
  188. package/dist/reactive/effects.d.ts.map +0 -1
  189. package/dist/reactive/index.d.ts +0 -20
  190. package/dist/reactive/index.d.ts.map +0 -1
  191. package/dist/reactive/interface.d.ts.map +0 -1
  192. package/dist/reactive/map.d.ts.map +0 -1
  193. package/dist/reactive/memoize.d.ts +0 -5
  194. package/dist/reactive/memoize.d.ts.map +0 -1
  195. package/dist/reactive/non-reactive-state.d.ts.map +0 -1
  196. package/dist/reactive/non-reactive.d.ts.map +0 -1
  197. package/dist/reactive/project.d.ts.map +0 -1
  198. package/dist/reactive/proxy-state.d.ts.map +0 -1
  199. package/dist/reactive/proxy.d.ts.map +0 -1
  200. package/dist/reactive/record.d.ts.map +0 -1
  201. package/dist/reactive/register.d.ts.map +0 -1
  202. package/dist/reactive/registry.d.ts.map +0 -1
  203. package/dist/reactive/set.d.ts.map +0 -1
  204. package/dist/reactive/tracking.d.ts.map +0 -1
  205. package/dist/reactive/types.d.ts.map +0 -1
  206. package/dist/std-decorators.d.ts.map +0 -1
  207. package/dist/utils.d.ts.map +0 -1
  208. package/dist/zone.d.ts.map +0 -1
  209. package/src/reactive/debug.ts +0 -517
  210. /package/dist/{async → src/async}/browser.d.ts +0 -0
  211. /package/dist/{async → src/async}/node.d.ts +0 -0
  212. /package/dist/{decorator.d.ts → src/decorator.d.ts} +0 -0
  213. /package/dist/{destroyable.d.ts → src/destroyable.d.ts} +0 -0
  214. /package/dist/{entry-browser.d.ts → src/entry-browser.d.ts} +0 -0
  215. /package/dist/{entry-node.d.ts → src/entry-node.d.ts} +0 -0
  216. /package/dist/{indexable.d.ts → src/indexable.d.ts} +0 -0
  217. /package/dist/{iterableWeak.d.ts → src/iterableWeak.d.ts} +0 -0
  218. /package/dist/{mixins.d.ts → src/mixins.d.ts} +0 -0
  219. /package/dist/{promiseChain.d.ts → src/promiseChain.d.ts} +0 -0
  220. /package/dist/{reactive → src/reactive}/deep-touch.d.ts +0 -0
  221. /package/dist/{reactive → src/reactive}/non-reactive-state.d.ts +0 -0
  222. /package/dist/{reactive → src/reactive}/non-reactive.d.ts +0 -0
  223. /package/dist/{reactive → src/reactive}/proxy-state.d.ts +0 -0
  224. /package/dist/{reactive → src/reactive}/proxy.d.ts +0 -0
  225. /package/dist/{reactive → src/reactive}/tracking.d.ts +0 -0
  226. /package/dist/{utils.d.ts → src/utils.d.ts} +0 -0
package/dist/browser.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { c as cleanup, S as ScopedCallback, d as EffectCloser, e as EffectAccess, f as State, a as Evolution, b as EffectCleanup, Z as ZoneAggregator, g as EffectOptions, E as EffectTrigger, C as CatchFunction, P as ProjectionContext } from './types-DaHFfhlN.js';
2
+ export { A as AZone, F as FunctionWrapper, R as ReactiveError, h as ReactiveErrorCode, i as Zone, j as ZoneHistory, k as asyncZone, o as reactiveOptions } from './types-DaHFfhlN.js';
3
+
1
4
  /**
2
5
  * Error thrown when decorator operations fail
3
6
  */
@@ -193,18 +196,19 @@ interface ContextManager<T = any> {
193
196
  * Base type for event maps - all event handlers must be functions
194
197
  */
195
198
  type EventsBase = Record<string, (...args: any[]) => void>;
199
+ declare const events: unique symbol;
200
+ declare const hooks$1: unique symbol;
196
201
  /**
197
202
  * A type-safe event system that provides a clean API for event handling
198
203
  * @template Events - The event map defining event names and their handler signatures
199
204
  */
200
205
  declare class Eventful<Events extends EventsBase> {
201
- #private;
206
+ private readonly [events];
207
+ private readonly [hooks$1];
202
208
  hook(cb: <EventType extends keyof Events>(event: EventType, ...args: Parameters<Events[EventType]>) => void): () => void;
203
- on(events: Partial<Events>): void;
204
- on<EventType extends keyof Events>(event: EventType, cb: Events[EventType]): () => void;
205
- off(events: Partial<Events>): void;
206
- off<EventType extends keyof Events>(event: EventType, cb?: Events[EventType]): void;
207
- emit<EventType extends keyof Events>(event: EventType, ...args: Parameters<Events[EventType]>): void;
209
+ on: ((events: Partial<Events>) => void) & (<EventType extends keyof Events>(event: EventType, cb: Events[EventType]) => () => void) & { [event in keyof Events]: (cb: Events[event]) => () => void; };
210
+ off: ((events: Partial<Events>) => void) & (<EventType extends keyof Events>(event: EventType, cb?: Events[EventType]) => void) & { [event in keyof Events]: (cb?: Events[event]) => void; };
211
+ emit: (<EventType extends keyof Events>(event: EventType, ...args: Parameters<Events[EventType]>) => void) & Events;
208
212
  }
209
213
 
210
214
  /**
@@ -546,399 +550,123 @@ type PromiseChain<T> = T extends (...args: infer Args) => infer R ? PromiseAnd<(
546
550
  */
547
551
  declare function chainPromise<T>(given: Promise<T> | T): PromiseChain<T>;
548
552
 
549
- declare abstract class AZone<T> {
550
- abstract active?: T;
551
- protected enter(value?: T): unknown;
552
- protected leave(entered: unknown): void;
553
- with<R>(value: T, fn: () => R): R;
554
- root<R>(fn: () => R): R;
555
- get zoned(): FunctionWrapper;
556
- }
557
- type FunctionWrapper = <R>(fn?: () => R) => R;
558
- declare class Zone<T> extends AZone<T> {
559
- active: T | undefined;
560
- }
561
- type HistoryValue<T> = {
562
- present: T | undefined;
563
- history: Set<T>;
564
- };
565
- declare class ZoneHistory<T> extends AZone<HistoryValue<T>> {
566
- private controlled;
567
- private history;
568
- readonly present: AZone<T>;
569
- has(value: T): boolean;
570
- some(predicate: (value: T) => boolean): boolean;
571
- constructor(controlled?: AZone<T>);
572
- get active(): HistoryValue<T> | undefined;
573
- set active(value: HistoryValue<T> | undefined);
574
- }
575
- declare class ZoneAggregator extends AZone<Map<AZone<unknown>, unknown>> {
576
- #private;
577
- constructor(...zones: AZone<unknown>[]);
578
- get active(): Map<AZone<unknown>, unknown> | undefined;
579
- set active(value: Map<AZone<unknown>, unknown> | undefined);
580
- enter(value?: Map<AZone<unknown>, unknown> | undefined): Map<AZone<unknown>, unknown>;
581
- leave(entered: Map<AZone<unknown>, unknown>): void;
582
- add(z: AZone<unknown>): void;
583
- delete(z: AZone<unknown>): void;
584
- clear(): void;
585
- }
586
- declare const asyncZone: ZoneAggregator;
587
-
588
- /**
589
- * Dependency access passed to user callbacks within effects/watch
590
- * Provides functions to track dependencies and information about the effect execution
591
- */
592
- interface DependencyAccess {
593
- /**
594
- * Tracks dependencies in the current effect context
595
- * Use this for normal dependency tracking within the effect
596
- * @example
597
- * ```typescript
598
- * effect(({ tracked }) => {
599
- * // In async context, use tracked to restore dependency tracking
600
- * await someAsyncOperation()
601
- * const value = tracked(() => state.count) // Tracks state.count in this effect
602
- * })
603
- * ```
604
- */
605
- tracked: FunctionWrapper;
606
- /**
607
- * Tracks dependencies in the parent effect context
608
- * Use this when child effects should track dependencies in the parent,
609
- * allowing parent cleanup to manage child effects while dependencies trigger the parent
610
- * @example
611
- * ```typescript
612
- * effect(({ ascend }) => {
613
- * const length = inputs.length
614
- * if (length > 0) {
615
- * ascend(() => {
616
- * // Dependencies here are tracked in the parent effect
617
- * inputs.forEach(item => console.log(item))
618
- * })
619
- * }
620
- * })
621
- * ```
622
- */
623
- ascend: FunctionWrapper;
624
- /**
625
- * Indicates whether the effect is running as a reaction (i.e. not the first call)
626
- * - `false`: First execution when the effect is created
627
- * - `true`: Subsequent executions triggered by dependency changes
628
- * @example
629
- * ```typescript
630
- * effect(({ reaction }) => {
631
- * if (!reaction) {
632
- * console.log('Effect initialized')
633
- * // Setup code that should only run once
634
- * } else {
635
- * console.log('Effect re-ran due to dependency change')
636
- * // Code that runs on every update
637
- * }
638
- * })
639
- * ```
640
- */
641
- reaction: boolean;
642
- }
643
- /**
644
- * Type for effect cleanup functions
645
- */
646
- type ScopedCallback = () => void;
647
553
  /**
648
- * Async execution mode for effects
649
- * - `cancel`: Cancel previous async execution when dependencies change (default)
650
- * - `queue`: Queue next execution to run after current completes
651
- * - `ignore`: Ignore new executions while async work is running
652
- */
653
- type AsyncExecutionMode = 'cancel' | 'queue' | 'ignore';
654
- /**
655
- * Options for effect creation
656
- */
657
- interface EffectOptions {
658
- /**
659
- * How to handle async effect executions when dependencies change
660
- * @default 'cancel'
661
- */
662
- asyncMode?: AsyncExecutionMode;
663
- /**
664
- * If true, this effect is "opaque" to deep optimizations: it sees the object reference itself
665
- * and must be notified when it changes, regardless of deep content similarity.
666
- * Use this for effects that depend on object identity (like memoize).
667
- */
668
- opaque?: boolean;
669
- }
670
- /**
671
- * Type for property evolution events
554
+ * Reactively attends to each entry of a collection or each key yielded by an
555
+ * enumeration callback. For each key, an inner effect runs the callback. When a
556
+ * key disappears, its inner effect is disposed. The callback may return a cleanup
557
+ * (like a regular effect closer).
558
+ *
559
+ * Accepts arrays, records, Maps, Sets, or a raw `() => Iterable<Key>` callback.
560
+ *
561
+ * @example
562
+ * ```typescript
563
+ * // Record shorthand
564
+ * attend(record, (key) => { console.log(key, record[key]) })
565
+ *
566
+ * // Array shorthand
567
+ * attend(array, (index) => { console.log(index, array[index]) })
568
+ *
569
+ * // Raw enumeration callback
570
+ * attend(() => Object.keys(record), (key) => { ... })
571
+ * ```
672
572
  */
673
- type PropEvolution = {
674
- type: 'set' | 'del' | 'add' | 'invalidate';
675
- prop: any;
676
- };
573
+ declare function attend<T>(source: readonly T[], callback: (index: number) => EffectCloser | void): ScopedCallback;
574
+ declare function attend<K, V>(source: Map<K, V>, callback: (key: K) => EffectCloser | void): ScopedCallback;
575
+ declare function attend<T>(source: Set<T>, callback: (value: T) => EffectCloser | void): ScopedCallback;
576
+ declare function attend<S extends Record<PropertyKey, any>>(source: S, callback: (key: keyof S & string) => EffectCloser | void): ScopedCallback;
577
+ declare function attend<Key>(enumerate: () => Iterable<Key>, callback: (key: Key) => EffectCloser | void): ScopedCallback;
677
578
  /**
678
- * Type for collection operation evolution events
579
+ * Result of a reactive scan, which is a reactive array of accumulated values
580
+ * with an attached cleanup function.
679
581
  */
680
- type BunchEvolution = {
681
- type: 'bunch';
682
- method: string;
582
+ type ScanResult<Output> = readonly Output[] & {
583
+ [cleanup]: ScopedCallback;
683
584
  };
684
- type Evolution = PropEvolution | BunchEvolution;
685
- type State = {
686
- evolution: Evolution;
687
- next: State;
688
- } | {};
689
585
  /**
690
- * Symbol to check if an effect is stopped
691
- */
692
- declare const stopped: unique symbol;
693
- /**
694
- * Symbol to access effect cleanup function
695
- */
696
- declare const cleanup$1: unique symbol;
697
- /**
698
- * Context for a running projection item effect
586
+ * Perform a reactive scan over an array of items.
587
+ *
588
+ * This implementation is highly optimized for performance and fine-grained reactivity:
589
+ * - **Incremental Updates**: Changes to an item only trigger re-computation from that
590
+ * point onwards in the result chain.
591
+ * - **Move Optimization**: If items are moved within the array, their accumulated
592
+ * values are reused as long as their predecessor remains the same.
593
+ * - **Duplicate Support**: Correctly handles multiple occurrences of the same object
594
+ * instance using an internal occurrence tracking mechanism.
595
+ * - **Memory Efficient**: Uses `WeakMap` for caching intermediates, which are
596
+ * automatically cleared when source items are garbage collected.
597
+ *
598
+ * @example
599
+ * ```typescript
600
+ * const source = reactive([{ val: 1 }, { val: 2 }, { val: 3 }])
601
+ * const sum = scan(source, (acc, item) => acc + item.val, 0)
602
+ *
603
+ * expect([...sum]).toEqual([1, 3, 6])
604
+ *
605
+ * // Modifying an item only re-computes subsequent sums
606
+ * source[1].val = 10
607
+ * expect([...sum]).toEqual([1, 11, 14])
608
+ * ```
609
+ *
610
+ * @param source The source array of objects (will be made reactive)
611
+ * @param callback The accumulator function called with (accumulator, currentItem)
612
+ * @param initialValue The starting value for the accumulation
613
+ * @returns A reactive array of accumulated values, with a [cleanup] property to stop the tracking
699
614
  */
700
- interface ProjectionContext {
701
- source: any;
702
- key?: any;
703
- target: any;
704
- depth: number;
705
- parent?: ProjectionContext;
706
- }
615
+ declare function scan<Input extends object, Output>(source: readonly Input[], callback: (acc: Output, val: Input) => Output, initialValue: Output): ScanResult<Output>;
707
616
  /**
708
- * Structured error codes for machine-readable diagnosis
617
+ * Lifts a callback that returns an array into a reactive array that automatically
618
+ * synchronizes with the source array returned by the callback.
619
+ *
620
+ * The returned reactive array will update whenever the callback's dependencies change,
621
+ * efficiently syncing only the elements that differ from the previous result.
622
+ *
623
+ * @example
624
+ * ```typescript
625
+ * const items = reactive([1, 2, 3])
626
+ * const doubled = lift(() => items.map(x => x * 2))
627
+ *
628
+ * console.log([...doubled]) // [2, 4, 6]
629
+ *
630
+ * items.push(4)
631
+ * console.log([...doubled]) // [2, 4, 6, 8]
632
+ * ```
633
+ *
634
+ * @param cb Callback function that returns an array
635
+ * @returns A reactive array synchronized with the callback's result, with a [cleanup] property to stop tracking
709
636
  */
710
- declare enum ReactiveErrorCode {
711
- CycleDetected = "CYCLE_DETECTED",
712
- MaxDepthExceeded = "MAX_DEPTH_EXCEEDED",
713
- MaxReactionExceeded = "MAX_REACTION_EXCEEDED",
714
- WriteInComputed = "WRITE_IN_COMPUTED",
715
- TrackingError = "TRACKING_ERROR",
716
- BrokenEffects = "BROKEN_EFFECTS"
717
- }
718
- type CycleDebugInfo = {
719
- code: ReactiveErrorCode.CycleDetected;
720
- cycle: string[];
721
- details?: string;
722
- };
723
- type MaxDepthDebugInfo = {
724
- code: ReactiveErrorCode.MaxDepthExceeded;
725
- depth: number;
726
- chain: string[];
727
- };
728
- type MaxReactionDebugInfo = {
729
- code: ReactiveErrorCode.MaxReactionExceeded;
730
- count: number;
731
- effect: string;
732
- };
733
- type BrokenEffectsDebugInfo = {
734
- code: ReactiveErrorCode.BrokenEffects;
735
- cause: any;
736
- };
737
- type GenericDebugInfo = {
738
- code: ReactiveErrorCode;
739
- causalChain?: string[];
740
- creationStack?: string;
741
- [key: string]: any;
637
+ declare function lift<Output extends any[]>(cb: (access: EffectAccess) => Output): Output & {
638
+ [cleanup]: ScopedCallback;
742
639
  };
743
- type ReactiveDebugInfo = CycleDebugInfo | MaxDepthDebugInfo | MaxReactionDebugInfo | BrokenEffectsDebugInfo | GenericDebugInfo;
744
- /**
745
- * Error class for reactive system errors
746
- */
747
- declare class ReactiveError extends Error {
748
- debugInfo?: ReactiveDebugInfo;
749
- constructor(message: string, debugInfo?: ReactiveDebugInfo);
750
- get code(): ReactiveErrorCode | undefined;
751
- get cause(): any;
752
- }
753
640
  /**
754
- * Global options for the reactive system
641
+ * Lifts a callback that returns an object into a reactive object that automatically
642
+ * synchronizes with the source object returned by the callback.
643
+ *
644
+ * The returned reactive object will update whenever the callback's dependencies change,
645
+ * efficiently syncing only the properties that differ from the previous result using
646
+ * Object.assign(). Properties that no longer exist in the source are automatically removed.
647
+ *
648
+ * @example
649
+ * ```typescript
650
+ * const user = reactive({ name: 'John', age: 30 })
651
+ * const profile = lift(() => ({
652
+ * displayName: user.name.toUpperCase(),
653
+ * isAdult: user.age >= 18,
654
+ * description: `${user.name} is ${user.age} years old`
655
+ * }))
656
+ *
657
+ * console.log(profile.displayName) // JOHN
658
+ * console.log(profile.isAdult) // true
659
+ *
660
+ * user.name = 'Jane'
661
+ * console.log(profile.displayName) // JANE
662
+ * console.log(profile.description) // Jane is 30 years old
663
+ * ```
664
+ *
665
+ * @param cb Callback function that returns an object
666
+ * @returns A reactive object synchronized with the callback's result, with a [cleanup] property to stop tracking
755
667
  */
756
- declare const options: {
757
- /**
758
- * Debug purpose: called when an effect is entered
759
- * @param effect - The effect that is entered
760
- */
761
- enter: (_effect: Function) => void;
762
- /**
763
- * Debug purpose: called when an effect is left
764
- * @param effect - The effect that is left
765
- */
766
- leave: (_effect: Function) => void;
767
- /**
768
- * Debug purpose: called when an effect is chained
769
- * @param target - The effect that is being triggered
770
- * @param caller - The effect that is calling the target
771
- */
772
- chain: (_targets: Function[], _caller?: Function) => void;
773
- /**
774
- * Debug purpose: called when an effect chain is started
775
- * @param target - The effect that is being triggered
776
- */
777
- beginChain: (_targets: Function[]) => void;
778
- /**
779
- * Debug purpose: called when an effect chain is ended
780
- */
781
- endChain: () => void;
782
- garbageCollected: (_fn: Function) => void;
783
- /**
784
- * Debug purpose: called when an object is touched
785
- * @param obj - The object that is touched
786
- * @param evolution - The type of change
787
- * @param props - The properties that changed
788
- * @param deps - The dependencies that changed
789
- */
790
- touched: (_obj: any, _evolution: Evolution, _props?: any[], _deps?: Set<ScopedCallback>) => void;
791
- /**
792
- * Debug purpose: called when an effect is skipped because it's already running
793
- * @param effect - The effect that is already running
794
- * @param runningChain - The array of effects from the detected one to the currently running one
795
- */
796
- skipRunningEffect: (_effect: ScopedCallback) => void;
797
- /**
798
- * Debug purpose: maximum effect chain (like call stack max depth)
799
- * Used to prevent infinite loops
800
- * @default 100
801
- */
802
- maxEffectChain: number;
803
- /**
804
- * Maximum number of times an effect can be triggered by the same cause in a single batch
805
- * Used to detect aggressive re-computation or infinite loops
806
- * @default 10
807
- */
808
- maxTriggerPerBatch: number;
809
- /**
810
- * Debug purpose: maximum effect reaction (like call stack max depth)
811
- * Used to prevent infinite loops
812
- * @default 'throw'
813
- */
814
- maxEffectReaction: "throw" | "debug" | "warn";
815
- /**
816
- * Callback called when a memoization discrepancy is detected (debug only)
817
- * When defined, memoized functions will run a second time (untracked) to verify consistency.
818
- * If the untracked run returns a different value than the cached one, this callback is triggered.
819
- *
820
- * This is the primary tool for detecting missing reactive dependencies in computed values.
821
- *
822
- * @param cached - The value currently in the memoization cache
823
- * @param fresh - The value obtained by re-running the function untracked
824
- * @param fn - The memoized function itself
825
- * @param args - Arguments passed to the function
826
- *
827
- * @example
828
- * ```typescript
829
- * reactiveOptions.onMemoizationDiscrepancy = (cached, fresh, fn, args) => {
830
- * throw new Error(`Memoization discrepancy in ${fn.name}!`);
831
- * };
832
- * ```
833
- */
834
- onMemoizationDiscrepancy: ((cached: any, fresh: any, fn: Function, args: any[], cause: "calculation" | "comparison") => void) | undefined;
835
- /**
836
- * How to handle cycles detected in effect batches.
837
- *
838
- * - `'none'` (Default): High-performance mode. Disables dependency graph maintenance and
839
- * Topological Sorting in favor of a simple FIFO queue. Use this for trustworthy, acyclic UI code.
840
- * Cycle detection is heuristic (uses execution counts).
841
- *
842
- * - `'throw'`: Traditional Topological Sorting. Guarantees dependency order and catches
843
- * circular dependencies mathematically before execution.
844
- *
845
- * - `'warn'`: Topological sorting, but logs a warning instead of throwing on cycles.
846
- * - `'break'`: Topological sorting, but silently breaks cycles.
847
- * - `'strict'`: Prevents cycle creation by checking the graph *during* dependency discovery.
848
- *
849
- * @default 'none'
850
- */
851
- cycleHandling: "none" | "throw" | "warn" | "break" | "strict";
852
- /**
853
- * Internal flag used by memoization discrepancy detector to avoid counting calls in tests
854
- * @warning Do not modify this flag manually, this flag is given by the engine
855
- */
856
- isVerificationRun: boolean;
857
- /**
858
- * Maximum depth for deep watching traversal
859
- * Used to prevent infinite recursion in circular references
860
- * @default 100
861
- */
862
- maxDeepWatchDepth: number;
863
- /**
864
- * Only react on instance members modification (not inherited properties)
865
- * For instance, do not track class methods
866
- * @default true
867
- */
868
- instanceMembers: boolean;
869
- /**
870
- * Ignore accessors (getters and setters) and only track direct properties
871
- * @default true
872
- */
873
- ignoreAccessors: boolean;
874
- /**
875
- * Enable recursive touching when objects with the same prototype are replaced
876
- * When enabled, replacing an object with another of the same prototype triggers
877
- * recursive diffing instead of notifying parent effects
878
- * @default true
879
- */
880
- recursiveTouching: boolean;
881
- /**
882
- * Default async execution mode for effects that return Promises
883
- * - 'cancel': Cancel previous async execution when dependencies change (default, enables async zone)
884
- * - 'queue': Queue next execution to run after current completes (enables async zone)
885
- * - 'ignore': Ignore new executions while async work is running (enables async zone)
886
- * - false: Disable async zone and async mode handling (effects run concurrently)
887
- *
888
- * **When truthy:** Enables async zone (Promise.prototype wrapping) for automatic context
889
- * preservation in Promise callbacks. Warning: This modifies Promise.prototype globally.
890
- * Only enable if no other library modifies Promise.prototype.
891
- *
892
- * **When false:** Async zone is disabled. Use `tracked()` manually in Promise callbacks.
893
- *
894
- * Can be overridden per-effect via EffectOptions
895
- * @default 'cancel'
896
- */
897
- asyncMode: AsyncExecutionMode | false;
898
- warn: (...args: any[]) => void;
899
- /**
900
- * Configuration for the introspection system
901
- */
902
- introspection: {
903
- /**
904
- * Whether to keep a history of mutations for debugging
905
- * @default false
906
- */
907
- enableHistory: boolean;
908
- /**
909
- * Number of mutations to keep in history
910
- * @default 50
911
- */
912
- historySize: number;
913
- };
914
- /**
915
- * Configuration for zone hooks - control which async APIs are hooked
916
- * Each option controls whether the corresponding async API is wrapped to preserve effect context
917
- * Only applies when asyncMode is enabled (truthy)
918
- * @deprecated Should take all when we made sure PIXI.create, Game.create, ... are -> .root()
919
- */
920
- zones: {
921
- /**
922
- * Hook setTimeout to preserve effect context
923
- * @default true
924
- */
925
- setTimeout: boolean;
926
- /**
927
- * Hook setInterval to preserve effect context
928
- * @default true
929
- */
930
- setInterval: boolean;
931
- /**
932
- * Hook requestAnimationFrame (runs in untracked context when hooked)
933
- * @default true
934
- */
935
- requestAnimationFrame: boolean;
936
- /**
937
- * Hook queueMicrotask to preserve effect context
938
- * @default true
939
- */
940
- queueMicrotask: boolean;
941
- };
668
+ declare function lift<Output extends object>(cb: (access: EffectAccess) => Output): Output & {
669
+ [cleanup]: ScopedCallback;
942
670
  };
943
671
 
944
672
  /**
@@ -962,72 +690,6 @@ declare function touched1(obj: any, evolution: Evolution, prop: any): void;
962
690
  */
963
691
  declare function touched(obj: any, evolution: Evolution, props?: Iterable<any>): void;
964
692
 
965
- /**
966
- * Debug utilities for the reactivity system
967
- * - Captures effect metadata (names, parent relationships)
968
- * - Records cause → consequence edges with object/prop labels
969
- * - Provides graph data for tooling (DevTools panel, etc.)
970
- */
971
-
972
- type NodeKind = 'effect' | 'external' | 'state';
973
- type EdgeKind = 'cause' | 'dependency' | 'trigger';
974
- interface EffectNode {
975
- id: string;
976
- label: string;
977
- type: NodeKind;
978
- depth: number;
979
- parentId?: string;
980
- debugName?: string;
981
- }
982
- interface ObjectNode {
983
- id: string;
984
- label: string;
985
- type: NodeKind;
986
- debugName?: string;
987
- }
988
- interface GraphEdge {
989
- id: string;
990
- source: string;
991
- target: string;
992
- type: EdgeKind;
993
- label: string;
994
- count?: number;
995
- }
996
- interface ReactivityGraph {
997
- nodes: Array<EffectNode | ObjectNode>;
998
- edges: GraphEdge[];
999
- meta: {
1000
- generatedAt: number;
1001
- devtoolsEnabled: boolean;
1002
- };
1003
- }
1004
- /**
1005
- * Assign a debug-friendly name to an effect (shown in DevTools)
1006
- */
1007
- declare function setEffectName(effect: ScopedCallback, name: string): void;
1008
- /**
1009
- * Assign a debug-friendly name to a reactive object
1010
- */
1011
- declare function setObjectName(obj: object, name: string): void;
1012
- /**
1013
- * Register an effect so it appears in the DevTools graph
1014
- */
1015
- declare function registerEffectForDebug(effect: ScopedCallback): void;
1016
- /**
1017
- * Register a reactive object so it appears in the DevTools graph
1018
- */
1019
- declare function registerObjectForDebug(obj: object): void;
1020
- /**
1021
- * Builds a graph representing current reactive state (effects, objects, and trigger edges)
1022
- */
1023
- declare function buildReactivityGraph(): ReactivityGraph;
1024
- /**
1025
- * Enables the DevTools bridge and exposes the debug API on window.
1026
- * Call as early as possible in development builds.
1027
- */
1028
- declare function enableDevTools(): void;
1029
- declare function isDevtoolsEnabled(): boolean;
1030
-
1031
693
  /**
1032
694
  * Deep watch an object and all its nested properties
1033
695
  * @param target - The object to watch deeply
@@ -1044,16 +706,52 @@ declare function isDevtoolsEnabled(): boolean;
1044
706
  */
1045
707
  declare function deepWatch<T extends object>(target: T, callback: (value: T) => void, { immediate }?: {
1046
708
  immediate?: boolean;
1047
- }): (() => void) | undefined;
709
+ }): EffectCleanup | undefined;
710
+
711
+ /**
712
+ * Aggregator for zones that need to be tracked along effects.
713
+ * ie. in each effect, the active zone of the given zoning will be the one active at effect's definition
714
+ */
715
+ declare const effectAggregator: ZoneAggregator;
716
+ declare function getActiveEffect(): ScopedCallback;
717
+ /**
718
+ * ADD a cleanup function to an object using the cleanup symbol.
719
+ * The cleanup function will be called when the object needs to be disposed.
720
+ *
721
+ * Note: most of the time, you don't need to use this function directly.
722
+ * The main use if for the cleanup function to be stored with the object, as GC calls the cleanup function when the *function* is garbage collected.
723
+ *
724
+ * @param obj - The object to attach the cleanup function to
725
+ * @param cleanupFn - The cleanup function to attach
726
+ * @returns The object with the cleanup function attached
727
+ */
728
+ declare function cleanedBy<T extends object>(obj: T, cleanupFn: ScopedCallback): T & {
729
+ [cleanup]: ScopedCallback;
730
+ };
731
+ /**
732
+ * Creates a derived value that automatically recomputes when dependencies change
733
+ * @param compute - Function that computes the derived value
734
+ * @returns Object with value and cleanup function
735
+ */
736
+ declare function derived<T>(compute: (dep: EffectAccess) => T): {
737
+ value: T;
738
+ [cleanup]: ScopedCallback;
739
+ };
1048
740
 
1049
- type EffectTracking = (obj: any, evolution: Evolution, prop: any) => void;
741
+ type EffectTracking = (obj: any, evolution: Evolution, prop: any, effect: EffectTrigger) => void;
1050
742
  interface ActivationRecord {
1051
- effect: ScopedCallback;
743
+ effect: EffectTrigger;
1052
744
  obj: any;
1053
745
  evolution: Evolution;
1054
746
  prop: any;
1055
747
  batchId: number;
1056
748
  }
749
+ /**
750
+ * Returns the activation log containing recent effect activations for debugging.
751
+ * The log is a circular buffer of the last 100 activations.
752
+ *
753
+ * @returns Array of activation records
754
+ */
1057
755
  declare function getActivationLog(): Omit<ActivationRecord, "batchId">[];
1058
756
  /**
1059
757
  * Registers a debug callback that is called when the current effect is triggered by a dependency change
@@ -1065,7 +763,7 @@ declare function getActivationLog(): Omit<ActivationRecord, "batchId">[];
1065
763
  * - The specific property that changed
1066
764
  *
1067
765
  * **Note:** The tracker callback is automatically removed after being called once. If you need
1068
- * to track multiple triggers, call `trackEffect` again within the effect.
766
+ * to track multiple triggers, call `onEffectTrigger` again within the effect.
1069
767
  *
1070
768
  * @param onTouch - Callback function that receives (obj, evolution, prop) when the effect is triggered
1071
769
  * @throws {Error} If called outside of an effect context
@@ -1076,7 +774,7 @@ declare function getActivationLog(): Omit<ActivationRecord, "batchId">[];
1076
774
  *
1077
775
  * effect(() => {
1078
776
  * // Register a tracker to see what triggers this effect
1079
- * trackEffect((obj, evolution, prop) => {
777
+ * onEffectTrigger((obj, evolution, prop) => {
1080
778
  * console.log(`Effect triggered by:`, {
1081
779
  * object: obj,
1082
780
  * change: evolution.type,
@@ -1089,15 +787,15 @@ declare function getActivationLog(): Omit<ActivationRecord, "batchId">[];
1089
787
  * })
1090
788
  *
1091
789
  * state.count = 5
1092
- * // Logs: Effect triggered by: { object: state, change: 'set', property: 'count' }
1093
790
  * ```
1094
791
  */
1095
- declare function trackEffect(onTouch: EffectTracking): void;
792
+ declare function onEffectTrigger(onTouch: EffectTracking, effect?: EffectTrigger): void;
793
+ declare function onEffectThrow(onThrow: CatchFunction, effect?: EffectTrigger): void;
1096
794
  /**
1097
795
  * Adds a cleanup function to be called when the current batch of effects completes
1098
796
  * @param cleanup - The cleanup function to add
1099
797
  */
1100
- declare function addBatchCleanup(cleanup: ScopedCallback): void;
798
+ declare function addBatchCleanup(cleanup: EffectCleanup): void;
1101
799
  /**
1102
800
  * Semantic alias for `addBatchCleanup` - defers work to the end of the current reactive batch.
1103
801
  *
@@ -1119,6 +817,14 @@ declare function addBatchCleanup(cleanup: ScopedCallback): void;
1119
817
  * ```
1120
818
  */
1121
819
  declare const defer: typeof addBatchCleanup;
820
+ /**
821
+ * Resets the reactive system to a consistent state.
822
+ * Call this after an unrecoverable error has set the system to "broken".
823
+ * This clears all batch state, effect dependency graphs, and watcher registrations.
824
+ * All existing effects become orphaned and must be recreated.
825
+ */
826
+ declare function reset(): void;
827
+
1122
828
  /**
1123
829
  * Decorator that makes methods atomic - batches all effects triggered within the method
1124
830
  */
@@ -1133,9 +839,9 @@ declare const atomic: LegacyPropertyDecorator<any> & ModernMethodDecorator<any>
1133
839
  * @param options - Options for effect execution
1134
840
  * @returns A cleanup function to stop the effect
1135
841
  */
1136
- declare function effect(fn: (access: DependencyAccess) => ScopedCallback | undefined | void | Promise<any>, effectOptions?: EffectOptions): ScopedCallback & {
1137
- [stopped]: boolean;
1138
- [cleanup$1]: () => void;
842
+ declare const effect: ((fn: (access: EffectAccess) => EffectCloser | undefined | void | Promise<any>, effectOptions?: EffectOptions) => EffectCleanup) & {
843
+ readonly opaque: any;
844
+ named(name: string): any;
1139
845
  };
1140
846
  /**
1141
847
  * Executes a function without tracking dependencies but maintains parent cleanup relationship
@@ -1149,7 +855,6 @@ declare function untracked<T>(fn: () => T): T;
1149
855
  * @param fn - The function to execute
1150
856
  */
1151
857
  declare function root<T>(fn: () => T): T;
1152
-
1153
858
  /**
1154
859
  * Creates a bidirectional binding between a reactive value and a non-reactive external value
1155
860
  * Prevents infinite loops by automatically suppressing circular notifications
@@ -1189,69 +894,31 @@ declare function biDi<T>(received: (value: T) => void, value: {
1189
894
  }): (value: T) => void;
1190
895
  declare function biDi<T>(received: (value: T) => void, get: () => T, set: (value: T) => void): (value: T) => void;
1191
896
 
1192
- /**
1193
- * Symbol for accessing the cleanup function on cleaned objects
1194
- */
1195
- declare const cleanup: unique symbol;
1196
- /**
1197
- * Options for the watch function
1198
- */
1199
- interface WatchOptions {
1200
- /** Whether to call the callback immediately */
1201
- immediate?: boolean;
1202
- /** Whether to watch nested properties */
1203
- deep?: boolean;
1204
- }
1205
- /**
1206
- * Watches a reactive value and calls a callback when it changes
1207
- * @param value - Function that returns the value to watch
1208
- * @param changed - Callback to call when the value changes
1209
- * @param options - Watch options
1210
- * @returns Cleanup function to stop watching
1211
- */
1212
- declare function watch<T>(value: (dep: DependencyAccess) => T, changed: (value: T, oldValue?: T) => void, options?: Omit<WatchOptions, 'deep'> & {
1213
- deep?: false;
1214
- }): ScopedCallback;
1215
- /**
1216
- * Watches a reactive value with deep watching enabled
1217
- * @param value - Function that returns the value to watch
1218
- * @param changed - Callback to call when the value changes
1219
- * @param options - Watch options with deep watching enabled
1220
- * @returns Cleanup function to stop watching
1221
- */
1222
- declare function watch<T extends object | any[]>(value: (dep: DependencyAccess) => T, changed: (value: T, oldValue?: T) => void, options?: Omit<WatchOptions, 'deep'> & {
1223
- deep: true;
1224
- }): ScopedCallback;
1225
- /**
1226
- * Watches a reactive object directly
1227
- * @param value - The reactive object to watch
1228
- * @param changed - Callback to call when the object changes
1229
- * @param options - Watch options
1230
- * @returns Cleanup function to stop watching
1231
- */
1232
- declare function watch<T extends object | any[]>(value: T, changed: (value: T) => void, options?: WatchOptions): ScopedCallback;
1233
- declare function unreactiveApplication<T extends object>(...args: (keyof T)[]): GenericClassDecorator<T>;
1234
- declare function unreactiveApplication<T extends object>(obj: T): T;
1235
- /**
1236
- * Decorator that marks classes or properties as non-reactive
1237
- * Prevents objects from being made reactive
1238
- */
1239
- declare const unreactive: LegacyClassDecorator<new (...args: any[]) => any> & ModernClassDecorator<new (...args: any[]) => any> & typeof unreactiveApplication;
1240
- declare function cleanedBy<T extends object>(obj: T, cleanupFn: ScopedCallback): T & {
1241
- [cleanup]: ScopedCallback;
1242
- };
1243
- /**
1244
- * Creates a derived value that automatically recomputes when dependencies change
1245
- * @param compute - Function that computes the derived value
1246
- * @returns Object with value and cleanup function
1247
- */
1248
- declare function derived<T>(compute: (dep: DependencyAccess) => T): {
1249
- value: T;
1250
- [cleanup]: ScopedCallback;
1251
- };
1252
-
1253
897
  type Memoizable = object | any[] | symbol | ((...args: any[]) => any);
1254
898
  declare function memoizeFunction<Result, Args extends Memoizable[]>(fn: (...args: Args) => Result): (...args: Args) => Result;
899
+ /**
900
+ * Decorator and function wrapper for memoizing computed values based on reactive dependencies.
901
+ *
902
+ * When used as a decorator on getters or methods, it caches the result and automatically
903
+ * invalidates the cache when reactive dependencies change.
904
+ *
905
+ * When used as a function wrapper, it memoizes based on object arguments (WeakMap-based cache).
906
+ *
907
+ * @example
908
+ * ```typescript
909
+ * class User {
910
+ * @memoize
911
+ * get fullName() {
912
+ * return `${this.firstName} ${this.lastName}`
913
+ * }
914
+ * }
915
+ *
916
+ * // Or as a function wrapper
917
+ * const expensive = memoize((obj: SomeObject) => {
918
+ * return heavyComputation(obj)
919
+ * })
920
+ * ```
921
+ */
1255
922
  declare const memoize: LegacyPropertyDecorator<any> & ModernMethodDecorator<any> & ModernGetterDecorator<any> & ModernAccessorDecorator<any> & typeof memoizeFunction;
1256
923
 
1257
924
  declare const immutables: Set<(tested: any) => boolean>;
@@ -1259,6 +926,31 @@ declare function isNonReactive(obj: any): boolean;
1259
926
  declare function registerNativeReactivity(originalClass: new (...args: any[]) => any, reactiveClass: new (...args: any[]) => any): void;
1260
927
 
1261
928
  type KeyFunction<T, K extends PropertyKey> = (item: T) => K;
929
+ /**
930
+ * Events emitted by the Register for CRUD operations
931
+ */
932
+ interface RegisterEvents<T, K extends PropertyKey> {
933
+ /**
934
+ * Emitted when a new item is added to the register
935
+ */
936
+ add: (item: T, key: K, index: number) => void;
937
+ /**
938
+ * Emitted when an item is removed from the register
939
+ */
940
+ delete: (item: T, key: K, index: number) => void;
941
+ /**
942
+ * Emitted when an item's value is updated (same key, new value)
943
+ */
944
+ update: (oldItem: T, newItem: T, key: K, index: number) => void;
945
+ /**
946
+ * Emitted when an item's key changes (rekey operation)
947
+ */
948
+ rekey: (item: T, oldKey: K, newKey: K, index: number) => void;
949
+ /**
950
+ * Index signature for EventsBase compatibility
951
+ */
952
+ [key: string]: (...args: any[]) => void;
953
+ }
1262
954
  interface RegisterInstance<T> extends ArrayReadForward<T> {
1263
955
  [index: number]: T;
1264
956
  }
@@ -1269,6 +961,20 @@ declare const RegisterClass_base: new () => ArrayReadForward<any> & {
1269
961
  declare class RegisterClass<T, K extends PropertyKey = PropertyKey> extends RegisterClass_base implements RegisterInstance<T> {
1270
962
  #private;
1271
963
  protected get [forwardArray](): readonly T[];
964
+ /**
965
+ * Register event listeners for CRUD operations
966
+ */
967
+ on(events: Partial<RegisterEvents<T, K>>): void;
968
+ on<EventType extends keyof RegisterEvents<T, K>>(event: EventType, cb: RegisterEvents<T, K>[EventType]): () => void;
969
+ /**
970
+ * Remove event listeners
971
+ */
972
+ off(events: Partial<RegisterEvents<T, K>>): void;
973
+ off<EventType extends keyof RegisterEvents<T, K>>(event: EventType, cb?: RegisterEvents<T, K>[EventType]): void;
974
+ /**
975
+ * Register a global hook that receives all events
976
+ */
977
+ hook(cb: <EventType extends keyof RegisterEvents<T, K>>(event: EventType, ...args: Parameters<RegisterEvents<T, K>[EventType]>) => void): () => void;
1272
978
  constructor(keyFn: KeyFunction<T, K>, initial?: Iterable<T>);
1273
979
  private ensureKey;
1274
980
  private assertValidKey;
@@ -1318,6 +1024,28 @@ declare class RegisterClass<T, K extends PropertyKey = PropertyKey> extends Regi
1318
1024
  }
1319
1025
  type Register<T, K extends PropertyKey = PropertyKey> = RegisterClass<T, K> & T[];
1320
1026
  declare const Register: new <T, K extends PropertyKey = PropertyKey>(keyFn: KeyFunction<T, K>, initial?: Iterable<T>) => Register<T, K>;
1027
+ /**
1028
+ * Creates a reactive Register - an ordered, array-like collection with stable key-based identity.
1029
+ *
1030
+ * Register combines array semantics (indexable access, ordering, iteration) with Map-like
1031
+ * key-based lookups. Items with the same key share the same value instance, making it ideal
1032
+ * for UI lists keyed by IDs or when you need to preserve identity across reorders.
1033
+ *
1034
+ * @param keyFn - Function that extracts the key from each item
1035
+ * @param initial - Optional initial items to populate the register
1036
+ * @returns A reactive Register instance
1037
+ *
1038
+ * @example
1039
+ * ```typescript
1040
+ * const users = register(
1041
+ * (user: User) => user.id,
1042
+ * [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
1043
+ * )
1044
+ *
1045
+ * users.push({ id: 3, name: 'Charlie' })
1046
+ * const bob = users.get(2) // Get by key
1047
+ * ```
1048
+ */
1321
1049
  declare function register<T, K extends PropertyKey = PropertyKey>(keyFn: KeyFunction<T, K>, initial?: Iterable<T>): Register<T, K>;
1322
1050
 
1323
1051
  /**
@@ -1409,7 +1137,7 @@ access: OrganizedAccess<Source, Key>,
1409
1137
  /**
1410
1138
  * The target object where organized data will be stored
1411
1139
  */
1412
- target: Target) => ScopedCallback | undefined;
1140
+ target: Target) => EffectCloser | undefined;
1413
1141
  /**
1414
1142
  * The result type of the organized function, combining the target object with cleanup capability.
1415
1143
  * @template Target - The type of the target object
@@ -1487,49 +1215,61 @@ declare function organize<T>(target: object, property: PropertyKey, access: {
1487
1215
  }): () => boolean;
1488
1216
 
1489
1217
  /**
1490
- * Result of a reactive scan, which is a reactive array of accumulated values
1491
- * with an attached cleanup function.
1218
+ * Options for the watch function
1492
1219
  */
1493
- type ScanResult<Output> = readonly Output[] & {
1494
- [cleanup]: ScopedCallback;
1495
- };
1220
+ interface WatchOptions {
1221
+ /** Whether to call the callback immediately */
1222
+ immediate?: boolean;
1223
+ /** Whether to watch nested properties */
1224
+ deep?: boolean;
1225
+ }
1496
1226
  /**
1497
- * Perform a reactive scan over an array of items.
1498
- *
1499
- * This implementation is highly optimized for performance and fine-grained reactivity:
1500
- * - **Incremental Updates**: Changes to an item only trigger re-computation from that
1501
- * point onwards in the result chain.
1502
- * - **Move Optimization**: If items are moved within the array, their accumulated
1503
- * values are reused as long as their predecessor remains the same.
1504
- * - **Duplicate Support**: Correctly handles multiple occurrences of the same object
1505
- * instance using an internal occurrence tracking mechanism.
1506
- * - **Memory Efficient**: Uses `WeakMap` for caching intermediates, which are
1507
- * automatically cleared when source items are garbage collected.
1508
- *
1509
- * @example
1510
- * ```typescript
1511
- * const source = reactive([{ val: 1 }, { val: 2 }, { val: 3 }])
1512
- * const sum = scan(source, (acc, item) => acc + item.val, 0)
1513
- *
1514
- * expect([...sum]).toEqual([1, 3, 6])
1227
+ * Watches a reactive value and calls a callback when it changes
1228
+ * @param value - Function that returns the value to watch
1229
+ * @param changed - Callback to call when the value changes
1230
+ * @param options - Watch options
1231
+ * @returns Cleanup function to stop watching
1232
+ */
1233
+ declare function watch<T>(value: (dep: EffectAccess) => T, changed: (value: T, oldValue?: T) => void, options?: Omit<WatchOptions, 'deep'> & {
1234
+ deep?: false;
1235
+ }): EffectCleanup;
1236
+ /**
1237
+ * Watches a reactive value with deep watching enabled
1238
+ * @param value - Function that returns the value to watch
1239
+ * @param changed - Callback to call when the value changes
1240
+ * @param options - Watch options with deep watching enabled
1241
+ * @returns Cleanup function to stop watching
1242
+ */
1243
+ declare function watch<T extends object | any[]>(value: (dep: EffectAccess) => T, changed: (value: T, oldValue?: T) => void, options?: Omit<WatchOptions, 'deep'> & {
1244
+ deep: true;
1245
+ }): EffectCleanup;
1246
+ /**
1247
+ * Watches a reactive object directly
1248
+ * @param value - The reactive object to watch
1249
+ * @param changed - Callback to call when the object changes
1250
+ * @param options - Watch options
1251
+ * @returns Cleanup function to stop watching
1252
+ */
1253
+ declare function watch<T extends object | any[]>(value: T, changed: (value: T) => void, options?: WatchOptions): EffectCleanup;
1254
+ declare function unreactiveApplication<T extends object>(...args: (keyof T)[]): GenericClassDecorator<T>;
1255
+ declare function unreactiveApplication<T extends object>(obj: T): T;
1256
+ /**
1257
+ * Decorator that marks classes or properties as non-reactive
1258
+ * Prevents objects from being made reactive
1259
+ */
1260
+ declare const unreactive: LegacyClassDecorator<new (...args: any[]) => any> & ModernClassDecorator<new (...args: any[]) => any> & typeof unreactiveApplication;
1261
+
1262
+ /**
1263
+ * Reactively defines properties on a target object based on a descriptors record.
1515
1264
  *
1516
- * // Modifying an item only re-computes subsequent sums
1517
- * source[1].val = 10
1518
- * expect([...sum]).toEqual([1, 11, 14])
1519
- * ```
1265
+ * It tracks the keys of the descriptors record and defines/updates/removes
1266
+ * properties on the target object as they change.
1520
1267
  *
1521
- * @param source The source array of objects (will be made reactive)
1522
- * @param callback The accumulator function called with (accumulator, currentItem)
1523
- * @param initialValue The starting value for the accumulation
1524
- * @returns A reactive array of accumulated values, with a [cleanup] property to stop the tracking
1268
+ * @param descriptors - A reactive record of property descriptors.
1269
+ * @param target - The object to define properties on (defaults to a new object).
1270
+ * @returns The target object with reactive property definitions.
1525
1271
  */
1526
- declare function scan<Input extends object, Output>(source: readonly Input[], callback: (acc: Output, val: Input) => Output, initialValue: Output): ScanResult<Output>;
1527
- declare function resolve<Output>(cb: () => Output[]): Output[] & {
1528
- [cleanup]: ScopedCallback;
1529
- };
1530
-
1531
- declare const effectAggregator: ZoneAggregator;
1532
- declare function getActiveEffect(): ScopedCallback;
1272
+ declare function describe<T extends object>(descriptors: Record<PropertyKey, PropertyDescriptor>, target?: T): T;
1533
1273
 
1534
1274
  /**
1535
1275
  * Object containing internal reactive system state for debugging and profiling
@@ -1560,11 +1300,7 @@ declare function cache(object: Object, propertyKey: PropertyKey, value: any): vo
1560
1300
  * @param descriptor - The descriptor properties to apply
1561
1301
  * @returns A class decorator that applies the descriptor to specified properties
1562
1302
  */
1563
- declare function describe(descriptor: {
1564
- enumerable?: boolean;
1565
- configurable?: boolean;
1566
- writable?: boolean;
1567
- }): <T>(...properties: (keyof T)[]) => GenericClassDecorator<T>;
1303
+ declare const descriptor: any;
1568
1304
  /**
1569
1305
  * Decorator that marks methods, properties, or classes as deprecated
1570
1306
  * Provides warning messages when deprecated items are used
@@ -1635,8 +1371,9 @@ declare function named<T extends Function>(name: string, fn: T): T;
1635
1371
 
1636
1372
  type Restorer = () => () => void;
1637
1373
  type Hook = () => Restorer;
1374
+ declare const hooks: Set<Hook>;
1638
1375
  declare const asyncHooks: {
1639
- addHook(_hook: Hook): () => void;
1376
+ addHook(hook: Hook): () => void;
1640
1377
  /**
1641
1378
  * [Hack] Sanitize a promise (or value) to prevent context leaks.
1642
1379
  * Default: Identity function.
@@ -1651,5 +1388,5 @@ declare const asyncHooks: {
1651
1388
  */
1652
1389
  declare const asyncHook: (hook: Hook) => () => void;
1653
1390
 
1654
- export { AZone, ArrayReadForward, DecoratorError, Destroyable, DestructionError, Eventful, FoolProof, Indexable, IterableWeakMap, IterableWeakSet, ReactiveBase, ReactiveError, ReactiveErrorCode, Register, Zone, ZoneAggregator, ZoneHistory, addBatchCleanup, allocated, allocatedValues, arrayEquals, asyncHook, asyncHooks, asyncZone, atomic, biDi, buildReactivityGraph, cache, cached, callOnGC, chainPromise, cleanedBy, cleanup, contentRef, debounce, decorator, deepCompare, deepWatch, defer, deprecated, derived, describe, destructor, effect, effectAggregator, enableDevTools, forwardArray, getActivationLog, getActiveEffect, getActiveProjection, getAt, getState, immutables, isCached, isConstructor, isDevtoolsEnabled, isNonReactive, isOwnAccessor, isReactive, legacyDecorator, memoize, mixin, modernDecorator, named, organize, organized, profileInfo, project, reactive, options as reactiveOptions, register, registerEffectForDebug, registerNativeReactivity, registerObjectForDebug, renamed, resolve, root, scan, setAt, setEffectName, setObjectName, tag, throttle, touched, touched1, trackEffect, unreactive, untracked, unwrap, watch, zip };
1655
- export type { ContextManager, Decorator, DecoratorDescription, DecoratorFactory, DependencyAccess, EventsBase, Evolution, FunctionWrapper, GenericClassDecorator, Hook, LegacyClassDecorator, LegacyPropertyDecorator, Memoizable, MixinClass, MixinFunction, ModernAccessorDecorator, ModernClassDecorator, ModernGetterDecorator, ModernMethodDecorator, ModernSetterDecorator, PromiseChain, ReactivityGraph, Restorer, ScanResult, ScopedCallback };
1391
+ export { ArrayReadForward, DecoratorError, EffectAccess as DependencyAccess, Destroyable, DestructionError, EffectCleanup, EffectOptions, EffectTrigger, Eventful, Evolution, FoolProof, Indexable, IterableWeakMap, IterableWeakSet, ReactiveBase, Register, ScopedCallback, ZoneAggregator, addBatchCleanup, allocated, allocatedValues, arrayEquals, asyncHook, asyncHooks, atomic, attend, biDi, cache, cached, callOnGC, chainPromise, cleanedBy, cleanup, contentRef, debounce, decorator, deepCompare, deepWatch, defer, deprecated, derived, describe, descriptor, destructor, effect, effectAggregator, forwardArray, getActivationLog, getActiveEffect, getActiveProjection, getAt, getState, hooks, immutables, isCached, isConstructor, isNonReactive, isOwnAccessor, isReactive, legacyDecorator, lift, memoize, mixin, modernDecorator, named, onEffectThrow, onEffectTrigger, organize, organized, profileInfo, project, reactive, register, registerNativeReactivity, renamed, reset, root, scan, setAt, tag, throttle, touched, touched1, unreactive, untracked, unwrap, watch, zip };
1392
+ export type { ContextManager, Decorator, DecoratorDescription, DecoratorFactory, EventsBase, GenericClassDecorator, Hook, LegacyClassDecorator, LegacyPropertyDecorator, Memoizable, MixinClass, MixinFunction, ModernAccessorDecorator, ModernClassDecorator, ModernGetterDecorator, ModernMethodDecorator, ModernSetterDecorator, PromiseChain, Restorer, ScanResult };