@tanstack/store 0.8.0 → 0.9.0

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 (64) hide show
  1. package/dist/cjs/alien.cjs +345 -0
  2. package/dist/cjs/alien.cjs.map +1 -0
  3. package/dist/cjs/alien.d.cts +57 -0
  4. package/dist/cjs/atom.cjs +222 -0
  5. package/dist/cjs/atom.cjs.map +1 -0
  6. package/dist/cjs/atom.d.cts +16 -0
  7. package/dist/cjs/batch.cjs +15 -0
  8. package/dist/cjs/batch.cjs.map +1 -0
  9. package/dist/cjs/batch.d.cts +1 -0
  10. package/dist/cjs/index.cjs +8 -12
  11. package/dist/cjs/index.cjs.map +1 -1
  12. package/dist/cjs/index.d.cts +3 -4
  13. package/dist/cjs/store.cjs +22 -29
  14. package/dist/cjs/store.cjs.map +1 -1
  15. package/dist/cjs/store.d.cts +11 -30
  16. package/dist/cjs/types.d.cts +47 -20
  17. package/dist/esm/alien.d.ts +57 -0
  18. package/dist/esm/alien.js +345 -0
  19. package/dist/esm/alien.js.map +1 -0
  20. package/dist/esm/atom.d.ts +16 -0
  21. package/dist/esm/atom.js +222 -0
  22. package/dist/esm/atom.js.map +1 -0
  23. package/dist/esm/batch.d.ts +1 -0
  24. package/dist/esm/batch.js +15 -0
  25. package/dist/esm/batch.js.map +1 -0
  26. package/dist/esm/index.d.ts +3 -4
  27. package/dist/esm/index.js +8 -12
  28. package/dist/esm/index.js.map +1 -1
  29. package/dist/esm/store.d.ts +11 -30
  30. package/dist/esm/store.js +23 -30
  31. package/dist/esm/store.js.map +1 -1
  32. package/dist/esm/types.d.ts +47 -20
  33. package/package.json +6 -7
  34. package/src/alien.ts +654 -0
  35. package/src/atom.ts +298 -0
  36. package/src/batch.ts +12 -0
  37. package/src/index.ts +3 -4
  38. package/src/store.ts +33 -72
  39. package/src/types.ts +60 -24
  40. package/dist/cjs/derived.cjs +0 -130
  41. package/dist/cjs/derived.cjs.map +0 -1
  42. package/dist/cjs/derived.d.cts +0 -50
  43. package/dist/cjs/effect.cjs +0 -24
  44. package/dist/cjs/effect.cjs.map +0 -1
  45. package/dist/cjs/effect.d.cts +0 -18
  46. package/dist/cjs/scheduler.cjs +0 -103
  47. package/dist/cjs/scheduler.cjs.map +0 -1
  48. package/dist/cjs/scheduler.d.cts +0 -27
  49. package/dist/cjs/types.cjs +0 -7
  50. package/dist/cjs/types.cjs.map +0 -1
  51. package/dist/esm/derived.d.ts +0 -50
  52. package/dist/esm/derived.js +0 -130
  53. package/dist/esm/derived.js.map +0 -1
  54. package/dist/esm/effect.d.ts +0 -18
  55. package/dist/esm/effect.js +0 -24
  56. package/dist/esm/effect.js.map +0 -1
  57. package/dist/esm/scheduler.d.ts +0 -27
  58. package/dist/esm/scheduler.js +0 -103
  59. package/dist/esm/scheduler.js.map +0 -1
  60. package/dist/esm/types.js +0 -7
  61. package/dist/esm/types.js.map +0 -1
  62. package/src/derived.ts +0 -219
  63. package/src/effect.ts +0 -42
  64. package/src/scheduler.ts +0 -146
