@fluixi/reactive 1.0.0-alpha.82 → 1.0.0-alpha.84

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 (169) hide show
  1. package/README.md +4 -0
  2. package/dist/cdn/reactive.cjs +2673 -1
  3. package/dist/cdn/reactive.global.js +2 -1
  4. package/dist/cdn/reactive.mjs +2657 -1
  5. package/dist/cdn/signal.cjs +299 -1
  6. package/dist/cdn/signal.d.ts +1 -1
  7. package/dist/cdn/signal.global.js +2 -1
  8. package/dist/cdn/signal.js +1 -1
  9. package/dist/cdn/signal.mjs +276 -1
  10. package/dist/index.cjs +2673 -1
  11. package/dist/index.mjs +2657 -1
  12. package/dist/lib/index.cjs +2674 -1
  13. package/dist/lib/index.js +1 -1
  14. package/dist/lib/index.mjs +2659 -1
  15. package/dist/lib/observable/index.cjs +386 -1
  16. package/dist/lib/observable/index.mjs +364 -1
  17. package/dist/lib/observable/observable.cjs +384 -1
  18. package/dist/lib/observable/observable.d.ts +0 -137
  19. package/dist/lib/observable/observable.d.ts.map +1 -1
  20. package/dist/lib/observable/observable.js +0 -71
  21. package/dist/lib/observable/observable.mjs +361 -1
  22. package/dist/lib/observable/subscription.cjs +180 -1
  23. package/dist/lib/observable/subscription.d.ts +0 -12
  24. package/dist/lib/observable/subscription.d.ts.map +1 -1
  25. package/dist/lib/observable/subscription.js +0 -12
  26. package/dist/lib/observable/subscription.mjs +157 -1
  27. package/dist/lib/observable/types.cjs +18 -1
  28. package/dist/lib/observable/types.d.ts.map +1 -1
  29. package/dist/lib/predicates.cjs +44 -1
  30. package/dist/lib/predicates.d.ts +2 -2
  31. package/dist/lib/predicates.js +2 -2
  32. package/dist/lib/predicates.mjs +23 -1
  33. package/dist/lib/signal/api.cjs +571 -1
  34. package/dist/lib/signal/api.d.ts +211 -1
  35. package/dist/lib/signal/api.d.ts.map +1 -1
  36. package/dist/lib/signal/api.js +207 -12
  37. package/dist/lib/signal/api.mjs +548 -1
  38. package/dist/lib/signal/cached-resource.cjs +672 -1
  39. package/dist/lib/signal/cached-resource.d.ts +28 -16
  40. package/dist/lib/signal/cached-resource.d.ts.map +1 -1
  41. package/dist/lib/signal/cached-resource.js +35 -29
  42. package/dist/lib/signal/cached-resource.mjs +650 -1
  43. package/dist/lib/signal/graph/children.cjs +325 -1
  44. package/dist/lib/signal/graph/children.js +1 -1
  45. package/dist/lib/signal/graph/children.mjs +302 -1
  46. package/dist/lib/signal/graph/compat.cjs +578 -1
  47. package/dist/lib/signal/graph/compat.d.ts +13 -13
  48. package/dist/lib/signal/graph/compat.d.ts.map +1 -1
  49. package/dist/lib/signal/graph/compat.js +51 -32
  50. package/dist/lib/signal/graph/compat.mjs +556 -1
  51. package/dist/lib/signal/graph/core.cjs +295 -1
  52. package/dist/lib/signal/graph/core.d.ts +28 -24
  53. package/dist/lib/signal/graph/core.d.ts.map +1 -1
  54. package/dist/lib/signal/graph/core.js +45 -31
  55. package/dist/lib/signal/graph/core.mjs +273 -1
  56. package/dist/lib/signal/graph/debounced.cjs +668 -1
  57. package/dist/lib/signal/graph/debounced.d.ts +5 -5
  58. package/dist/lib/signal/graph/debounced.d.ts.map +1 -1
  59. package/dist/lib/signal/graph/debounced.js +5 -5
  60. package/dist/lib/signal/graph/debounced.mjs +645 -1
  61. package/dist/lib/signal/graph/derived.cjs +496 -1
  62. package/dist/lib/signal/graph/derived.d.ts +1 -1
  63. package/dist/lib/signal/graph/derived.js +1 -1
  64. package/dist/lib/signal/graph/derived.mjs +473 -1
  65. package/dist/lib/signal/graph/detect.cjs +66 -1
  66. package/dist/lib/signal/graph/detect.mjs +45 -1
  67. package/dist/lib/signal/graph/error-boundary.cjs +301 -1
  68. package/dist/lib/signal/graph/error-boundary.js +3 -3
  69. package/dist/lib/signal/graph/error-boundary.mjs +278 -1
  70. package/dist/lib/signal/graph/index.cjs +305 -1
  71. package/dist/lib/signal/graph/index.d.ts +7 -6
  72. package/dist/lib/signal/graph/index.d.ts.map +1 -1
  73. package/dist/lib/signal/graph/index.js +7 -6
  74. package/dist/lib/signal/graph/index.mjs +283 -1
  75. package/dist/lib/signal/graph/observe.cjs +163 -0
  76. package/dist/lib/signal/graph/observe.d.ts +141 -0
  77. package/dist/lib/signal/graph/observe.d.ts.map +1 -0
  78. package/dist/lib/signal/graph/observe.js +149 -0
  79. package/dist/lib/signal/graph/observe.mjs +140 -0
  80. package/dist/lib/signal/graph/resource.cjs +620 -1
  81. package/dist/lib/signal/graph/resource.d.ts +1 -1
  82. package/dist/lib/signal/graph/resource.js +7 -8
  83. package/dist/lib/signal/graph/resource.mjs +597 -1
  84. package/dist/lib/signal/graph/runtime.cjs +501 -1
  85. package/dist/lib/signal/graph/runtime.d.ts +9 -9
  86. package/dist/lib/signal/graph/runtime.d.ts.map +1 -1
  87. package/dist/lib/signal/graph/runtime.js +56 -37
  88. package/dist/lib/signal/graph/runtime.mjs +478 -1
  89. package/dist/lib/signal/graph/signal-next.cjs +1208 -1
  90. package/dist/lib/signal/graph/signal-next.d.ts +5 -5
  91. package/dist/lib/signal/graph/signal-next.d.ts.map +1 -1
  92. package/dist/lib/signal/graph/signal-next.js +14 -12
  93. package/dist/lib/signal/graph/signal-next.mjs +1186 -1
  94. package/dist/lib/signal/graph/ssr-hooks.cjs +60 -1
  95. package/dist/lib/signal/graph/ssr-hooks.d.ts +6 -7
  96. package/dist/lib/signal/graph/ssr-hooks.d.ts.map +1 -1
  97. package/dist/lib/signal/graph/ssr-hooks.js +6 -7
  98. package/dist/lib/signal/graph/ssr-hooks.mjs +39 -1
  99. package/dist/lib/signal/graph/state.cjs +72 -1
  100. package/dist/lib/signal/graph/state.d.ts +43 -10
  101. package/dist/lib/signal/graph/state.d.ts.map +1 -1
  102. package/dist/lib/signal/graph/state.js +83 -21
  103. package/dist/lib/signal/graph/state.mjs +49 -1
  104. package/dist/lib/signal/graph/suspense.cjs +301 -1
  105. package/dist/lib/signal/graph/suspense.js +4 -4
  106. package/dist/lib/signal/graph/suspense.mjs +278 -1
  107. package/dist/lib/signal/index-legacy.cjs +2540 -1
  108. package/dist/lib/signal/index-legacy.d.ts +1 -1
  109. package/dist/lib/signal/index-legacy.js +1 -1
  110. package/dist/lib/signal/index-legacy.mjs +2518 -1
  111. package/dist/lib/signal/index.cjs +1275 -1
  112. package/dist/lib/signal/index.d.ts +5 -2
  113. package/dist/lib/signal/index.d.ts.map +1 -1
  114. package/dist/lib/signal/index.js +8 -3
  115. package/dist/lib/signal/index.mjs +1253 -1
  116. package/dist/lib/signal/list.cjs +549 -1
  117. package/dist/lib/signal/list.d.ts +5 -5
  118. package/dist/lib/signal/list.js +10 -10
  119. package/dist/lib/signal/list.mjs +526 -1
  120. package/dist/lib/signal/resource-api.cjs +626 -1
  121. package/dist/lib/signal/resource-api.d.ts +5 -5
  122. package/dist/lib/signal/resource-api.js +5 -5
  123. package/dist/lib/signal/resource-api.mjs +603 -1
  124. package/dist/lib/signal/signal.cjs +2023 -1
  125. package/dist/lib/signal/signal.d.ts +4 -4
  126. package/dist/lib/signal/signal.d.ts.map +1 -1
  127. package/dist/lib/signal/signal.js +22 -23
  128. package/dist/lib/signal/signal.mjs +2000 -1
  129. package/dist/lib/signal/types.cjs +38 -1
  130. package/dist/lib/signal/types.d.ts.map +1 -1
  131. package/dist/lib/signal/types.js +2 -2
  132. package/dist/lib/signal/types.mjs +17 -1
  133. package/dist/lib/signal/utilities.cjs +1012 -1
  134. package/dist/lib/signal/utilities.d.ts +0 -108
  135. package/dist/lib/signal/utilities.d.ts.map +1 -1
  136. package/dist/lib/signal/utilities.js +0 -158
  137. package/dist/lib/signal/utilities.mjs +990 -1
  138. package/dist/lib/store/api.cjs +612 -1
  139. package/dist/lib/store/api.d.ts +33 -0
  140. package/dist/lib/store/api.d.ts.map +1 -1
  141. package/dist/lib/store/api.js +41 -8
  142. package/dist/lib/store/api.mjs +596 -1
  143. package/dist/lib/store/index.cjs +691 -1
  144. package/dist/lib/store/index.js +1 -1
  145. package/dist/lib/store/index.mjs +676 -1
  146. package/dist/lib/store/setter.types.cjs +18 -1
  147. package/dist/lib/store/setter.types.d.ts +43 -3
  148. package/dist/lib/store/setter.types.d.ts.map +1 -1
  149. package/dist/lib/store/store.cjs +658 -1
  150. package/dist/lib/store/store.d.ts +72 -0
  151. package/dist/lib/store/store.d.ts.map +1 -1
  152. package/dist/lib/store/store.js +294 -11
  153. package/dist/lib/store/store.mjs +644 -1
  154. package/dist/lib/store/types.cjs +18 -1
  155. package/dist/lib/store/types.d.ts +1 -1
  156. package/dist/lib/store/types.d.ts.map +1 -1
  157. package/dist/lib/store/utils.cjs +43 -1
  158. package/dist/lib/store/utils.d.ts +1 -1
  159. package/dist/lib/store/utils.js +1 -1
  160. package/dist/lib/store/utils.mjs +22 -1
  161. package/dist/lib/subject.cjs +450 -1
  162. package/dist/lib/subject.js +3 -91
  163. package/dist/lib/subject.mjs +427 -1
  164. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  165. package/dist/version.generated.cjs +27 -1
  166. package/dist/version.generated.d.ts +1 -1
  167. package/dist/version.generated.js +2 -2
  168. package/dist/version.generated.mjs +7 -1
  169. package/package.json +5 -4
