mutts 1.0.13 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BROWSER_ASYNC_POLYFILL.md +79 -0
- package/README.md +2 -2
- package/dist/browser.cjs +145 -26
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +42 -9
- package/dist/browser.dev.cjs +12 -2
- package/dist/browser.dev.cjs.map +1 -1
- package/dist/browser.dev.d.ts +2 -2
- package/dist/browser.dev.esm.js +2 -2
- package/dist/browser.esm.js +137 -28
- package/dist/browser.esm.js.map +1 -1
- package/dist/chunks/{index-CAdnMJev.cjs → index-BnTNC9eC.cjs} +158 -90
- package/dist/chunks/index-BnTNC9eC.cjs.map +1 -0
- package/dist/chunks/{index-XsYTUhHx.esm.js → index-CAWVZL7P.esm.js} +156 -88
- package/dist/chunks/index-CAWVZL7P.esm.js.map +1 -0
- package/dist/chunks/node-Df_5r_WA.cjs +187 -0
- package/dist/chunks/node-Df_5r_WA.cjs.map +1 -0
- package/dist/chunks/node-DuIduHw3.esm.js +185 -0
- package/dist/chunks/node-DuIduHw3.esm.js.map +1 -0
- package/dist/chunks/{proxy-BtmPFjSr.esm.js → proxy-C2lnvvbx.esm.js} +652 -222
- package/dist/chunks/proxy-C2lnvvbx.esm.js.map +1 -0
- package/dist/chunks/{proxy-DBHj3kGK.cjs → proxy-HA_QQnd5.cjs} +662 -223
- package/dist/chunks/proxy-HA_QQnd5.cjs.map +1 -0
- package/dist/debug.cjs +37 -10
- package/dist/debug.cjs.map +1 -1
- package/dist/debug.esm.js +37 -10
- package/dist/debug.esm.js.map +1 -1
- package/dist/mutts.umd.js +4086 -3469
- package/dist/mutts.umd.js.map +1 -1
- package/dist/mutts.umd.min.js +1 -1
- package/dist/mutts.umd.min.js.map +1 -1
- package/dist/node.cjs +13 -3
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.dev.cjs +13 -3
- package/dist/node.dev.cjs.map +1 -1
- package/dist/node.dev.d.ts +2 -2
- package/dist/node.dev.esm.js +3 -3
- package/dist/node.esm.js +3 -3
- package/dist/types.d.ts +30 -15
- package/docs/ai/api-reference.md +3 -1
- package/docs/ai/manual.md +17 -5
- package/docs/reactive/advanced.md +169 -10
- package/docs/reactive/debugging.md +15 -13
- package/docs/reactive.md +2 -1
- package/package.json +12 -7
- package/dist/chunks/index-CAdnMJev.cjs.map +0 -1
- package/dist/chunks/index-XsYTUhHx.esm.js.map +0 -1
- package/dist/chunks/node-DrrphEPf.cjs +0 -98
- package/dist/chunks/node-DrrphEPf.cjs.map +0 -1
- package/dist/chunks/node-NEZvVo4M.esm.js +0 -96
- package/dist/chunks/node-NEZvVo4M.esm.js.map +0 -1
- package/dist/chunks/proxy-BtmPFjSr.esm.js.map +0 -1
- package/dist/chunks/proxy-DBHj3kGK.cjs.map +0 -1
package/dist/node.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
require('./chunks/node-
|
|
4
|
-
var index = require('./chunks/index-
|
|
5
|
-
var proxy = require('./chunks/proxy-
|
|
3
|
+
require('./chunks/node-Df_5r_WA.cjs');
|
|
4
|
+
var index = require('./chunks/index-BnTNC9eC.cjs');
|
|
5
|
+
var proxy = require('./chunks/proxy-HA_QQnd5.cjs');
|
|
6
6
|
require('node:async_hooks');
|
|
7
7
|
|
|
8
8
|
|
|
@@ -83,6 +83,7 @@ exports.getActivationLog = proxy.getActivationLog;
|
|
|
83
83
|
exports.getActiveEffect = proxy.getActiveEffect;
|
|
84
84
|
exports.getState = proxy.getState;
|
|
85
85
|
exports.hooks = proxy.hooks;
|
|
86
|
+
exports.inert = proxy.inert;
|
|
86
87
|
exports.inheritCaption = proxy.inheritCaption;
|
|
87
88
|
exports.isConstructor = proxy.isConstructor;
|
|
88
89
|
exports.isDev = proxy.isDev;
|
|
@@ -90,26 +91,35 @@ exports.isNonReactive = proxy.isNonReactive;
|
|
|
90
91
|
exports.isObject = proxy.isObject;
|
|
91
92
|
exports.isProd = proxy.isProd;
|
|
92
93
|
exports.isReactive = proxy.isReactive;
|
|
94
|
+
exports.isReactiveBroken = proxy.isReactiveBroken;
|
|
93
95
|
exports.isTest = proxy.isTest;
|
|
94
96
|
exports.legacyDecorator = proxy.legacyDecorator;
|
|
95
97
|
exports.link = proxy.link;
|
|
98
|
+
exports.markRaw = proxy.markRaw;
|
|
99
|
+
exports.markRawProps = proxy.markRawProps;
|
|
96
100
|
exports.mixin = proxy.mixin;
|
|
97
101
|
exports.modernDecorator = proxy.modernDecorator;
|
|
98
102
|
exports.named = proxy.named;
|
|
99
103
|
exports.objectToProxy = proxy.objectToProxy;
|
|
100
104
|
exports.onEffectThrow = proxy.onEffectThrow;
|
|
105
|
+
exports.onReactiveBroken = proxy.onReactiveBroken;
|
|
106
|
+
exports.onReactiveReset = proxy.onReactiveReset;
|
|
101
107
|
exports.prodPreset = proxy.prodPreset;
|
|
102
108
|
exports.proxyToObject = proxy.proxyToObject;
|
|
103
109
|
exports.reactive = proxy.reactive;
|
|
104
110
|
exports.reactiveOptions = proxy.options;
|
|
111
|
+
exports.readonlyReactive = proxy.readonlyReactive;
|
|
105
112
|
exports.reset = proxy.reset;
|
|
106
113
|
exports.root = proxy.root;
|
|
114
|
+
exports.shallowReactive = proxy.shallowReactive;
|
|
107
115
|
exports.tag = proxy.tag;
|
|
116
|
+
exports.toRaw = proxy.toRaw;
|
|
108
117
|
exports.touched = proxy.touched;
|
|
109
118
|
exports.touched1 = proxy.touched1;
|
|
110
119
|
exports.unlink = proxy.unlink;
|
|
111
120
|
exports.untracked = proxy.untracked;
|
|
112
121
|
exports.unwrap = proxy.unwrap;
|
|
113
122
|
exports.withEffectContext = proxy.withEffectContext;
|
|
123
|
+
exports.wrapInert = proxy.wrapInert;
|
|
114
124
|
exports.zip = proxy.zip;
|
|
115
125
|
//# sourceMappingURL=node.cjs.map
|
package/dist/node.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"node.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/node.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { ArrayDiffResult, ArrayReadForward, Captioned, CompareSymbol, ContextManager, Decorator, DecoratorDescription, DecoratorError, DecoratorFactory, Destroyable, DestructionError, EffectContext, Eventful, EventsBase, GenericClassDecorator, Hook, Indexable, IterableWeakMap, IterableWeakSet, LegacyClassDecorator, LegacyPropertyDecorator, Memoizable, MemoizableArgument, MixinClass, MixinFunction, ModernAccessorDecorator, ModernClassDecorator, ModernGetterDecorator, ModernMethodDecorator, ModernSetterDecorator, PromiseChain, ReactiveBase, Resource, Restorer, addBatchCleanup, addUnreactiveProps, allocated, allocatedValues, arrayDiff, arrayEquals, assertUntracked, asyncHook, asyncHooks, atom, atomic, attend, biDi, cache, cached, callOnGC, captioned, captured, caught, chainPromise, createFlavor, debounce, decorator, deepCompare, deepWatch, defer, deprecated, descriptor, destructor, effect, effectAggregator, effectContext, flavorOptions, flavored, forwardArray, getActivationLog, getActiveEffect, getAt, getState, hooks, inheritCaption, isCached, isConstructor, isDev, isNonReactive, isObject, isProd, isTest, legacyDecorator, lift, link, memoize, mixin, modernDecorator, morph, named, onEffectThrow, organize, organized, profileInfo, reactive, reset, resource, root, setAt, tag, throttle, touched, touched1, unlink, unreactive, untracked, watch, when, withEffectContext, zip } from './browser.js';
|
|
2
|
-
export { A as AZone, C as CleanupReason, c as EffectAccess, b as EffectCleanup, d as EffectCloser, g as EffectOptions, E as EffectTrigger, a as Evolution, G as GetterWrapper, H as HistoryValue, P as PropTrigger, R as ReactiveError,
|
|
1
|
+
export { ArrayDiffResult, ArrayReadForward, Captioned, CompareSymbol, ContextManager, Decorator, DecoratorDescription, DecoratorError, DecoratorFactory, Destroyable, DestructionError, EffectContext, Eventful, EventsBase, GenericClassDecorator, Hook, Indexable, IterableWeakMap, IterableWeakSet, LegacyClassDecorator, LegacyPropertyDecorator, Memoizable, MemoizableArgument, MixinClass, MixinFunction, ModernAccessorDecorator, ModernClassDecorator, ModernGetterDecorator, ModernMethodDecorator, ModernSetterDecorator, MorphPosition, PromiseChain, ReactiveBase, Resource, Restorer, addBatchCleanup, addUnreactiveProps, allocated, allocatedValues, arrayDiff, arrayEquals, assertUntracked, asyncHook, asyncHooks, atom, atomic, attend, biDi, cache, cached, callOnGC, captioned, captured, caught, chainPromise, createFlavor, debounce, decorator, deepCompare, deepWatch, defer, deprecated, descriptor, destructor, effect, effectAggregator, effectContext, flavorOptions, flavored, forwardArray, getActivationLog, getActiveEffect, getAt, getState, hooks, inert, inheritCaption, isCached, isConstructor, isDev, isNonReactive, isObject, isProd, isReactiveBroken, isTest, legacyDecorator, lift, link, markRaw, markRawProps, memoize, mixin, modernDecorator, morph, named, onEffectThrow, onReactiveBroken, onReactiveReset, organize, organized, profileInfo, reactive, readonlyReactive, reset, resource, root, setAt, shallowReactive, tag, throttle, touched, touched1, unlink, unreactive, untracked, watch, when, withEffectContext, wrapInert, zip } from './browser.js';
|
|
2
|
+
export { A as AZone, C as CleanupReason, h as CycleHandlingMode, D as DeprecatedCycleHandlingMode, c as EffectAccess, b as EffectCleanup, d as EffectCloser, g as EffectOptions, E as EffectTrigger, a as Evolution, G as GetterWrapper, H as HistoryValue, P as PropTrigger, R as ReactiveError, i as ReactiveErrorCode, j as SchedulerMode, S as ScopedCallback, k as Zone, Z as ZoneAggregator, l as ZoneHistory, m as asyncZone, n as debugPreset, o as devPreset, p as formatCleanupReason, q as isReactive, r as objectToProxy, s as prodPreset, t as proxyToObject, u as reactiveOptions, v as toRaw, w as unwrap } from './types.js';
|
package/dist/node.dev.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
require('./debug.cjs');
|
|
4
|
-
require('./chunks/node-
|
|
5
|
-
var index = require('./chunks/index-
|
|
6
|
-
var proxy = require('./chunks/proxy-
|
|
4
|
+
require('./chunks/node-Df_5r_WA.cjs');
|
|
5
|
+
var index = require('./chunks/index-BnTNC9eC.cjs');
|
|
6
|
+
var proxy = require('./chunks/proxy-HA_QQnd5.cjs');
|
|
7
7
|
require('node:async_hooks');
|
|
8
8
|
|
|
9
9
|
|
|
@@ -84,6 +84,7 @@ exports.getActivationLog = proxy.getActivationLog;
|
|
|
84
84
|
exports.getActiveEffect = proxy.getActiveEffect;
|
|
85
85
|
exports.getState = proxy.getState;
|
|
86
86
|
exports.hooks = proxy.hooks;
|
|
87
|
+
exports.inert = proxy.inert;
|
|
87
88
|
exports.inheritCaption = proxy.inheritCaption;
|
|
88
89
|
exports.isConstructor = proxy.isConstructor;
|
|
89
90
|
exports.isDev = proxy.isDev;
|
|
@@ -91,26 +92,35 @@ exports.isNonReactive = proxy.isNonReactive;
|
|
|
91
92
|
exports.isObject = proxy.isObject;
|
|
92
93
|
exports.isProd = proxy.isProd;
|
|
93
94
|
exports.isReactive = proxy.isReactive;
|
|
95
|
+
exports.isReactiveBroken = proxy.isReactiveBroken;
|
|
94
96
|
exports.isTest = proxy.isTest;
|
|
95
97
|
exports.legacyDecorator = proxy.legacyDecorator;
|
|
96
98
|
exports.link = proxy.link;
|
|
99
|
+
exports.markRaw = proxy.markRaw;
|
|
100
|
+
exports.markRawProps = proxy.markRawProps;
|
|
97
101
|
exports.mixin = proxy.mixin;
|
|
98
102
|
exports.modernDecorator = proxy.modernDecorator;
|
|
99
103
|
exports.named = proxy.named;
|
|
100
104
|
exports.objectToProxy = proxy.objectToProxy;
|
|
101
105
|
exports.onEffectThrow = proxy.onEffectThrow;
|
|
106
|
+
exports.onReactiveBroken = proxy.onReactiveBroken;
|
|
107
|
+
exports.onReactiveReset = proxy.onReactiveReset;
|
|
102
108
|
exports.prodPreset = proxy.prodPreset;
|
|
103
109
|
exports.proxyToObject = proxy.proxyToObject;
|
|
104
110
|
exports.reactive = proxy.reactive;
|
|
105
111
|
exports.reactiveOptions = proxy.options;
|
|
112
|
+
exports.readonlyReactive = proxy.readonlyReactive;
|
|
106
113
|
exports.reset = proxy.reset;
|
|
107
114
|
exports.root = proxy.root;
|
|
115
|
+
exports.shallowReactive = proxy.shallowReactive;
|
|
108
116
|
exports.tag = proxy.tag;
|
|
117
|
+
exports.toRaw = proxy.toRaw;
|
|
109
118
|
exports.touched = proxy.touched;
|
|
110
119
|
exports.touched1 = proxy.touched1;
|
|
111
120
|
exports.unlink = proxy.unlink;
|
|
112
121
|
exports.untracked = proxy.untracked;
|
|
113
122
|
exports.unwrap = proxy.unwrap;
|
|
114
123
|
exports.withEffectContext = proxy.withEffectContext;
|
|
124
|
+
exports.wrapInert = proxy.wrapInert;
|
|
115
125
|
exports.zip = proxy.zip;
|
|
116
126
|
//# sourceMappingURL=node.dev.cjs.map
|
package/dist/node.dev.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.dev.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"node.dev.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/node.dev.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { A as AZone, C as CleanupReason, c as EffectAccess, b as EffectCleanup, d as EffectCloser, g as EffectOptions, E as EffectTrigger, a as Evolution, G as GetterWrapper, H as HistoryValue, P as PropTrigger, R as ReactiveError,
|
|
2
|
-
export { ArrayDiffResult, ArrayReadForward, Captioned, CompareSymbol, ContextManager, Decorator, DecoratorDescription, DecoratorError, DecoratorFactory, Destroyable, DestructionError, EffectContext, Eventful, EventsBase, GenericClassDecorator, Hook, Indexable, IterableWeakMap, IterableWeakSet, LegacyClassDecorator, LegacyPropertyDecorator, Memoizable, MemoizableArgument, MixinClass, MixinFunction, ModernAccessorDecorator, ModernClassDecorator, ModernGetterDecorator, ModernMethodDecorator, ModernSetterDecorator, PromiseChain, ReactiveBase, Resource, Restorer, addBatchCleanup, addUnreactiveProps, allocated, allocatedValues, arrayDiff, arrayEquals, assertUntracked, asyncHook, asyncHooks, atom, atomic, attend, biDi, cache, cached, callOnGC, captioned, captured, caught, chainPromise, createFlavor, debounce, decorator, deepCompare, deepWatch, defer, deprecated, descriptor, destructor, effect, effectAggregator, effectContext, flavorOptions, flavored, forwardArray, getActivationLog, getActiveEffect, getAt, getState, hooks, inheritCaption, isCached, isConstructor, isDev, isNonReactive, isObject, isProd, isTest, legacyDecorator, lift, link, memoize, mixin, modernDecorator, morph, named, onEffectThrow, organize, organized, profileInfo, reactive, reset, resource, root, setAt, tag, throttle, touched, touched1, unlink, unreactive, untracked, watch, when, withEffectContext, zip } from './browser.js';
|
|
1
|
+
export { A as AZone, C as CleanupReason, h as CycleHandlingMode, D as DeprecatedCycleHandlingMode, c as EffectAccess, b as EffectCleanup, d as EffectCloser, g as EffectOptions, E as EffectTrigger, a as Evolution, G as GetterWrapper, H as HistoryValue, P as PropTrigger, R as ReactiveError, i as ReactiveErrorCode, j as SchedulerMode, S as ScopedCallback, k as Zone, Z as ZoneAggregator, l as ZoneHistory, m as asyncZone, n as debugPreset, o as devPreset, p as formatCleanupReason, q as isReactive, r as objectToProxy, s as prodPreset, t as proxyToObject, u as reactiveOptions, v as toRaw, w as unwrap } from './types.js';
|
|
2
|
+
export { ArrayDiffResult, ArrayReadForward, Captioned, CompareSymbol, ContextManager, Decorator, DecoratorDescription, DecoratorError, DecoratorFactory, Destroyable, DestructionError, EffectContext, Eventful, EventsBase, GenericClassDecorator, Hook, Indexable, IterableWeakMap, IterableWeakSet, LegacyClassDecorator, LegacyPropertyDecorator, Memoizable, MemoizableArgument, MixinClass, MixinFunction, ModernAccessorDecorator, ModernClassDecorator, ModernGetterDecorator, ModernMethodDecorator, ModernSetterDecorator, MorphPosition, PromiseChain, ReactiveBase, Resource, Restorer, addBatchCleanup, addUnreactiveProps, allocated, allocatedValues, arrayDiff, arrayEquals, assertUntracked, asyncHook, asyncHooks, atom, atomic, attend, biDi, cache, cached, callOnGC, captioned, captured, caught, chainPromise, createFlavor, debounce, decorator, deepCompare, deepWatch, defer, deprecated, descriptor, destructor, effect, effectAggregator, effectContext, flavorOptions, flavored, forwardArray, getActivationLog, getActiveEffect, getAt, getState, hooks, inert, inheritCaption, isCached, isConstructor, isDev, isNonReactive, isObject, isProd, isReactiveBroken, isTest, legacyDecorator, lift, link, markRaw, markRawProps, memoize, mixin, modernDecorator, morph, named, onEffectThrow, onReactiveBroken, onReactiveReset, organize, organized, profileInfo, reactive, readonlyReactive, reset, resource, root, setAt, shallowReactive, tag, throttle, touched, touched1, unlink, unreactive, untracked, watch, when, withEffectContext, wrapInert, zip } from './browser.js';
|
package/dist/node.dev.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import './debug.esm.js';
|
|
2
|
-
import './chunks/node-
|
|
3
|
-
export { A as ArrayReadForward, D as Destroyable, a as DestructionError, E as Eventful, I as Indexable, b as allocated, c as allocatedValues, d as arrayDiff, e as attend, f as cache, g as cached, h as callOnGC, i as chainPromise, j as debounce, k as deepWatch, l as deprecated, m as descriptor, n as destructor, o as forwardArray, p as getAt, q as isCached, r as lift, s as memoize, t as morph, u as organize, v as organized, w as profileInfo, x as resource, y as setAt, z as throttle, B as unreactive, C as watch, F as when } from './chunks/index-
|
|
4
|
-
export { A as AZone, C as CompareSymbol, D as DecoratorError, I as IterableWeakMap, a as IterableWeakSet, R as ReactiveBase, b as ReactiveError, c as ReactiveErrorCode, Z as Zone, d as ZoneAggregator, e as ZoneHistory, f as addBatchCleanup, g as addUnreactiveProps, h as arrayEquals, i as assertUntracked, j as asyncHook, k as asyncHooks, l as asyncZone, m as atom, n as atomic, o as biDi, p as captioned, q as captured, r as caught, s as createFlavor, t as debugPreset, u as decorator, v as deepCompare, w as defer, x as devPreset, y as effect, z as effectAggregator, B as effectContext, E as flavorOptions, F as flavored, G as formatCleanupReason, H as getActivationLog, J as getActiveEffect, K as getState, L as hooks, M as
|
|
2
|
+
import './chunks/node-DuIduHw3.esm.js';
|
|
3
|
+
export { A as ArrayReadForward, D as Destroyable, a as DestructionError, E as Eventful, I as Indexable, b as allocated, c as allocatedValues, d as arrayDiff, e as attend, f as cache, g as cached, h as callOnGC, i as chainPromise, j as debounce, k as deepWatch, l as deprecated, m as descriptor, n as destructor, o as forwardArray, p as getAt, q as isCached, r as lift, s as memoize, t as morph, u as organize, v as organized, w as profileInfo, x as resource, y as setAt, z as throttle, B as unreactive, C as watch, F as when } from './chunks/index-CAWVZL7P.esm.js';
|
|
4
|
+
export { A as AZone, C as CompareSymbol, D as DecoratorError, I as IterableWeakMap, a as IterableWeakSet, R as ReactiveBase, b as ReactiveError, c as ReactiveErrorCode, Z as Zone, d as ZoneAggregator, e as ZoneHistory, f as addBatchCleanup, g as addUnreactiveProps, h as arrayEquals, i as assertUntracked, j as asyncHook, k as asyncHooks, l as asyncZone, m as atom, n as atomic, o as biDi, p as captioned, q as captured, r as caught, s as createFlavor, t as debugPreset, u as decorator, v as deepCompare, w as defer, x as devPreset, y as effect, z as effectAggregator, B as effectContext, E as flavorOptions, F as flavored, G as formatCleanupReason, H as getActivationLog, J as getActiveEffect, K as getState, L as hooks, M as inert, N as inheritCaption, O as isConstructor, P as isDev, Q as isNonReactive, S as isObject, T as isProd, U as isReactive, V as isReactiveBroken, W as isTest, X as legacyDecorator, Y as link, _ as markRaw, $ as markRawProps, a0 as mixin, a1 as modernDecorator, a2 as named, a3 as objectToProxy, a4 as onEffectThrow, a5 as onReactiveBroken, a6 as onReactiveReset, a7 as prodPreset, a8 as proxyToObject, a9 as reactive, aa as reactiveOptions, ab as readonlyReactive, ac as reset, ad as root, ae as shallowReactive, af as tag, ag as toRaw, ah as touched, ai as touched1, aj as unlink, ak as untracked, al as unwrap, am as withEffectContext, an as wrapInert, ao as zip } from './chunks/proxy-C2lnvvbx.esm.js';
|
|
5
5
|
import 'node:async_hooks';
|
|
6
6
|
//# sourceMappingURL=node.dev.esm.js.map
|
package/dist/node.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import './chunks/node-
|
|
2
|
-
export { A as ArrayReadForward, D as Destroyable, a as DestructionError, E as Eventful, I as Indexable, b as allocated, c as allocatedValues, d as arrayDiff, e as attend, f as cache, g as cached, h as callOnGC, i as chainPromise, j as debounce, k as deepWatch, l as deprecated, m as descriptor, n as destructor, o as forwardArray, p as getAt, q as isCached, r as lift, s as memoize, t as morph, u as organize, v as organized, w as profileInfo, x as resource, y as setAt, z as throttle, B as unreactive, C as watch, F as when } from './chunks/index-
|
|
3
|
-
export { A as AZone, C as CompareSymbol, D as DecoratorError, I as IterableWeakMap, a as IterableWeakSet, R as ReactiveBase, b as ReactiveError, c as ReactiveErrorCode, Z as Zone, d as ZoneAggregator, e as ZoneHistory, f as addBatchCleanup, g as addUnreactiveProps, h as arrayEquals, i as assertUntracked, j as asyncHook, k as asyncHooks, l as asyncZone, m as atom, n as atomic, o as biDi, p as captioned, q as captured, r as caught, s as createFlavor, t as debugPreset, u as decorator, v as deepCompare, w as defer, x as devPreset, y as effect, z as effectAggregator, B as effectContext, E as flavorOptions, F as flavored, G as formatCleanupReason, H as getActivationLog, J as getActiveEffect, K as getState, L as hooks, M as
|
|
1
|
+
import './chunks/node-DuIduHw3.esm.js';
|
|
2
|
+
export { A as ArrayReadForward, D as Destroyable, a as DestructionError, E as Eventful, I as Indexable, b as allocated, c as allocatedValues, d as arrayDiff, e as attend, f as cache, g as cached, h as callOnGC, i as chainPromise, j as debounce, k as deepWatch, l as deprecated, m as descriptor, n as destructor, o as forwardArray, p as getAt, q as isCached, r as lift, s as memoize, t as morph, u as organize, v as organized, w as profileInfo, x as resource, y as setAt, z as throttle, B as unreactive, C as watch, F as when } from './chunks/index-CAWVZL7P.esm.js';
|
|
3
|
+
export { A as AZone, C as CompareSymbol, D as DecoratorError, I as IterableWeakMap, a as IterableWeakSet, R as ReactiveBase, b as ReactiveError, c as ReactiveErrorCode, Z as Zone, d as ZoneAggregator, e as ZoneHistory, f as addBatchCleanup, g as addUnreactiveProps, h as arrayEquals, i as assertUntracked, j as asyncHook, k as asyncHooks, l as asyncZone, m as atom, n as atomic, o as biDi, p as captioned, q as captured, r as caught, s as createFlavor, t as debugPreset, u as decorator, v as deepCompare, w as defer, x as devPreset, y as effect, z as effectAggregator, B as effectContext, E as flavorOptions, F as flavored, G as formatCleanupReason, H as getActivationLog, J as getActiveEffect, K as getState, L as hooks, M as inert, N as inheritCaption, O as isConstructor, P as isDev, Q as isNonReactive, S as isObject, T as isProd, U as isReactive, V as isReactiveBroken, W as isTest, X as legacyDecorator, Y as link, _ as markRaw, $ as markRawProps, a0 as mixin, a1 as modernDecorator, a2 as named, a3 as objectToProxy, a4 as onEffectThrow, a5 as onReactiveBroken, a6 as onReactiveReset, a7 as prodPreset, a8 as proxyToObject, a9 as reactive, aa as reactiveOptions, ab as readonlyReactive, ac as reset, ad as root, ae as shallowReactive, af as tag, ag as toRaw, ah as touched, ai as touched1, aj as unlink, ak as untracked, al as unwrap, am as withEffectContext, an as wrapInert, ao as zip } from './chunks/proxy-C2lnvvbx.esm.js';
|
|
4
4
|
import 'node:async_hooks';
|
|
5
5
|
//# sourceMappingURL=node.esm.js.map
|
package/dist/types.d.ts
CHANGED
|
@@ -278,6 +278,9 @@ declare class ReactiveError extends Error {
|
|
|
278
278
|
get code(): ReactiveErrorCode | undefined;
|
|
279
279
|
get cause(): any;
|
|
280
280
|
}
|
|
281
|
+
type SchedulerMode = 'raw' | 'ordered' | 'debug';
|
|
282
|
+
type DeprecatedCycleHandlingMode = 'production' | 'development' | 'debug';
|
|
283
|
+
type CycleHandlingMode = SchedulerMode | DeprecatedCycleHandlingMode;
|
|
281
284
|
/**
|
|
282
285
|
* Global options for the reactive system
|
|
283
286
|
*/
|
|
@@ -367,22 +370,33 @@ declare const options: {
|
|
|
367
370
|
*/
|
|
368
371
|
onMemoizationDiscrepancy: ((cached: any, fresh: any, fn: Function, args: any[], cause: "calculation" | "comparison") => void) | undefined;
|
|
369
372
|
/**
|
|
370
|
-
*
|
|
373
|
+
* Effect scheduler mode.
|
|
371
374
|
*
|
|
372
|
-
* - `'
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
+
* - `'ordered'` (Default): maintains the causal effect graph so effects that are already
|
|
376
|
+
* queued together can run in dependency order. It also preserves parent/child effect
|
|
377
|
+
* lifecycle ordering and catches cycles eagerly when edges are created.
|
|
375
378
|
*
|
|
376
|
-
* - `'
|
|
377
|
-
*
|
|
378
|
-
* basic path information. Good balance of debugging help with moderate overhead.
|
|
379
|
+
* - `'raw'`: fastest FIFO scheduler. It does not maintain the effect graph.
|
|
380
|
+
* Cycle detection is heuristic, using maxEffectChain execution counts.
|
|
379
381
|
*
|
|
380
|
-
* - `'debug'`:
|
|
381
|
-
*
|
|
382
|
+
* - `'debug'`: ordered scheduling plus the most detailed graph diagnostics. Highest overhead,
|
|
383
|
+
* best for investigation.
|
|
382
384
|
*
|
|
383
|
-
* @default '
|
|
385
|
+
* @default 'ordered'
|
|
384
386
|
*/
|
|
385
|
-
|
|
387
|
+
scheduler: SchedulerMode;
|
|
388
|
+
/**
|
|
389
|
+
* @deprecated Use `scheduler` instead.
|
|
390
|
+
*
|
|
391
|
+
* Backward-compatible alias for older names:
|
|
392
|
+
* - `'production'` maps to `scheduler = 'raw'`
|
|
393
|
+
* - `'development'` maps to `scheduler = 'ordered'`
|
|
394
|
+
* - `'debug'` maps to `scheduler = 'debug'`
|
|
395
|
+
*
|
|
396
|
+
* The new names describe scheduler behavior rather than runtime environment.
|
|
397
|
+
*/
|
|
398
|
+
get cycleHandling(): SchedulerMode;
|
|
399
|
+
set cycleHandling(mode: CycleHandlingMode);
|
|
386
400
|
/**
|
|
387
401
|
* Internal flag used by memoization discrepancy detector to avoid counting calls in tests
|
|
388
402
|
* @warning Do not modify this flag manually, this flag is given by the engine
|
|
@@ -455,18 +469,19 @@ declare const options: {
|
|
|
455
469
|
logErrors: boolean;
|
|
456
470
|
enableHistory: boolean;
|
|
457
471
|
historySize: number;
|
|
458
|
-
} |
|
|
472
|
+
} | undefined;
|
|
459
473
|
};
|
|
460
474
|
/** Production preset: no introspection, heuristic cycle detection, minimal overhead */
|
|
461
475
|
declare const prodPreset: Partial<typeof options>;
|
|
462
|
-
/** Development preset
|
|
476
|
+
/** Development preset: introspection on, early cycle detection, warnings */
|
|
463
477
|
declare const devPreset: Partial<typeof options>;
|
|
464
478
|
/** Debug preset: full diagnostics, throws on violations, rich lineage capture */
|
|
465
479
|
declare const debugPreset: Partial<typeof options>;
|
|
466
480
|
declare const objectToProxy: WeakMap<object, object>;
|
|
467
481
|
declare const proxyToObject: WeakMap<object, object>;
|
|
468
482
|
declare function unwrap<T>(obj: T): T;
|
|
483
|
+
declare const toRaw: typeof unwrap;
|
|
469
484
|
declare function isReactive(obj: any): boolean;
|
|
470
485
|
|
|
471
|
-
export { AZone as A, ReactiveError as R, ZoneAggregator as Z, ReactiveErrorCode as
|
|
472
|
-
export type { CleanupReason as C, EffectTrigger as E, GetterWrapper as G, HistoryValue as H, PropTrigger as P, ScopedCallback as S, Evolution as a, EffectCleanup as b, EffectAccess as c, EffectCloser as d, State as e, CatchFunction as f, EffectOptions as g };
|
|
486
|
+
export { AZone as A, ReactiveError as R, ZoneAggregator as Z, ReactiveErrorCode as i, Zone as k, ZoneHistory as l, asyncZone as m, debugPreset as n, devPreset as o, formatCleanupReason as p, isReactive as q, objectToProxy as r, prodPreset as s, proxyToObject as t, options as u, toRaw as v, unwrap as w };
|
|
487
|
+
export type { CleanupReason as C, DeprecatedCycleHandlingMode as D, EffectTrigger as E, GetterWrapper as G, HistoryValue as H, PropTrigger as P, ScopedCallback as S, Evolution as a, EffectCleanup as b, EffectAccess as c, EffectCloser as d, State as e, CatchFunction as f, EffectOptions as g, CycleHandlingMode as h, SchedulerMode as j };
|
package/docs/ai/api-reference.md
CHANGED
|
@@ -185,7 +185,9 @@ export declare function deprecated(message?: string): Function;
|
|
|
185
185
|
// buildReactivityGraph, getMutationHistory, getDependents, getDependencies, etc.
|
|
186
186
|
|
|
187
187
|
export declare const reactiveOptions: {
|
|
188
|
-
|
|
188
|
+
scheduler: 'raw' | 'ordered' | 'debug';
|
|
189
|
+
/** @deprecated Use scheduler instead. */
|
|
190
|
+
cycleHandling: 'raw' | 'ordered' | 'debug' | 'production' | 'development';
|
|
189
191
|
introspection: unknown;
|
|
190
192
|
};
|
|
191
193
|
|
package/docs/ai/manual.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## 1. MENTAL MODEL
|
|
8
8
|
|
|
9
|
-
Proxy-based **fine-grained reactivity** — changes propagate synchronously through dependency-tracked effects. No VDOM, no scheduler, no hooks.
|
|
9
|
+
Proxy-based **fine-grained reactivity** — changes propagate synchronously through dependency-tracked effects. No VDOM, no async render scheduler, no hooks.
|
|
10
10
|
|
|
11
11
|
| Concept | Mutts |
|
|
12
12
|
|---------|-------|
|
|
@@ -202,6 +202,8 @@ const updateBoth = atomic((a, b) => { state.a = a; state.b = b }) // effects fir
|
|
|
202
202
|
// Decorator: @atomic on methods
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
+
`atomic()` wraps for later invocation but still executes synchronously when called. Internally it behaves like `batch(fn, { immediate: true })`, so nested atomic calls join the active batch by default instead of creating an implicit child batch.
|
|
206
|
+
|
|
205
207
|
### 3.7 atom() — Immediate atomic execution
|
|
206
208
|
|
|
207
209
|
```ts
|
|
@@ -209,6 +211,16 @@ atom(() => { state.a = 1; state.b = 2 }) // runs now, effects fire once
|
|
|
209
211
|
// Unlike atomic() which wraps for later, atom() executes immediately
|
|
210
212
|
```
|
|
211
213
|
|
|
214
|
+
The explicit batching API is now:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
batch(fnOrEffects, { immediate?: boolean, contained?: boolean, caller?: EffectTrigger })
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
- `batch(fn)` joins the current batch when nested
|
|
221
|
+
- `batch(fn, { immediate: true })` runs `fn` now and queues its consequences into the active batch
|
|
222
|
+
- `batch(fn, { contained: true })` creates an isolated nested batch that flushes before returning
|
|
223
|
+
|
|
212
224
|
### 3.8 defer() — Avoid cycles
|
|
213
225
|
|
|
214
226
|
```ts
|
|
@@ -396,10 +408,10 @@ effect(() => {
|
|
|
396
408
|
```ts
|
|
397
409
|
import { reactiveOptions } from 'mutts'
|
|
398
410
|
|
|
399
|
-
//
|
|
400
|
-
reactiveOptions.
|
|
401
|
-
reactiveOptions.
|
|
402
|
-
reactiveOptions.
|
|
411
|
+
// Scheduler / cycle detection
|
|
412
|
+
reactiveOptions.scheduler = 'ordered' // default: causal graph ordering, eager cycles
|
|
413
|
+
reactiveOptions.scheduler = 'raw' // fastest FIFO mode, heuristic cycles
|
|
414
|
+
reactiveOptions.scheduler = 'debug' // ordered mode plus heavier diagnostics
|
|
403
415
|
|
|
404
416
|
// Lifecycle hooks (all wrapped via optionCall for safety)
|
|
405
417
|
reactiveOptions.enter = (effect) => {} // before effect runs
|
|
@@ -45,7 +45,7 @@ The wrapped function preserves its signature (parameters and return value), and
|
|
|
45
45
|
|
|
46
46
|
### `atom()` - Immediate Atomic Execution
|
|
47
47
|
|
|
48
|
-
While `atomic()` **wraps** a function for later calls, `atom()` **runs** a function immediately and atomically. It
|
|
48
|
+
While `atomic()` **wraps** a function for later calls, `atom()` **runs** a function immediately and atomically. It uses `batch(fn, { immediate: true })`, so it executes right away even inside an existing batch while still contributing its triggered effects to the active transaction.
|
|
49
49
|
|
|
50
50
|
```typescript
|
|
51
51
|
import { atom, reactive, effect } from 'mutts'
|
|
@@ -80,6 +80,122 @@ const update = atomic((a, b) => { state.a = a; state.b = b })
|
|
|
80
80
|
update(1, 2) // runs when called
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
### `batch()` - Explicit Batch Control
|
|
84
|
+
|
|
85
|
+
`batch()` now uses an options object:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
batch(effectOrEffects, {
|
|
89
|
+
immediate?: boolean,
|
|
90
|
+
contained?: boolean,
|
|
91
|
+
caller?: EffectTrigger,
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The main modes are:
|
|
96
|
+
|
|
97
|
+
- default nested behavior: if a batch is already active, `batch(fn)` joins that existing batch instead of creating an implicit child batch
|
|
98
|
+
- `immediate: true`: execute the provided function now, but keep all triggered effects inside the current batch
|
|
99
|
+
- `contained: true`: force a fresh local batch that drains before returning, even when called from inside another batch
|
|
100
|
+
- `caller`: advanced internal override for causal chaining; most user code should omit it
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { batch, effect, reactive } from 'mutts'
|
|
104
|
+
|
|
105
|
+
const state = reactive({ a: 0, b: 0 })
|
|
106
|
+
|
|
107
|
+
effect(() => {
|
|
108
|
+
console.log(state.a, state.b)
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
batch(() => {
|
|
112
|
+
state.a = 1
|
|
113
|
+
state.b = 2
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
batch(() => {
|
|
117
|
+
state.a = 3
|
|
118
|
+
}, { immediate: true })
|
|
119
|
+
|
|
120
|
+
batch(() => {
|
|
121
|
+
state.b = 4
|
|
122
|
+
}, { immediate: true, contained: true })
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
#### Nested semantics
|
|
126
|
+
|
|
127
|
+
Nested batching is no longer implicitly contained.
|
|
128
|
+
|
|
129
|
+
- `batch(fn)` inside another batch joins the parent batch
|
|
130
|
+
- `batch(fn, { immediate: true })` runs `fn` now and queues its consequences into the parent batch
|
|
131
|
+
- `batch(fn, { contained: true })` creates an isolated sub-batch and flushes it before returning
|
|
132
|
+
|
|
133
|
+
Use `contained: true` only when you explicitly need sub-transaction behavior.
|
|
134
|
+
|
|
135
|
+
### Effect Ordering with Phase Tokens
|
|
136
|
+
|
|
137
|
+
Effects are usually ordered by their data dependencies: an effect that reads a reactive property is eligible to re-run after another effect changes that property. Mutts uses those causal links as an execution graph by default. The `reactiveOptions.scheduler` option controls how much of that graph is maintained for scheduling and diagnostics:
|
|
138
|
+
|
|
139
|
+
- `scheduler: 'ordered'` (default): effects that are already queued together are processed in dependency order when possible, so consequences run after the effects that caused them. Parent effects also run before their queued child effects, which lets parent cleanup stop stale children before they re-run.
|
|
140
|
+
- `scheduler: 'debug'`: ordered scheduling plus heavier diagnostics for investigation.
|
|
141
|
+
- `scheduler: 'raw'`: graph maintenance is disabled for speed, and already-queued effects use FIFO ordering with heuristic cycle protection.
|
|
142
|
+
|
|
143
|
+
When you need to make a render phase or other side-effect phase explicit, use an ordinary reactive "phase token": one effect advances the token, and later effects read it.
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { effect, reactive } from 'mutts'
|
|
147
|
+
|
|
148
|
+
const phase = reactive({
|
|
149
|
+
measured: 0,
|
|
150
|
+
positioned: 0,
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
effect`render:measure`(() => {
|
|
154
|
+
measureDom()
|
|
155
|
+
phase.measured++
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
effect`render:position`(() => {
|
|
159
|
+
phase.measured
|
|
160
|
+
positionDom()
|
|
161
|
+
phase.positioned++
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
effect`render:paint`(() => {
|
|
165
|
+
phase.positioned
|
|
166
|
+
paintDom()
|
|
167
|
+
})
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
This is sometimes called a beacon, barrier, or phase marker in application code, but it does not need a special primitive: the token is just reactive state. The important part is that the dependency is visible. The second effect does not merely rely on incidental registration order; it declares "I am downstream of `phase.measured`."
|
|
171
|
+
|
|
172
|
+
This phase-token pattern also works in `scheduler: 'raw'` when the token is the downstream effect's actual scheduling dependency: the producer runs, advances the token, and that write queues the consumer afterward. That ordering comes from normal queuing, not from the dependency graph. What raw mode does not do is topologically reorder two effects that were already queued independently by some other write.
|
|
173
|
+
|
|
174
|
+
If the downstream effect should be scheduled only by the phase token, and not directly by the raw state used by the producer, read the raw payload untracked:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { effect, reactive, untracked } from 'mutts'
|
|
178
|
+
|
|
179
|
+
const state = reactive({ input: '' })
|
|
180
|
+
const phase = reactive({ rendered: 0 })
|
|
181
|
+
|
|
182
|
+
effect`render:first-pass`(() => {
|
|
183
|
+
state.input
|
|
184
|
+
renderFirstPass()
|
|
185
|
+
phase.rendered++
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
effect`render:second-pass`(() => {
|
|
189
|
+
phase.rendered
|
|
190
|
+
|
|
191
|
+
untracked`render:second-pass:payload`(() => {
|
|
192
|
+
renderSecondPass(state.input)
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Use `defer()` instead when the desired ordering is "after the whole current batch has settled" rather than "after this producer effect advances this phase."
|
|
198
|
+
|
|
83
199
|
### `addBatchCleanup()` / `defer()` - Deferring Work to Avoid Cycles
|
|
84
200
|
|
|
85
201
|
When an effect needs to perform an action that would modify state the effect depends on, this can create a reactive cycle. The `addBatchCleanup` function (also exported as `defer` for semantic clarity) allows you to defer such work until after the current batch of effects completes.
|
|
@@ -238,7 +354,7 @@ addBatchCleanup(() => {
|
|
|
238
354
|
|
|
239
355
|
**Nested Batches:**
|
|
240
356
|
|
|
241
|
-
Callbacks added in nested batches are collected and run when the **outermost batch** completes:
|
|
357
|
+
Callbacks added in inherited nested batches are collected and run when the **outermost batch** completes:
|
|
242
358
|
|
|
243
359
|
```typescript
|
|
244
360
|
effect(() => {
|
|
@@ -252,7 +368,15 @@ effect(() => {
|
|
|
252
368
|
// Output:
|
|
253
369
|
// Outer deferred
|
|
254
370
|
// Inner deferred
|
|
255
|
-
// (Both run after outer batch completes)
|
|
371
|
+
// (Both run after outer batch completes because `atomic()` joins the active batch)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
If you need deferred callbacks to flush within an isolated nested batch, use an explicitly contained batch:
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
batch(() => {
|
|
378
|
+
addBatchCleanup(() => console.log('Contained deferred'))
|
|
379
|
+
}, { contained: true })
|
|
256
380
|
```
|
|
257
381
|
|
|
258
382
|
**Error Handling:**
|
|
@@ -935,7 +1059,7 @@ When you replace a reactive object with another object that shares the same prot
|
|
|
935
1059
|
|
|
936
1060
|
- Watchers attached to the container are *not* re-fired if the container's prototype did not change (this avoids unnecessary parent effect re-runs).
|
|
937
1061
|
- Watchers attached to nested properties are re-evaluated only for keys that actually changed (added, removed, or whose values differ).
|
|
938
|
-
- For arrays, the
|
|
1062
|
+
- For arrays, the behavior stays index-oriented: replacing an element at index `i` fires a touch for that index (and `length` if needed) rather than diffing the element recursively. This preserves reorder detection.
|
|
939
1063
|
- Prototype chain properties are compared when both objects have prototype chains, ensuring changes to prototype-level properties are detected.
|
|
940
1064
|
|
|
941
1065
|
**Integration with Prototype Chains:**
|
|
@@ -981,7 +1105,7 @@ expect(titleWatcher).toHaveBeenCalledTimes(2)
|
|
|
981
1105
|
expect(viewsWatcher).toHaveBeenCalledTimes(2)
|
|
982
1106
|
```
|
|
983
1107
|
|
|
984
|
-
This
|
|
1108
|
+
This behavior keeps container-level watchers stable while still delivering fine-grained updates to nested effects—ideal when you replace data structures with freshly fetched objects that share the same prototype.
|
|
985
1109
|
|
|
986
1110
|
### Origin Filtering
|
|
987
1111
|
|
|
@@ -1243,17 +1367,36 @@ state.items = fetchedItems // deep touch diffs old vs new per-index — no lift
|
|
|
1243
1367
|
```typescript
|
|
1244
1368
|
import { morph } from 'mutts'
|
|
1245
1369
|
|
|
1370
|
+
// Arrays: (item, position, access?) => O
|
|
1246
1371
|
function morph<I, O>(
|
|
1247
1372
|
source: readonly I[] | (() => readonly I[]),
|
|
1248
|
-
fn: (arg: I) => O,
|
|
1373
|
+
fn: (arg: I, position: { index: number }, access?: EffectAccess) => O,
|
|
1249
1374
|
options?: { pure?: boolean | ((i: I) => boolean) }
|
|
1250
1375
|
): O[]
|
|
1376
|
+
|
|
1377
|
+
// Maps: (value, key, access?) => O
|
|
1378
|
+
function morph<K, V, O>(
|
|
1379
|
+
source: Map<K, V>,
|
|
1380
|
+
fn: (arg: V, key: K, access?: EffectAccess) => O,
|
|
1381
|
+
options?: { pure?: boolean | ((i: V) => boolean) }
|
|
1382
|
+
): Map<K, O>
|
|
1383
|
+
|
|
1384
|
+
// Records: (value, key, access?) => O
|
|
1385
|
+
function morph<S extends Record<PropertyKey, any>, O>(
|
|
1386
|
+
source: S,
|
|
1387
|
+
fn: (arg: S[keyof S], key: keyof S, access?: EffectAccess) => O,
|
|
1388
|
+
options?: { pure?: boolean | ((i: S[keyof S]) => boolean) }
|
|
1389
|
+
): { [K in keyof S]: O }
|
|
1251
1390
|
```
|
|
1252
1391
|
|
|
1253
1392
|
**Parameters**
|
|
1254
1393
|
|
|
1255
|
-
- `source`: a reactive array or a function returning one. Array mutations are tracked via `arrayDiff`.
|
|
1256
|
-
- `fn`: mapping callback.
|
|
1394
|
+
- `source`: a reactive array, Map, or record, or a function returning one. Array mutations are tracked via `arrayDiff`.
|
|
1395
|
+
- `fn`: mapping callback. Signature varies by source type:
|
|
1396
|
+
- Arrays: `(item, position, access?) => O` where `position.index` is the current index
|
|
1397
|
+
- Maps: `(value, key, access?) => O`
|
|
1398
|
+
- Records: `(value, key, access?) => O`
|
|
1399
|
+
In the default (non-pure) mode, each element's computation runs inside its own effect, so reactive reads inside `fn` are tracked and will invalidate that element's cache when they change.
|
|
1257
1400
|
- `options.pure`: controls per-item effect creation. `true` skips effects for all items (same as `morph.pure`). A **predicate function** `(i: I) => boolean` decides per-item: return `true` to skip the effect (pure), `false` to create one (reactive). The predicate receives the input item and is evaluated once per cache slot on first access.
|
|
1258
1401
|
|
|
1259
1402
|
**Behaviour**
|
|
@@ -1261,6 +1404,7 @@ function morph<I, O>(
|
|
|
1261
1404
|
- **Lazy**: elements are only computed when accessed (e.g. `result[0]`). Unaccessed indices remain `undefined` in the cache.
|
|
1262
1405
|
- **Identity stable**: the returned reactive array proxy is the same object across source mutations. Only affected indices are invalidated.
|
|
1263
1406
|
- **Per-item effects** (default): each accessed element gets its own effect. If `fn` reads reactive values beyond its argument, changes to those values invalidate and recompute only the affected elements.
|
|
1407
|
+
- **Reactive position**: For arrays, the `position` object is stable per item and its `index` updates reactively when items move due to shifts/reorders.
|
|
1264
1408
|
- **Cleanup**: the returned array is `cleanedBy` the internal morph effect. When the parent effect is disposed, the morph effect and all per-item effects are cleaned up.
|
|
1265
1409
|
|
|
1266
1410
|
**Basic usage**
|
|
@@ -1281,6 +1425,21 @@ console.log(upper[3]) // "DAVE"
|
|
|
1281
1425
|
items.splice(1, 1) // Remove 'bob' — indices shift, cache invalidated for affected positions
|
|
1282
1426
|
```
|
|
1283
1427
|
|
|
1428
|
+
**Using position.index**
|
|
1429
|
+
|
|
1430
|
+
```typescript
|
|
1431
|
+
const items = reactive(['a', 'b', 'c'])
|
|
1432
|
+
const indexed = morph(items, (item, position) => `${item}@${position.index}`)
|
|
1433
|
+
|
|
1434
|
+
console.log(indexed[0]) // "a@0"
|
|
1435
|
+
console.log(indexed[1]) // "b@1"
|
|
1436
|
+
|
|
1437
|
+
items.unshift('x') // Insert at beginning
|
|
1438
|
+
console.log(indexed[0]) // "x@0"
|
|
1439
|
+
console.log(indexed[1]) // "a@1" — position.index updated reactively
|
|
1440
|
+
console.log(indexed[2]) // "b@2"
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1284
1443
|
**With reactive callback dependencies**
|
|
1285
1444
|
|
|
1286
1445
|
```typescript
|
|
@@ -1491,7 +1650,7 @@ For a full guide on debugging, including cycle detection and memoization discrep
|
|
|
1491
1650
|
|
|
1492
1651
|
### Quick Summary
|
|
1493
1652
|
|
|
1494
|
-
- **Cycle Detection**: Automatically catch circular dependencies via `reactiveOptions.
|
|
1495
|
-
- **
|
|
1653
|
+
- **Cycle Detection**: Automatically catch circular dependencies via `reactiveOptions.scheduler`. Note: Instant mathematical detection requires choosing `'ordered'` or `'debug'` mode.
|
|
1654
|
+
- **Ordered Mode**: The default `reactiveOptions.scheduler` is set to `'ordered'`, preserving causal ordering and parent/child effect lifecycle ordering.
|
|
1496
1655
|
- **Memoization Discrepancy**: Detect "missing dependencies" by running computations twice during development using `reactiveOptions.onMemoizationDiscrepancy`.
|
|
1497
1656
|
- **Global Hooks**: Use `reactiveOptions.touched`, `enter`, and `leave` to observe system activity.
|