@@ -1,50 +0,0 @@
1
- import { Store } from './store.cjs';
2
- import { Listener } from './types.cjs';
3
- export type UnwrapDerivedOrStore<T> = T extends Derived<infer InnerD> ? InnerD : T extends Store<infer InnerS> ? InnerS : never;
4
- type UnwrapReadonlyDerivedOrStoreArray<TArr extends ReadonlyArray<Derived<any> | Store<any>>> = TArr extends readonly [] ? [] : TArr extends readonly [infer Head, ...infer Tail] ? Head extends Derived<any> | Store<any> ? Tail extends ReadonlyArray<Derived<any> | Store<any>> ? [
5
- UnwrapDerivedOrStore<Head>,
6
- ...UnwrapReadonlyDerivedOrStoreArray<Tail>
7
- ] : [UnwrapDerivedOrStore<Head>] : [] : TArr extends ReadonlyArray<Derived<any> | Store<any>> ? Array<UnwrapDerivedOrStore<TArr[number]>> : [];
8
- export interface DerivedFnProps<TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>, TUnwrappedArr extends UnwrapReadonlyDerivedOrStoreArray<TArr> = UnwrapReadonlyDerivedOrStoreArray<TArr>> {
9
- /**
10
- * `undefined` if it's the first run
11
- * @privateRemarks this also cannot be typed as TState, as it breaks the inferencing of the function's return type when an argument is used - even with `NoInfer` usage
12
- */
13
- prevVal: unknown | undefined;
14
- prevDepVals: TUnwrappedArr | undefined;
15
- currDepVals: TUnwrappedArr;
16
- }
17
- export interface DerivedOptions<TState, TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>> {
18
- onSubscribe?: (listener: Listener<TState>, derived: Derived<TState>) => () => void;
19
- onUpdate?: () => void;
20
- deps: TArr;
21
- /**
22
- * Values of the `deps` from before and after the current invocation of `fn`
23
- */
24
- fn: (props: DerivedFnProps<TArr>) => TState;
25
- }
26
- export declare class Derived<TState, const TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>> {
27
- listeners: Set<Listener<TState>>;
28
- state: TState;
29
- prevState: TState | undefined;
30
- options: DerivedOptions<TState, TArr>;
31
- /**
32
- * Functions representing the subscriptions. Call a function to cleanup
33
- * @private
34
- */
35
- _subscriptions: Array<() => void>;
36
- lastSeenDepValues: Array<unknown>;
37
- getDepVals: () => {
38
- prevDepVals: unknown[];
39
- currDepVals: unknown[];
40
- prevVal: NonNullable<TState> | undefined;
41
- };
42
- constructor(options: DerivedOptions<TState, TArr>);
43
- registerOnGraph(deps?: ReadonlyArray<Derived<any> | Store<any>>): void;
44
- unregisterFromGraph(deps?: ReadonlyArray<Derived<any> | Store<any>>): void;
45
- recompute: () => void;
46
- checkIfRecalculationNeededDeeply: () => void;
47
- mount: () => () => void;
48
- subscribe: (listener: Listener<TState>) => () => void;
49
- }
50
- export {};
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const derived = require("./derived.cjs");
4
- class Effect {
5
- constructor(opts) {
6
- const { eager, fn, ...derivedProps } = opts;
7
- this._derived = new derived.Derived({
8
- ...derivedProps,
9
- fn: () => {
10
- },
11
- onUpdate() {
12
- fn();
13
- }
14
- });
15
- if (eager) {
16
- fn();
17
- }
18
- }
19
- mount() {
20
- return this._derived.mount();
21
- }
22
- }
23
- exports.Effect = Effect;
24
- //# sourceMappingURL=effect.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"effect.cjs","sources":["../../src/effect.ts"],"sourcesContent":["import { Derived } from './derived'\nimport type { DerivedOptions } from './derived'\n\ninterface EffectOptions\n extends Omit<\n DerivedOptions<unknown>,\n 'onUpdate' | 'onSubscribe' | 'lazy' | 'fn'\n > {\n /**\n * Should the effect trigger immediately?\n * @default false\n */\n eager?: boolean\n fn: () => void\n}\n\nexport class Effect {\n /**\n * @private\n */\n _derived: Derived<void>\n\n constructor(opts: EffectOptions) {\n const { eager, fn, ...derivedProps } = opts\n\n this._derived = new Derived({\n ...derivedProps,\n fn: () => {},\n onUpdate() {\n fn()\n },\n })\n\n if (eager) {\n fn()\n }\n }\n\n mount() {\n return this._derived.mount()\n }\n}\n"],"names":["Derived"],"mappings":";;;AAgBO,MAAM,OAAO;AAAA,EAMlB,YAAY,MAAqB;AAC/B,UAAM,EAAE,OAAO,IAAI,GAAG,iBAAiB;AAEvC,SAAK,WAAW,IAAIA,gBAAQ;AAAA,MAC1B,GAAG;AAAA,MACH,IAAI,MAAM;AAAA,MAAC;AAAA,MACX,WAAW;AACT,WAAA;AAAA,MACF;AAAA,IAAA,CACD;AAED,QAAI,OAAO;AACT,SAAA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAQ;AACN,WAAO,KAAK,SAAS,MAAA;AAAA,EACvB;AACF;;"}
@@ -1,18 +0,0 @@
1
- import { Derived, DerivedOptions } from './derived.cjs';
2
- interface EffectOptions extends Omit<DerivedOptions<unknown>, 'onUpdate' | 'onSubscribe' | 'lazy' | 'fn'> {
3
- /**
4
- * Should the effect trigger immediately?
5
- * @default false
6
- */
7
- eager?: boolean;
8
- fn: () => void;
9
- }
10
- export declare class Effect {
11
- /**
12
- * @private
13
- */
14
- _derived: Derived<void>;
15
- constructor(opts: EffectOptions);
16
- mount(): () => void;
17
- }
18
- export {};
@@ -1,103 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const __storeToDerived = /* @__PURE__ */ new WeakMap();
4
- const __derivedToStore = /* @__PURE__ */ new WeakMap();
5
- const __depsThatHaveWrittenThisTick = {
6
- current: []
7
- };
8
- let __isFlushing = false;
9
- let __batchDepth = 0;
10
- const __pendingUpdates = /* @__PURE__ */ new Set();
11
- const __initialBatchValues = /* @__PURE__ */ new Map();
12
- function __flush_internals(relatedVals) {
13
- for (const derived of relatedVals) {
14
- if (__depsThatHaveWrittenThisTick.current.includes(derived)) {
15
- continue;
16
- }
17
- __depsThatHaveWrittenThisTick.current.push(derived);
18
- derived.recompute();
19
- const stores = __derivedToStore.get(derived);
20
- if (stores) {
21
- for (const store of stores) {
22
- const relatedLinkedDerivedVals = __storeToDerived.get(store);
23
- if (!(relatedLinkedDerivedVals == null ? void 0 : relatedLinkedDerivedVals.length)) continue;
24
- __flush_internals(relatedLinkedDerivedVals);
25
- }
26
- }
27
- }
28
- }
29
- function __notifyListeners(store) {
30
- const value = {
31
- prevVal: store.prevState,
32
- currentVal: store.state
33
- };
34
- for (const listener of store.listeners) {
35
- listener(value);
36
- }
37
- }
38
- function __notifyDerivedListeners(derived) {
39
- const value = {
40
- prevVal: derived.prevState,
41
- currentVal: derived.state
42
- };
43
- for (const listener of derived.listeners) {
44
- listener(value);
45
- }
46
- }
47
- function __flush(store) {
48
- if (__batchDepth > 0 && !__initialBatchValues.has(store)) {
49
- __initialBatchValues.set(store, store.prevState);
50
- }
51
- __pendingUpdates.add(store);
52
- if (__batchDepth > 0) return;
53
- if (__isFlushing) return;
54
- try {
55
- __isFlushing = true;
56
- while (__pendingUpdates.size > 0) {
57
- const stores = Array.from(__pendingUpdates);
58
- __pendingUpdates.clear();
59
- for (const store2 of stores) {
60
- const prevState = __initialBatchValues.get(store2) ?? store2.prevState;
61
- store2.prevState = prevState;
62
- __notifyListeners(store2);
63
- }
64
- for (const store2 of stores) {
65
- const derivedVals = __storeToDerived.get(store2);
66
- if (!derivedVals) continue;
67
- __depsThatHaveWrittenThisTick.current.push(store2);
68
- __flush_internals(derivedVals);
69
- }
70
- for (const store2 of stores) {
71
- const derivedVals = __storeToDerived.get(store2);
72
- if (!derivedVals) continue;
73
- for (const derived of derivedVals) {
74
- __notifyDerivedListeners(derived);
75
- }
76
- }
77
- }
78
- } finally {
79
- __isFlushing = false;
80
- __depsThatHaveWrittenThisTick.current = [];
81
- __initialBatchValues.clear();
82
- }
83
- }
84
- function batch(fn) {
85
- __batchDepth++;
86
- try {
87
- fn();
88
- } finally {
89
- __batchDepth--;
90
- if (__batchDepth === 0) {
91
- const pendingUpdateToFlush = __pendingUpdates.values().next().value;
92
- if (pendingUpdateToFlush) {
93
- __flush(pendingUpdateToFlush);
94
- }
95
- }
96
- }
97
- }
98
- exports.__depsThatHaveWrittenThisTick = __depsThatHaveWrittenThisTick;
99
- exports.__derivedToStore = __derivedToStore;
100
- exports.__flush = __flush;
101
- exports.__storeToDerived = __storeToDerived;
102
- exports.batch = batch;
103
- //# sourceMappingURL=scheduler.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scheduler.cjs","sources":["../../src/scheduler.ts"],"sourcesContent":["import type { Derived } from './derived'\nimport type { Store } from './store'\n\n/**\n * This is here to solve the pyramid dependency problem where:\n * A\n * / \\\n * B C\n * \\ /\n * D\n *\n * Where we deeply traverse this tree, how do we avoid D being recomputed twice; once when B is updated, once when C is.\n *\n * To solve this, we create linkedDeps that allows us to sync avoid writes to the state until all of the deps have been\n * resolved.\n *\n * This is a record of stores, because derived stores are not able to write values to, but stores are\n */\nexport const __storeToDerived = new WeakMap<\n Store<unknown>,\n Array<Derived<unknown>>\n>()\nexport const __derivedToStore = new WeakMap<\n Derived<unknown>,\n Set<Store<unknown>>\n>()\n\nexport const __depsThatHaveWrittenThisTick = {\n current: [] as Array<Derived<unknown> | Store<unknown>>,\n}\n\nlet __isFlushing = false\nlet __batchDepth = 0\nconst __pendingUpdates = new Set<Store<unknown>>()\n// Add a map to store initial values before batch\nconst __initialBatchValues = new Map<Store<unknown>, unknown>()\n\nfunction __flush_internals(relatedVals: ReadonlyArray<Derived<unknown>>) {\n for (const derived of relatedVals) {\n if (__depsThatHaveWrittenThisTick.current.includes(derived)) {\n continue\n }\n\n __depsThatHaveWrittenThisTick.current.push(derived)\n derived.recompute()\n\n const stores = __derivedToStore.get(derived)\n if (stores) {\n for (const store of stores) {\n const relatedLinkedDerivedVals = __storeToDerived.get(store)\n if (!relatedLinkedDerivedVals?.length) continue\n __flush_internals(relatedLinkedDerivedVals)\n }\n }\n }\n}\n\nfunction __notifyListeners(store: Store<unknown>) {\n const value = {\n prevVal: store.prevState as never,\n currentVal: store.state as never,\n }\n for (const listener of store.listeners) {\n listener(value)\n }\n}\n\nfunction __notifyDerivedListeners(derived: Derived<unknown>) {\n const value = {\n prevVal: derived.prevState as never,\n currentVal: derived.state as never,\n }\n for (const listener of derived.listeners) {\n listener(value)\n }\n}\n\n/**\n * @private only to be called from `Store` on write\n */\nexport function __flush(store: Store<unknown>) {\n // If we're starting a batch, store the initial values\n if (__batchDepth > 0 && !__initialBatchValues.has(store)) {\n __initialBatchValues.set(store, store.prevState)\n }\n\n __pendingUpdates.add(store)\n\n if (__batchDepth > 0) return\n if (__isFlushing) return\n\n try {\n __isFlushing = true\n\n while (__pendingUpdates.size > 0) {\n const stores = Array.from(__pendingUpdates)\n __pendingUpdates.clear()\n\n // First notify listeners with updated values\n for (const store of stores) {\n // Use initial batch values for prevState if we have them\n const prevState = __initialBatchValues.get(store) ?? store.prevState\n store.prevState = prevState\n __notifyListeners(store)\n }\n\n // Then update all derived values\n for (const store of stores) {\n const derivedVals = __storeToDerived.get(store)\n if (!derivedVals) continue\n\n __depsThatHaveWrittenThisTick.current.push(store)\n __flush_internals(derivedVals)\n }\n\n // Notify derived listeners after recomputing\n for (const store of stores) {\n const derivedVals = __storeToDerived.get(store)\n if (!derivedVals) continue\n\n for (const derived of derivedVals) {\n __notifyDerivedListeners(derived)\n }\n }\n }\n } finally {\n __isFlushing = false\n __depsThatHaveWrittenThisTick.current = []\n __initialBatchValues.clear()\n }\n}\n\nexport function batch(fn: () => void) {\n __batchDepth++\n try {\n fn()\n } finally {\n __batchDepth--\n if (__batchDepth === 0) {\n const pendingUpdateToFlush = __pendingUpdates.values().next().value\n if (pendingUpdateToFlush) {\n __flush(pendingUpdateToFlush) // Trigger flush of all pending updates\n }\n }\n }\n}\n"],"names":["store"],"mappings":";;AAkBO,MAAM,uCAAuB,QAAA;AAI7B,MAAM,uCAAuB,QAAA;AAK7B,MAAM,gCAAgC;AAAA,EAC3C,SAAS,CAAA;AACX;AAEA,IAAI,eAAe;AACnB,IAAI,eAAe;AACnB,MAAM,uCAAuB,IAAA;AAE7B,MAAM,2CAA2B,IAAA;AAEjC,SAAS,kBAAkB,aAA8C;AACvE,aAAW,WAAW,aAAa;AACjC,QAAI,8BAA8B,QAAQ,SAAS,OAAO,GAAG;AAC3D;AAAA,IACF;AAEA,kCAA8B,QAAQ,KAAK,OAAO;AAClD,YAAQ,UAAA;AAER,UAAM,SAAS,iBAAiB,IAAI,OAAO;AAC3C,QAAI,QAAQ;AACV,iBAAW,SAAS,QAAQ;AAC1B,cAAM,2BAA2B,iBAAiB,IAAI,KAAK;AAC3D,YAAI,EAAC,qEAA0B,QAAQ;AACvC,0BAAkB,wBAAwB;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,OAAuB;AAChD,QAAM,QAAQ;AAAA,IACZ,SAAS,MAAM;AAAA,IACf,YAAY,MAAM;AAAA,EAAA;AAEpB,aAAW,YAAY,MAAM,WAAW;AACtC,aAAS,KAAK;AAAA,EAChB;AACF;AAEA,SAAS,yBAAyB,SAA2B;AAC3D,QAAM,QAAQ;AAAA,IACZ,SAAS,QAAQ;AAAA,IACjB,YAAY,QAAQ;AAAA,EAAA;AAEtB,aAAW,YAAY,QAAQ,WAAW;AACxC,aAAS,KAAK;AAAA,EAChB;AACF;AAKO,SAAS,QAAQ,OAAuB;AAE7C,MAAI,eAAe,KAAK,CAAC,qBAAqB,IAAI,KAAK,GAAG;AACxD,yBAAqB,IAAI,OAAO,MAAM,SAAS;AAAA,EACjD;AAEA,mBAAiB,IAAI,KAAK;AAE1B,MAAI,eAAe,EAAG;AACtB,MAAI,aAAc;AAElB,MAAI;AACF,mBAAe;AAEf,WAAO,iBAAiB,OAAO,GAAG;AAChC,YAAM,SAAS,MAAM,KAAK,gBAAgB;AAC1C,uBAAiB,MAAA;AAGjB,iBAAWA,UAAS,QAAQ;AAE1B,cAAM,YAAY,qBAAqB,IAAIA,MAAK,KAAKA,OAAM;AAC3DA,eAAM,YAAY;AAClB,0BAAkBA,MAAK;AAAA,MACzB;AAGA,iBAAWA,UAAS,QAAQ;AAC1B,cAAM,cAAc,iBAAiB,IAAIA,MAAK;AAC9C,YAAI,CAAC,YAAa;AAElB,sCAA8B,QAAQ,KAAKA,MAAK;AAChD,0BAAkB,WAAW;AAAA,MAC/B;AAGA,iBAAWA,UAAS,QAAQ;AAC1B,cAAM,cAAc,iBAAiB,IAAIA,MAAK;AAC9C,YAAI,CAAC,YAAa;AAElB,mBAAW,WAAW,aAAa;AACjC,mCAAyB,OAAO;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAAA,EACF,UAAA;AACE,mBAAe;AACf,kCAA8B,UAAU,CAAA;AACxC,yBAAqB,MAAA;AAAA,EACvB;AACF;AAEO,SAAS,MAAM,IAAgB;AACpC;AACA,MAAI;AACF,OAAA;AAAA,EACF,UAAA;AACE;AACA,QAAI,iBAAiB,GAAG;AACtB,YAAM,uBAAuB,iBAAiB,OAAA,EAAS,OAAO;AAC9D,UAAI,sBAAsB;AACxB,gBAAQ,oBAAoB;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF;;;;;;"}
@@ -1,27 +0,0 @@
1
- import { Derived } from './derived.cjs';
2
- import { Store } from './store.cjs';
3
- /**
4
- * This is here to solve the pyramid dependency problem where:
5
- * A
6
- * / \
7
- * B C
8
- * \ /
9
- * D
10
- *
11
- * Where we deeply traverse this tree, how do we avoid D being recomputed twice; once when B is updated, once when C is.
12
- *
13
- * To solve this, we create linkedDeps that allows us to sync avoid writes to the state until all of the deps have been
14
- * resolved.
15
- *
16
- * This is a record of stores, because derived stores are not able to write values to, but stores are
17
- */
18
- export declare const __storeToDerived: WeakMap<Store<unknown, (cb: unknown) => unknown>, Derived<unknown, readonly any[]>[]>;
19
- export declare const __derivedToStore: WeakMap<Derived<unknown, readonly any[]>, Set<Store<unknown, (cb: unknown) => unknown>>>;
20
- export declare const __depsThatHaveWrittenThisTick: {
21
- current: Array<Derived<unknown> | Store<unknown>>;
22
- };
23
- /**
24
- * @private only to be called from `Store` on write
25
- */
26
- export declare function __flush(store: Store<unknown>): void;
27
- export declare function batch(fn: () => void): void;
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- function isUpdaterFunction(updater) {
4
- return typeof updater === "function";
5
- }
6
- exports.isUpdaterFunction = isUpdaterFunction;
7
- //# sourceMappingURL=types.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.cjs","sources":["../../src/types.ts"],"sourcesContent":["/**\n * @private\n */\nexport type AnyUpdater = (prev: any) => any\n\n/**\n * Type-safe updater that can be either a function or direct value\n */\nexport type Updater<T> = ((prev: T) => T) | T\n\n/**\n * @private\n */\nexport interface ListenerValue<T> {\n readonly prevVal: T\n readonly currentVal: T\n}\n\n/**\n * @private\n */\nexport type Listener<T> = (value: ListenerValue<T>) => void\n\n/**\n * Type guard to check if updater is a function\n */\nexport function isUpdaterFunction<T>(\n updater: Updater<T>,\n): updater is (prev: T) => T {\n return typeof updater === 'function'\n}\n"],"names":[],"mappings":";;AA0BO,SAAS,kBACd,SAC2B;AAC3B,SAAO,OAAO,YAAY;AAC5B;;"}
@@ -1,50 +0,0 @@
1
- import { Store } from './store.js';
2
- import { Listener } from './types.js';
3
- export type UnwrapDerivedOrStore<T> = T extends Derived<infer InnerD> ? InnerD : T extends Store<infer InnerS> ? InnerS : never;
4
- type UnwrapReadonlyDerivedOrStoreArray<TArr extends ReadonlyArray<Derived<any> | Store<any>>> = TArr extends readonly [] ? [] : TArr extends readonly [infer Head, ...infer Tail] ? Head extends Derived<any> | Store<any> ? Tail extends ReadonlyArray<Derived<any> | Store<any>> ? [
5
- UnwrapDerivedOrStore<Head>,
6
- ...UnwrapReadonlyDerivedOrStoreArray<Tail>
7
- ] : [UnwrapDerivedOrStore<Head>] : [] : TArr extends ReadonlyArray<Derived<any> | Store<any>> ? Array<UnwrapDerivedOrStore<TArr[number]>> : [];
8
- export interface DerivedFnProps<TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>, TUnwrappedArr extends UnwrapReadonlyDerivedOrStoreArray<TArr> = UnwrapReadonlyDerivedOrStoreArray<TArr>> {
9
- /**
10
- * `undefined` if it's the first run
11
- * @privateRemarks this also cannot be typed as TState, as it breaks the inferencing of the function's return type when an argument is used - even with `NoInfer` usage
12
- */
13
- prevVal: unknown | undefined;
14
- prevDepVals: TUnwrappedArr | undefined;
15
- currDepVals: TUnwrappedArr;
16
- }
17
- export interface DerivedOptions<TState, TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>> {
18
- onSubscribe?: (listener: Listener<TState>, derived: Derived<TState>) => () => void;
19
- onUpdate?: () => void;
20
- deps: TArr;
21
- /**
22
- * Values of the `deps` from before and after the current invocation of `fn`
23
- */
24
- fn: (props: DerivedFnProps<TArr>) => TState;
25
- }
26
- export declare class Derived<TState, const TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>> {
27
- listeners: Set<Listener<TState>>;
28
- state: TState;
29
- prevState: TState | undefined;
30
- options: DerivedOptions<TState, TArr>;
31
- /**
32
- * Functions representing the subscriptions. Call a function to cleanup
33
- * @private
34
- */
35
- _subscriptions: Array<() => void>;
36
- lastSeenDepValues: Array<unknown>;
37
- getDepVals: () => {
38
- prevDepVals: unknown[];
39
- currDepVals: unknown[];
40
- prevVal: NonNullable<TState> | undefined;
41
- };
42
- constructor(options: DerivedOptions<TState, TArr>);
43
- registerOnGraph(deps?: ReadonlyArray<Derived<any> | Store<any>>): void;
44
- unregisterFromGraph(deps?: ReadonlyArray<Derived<any> | Store<any>>): void;
45
- recompute: () => void;
46
- checkIfRecalculationNeededDeeply: () => void;
47
- mount: () => () => void;
48
- subscribe: (listener: Listener<TState>) => () => void;
49
- }
50
- export {};
@@ -1,130 +0,0 @@
1
- import { Store } from "./store.js";
2
- import { __storeToDerived, __derivedToStore } from "./scheduler.js";
3
- class Derived {
4
- constructor(options) {
5
- this.listeners = /* @__PURE__ */ new Set();
6
- this._subscriptions = [];
7
- this.lastSeenDepValues = [];
8
- this.getDepVals = () => {
9
- const l = this.options.deps.length;
10
- const prevDepVals = new Array(l);
11
- const currDepVals = new Array(l);
12
- for (let i = 0; i < l; i++) {
13
- const dep = this.options.deps[i];
14
- prevDepVals[i] = dep.prevState;
15
- currDepVals[i] = dep.state;
16
- }
17
- this.lastSeenDepValues = currDepVals;
18
- return {
19
- prevDepVals,
20
- currDepVals,
21
- prevVal: this.prevState ?? void 0
22
- };
23
- };
24
- this.recompute = () => {
25
- var _a, _b;
26
- this.prevState = this.state;
27
- const depVals = this.getDepVals();
28
- this.state = this.options.fn(depVals);
29
- (_b = (_a = this.options).onUpdate) == null ? void 0 : _b.call(_a);
30
- };
31
- this.checkIfRecalculationNeededDeeply = () => {
32
- for (const dep of this.options.deps) {
33
- if (dep instanceof Derived) {
34
- dep.checkIfRecalculationNeededDeeply();
35
- }
36
- }
37
- let shouldRecompute = false;
38
- const lastSeenDepValues = this.lastSeenDepValues;
39
- const { currDepVals } = this.getDepVals();
40
- for (let i = 0; i < currDepVals.length; i++) {
41
- if (currDepVals[i] !== lastSeenDepValues[i]) {
42
- shouldRecompute = true;
43
- break;
44
- }
45
- }
46
- if (shouldRecompute) {
47
- this.recompute();
48
- }
49
- };
50
- this.mount = () => {
51
- this.registerOnGraph();
52
- this.checkIfRecalculationNeededDeeply();
53
- return () => {
54
- this.unregisterFromGraph();
55
- for (const cleanup of this._subscriptions) {
56
- cleanup();
57
- }
58
- };
59
- };
60
- this.subscribe = (listener) => {
61
- var _a, _b;
62
- this.listeners.add(listener);
63
- const unsub = (_b = (_a = this.options).onSubscribe) == null ? void 0 : _b.call(_a, listener, this);
64
- return () => {
65
- this.listeners.delete(listener);
66
- unsub == null ? void 0 : unsub();
67
- };
68
- };
69
- this.options = options;
70
- this.state = options.fn({
71
- prevDepVals: void 0,
72
- prevVal: void 0,
73
- currDepVals: this.getDepVals().currDepVals
74
- });
75
- }
76
- registerOnGraph(deps = this.options.deps) {
77
- const toSort = /* @__PURE__ */ new Set();
78
- for (const dep of deps) {
79
- if (dep instanceof Derived) {
80
- dep.registerOnGraph();
81
- this.registerOnGraph(dep.options.deps);
82
- } else if (dep instanceof Store) {
83
- let relatedLinkedDerivedVals = __storeToDerived.get(dep);
84
- if (!relatedLinkedDerivedVals) {
85
- relatedLinkedDerivedVals = [this];
86
- __storeToDerived.set(dep, relatedLinkedDerivedVals);
87
- } else if (!relatedLinkedDerivedVals.includes(this)) {
88
- relatedLinkedDerivedVals.push(this);
89
- toSort.add(relatedLinkedDerivedVals);
90
- }
91
- let relatedStores = __derivedToStore.get(this);
92
- if (!relatedStores) {
93
- relatedStores = /* @__PURE__ */ new Set();
94
- __derivedToStore.set(this, relatedStores);
95
- }
96
- relatedStores.add(dep);
97
- }
98
- }
99
- for (const arr of toSort) {
100
- arr.sort((a, b) => {
101
- if (a instanceof Derived && a.options.deps.includes(b)) return 1;
102
- if (b instanceof Derived && b.options.deps.includes(a)) return -1;
103
- return 0;
104
- });
105
- }
106
- }
107
- unregisterFromGraph(deps = this.options.deps) {
108
- for (const dep of deps) {
109
- if (dep instanceof Derived) {
110
- this.unregisterFromGraph(dep.options.deps);
111
- } else if (dep instanceof Store) {
112
- const relatedLinkedDerivedVals = __storeToDerived.get(dep);
113
- if (relatedLinkedDerivedVals) {
114
- relatedLinkedDerivedVals.splice(
115
- relatedLinkedDerivedVals.indexOf(this),
116
- 1
117
- );
118
- }
119
- const relatedStores = __derivedToStore.get(this);
120
- if (relatedStores) {
121
- relatedStores.delete(dep);
122
- }
123
- }
124
- }
125
- }
126
- }
127
- export {
128
- Derived
129
- };
130
- //# sourceMappingURL=derived.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"derived.js","sources":["../../src/derived.ts"],"sourcesContent":["import { Store } from './store'\nimport { __derivedToStore, __storeToDerived } from './scheduler'\nimport type { Listener } from './types'\n\nexport type UnwrapDerivedOrStore<T> =\n T extends Derived<infer InnerD>\n ? InnerD\n : T extends Store<infer InnerS>\n ? InnerS\n : never\n\ntype UnwrapReadonlyDerivedOrStoreArray<\n TArr extends ReadonlyArray<Derived<any> | Store<any>>,\n> = TArr extends readonly []\n ? []\n : TArr extends readonly [infer Head, ...infer Tail]\n ? Head extends Derived<any> | Store<any>\n ? Tail extends ReadonlyArray<Derived<any> | Store<any>>\n ? [\n UnwrapDerivedOrStore<Head>,\n ...UnwrapReadonlyDerivedOrStoreArray<Tail>,\n ]\n : [UnwrapDerivedOrStore<Head>]\n : []\n : TArr extends ReadonlyArray<Derived<any> | Store<any>>\n ? Array<UnwrapDerivedOrStore<TArr[number]>>\n : []\n\n// Can't have currVal, as it's being evaluated from the current derived fn\nexport interface DerivedFnProps<\n TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>,\n TUnwrappedArr extends\n UnwrapReadonlyDerivedOrStoreArray<TArr> = UnwrapReadonlyDerivedOrStoreArray<TArr>,\n> {\n // `undefined` if it's the first run\n /**\n * `undefined` if it's the first run\n * @privateRemarks this also cannot be typed as TState, as it breaks the inferencing of the function's return type when an argument is used - even with `NoInfer` usage\n */\n prevVal: unknown | undefined\n prevDepVals: TUnwrappedArr | undefined\n currDepVals: TUnwrappedArr\n}\n\nexport interface DerivedOptions<\n TState,\n TArr extends ReadonlyArray<Derived<any> | Store<any>> = ReadonlyArray<any>,\n> {\n onSubscribe?: (\n listener: Listener<TState>,\n derived: Derived<TState>,\n ) => () => void\n onUpdate?: () => void\n deps: TArr\n /**\n * Values of the `deps` from before and after the current invocation of `fn`\n */\n fn: (props: DerivedFnProps<TArr>) => TState\n}\n\nexport class Derived<\n TState,\n const TArr extends ReadonlyArray<\n Derived<any> | Store<any>\n > = ReadonlyArray<any>,\n> {\n listeners = new Set<Listener<TState>>()\n state: TState\n prevState: TState | undefined\n options: DerivedOptions<TState, TArr>\n\n /**\n * Functions representing the subscriptions. Call a function to cleanup\n * @private\n */\n _subscriptions: Array<() => void> = []\n\n lastSeenDepValues: Array<unknown> = []\n getDepVals = () => {\n const l = this.options.deps.length\n const prevDepVals = new Array<unknown>(l)\n const currDepVals = new Array<unknown>(l)\n for (let i = 0; i < l; i++) {\n const dep = this.options.deps[i]!\n prevDepVals[i] = dep.prevState\n currDepVals[i] = dep.state\n }\n this.lastSeenDepValues = currDepVals\n return {\n prevDepVals,\n currDepVals,\n prevVal: this.prevState ?? undefined,\n }\n }\n\n constructor(options: DerivedOptions<TState, TArr>) {\n this.options = options\n this.state = options.fn({\n prevDepVals: undefined,\n prevVal: undefined,\n currDepVals: this.getDepVals().currDepVals as never,\n })\n }\n\n registerOnGraph(\n deps: ReadonlyArray<Derived<any> | Store<any>> = this.options.deps,\n ) {\n const toSort = new Set<Array<Derived<unknown>>>()\n for (const dep of deps) {\n if (dep instanceof Derived) {\n // First register the intermediate derived value if it's not already registered\n dep.registerOnGraph()\n // Then register this derived with the dep's underlying stores\n this.registerOnGraph(dep.options.deps)\n } else if (dep instanceof Store) {\n // Register the derived as related derived to the store\n let relatedLinkedDerivedVals = __storeToDerived.get(dep)\n if (!relatedLinkedDerivedVals) {\n relatedLinkedDerivedVals = [this as never]\n __storeToDerived.set(dep, relatedLinkedDerivedVals)\n } else if (!relatedLinkedDerivedVals.includes(this as never)) {\n relatedLinkedDerivedVals.push(this as never)\n toSort.add(relatedLinkedDerivedVals)\n }\n\n // Register the store as a related store to this derived\n let relatedStores = __derivedToStore.get(this as never)\n if (!relatedStores) {\n relatedStores = new Set()\n __derivedToStore.set(this as never, relatedStores)\n }\n relatedStores.add(dep)\n }\n }\n for (const arr of toSort) {\n // First sort deriveds by dependency order\n arr.sort((a, b) => {\n // If a depends on b, b should go first\n if (a instanceof Derived && a.options.deps.includes(b)) return 1\n // If b depends on a, a should go first\n if (b instanceof Derived && b.options.deps.includes(a)) return -1\n return 0\n })\n }\n }\n\n unregisterFromGraph(\n deps: ReadonlyArray<Derived<any> | Store<any>> = this.options.deps,\n ) {\n for (const dep of deps) {\n if (dep instanceof Derived) {\n this.unregisterFromGraph(dep.options.deps)\n } else if (dep instanceof Store) {\n const relatedLinkedDerivedVals = __storeToDerived.get(dep)\n if (relatedLinkedDerivedVals) {\n relatedLinkedDerivedVals.splice(\n relatedLinkedDerivedVals.indexOf(this as never),\n 1,\n )\n }\n\n const relatedStores = __derivedToStore.get(this as never)\n if (relatedStores) {\n relatedStores.delete(dep)\n }\n }\n }\n }\n\n recompute = () => {\n this.prevState = this.state\n const depVals = this.getDepVals()\n this.state = this.options.fn(depVals as never)\n\n this.options.onUpdate?.()\n }\n\n checkIfRecalculationNeededDeeply = () => {\n for (const dep of this.options.deps) {\n if (dep instanceof Derived) {\n dep.checkIfRecalculationNeededDeeply()\n }\n }\n let shouldRecompute = false\n const lastSeenDepValues = this.lastSeenDepValues\n const { currDepVals } = this.getDepVals()\n for (let i = 0; i < currDepVals.length; i++) {\n if (currDepVals[i] !== lastSeenDepValues[i]) {\n shouldRecompute = true\n break\n }\n }\n\n if (shouldRecompute) {\n this.recompute()\n }\n }\n\n mount = () => {\n this.registerOnGraph()\n this.checkIfRecalculationNeededDeeply()\n\n return () => {\n this.unregisterFromGraph()\n for (const cleanup of this._subscriptions) {\n cleanup()\n }\n }\n }\n\n subscribe = (listener: Listener<TState>) => {\n this.listeners.add(listener)\n const unsub = this.options.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,18 +0,0 @@
1
- import { Derived, DerivedOptions } from './derived.js';
2
- interface EffectOptions extends Omit<DerivedOptions<unknown>, 'onUpdate' | 'onSubscribe' | 'lazy' | 'fn'> {
3
- /**
4
- * Should the effect trigger immediately?
5
- * @default false
6
- */
7
- eager?: boolean;
8
- fn: () => void;
9
- }
10
- export declare class Effect {
11
- /**
12
- * @private
13
- */
14
- _derived: Derived<void>;
15
- constructor(opts: EffectOptions);
16
- mount(): () => void;
17
- }
18
- export {};
@@ -1,24 +0,0 @@
1
- import { Derived } from "./derived.js";
2
- class Effect {
3
- constructor(opts) {
4
- const { eager, fn, ...derivedProps } = opts;
5
- this._derived = new Derived({
6
- ...derivedProps,
7
- fn: () => {
8
- },
9
- onUpdate() {
10
- fn();
11
- }
12
- });
13
- if (eager) {
14
- fn();
15
- }
16
- }
17
- mount() {
18
- return this._derived.mount();
19
- }
20
- }
21
- export {
22
- Effect
23
- };
24
- //# sourceMappingURL=effect.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"effect.js","sources":["../../src/effect.ts"],"sourcesContent":["import { Derived } from './derived'\nimport type { DerivedOptions } from './derived'\n\ninterface EffectOptions\n extends Omit<\n DerivedOptions<unknown>,\n 'onUpdate' | 'onSubscribe' | 'lazy' | 'fn'\n > {\n /**\n * Should the effect trigger immediately?\n * @default false\n */\n eager?: boolean\n fn: () => void\n}\n\nexport class Effect {\n /**\n * @private\n */\n _derived: Derived<void>\n\n constructor(opts: EffectOptions) {\n const { eager, fn, ...derivedProps } = opts\n\n this._derived = new Derived({\n ...derivedProps,\n fn: () => {},\n onUpdate() {\n fn()\n },\n })\n\n if (eager) {\n fn()\n }\n }\n\n mount() {\n return this._derived.mount()\n }\n}\n"],"names":[],"mappings":";AAgBO,MAAM,OAAO;AAAA,EAMlB,YAAY,MAAqB;AAC/B,UAAM,EAAE,OAAO,IAAI,GAAG,iBAAiB;AAEvC,SAAK,WAAW,IAAI,QAAQ;AAAA,MAC1B,GAAG;AAAA,MACH,IAAI,MAAM;AAAA,MAAC;AAAA,MACX,WAAW;AACT,WAAA;AAAA,MACF;AAAA,IAAA,CACD;AAED,QAAI,OAAO;AACT,SAAA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAQ;AACN,WAAO,KAAK,SAAS,MAAA;AAAA,EACvB;AACF;"}
@@ -1,27 +0,0 @@
1
- import { Derived } from './derived.js';
2
- import { Store } from './store.js';
3
- /**
4
- * This is here to solve the pyramid dependency problem where:
5
- * A
6
- * / \
7
- * B C
8
- * \ /
9
- * D
10
- *
11
- * Where we deeply traverse this tree, how do we avoid D being recomputed twice; once when B is updated, once when C is.
12
- *
13
- * To solve this, we create linkedDeps that allows us to sync avoid writes to the state until all of the deps have been
14
- * resolved.
15
- *
16
- * This is a record of stores, because derived stores are not able to write values to, but stores are
17
- */
18
- export declare const __storeToDerived: WeakMap<Store<unknown, (cb: unknown) => unknown>, Derived<unknown, readonly any[]>[]>;
19
- export declare const __derivedToStore: WeakMap<Derived<unknown, readonly any[]>, Set<Store<unknown, (cb: unknown) => unknown>>>;
20
- export declare const __depsThatHaveWrittenThisTick: {
21
- current: Array<Derived<unknown> | Store<unknown>>;
22
- };
23
- /**
24
- * @private only to be called from `Store` on write
25
- */
26
- export declare function __flush(store: Store<unknown>): void;
27
- export declare function batch(fn: () => void): void;
@@ -1,103 +0,0 @@
1
- const __storeToDerived = /* @__PURE__ */ new WeakMap();
2
- const __derivedToStore = /* @__PURE__ */ new WeakMap();
3
- const __depsThatHaveWrittenThisTick = {
4
- current: []
5
- };
6
- let __isFlushing = false;
7
- let __batchDepth = 0;
8
- const __pendingUpdates = /* @__PURE__ */ new Set();
9
- const __initialBatchValues = /* @__PURE__ */ new Map();
10
- function __flush_internals(relatedVals) {
11
- for (const derived of relatedVals) {
12
- if (__depsThatHaveWrittenThisTick.current.includes(derived)) {
13
- continue;
14
- }
15
- __depsThatHaveWrittenThisTick.current.push(derived);
16
- derived.recompute();
17
- const stores = __derivedToStore.get(derived);
18
- if (stores) {
19
- for (const store of stores) {
20
- const relatedLinkedDerivedVals = __storeToDerived.get(store);
21
- if (!(relatedLinkedDerivedVals == null ? void 0 : relatedLinkedDerivedVals.length)) continue;
22
- __flush_internals(relatedLinkedDerivedVals);
23
- }
24
- }
25
- }
26
- }
27
- function __notifyListeners(store) {
28
- const value = {
29
- prevVal: store.prevState,
30
- currentVal: store.state
31
- };
32
- for (const listener of store.listeners) {
33
- listener(value);
34
- }
35
- }
36
- function __notifyDerivedListeners(derived) {
37
- const value = {
38
- prevVal: derived.prevState,
39
- currentVal: derived.state
40
- };
41
- for (const listener of derived.listeners) {
42
- listener(value);
43
- }
44
- }
45
- function __flush(store) {
46
- if (__batchDepth > 0 && !__initialBatchValues.has(store)) {
47
- __initialBatchValues.set(store, store.prevState);
48
- }
49
- __pendingUpdates.add(store);
50
- if (__batchDepth > 0) return;
51
- if (__isFlushing) return;
52
- try {
53
- __isFlushing = true;
54
- while (__pendingUpdates.size > 0) {
55
- const stores = Array.from(__pendingUpdates);
56
- __pendingUpdates.clear();
57
- for (const store2 of stores) {
58
- const prevState = __initialBatchValues.get(store2) ?? store2.prevState;
59
- store2.prevState = prevState;
60
- __notifyListeners(store2);
61
- }
62
- for (const store2 of stores) {
63
- const derivedVals = __storeToDerived.get(store2);
64
- if (!derivedVals) continue;
65
- __depsThatHaveWrittenThisTick.current.push(store2);
66
- __flush_internals(derivedVals);
67
- }
68
- for (const store2 of stores) {
69
- const derivedVals = __storeToDerived.get(store2);
70
- if (!derivedVals) continue;
71
- for (const derived of derivedVals) {
72
- __notifyDerivedListeners(derived);
73
- }
74
- }
75
- }
76
- } finally {
77
- __isFlushing = false;
78
- __depsThatHaveWrittenThisTick.current = [];
79
- __initialBatchValues.clear();
80
- }
81
- }
82
- function batch(fn) {
83
- __batchDepth++;
84
- try {
85
- fn();
86
- } finally {
87
- __batchDepth--;
88
- if (__batchDepth === 0) {
89
- const pendingUpdateToFlush = __pendingUpdates.values().next().value;
90
- if (pendingUpdateToFlush) {
91
- __flush(pendingUpdateToFlush);
92
- }
93
- }
94
- }
95
- }
96
- export {
97
- __depsThatHaveWrittenThisTick,
98
- __derivedToStore,
99
- __flush,
100
- __storeToDerived,
101
- batch
102
- };
103
- //# sourceMappingURL=scheduler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scheduler.js","sources":["../../src/scheduler.ts"],"sourcesContent":["import type { Derived } from './derived'\nimport type { Store } from './store'\n\n/**\n * This is here to solve the pyramid dependency problem where:\n * A\n * / \\\n * B C\n * \\ /\n * D\n *\n * Where we deeply traverse this tree, how do we avoid D being recomputed twice; once when B is updated, once when C is.\n *\n * To solve this, we create linkedDeps that allows us to sync avoid writes to the state until all of the deps have been\n * resolved.\n *\n * This is a record of stores, because derived stores are not able to write values to, but stores are\n */\nexport const __storeToDerived = new WeakMap<\n Store<unknown>,\n Array<Derived<unknown>>\n>()\nexport const __derivedToStore = new WeakMap<\n Derived<unknown>,\n Set<Store<unknown>>\n>()\n\nexport const __depsThatHaveWrittenThisTick = {\n current: [] as Array<Derived<unknown> | Store<unknown>>,\n}\n\nlet __isFlushing = false\nlet __batchDepth = 0\nconst __pendingUpdates = new Set<Store<unknown>>()\n// Add a map to store initial values before batch\nconst __initialBatchValues = new Map<Store<unknown>, unknown>()\n\nfunction __flush_internals(relatedVals: ReadonlyArray<Derived<unknown>>) {\n for (const derived of relatedVals) {\n if (__depsThatHaveWrittenThisTick.current.includes(derived)) {\n continue\n }\n\n __depsThatHaveWrittenThisTick.current.push(derived)\n derived.recompute()\n\n const stores = __derivedToStore.get(derived)\n if (stores) {\n for (const store of stores) {\n const relatedLinkedDerivedVals = __storeToDerived.get(store)\n if (!relatedLinkedDerivedVals?.length) continue\n __flush_internals(relatedLinkedDerivedVals)\n }\n }\n }\n}\n\nfunction __notifyListeners(store: Store<unknown>) {\n const value = {\n prevVal: store.prevState as never,\n currentVal: store.state as never,\n }\n for (const listener of store.listeners) {\n listener(value)\n }\n}\n\nfunction __notifyDerivedListeners(derived: Derived<unknown>) {\n const value = {\n prevVal: derived.prevState as never,\n currentVal: derived.state as never,\n }\n for (const listener of derived.listeners) {\n listener(value)\n }\n}\n\n/**\n * @private only to be called from `Store` on write\n */\nexport function __flush(store: Store<unknown>) {\n // If we're starting a batch, store the initial values\n if (__batchDepth > 0 && !__initialBatchValues.has(store)) {\n __initialBatchValues.set(store, store.prevState)\n }\n\n __pendingUpdates.add(store)\n\n if (__batchDepth > 0) return\n if (__isFlushing) return\n\n try {\n __isFlushing = true\n\n while (__pendingUpdates.size > 0) {\n const stores = Array.from(__pendingUpdates)\n __pendingUpdates.clear()\n\n // First notify listeners with updated values\n for (const store of stores) {\n // Use initial batch values for prevState if we have them\n const prevState = __initialBatchValues.get(store) ?? store.prevState\n store.prevState = prevState\n __notifyListeners(store)\n }\n\n // Then update all derived values\n for (const store of stores) {\n const derivedVals = __storeToDerived.get(store)\n if (!derivedVals) continue\n\n __depsThatHaveWrittenThisTick.current.push(store)\n __flush_internals(derivedVals)\n }\n\n // Notify derived listeners after recomputing\n for (const store of stores) {\n const derivedVals = __storeToDerived.get(store)\n if (!derivedVals) continue\n\n for (const derived of derivedVals) {\n __notifyDerivedListeners(derived)\n }\n }\n }\n } finally {\n __isFlushing = false\n __depsThatHaveWrittenThisTick.current = []\n __initialBatchValues.clear()\n }\n}\n\nexport function batch(fn: () => void) {\n __batchDepth++\n try {\n fn()\n } finally {\n __batchDepth--\n if (__batchDepth === 0) {\n const pendingUpdateToFlush = __pendingUpdates.values().next().value\n if (pendingUpdateToFlush) {\n __flush(pendingUpdateToFlush) // Trigger flush of all pending updates\n }\n }\n }\n}\n"],"names":["store"],"mappings":"AAkBO,MAAM,uCAAuB,QAAA;AAI7B,MAAM,uCAAuB,QAAA;AAK7B,MAAM,gCAAgC;AAAA,EAC3C,SAAS,CAAA;AACX;AAEA,IAAI,eAAe;AACnB,IAAI,eAAe;AACnB,MAAM,uCAAuB,IAAA;AAE7B,MAAM,2CAA2B,IAAA;AAEjC,SAAS,kBAAkB,aAA8C;AACvE,aAAW,WAAW,aAAa;AACjC,QAAI,8BAA8B,QAAQ,SAAS,OAAO,GAAG;AAC3D;AAAA,IACF;AAEA,kCAA8B,QAAQ,KAAK,OAAO;AAClD,YAAQ,UAAA;AAER,UAAM,SAAS,iBAAiB,IAAI,OAAO;AAC3C,QAAI,QAAQ;AACV,iBAAW,SAAS,QAAQ;AAC1B,cAAM,2BAA2B,iBAAiB,IAAI,KAAK;AAC3D,YAAI,EAAC,qEAA0B,QAAQ;AACvC,0BAAkB,wBAAwB;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,OAAuB;AAChD,QAAM,QAAQ;AAAA,IACZ,SAAS,MAAM;AAAA,IACf,YAAY,MAAM;AAAA,EAAA;AAEpB,aAAW,YAAY,MAAM,WAAW;AACtC,aAAS,KAAK;AAAA,EAChB;AACF;AAEA,SAAS,yBAAyB,SAA2B;AAC3D,QAAM,QAAQ;AAAA,IACZ,SAAS,QAAQ;AAAA,IACjB,YAAY,QAAQ;AAAA,EAAA;AAEtB,aAAW,YAAY,QAAQ,WAAW;AACxC,aAAS,KAAK;AAAA,EAChB;AACF;AAKO,SAAS,QAAQ,OAAuB;AAE7C,MAAI,eAAe,KAAK,CAAC,qBAAqB,IAAI,KAAK,GAAG;AACxD,yBAAqB,IAAI,OAAO,MAAM,SAAS;AAAA,EACjD;AAEA,mBAAiB,IAAI,KAAK;AAE1B,MAAI,eAAe,EAAG;AACtB,MAAI,aAAc;AAElB,MAAI;AACF,mBAAe;AAEf,WAAO,iBAAiB,OAAO,GAAG;AAChC,YAAM,SAAS,MAAM,KAAK,gBAAgB;AAC1C,uBAAiB,MAAA;AAGjB,iBAAWA,UAAS,QAAQ;AAE1B,cAAM,YAAY,qBAAqB,IAAIA,MAAK,KAAKA,OAAM;AAC3DA,eAAM,YAAY;AAClB,0BAAkBA,MAAK;AAAA,MACzB;AAGA,iBAAWA,UAAS,QAAQ;AAC1B,cAAM,cAAc,iBAAiB,IAAIA,MAAK;AAC9C,YAAI,CAAC,YAAa;AAElB,sCAA8B,QAAQ,KAAKA,MAAK;AAChD,0BAAkB,WAAW;AAAA,MAC/B;AAGA,iBAAWA,UAAS,QAAQ;AAC1B,cAAM,cAAc,iBAAiB,IAAIA,MAAK;AAC9C,YAAI,CAAC,YAAa;AAElB,mBAAW,WAAW,aAAa;AACjC,mCAAyB,OAAO;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAAA,EACF,UAAA;AACE,mBAAe;AACf,kCAA8B,UAAU,CAAA;AACxC,yBAAqB,MAAA;AAAA,EACvB;AACF;AAEO,SAAS,MAAM,IAAgB;AACpC;AACA,MAAI;AACF,OAAA;AAAA,EACF,UAAA;AACE;AACA,QAAI,iBAAiB,GAAG;AACtB,YAAM,uBAAuB,iBAAiB,OAAA,EAAS,OAAO;AAC9D,UAAI,sBAAsB;AACxB,gBAAQ,oBAAoB;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF;"}