@@ -1,3 +1,4 @@
1
+ import { type Context, type Owner } from './graph/runtime.js';
1
2
  import type { Accessor, Setter, SignalOptions } from './signal.js';
2
3
  /** A writable reactive value: call it to read, `.set()` to write. */
3
4
  export type SignalHandle<T> = Accessor<T> & {
@@ -5,9 +6,218 @@ export type SignalHandle<T> = Accessor<T> & {
5
6
  };
6
7
  /** A derived value. Read-only, so it is just the accessor. */
7
8
  export type MemoHandle<T> = Accessor<T>;
9
+ /**
10
+ * A writable reactive value.
11
+ *
12
+ * The returned function *is* the accessor, with `set` hung off it, so it passes
13
+ * anywhere an accessor is expected and a read is an ordinary call. Reading inside a
14
+ * tracked scope subscribes that scope; reading outside one does not.
15
+ *
16
+ * `options.equals` decides what counts as a change and defaults to `===`. A write that
17
+ * compares equal notifies nobody, which is how a reflect loop or a feedback cycle
18
+ * terminates.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const count = signal(0);
23
+ * count(); // 0
24
+ * count.set(1); // write a value
25
+ * count.set((n) => n + 1); // or derive from the previous one
26
+ * ```
27
+ *
28
+ * @example A function value has to be wrapped, because a bare function is read as an
29
+ * updater and called:
30
+ * ```ts
31
+ * const handler = signal<() => void>(() => {});
32
+ * handler.set(() => myCallback); // stores myCallback
33
+ * handler.set(myCallback); // calls myCallback and stores what it returned
34
+ * ```
35
+ *
36
+ * @example Deep values compare by identity unless told otherwise:
37
+ * ```ts
38
+ * const point = signal({ x: 0 }, { equals: (a, b) => a.x === b.x });
39
+ * ```
40
+ */
8
41
  export declare function signal<T>(value: T, options?: SignalOptions<T>): SignalHandle<T>;
9
42
  export declare function signal<T = undefined>(): SignalHandle<T | undefined>;
43
+ /**
44
+ * A derived value, computed once per change and cached.
45
+ *
46
+ * Lazy and pull-based: the function does not run until something reads the memo, and
47
+ * then not again until one of its own dependencies changes. That is the difference from
48
+ * {@link computed}, which exists to do work rather than to hold a value.
49
+ *
50
+ * `prev` is the previous result, which makes an accumulator cheap without a second
51
+ * signal to hold it.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const first = signal('Ada');
56
+ * const last = signal('Lovelace');
57
+ * const full = memo(() => `${first()} ${last()}`);
58
+ * full(); // 'Ada Lovelace', computed now
59
+ * full(); // cached, the function did not run again
60
+ * ```
61
+ *
62
+ * @example Reading the previous value:
63
+ * ```ts
64
+ * const high = memo((prev = 0) => Math.max(prev, reading()), 0);
65
+ * ```
66
+ */
10
67
  export declare function memo<T>(fn: (prev?: T) => T, value?: T, options?: SignalOptions<T>): MemoHandle<T>;
11
- /** Run `fn` and re-run it when anything it read changes. Returns its disposer. */
68
+ /**
69
+ * Run `fn` now, and again whenever anything it read changes.
70
+ *
71
+ * Dependencies are collected by reading, not declared, so they are whatever the last
72
+ * run actually touched. A branch not taken subscribes to nothing, and a read behind a
73
+ * condition comes and goes with it.
74
+ *
75
+ * Eager. It runs once on creation and again as soon as a dependency is written, in the
76
+ * same task as the write. `batch` is what coalesces a group of writes into one run.
77
+ *
78
+ * Teardown goes through `onCleanup`, which runs before the next execution and once more
79
+ * on disposal. A returned function is **not** teardown: the return value is carried
80
+ * forward as the next call's `prev`, so returning a disposer silently leaks it. The
81
+ * effect is owned by the enclosing {@link root}, so disposing that disposes this.
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * const query = signal('');
86
+ * effect(() => console.log('searching', query()));
87
+ * ```
88
+ *
89
+ * @example Teardown between runs, via onCleanup rather than a return:
90
+ * ```ts
91
+ * effect(() => {
92
+ * const id = setInterval(tick, delay());
93
+ * onCleanup(() => clearInterval(id));
94
+ * });
95
+ * ```
96
+ *
97
+ * @example Writing a signal an effect reads re-triggers it. Break the cycle with
98
+ * `untrack`, or make the write compare equal:
99
+ * ```ts
100
+ * effect(() => save(untrack(() => draft())));
101
+ * ```
102
+ *
103
+ * @returns Its disposer, for an effect created outside a root.
104
+ */
12
105
  export declare function effect<T>(fn: (prev?: T) => T | (() => void), value?: T): () => void;
106
+ /**
107
+ * The rest of the `create` prefix, dropped.
108
+ *
109
+ * Each one calls through to the long name with the same arguments. Both spellings stay
110
+ * and mix freely; the graph does not know which was written.
111
+ *
112
+ * `onCleanup`, `getOwner` and `runWithOwner` keep their names. The rule here is losing
113
+ * a `create` that adds nothing, and none of those three has one; `cleanup` would also
114
+ * lose the sense that it registers a callback rather than performing one now.
115
+ */
116
+ /**
117
+ * An owner scope with an explicit disposer.
118
+ *
119
+ * Every signal, memo, effect and nested scope created while `fn` runs belongs to this
120
+ * one, and `dispose()` takes all of them down together. Without an owner an effect has
121
+ * nothing to tear it down, which is the usual source of a leak.
122
+ *
123
+ * A root created inside another root is attached to it, so disposal is recursive. To
124
+ * detach deliberately, create the root where no owner is current.
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * const stop = root((dispose) => {
129
+ * effect(() => render(state()));
130
+ * onCleanup(() => detachListeners());
131
+ * return dispose;
132
+ * });
133
+ * stop(); // effect and cleanup both run
134
+ * ```
135
+ *
136
+ * @returns Whatever `fn` returns. Return the disposer when the caller needs it.
137
+ */
138
+ export declare function root<T>(fn: (dispose: () => void) => T): T;
139
+ /**
140
+ * The effect form `@fluixi/dom` wires its bindings with.
141
+ *
142
+ * Timing is identical to {@link effect} in this runtime: both are eager, and both
143
+ * re-run in the task that wrote their dependency. The render-versus-commit distinction
144
+ * the name suggests is a DOM-layer concern, not a graph one, so do not reach for this
145
+ * expecting different scheduling.
146
+ *
147
+ * What differs is that it is not reported to devtools. Every DOM binding goes through
148
+ * here, and a graph carrying one node per text node is not a graph anyone reads.
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * renderEffect(() => el.setAttribute('aria-expanded', String(open())));
153
+ * ```
154
+ */
155
+ export declare function renderEffect<T>(fn: (prev?: T) => T | (() => void), value?: T): () => void;
156
+ /**
157
+ * A tracked computation whose result nobody reads.
158
+ *
159
+ * Eager where {@link memo} is lazy. A memo that nothing reads never runs at all, so a
160
+ * memo written for its side effect silently does nothing; this is the form for work
161
+ * that has to happen on every change.
162
+ *
163
+ * Timing matches {@link effect}, and so does ordering: they run in creation order, not
164
+ * in two phases. A `computed` that writes a signal an effect reads has to be created
165
+ * first for the effect to see the settled value.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * computed(() => {
170
+ * valid.set(email().includes('@')); // derive into another signal
171
+ * });
172
+ * ```
173
+ *
174
+ * @example `prev` threads the last result through, with no signal to hold it:
175
+ * ```ts
176
+ * computed((runs = 0) => {
177
+ * void query();
178
+ * return runs + 1;
179
+ * }, 0);
180
+ * ```
181
+ */
182
+ export declare function computed<T>(fn: (prev?: T) => T, value?: T): void;
183
+ /**
184
+ * A context key: a value passed down an owner tree instead of through props.
185
+ *
186
+ * Lookup walks owners, not the DOM, so a consumer sees whatever provider encloses it
187
+ * reactively. A consumer with no provider above it gets `defaultValue`, which is why
188
+ * supplying one is usually better than handling undefined everywhere.
189
+ *
190
+ * Pass `name`. Unnamed, the key is a bare symbol and a devtools panel has nothing to
191
+ * label the node with.
192
+ *
193
+ * @example
194
+ * ```ts
195
+ * const Theme = context<'light' | 'dark'>('light', 'theme');
196
+ *
197
+ * // provider side, as a component
198
+ * Theme.Provider({ value: 'dark', children: () => renderPage() });
199
+ *
200
+ * // consumer side, anywhere below it
201
+ * const theme = useContext(Theme); // 'dark' here, 'light' with no provider
202
+ * ```
203
+ */
204
+ export declare function context<T>(defaultValue?: T, name?: string): Context<T>;
205
+ /**
206
+ * A child scope of `parent`, created without entering it.
207
+ *
208
+ * Low level, and rarely the right tool. {@link root} both creates a scope and makes it
209
+ * current, which is what almost all code wants. This hands back an owner to hold and
210
+ * enter later with `runWithOwner`, for a scope whose lifetime does not match the call
211
+ * that created it: a cached subtree, or one list row among many.
212
+ *
213
+ * Disposing `parent` disposes this, since it is attached on creation.
214
+ *
215
+ * @example
216
+ * ```ts
217
+ * const scope = childOwner(getOwner());
218
+ * // later, and possibly from another task
219
+ * runWithOwner(scope, () => effect(() => paint(row())));
220
+ * ```
221
+ */
222
+ export declare function childOwner(parent: Owner | null): Owner;
13
223
  //# sourceMappingURL=api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/lib/signal/api.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,qEAAqE;AACrE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC;AAE/D,8DAA8D;AAC9D,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AAExC,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AACjF,wBAAgB,MAAM,CAAC,CAAC,GAAG,SAAS,KAAK,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAMrE,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAEjG;AAED,kFAAkF;AAClF,wBAAgB,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,CAEnF"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/lib/signal/api.ts"],"names":[],"mappings":"AAiCA,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,KAAK,EACX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,qEAAqE;AACrE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC;AAE/D,8DAA8D;AAC9D,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AACjF,wBAAgB,MAAM,CAAC,CAAC,GAAG,SAAS,KAAK,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAMrE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAEjG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,CAEnF;AAED;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAEzD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,CAEzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAEhE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAEtE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAEtD"}
@@ -1,31 +1,226 @@
1
1
  /**
2
- * The short reactive API: `signal`, `memo`, `effect`.
2
+ * The short reactive API: the `create` prefix dropped, where dropping it loses nothing.
3
+ *
4
+ * signal memo effect root renderEffect computed context childOwner
3
5
  *
4
6
  * const count = signal(0);
5
7
  * count(); // read
6
8
  * count.set(1); // write
7
9
  *
8
- * `signal` is `createSignal` with the setter attached to the accessor instead of handed
9
- * back beside it. The function IS that accessor, so a read is the same call it always
10
- * was, `count` passes anywhere an accessor is expected, and only the write changes
11
- * spelling. `memo` is `createMemo` under a shorter name a derived value has nothing to
12
- * set, so there is nothing to attach.
10
+ * `signal` is `createSignal` with the setter attached to the accessor rather than handed
11
+ * back beside it. The returned function is the accessor itself, so a read is the call it
12
+ * always was and `count` still passes anywhere an accessor is expected. Only the write
13
+ * changes spelling. `memo` is `createMemo` renamed and no more than that: a derived value
14
+ * has nothing to set, so there is nothing to attach.
15
+ *
16
+ * The rule across the API is to read a thing the way its shape implies. A call for a
17
+ * value, a property for an object (see `store`), and `.set()` to write.
13
18
  *
14
- * The rule across the API: read it the way its shape implies a call for a value, a
15
- * property for an object (see `store`) and `.set()` writes.
19
+ * The long names are unchanged and the two spellings are one primitive, so they mix
20
+ * freely. `onCleanup`, `getOwner` and `runWithOwner` are not here: they have no `create`
21
+ * to drop, and `cleanup` would read as performing one rather than registering one.
16
22
  *
17
- * `createSignal` and friends are unchanged; the two forms are one primitive and mix
18
- * freely.
23
+ * Two of these names promise scheduling they do not deliver, which the per-function
24
+ * docs say outright: `renderEffect` has the same timing as `effect`, and `computed` runs
25
+ * in creation order alongside it rather than in an earlier phase.
19
26
  */
20
- import { createEffect, createMemo, createSignal } from './graph/compat.js';
27
+ import { createComputed, createEffect, createMemo, createRenderEffect, createSignal, } from './graph/compat.js';
28
+ import { createChildOwner, createContext, createRoot, } from './graph/runtime.js';
21
29
  export function signal(value, options) {
22
30
  const [read, write] = createSignal(value, options);
23
31
  return Object.assign(read, { set: write });
24
32
  }
33
+ /**
34
+ * A derived value, computed once per change and cached.
35
+ *
36
+ * Lazy and pull-based: the function does not run until something reads the memo, and
37
+ * then not again until one of its own dependencies changes. That is the difference from
38
+ * {@link computed}, which exists to do work rather than to hold a value.
39
+ *
40
+ * `prev` is the previous result, which makes an accumulator cheap without a second
41
+ * signal to hold it.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * const first = signal('Ada');
46
+ * const last = signal('Lovelace');
47
+ * const full = memo(() => `${first()} ${last()}`);
48
+ * full(); // 'Ada Lovelace', computed now
49
+ * full(); // cached, the function did not run again
50
+ * ```
51
+ *
52
+ * @example Reading the previous value:
53
+ * ```ts
54
+ * const high = memo((prev = 0) => Math.max(prev, reading()), 0);
55
+ * ```
56
+ */
25
57
  export function memo(fn, value, options) {
26
58
  return createMemo(fn, value, options);
27
59
  }
28
- /** Run `fn` and re-run it when anything it read changes. Returns its disposer. */
60
+ /**
61
+ * Run `fn` now, and again whenever anything it read changes.
62
+ *
63
+ * Dependencies are collected by reading, not declared, so they are whatever the last
64
+ * run actually touched. A branch not taken subscribes to nothing, and a read behind a
65
+ * condition comes and goes with it.
66
+ *
67
+ * Eager. It runs once on creation and again as soon as a dependency is written, in the
68
+ * same task as the write. `batch` is what coalesces a group of writes into one run.
69
+ *
70
+ * Teardown goes through `onCleanup`, which runs before the next execution and once more
71
+ * on disposal. A returned function is **not** teardown: the return value is carried
72
+ * forward as the next call's `prev`, so returning a disposer silently leaks it. The
73
+ * effect is owned by the enclosing {@link root}, so disposing that disposes this.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const query = signal('');
78
+ * effect(() => console.log('searching', query()));
79
+ * ```
80
+ *
81
+ * @example Teardown between runs, via onCleanup rather than a return:
82
+ * ```ts
83
+ * effect(() => {
84
+ * const id = setInterval(tick, delay());
85
+ * onCleanup(() => clearInterval(id));
86
+ * });
87
+ * ```
88
+ *
89
+ * @example Writing a signal an effect reads re-triggers it. Break the cycle with
90
+ * `untrack`, or make the write compare equal:
91
+ * ```ts
92
+ * effect(() => save(untrack(() => draft())));
93
+ * ```
94
+ *
95
+ * @returns Its disposer, for an effect created outside a root.
96
+ */
29
97
  export function effect(fn, value) {
30
98
  return createEffect(fn, value);
31
99
  }
100
+ /**
101
+ * The rest of the `create` prefix, dropped.
102
+ *
103
+ * Each one calls through to the long name with the same arguments. Both spellings stay
104
+ * and mix freely; the graph does not know which was written.
105
+ *
106
+ * `onCleanup`, `getOwner` and `runWithOwner` keep their names. The rule here is losing
107
+ * a `create` that adds nothing, and none of those three has one; `cleanup` would also
108
+ * lose the sense that it registers a callback rather than performing one now.
109
+ */
110
+ /**
111
+ * An owner scope with an explicit disposer.
112
+ *
113
+ * Every signal, memo, effect and nested scope created while `fn` runs belongs to this
114
+ * one, and `dispose()` takes all of them down together. Without an owner an effect has
115
+ * nothing to tear it down, which is the usual source of a leak.
116
+ *
117
+ * A root created inside another root is attached to it, so disposal is recursive. To
118
+ * detach deliberately, create the root where no owner is current.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * const stop = root((dispose) => {
123
+ * effect(() => render(state()));
124
+ * onCleanup(() => detachListeners());
125
+ * return dispose;
126
+ * });
127
+ * stop(); // effect and cleanup both run
128
+ * ```
129
+ *
130
+ * @returns Whatever `fn` returns. Return the disposer when the caller needs it.
131
+ */
132
+ export function root(fn) {
133
+ return createRoot(fn);
134
+ }
135
+ /**
136
+ * The effect form `@fluixi/dom` wires its bindings with.
137
+ *
138
+ * Timing is identical to {@link effect} in this runtime: both are eager, and both
139
+ * re-run in the task that wrote their dependency. The render-versus-commit distinction
140
+ * the name suggests is a DOM-layer concern, not a graph one, so do not reach for this
141
+ * expecting different scheduling.
142
+ *
143
+ * What differs is that it is not reported to devtools. Every DOM binding goes through
144
+ * here, and a graph carrying one node per text node is not a graph anyone reads.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * renderEffect(() => el.setAttribute('aria-expanded', String(open())));
149
+ * ```
150
+ */
151
+ export function renderEffect(fn, value) {
152
+ return createRenderEffect(fn, value);
153
+ }
154
+ /**
155
+ * A tracked computation whose result nobody reads.
156
+ *
157
+ * Eager where {@link memo} is lazy. A memo that nothing reads never runs at all, so a
158
+ * memo written for its side effect silently does nothing; this is the form for work
159
+ * that has to happen on every change.
160
+ *
161
+ * Timing matches {@link effect}, and so does ordering: they run in creation order, not
162
+ * in two phases. A `computed` that writes a signal an effect reads has to be created
163
+ * first for the effect to see the settled value.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * computed(() => {
168
+ * valid.set(email().includes('@')); // derive into another signal
169
+ * });
170
+ * ```
171
+ *
172
+ * @example `prev` threads the last result through, with no signal to hold it:
173
+ * ```ts
174
+ * computed((runs = 0) => {
175
+ * void query();
176
+ * return runs + 1;
177
+ * }, 0);
178
+ * ```
179
+ */
180
+ export function computed(fn, value) {
181
+ createComputed(fn, value);
182
+ }
183
+ /**
184
+ * A context key: a value passed down an owner tree instead of through props.
185
+ *
186
+ * Lookup walks owners, not the DOM, so a consumer sees whatever provider encloses it
187
+ * reactively. A consumer with no provider above it gets `defaultValue`, which is why
188
+ * supplying one is usually better than handling undefined everywhere.
189
+ *
190
+ * Pass `name`. Unnamed, the key is a bare symbol and a devtools panel has nothing to
191
+ * label the node with.
192
+ *
193
+ * @example
194
+ * ```ts
195
+ * const Theme = context<'light' | 'dark'>('light', 'theme');
196
+ *
197
+ * // provider side, as a component
198
+ * Theme.Provider({ value: 'dark', children: () => renderPage() });
199
+ *
200
+ * // consumer side, anywhere below it
201
+ * const theme = useContext(Theme); // 'dark' here, 'light' with no provider
202
+ * ```
203
+ */
204
+ export function context(defaultValue, name) {
205
+ return createContext(defaultValue, name);
206
+ }
207
+ /**
208
+ * A child scope of `parent`, created without entering it.
209
+ *
210
+ * Low level, and rarely the right tool. {@link root} both creates a scope and makes it
211
+ * current, which is what almost all code wants. This hands back an owner to hold and
212
+ * enter later with `runWithOwner`, for a scope whose lifetime does not match the call
213
+ * that created it: a cached subtree, or one list row among many.
214
+ *
215
+ * Disposing `parent` disposes this, since it is attached on creation.
216
+ *
217
+ * @example
218
+ * ```ts
219
+ * const scope = childOwner(getOwner());
220
+ * // later, and possibly from another task
221
+ * runWithOwner(scope, () => effect(() => paint(row())));
222
+ * ```
223
+ */
224
+ export function childOwner(parent) {
225
+ return createChildOwner(parent);
226
+ }