@torpor/view 0.4.18 → 1.0.1

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 (72) hide show
  1. package/README.md +41 -16
  2. package/dist/Cleanup-D0wvGW5d.d.cts +9 -0
  3. package/dist/Cleanup-D0wvGW5d.d.cts.map +1 -0
  4. package/dist/Cleanup-D0wvGW5d.d.mts +9 -0
  5. package/dist/Cleanup-D0wvGW5d.d.mts.map +1 -0
  6. package/dist/Component-0MH0zd-m.d.cts +11 -0
  7. package/dist/Component-0MH0zd-m.d.cts.map +1 -0
  8. package/dist/Component-0MH0zd-m.d.mts +11 -0
  9. package/dist/Component-0MH0zd-m.d.mts.map +1 -0
  10. package/dist/Effect-BTKurOpr.d.mts +381 -0
  11. package/dist/Effect-BTKurOpr.d.mts.map +1 -0
  12. package/dist/Effect-COl3aRJV.d.cts +381 -0
  13. package/dist/Effect-COl3aRJV.d.cts.map +1 -0
  14. package/dist/compile.cjs +1734 -739
  15. package/dist/compile.d.cts +85 -50
  16. package/dist/compile.d.cts.map +1 -1
  17. package/dist/compile.d.mts +85 -50
  18. package/dist/compile.d.mts.map +1 -1
  19. package/dist/compile.mjs +1737 -741
  20. package/dist/compile.mjs.map +1 -1
  21. package/dist/dev.cjs +62 -63
  22. package/dist/dev.d.cts +4 -3
  23. package/dist/dev.d.cts.map +1 -1
  24. package/dist/dev.d.mts +4 -3
  25. package/dist/dev.d.mts.map +1 -1
  26. package/dist/dev.mjs +61 -62
  27. package/dist/dev.mjs.map +1 -1
  28. package/dist/{devContext-B3yskfhA.cjs → devContext-BulTn3U5.cjs} +6 -9
  29. package/dist/{devContext-CQ8RhBX-.mjs → devContext-ZNsPyOgB.mjs} +3 -4
  30. package/dist/devContext-ZNsPyOgB.mjs.map +1 -0
  31. package/dist/fromWebSocket-1QOjcrHE.cjs +182 -0
  32. package/dist/fromWebSocket-B52kN3-W.d.mts +91 -0
  33. package/dist/fromWebSocket-B52kN3-W.d.mts.map +1 -0
  34. package/dist/fromWebSocket-DeB35Q4w.d.cts +91 -0
  35. package/dist/fromWebSocket-DeB35Q4w.d.cts.map +1 -0
  36. package/dist/fromWebSocket-Dxc_uwm1.mjs +137 -0
  37. package/dist/fromWebSocket-Dxc_uwm1.mjs.map +1 -0
  38. package/dist/index.cjs +2109 -494
  39. package/dist/index.d.cts +608 -112
  40. package/dist/index.d.cts.map +1 -1
  41. package/dist/index.d.mts +608 -112
  42. package/dist/index.d.mts.map +1 -1
  43. package/dist/index.mjs +2088 -490
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/ssr.cjs +78 -17
  46. package/dist/ssr.d.cts +64 -11
  47. package/dist/ssr.d.cts.map +1 -1
  48. package/dist/ssr.d.mts +64 -11
  49. package/dist/ssr.d.mts.map +1 -1
  50. package/dist/ssr.mjs +67 -14
  51. package/dist/ssr.mjs.map +1 -1
  52. package/package.json +21 -19
  53. package/dist/Cleanup-CYsytTEc.d.cts +0 -9
  54. package/dist/Cleanup-CYsytTEc.d.cts.map +0 -1
  55. package/dist/Cleanup-CgjyN0lW.d.mts +0 -9
  56. package/dist/Cleanup-CgjyN0lW.d.mts.map +0 -1
  57. package/dist/Component-DmWGMgak.d.mts +0 -11
  58. package/dist/Component-DmWGMgak.d.mts.map +0 -1
  59. package/dist/Component-kGLRFYg2.d.cts +0 -11
  60. package/dist/Component-kGLRFYg2.d.cts.map +0 -1
  61. package/dist/Region-Bb6HAb-F.d.cts +0 -201
  62. package/dist/Region-Bb6HAb-F.d.cts.map +0 -1
  63. package/dist/Region-CTchywkr.d.mts +0 -201
  64. package/dist/Region-CTchywkr.d.mts.map +0 -1
  65. package/dist/devContext-CQ8RhBX-.mjs.map +0 -1
  66. package/dist/formatText-BNP3P38F.d.cts +0 -17
  67. package/dist/formatText-BNP3P38F.d.cts.map +0 -1
  68. package/dist/formatText-D6Ov8Ub0.d.mts +0 -17
  69. package/dist/formatText-D6Ov8Ub0.d.mts.map +0 -1
  70. package/dist/formatText-DTIRmc3X.mjs +0 -61
  71. package/dist/formatText-DTIRmc3X.mjs.map +0 -1
  72. package/dist/formatText-Dhl2O0Ee.cjs +0 -96
package/dist/index.d.cts CHANGED
@@ -1,8 +1,7 @@
1
- import { n as SlotRender, t as Component } from "./Component-kGLRFYg2.cjs";
2
- import { t as Cleanup } from "./Cleanup-CYsytTEc.cjs";
3
- import { n as Effect, t as Region } from "./Region-Bb6HAb-F.cjs";
4
- import { a as ClassValue, i as buildClasses, n as buildStyles, r as StyleValue, t as formatText } from "./formatText-BNP3P38F.cjs";
5
-
1
+ import { n as SlotRender, t as Component } from "./Component-0MH0zd-m.cjs";
2
+ import { t as Cleanup } from "./Cleanup-D0wvGW5d.cjs";
3
+ import { n as Region, t as Effect } from "./Effect-COl3aRJV.cjs";
4
+ import { a as buildStyles, c as ClassValue, i as StreamSource, n as fromServer, o as StyleValue, r as fromElement, s as buildClasses, t as fromWebSocket } from "./fromWebSocket-DeB35Q4w.cjs";
6
5
  //#region src/types/Animation.d.ts
7
6
  interface Animation {
8
7
  keyframes: Keyframe[] | PropertyIndexedKeyframes;
@@ -15,46 +14,162 @@ declare function addAnimation(el: HTMLElement, entry?: Animation, exit?: Animati
15
14
  //#region src/render/addEvent.d.ts
16
15
  declare function addEvent(el: Element, type: string, listener: ((this: Element, ev: any) => any) | undefined | null): void;
17
16
  //#endregion
17
+ //#region src/render/addElement.d.ts
18
+ /**
19
+ * Companion to `addFragment` for the single-root-element codegen path. Wires
20
+ * a cloned root element (produced by `getElementFragment`) into the live DOM
21
+ * tree, sets the active region's start/end nodes, and runs the same
22
+ * mount-time side effects as `addFragment` (`$onmount` effects, stashed event
23
+ * listeners, stashed animations).
24
+ *
25
+ * Differences from `addFragment`:
26
+ * - `node` is both the start and end of the region (no
27
+ * `fragment.firstChild`/`fragment.lastChild` indirection).
28
+ * - When hydrating, the existing DOM node is reused (the cloned `node` is
29
+ * discarded); `endNode` is still `node` because `nodeRootElement` returns
30
+ * the hydration cursor's node in that case, not the cloned one.
31
+ *
32
+ * @param node The root element (cloned by `getElementFragment`, or the
33
+ * hydration cursor's node when hydrating).
34
+ * @param parent The intended parent element.
35
+ * @param before The sibling to insert before (or `null` to append).
36
+ */
37
+ declare function addElement(node: Element, parent: ParentNode, before: Node | null): void;
38
+ //#endregion
18
39
  //#region src/render/addFragment.d.ts
19
- declare function addFragment(fragment: DocumentFragment, parent: ParentNode, before: Node | null, endNode?: ChildNode): void;
40
+ declare function addFragment(fragment: DocumentFragment, parent: ParentNode, before: Node | null, endNode?: ChildNode, startNode?: ChildNode): void;
20
41
  //#endregion
21
42
  //#region src/render/applyProps.d.ts
22
43
  declare function applyProps(el: Element, props: Record<string, any> | undefined, propNamesUsed: string[]): void;
23
44
  //#endregion
24
45
  //#region src/render/clearLayoutSlot.d.ts
46
+ /**
47
+ * Clears a region that was created by `fillLayoutSlot`: tears down the
48
+ * rendered content and its effects, leaving the surrounding layout intact
49
+ * so the slot can be refilled.
50
+ *
51
+ * @param region The region to clear
52
+ */
25
53
  declare function clearLayoutSlot(region: Region): void;
26
54
  //#endregion
27
55
  //#region src/render/fillLayoutSlot.d.ts
28
- declare function fillLayoutSlot(component: Component, slot: SlotRender, parent: ParentNode, anchor: Node | null, $props?: Record<string, string>, $context?: Record<PropertyKey, any>): Region;
56
+ /**
57
+ * Renders a component into a persistent layout slot, and returns the region
58
+ * it was rendered into. Used by the layout engine during navigation: the
59
+ * component is created inside `parent` at `anchor`, with `slot` as its child
60
+ * slot render, and the returned region can later be passed to
61
+ * `clearLayoutSlot` to tear the page down — leaving the layout itself
62
+ * intact — before refilling the slot.
63
+ *
64
+ * @param component The component to render into the slot
65
+ * @param slot The slot render to pass to the component
66
+ * @param parent The parent node to render into
67
+ * @param anchor The node to insert content before, or null to append
68
+ * @param $props Optional props to pass to the component
69
+ * @param $context Optional context to pass to the component
70
+ */
71
+ declare function fillLayoutSlot(component: Component, slot: SlotRender, parent: ParentNode, anchor: Node | null, $props?: Record<PropertyKey, any>, $context?: Record<PropertyKey, any>): Region;
72
+ //#endregion
73
+ //#region src/render/formatText.d.ts
74
+ declare function formatText(value: any): string;
75
+ //#endregion
76
+ //#region src/render/firstInsideNode.d.ts
77
+ /**
78
+ * Gets the first node that was inside the hydration block for the given
79
+ * anchor node, or `undefined` if the anchor wasn't hydrated through
80
+ * hydration markers.
81
+ */
82
+ declare function firstInsideNode(anchor: ChildNode): ChildNode | null | undefined;
29
83
  //#endregion
30
84
  //#region src/render/getFragment.d.ts
31
85
  declare function getFragment(document: Document, array: DocumentFragment[], index: number, html: string, ns?: boolean): DocumentFragment;
32
86
  //#endregion
87
+ //#region src/render/getElementFragment.d.ts
88
+ /**
89
+ * Returns a clone of the cached template's single root element, bypassing the
90
+ * `DocumentFragment` wrapper that `getFragment` produces.
91
+ *
92
+ * Used by the compiler-emitted `createListItem` for `@for` bodies (and other
93
+ * fragments) whose template has exactly one rendering root child — e.g.
94
+ * `<tr><td>...</td>...</tr>`. Cloning `template.content.firstElementChild`
95
+ * directly saves the per-row `DocumentFragment` allocation that `getFragment`'s
96
+ * `cloneNode(true)` on the cached template's content would otherwise produce,
97
+ * which dominates the cost of bulk-row creates (`run`/`add`/`runlots`).
98
+ *
99
+ * Contract: the compiler only emits `t_fragment_el` for fragment indices whose
100
+ * template has exactly one rendering root, and that root is an `Element`. The
101
+ * cache array (`t_fragment_els`) is separate from `t_fragments` so each helper
102
+ * only ever sees its own cached type at a given index.
103
+ *
104
+ * @param document The owner document (used to build the cached `<template>`).
105
+ * @param array The per-component `t_fragment_els` cache.
106
+ * @param index The fragment's index in the cache.
107
+ * @param html The fragment's HTML source, with `#` placeholders for reactive
108
+ * text and `<!>` for anchor comments.
109
+ * @param ns When true, the template is created in the SVG namespace (its
110
+ * `firstElementChild` is then an SVG element).
111
+ */
112
+ declare function getElementFragment(document: Document, array: Element[], index: number, html: string, ns?: boolean): Element;
113
+ //#endregion
33
114
  //#region src/render/hydrate.d.ts
34
115
  /**
35
- * Hydrates a component into an existing DOM tree
36
- * @param parent The parent node
37
- * @param component The component to mount
38
- * @param props An object containing component props
39
- */
116
+ * Hydrates a component into an existing DOM tree
117
+ * @param parent The parent node
118
+ * @param component The component to mount
119
+ * @param props An object containing component props
120
+ */
40
121
  declare function hydrate(parent: ParentNode, component: Component, props?: Record<string, any>, slots?: Record<string, SlotRender>): void;
41
122
  //#endregion
42
123
  //#region src/render/mount.d.ts
43
124
  /**
44
- * Mounts a component into a DOM node
45
- *
46
- * @param parent The node to mount the component into
47
- * @param component The component to mount
48
- * @param props An object containing component props
49
- */
125
+ * Mounts a component into a DOM node
126
+ *
127
+ * @param parent The node to mount the component into
128
+ * @param component The component to mount
129
+ * @param props An object containing component props
130
+ */
50
131
  declare function mount(parent: ParentNode, component: Component, props?: Record<string, any>, slots?: Record<string, SlotRender>): void;
51
132
  //#endregion
52
- //#region src/types/ListItem.d.ts
53
- interface ListItem extends Region {
54
- data: Record<string, any>;
133
+ //#region src/render/unmount.d.ts
134
+ /**
135
+ * Tears down the current UI: disposes the root region tree (running effect
136
+ * cleanups and detaching subscriptions), resets the render context, and
137
+ * removes any remaining child nodes from `parent`.
138
+ *
139
+ * Call this before `mount`ing a fresh component tree into the same container
140
+ * (e.g. when client-side navigating to a route whose layout chain differs
141
+ * from the previous one). `mount` refuses to mount into a non-empty parent
142
+ * and reuses an existing root region, so both must be cleared first.
143
+ *
144
+ * @param parent The container that the previous UI was mounted into
145
+ */
146
+ declare function unmount(parent: ParentNode): void;
147
+ //#endregion
148
+ //#region src/types/ListItemSpec.d.ts
149
+ /**
150
+ * A lightweight, per-row descriptor emitted by the compiler's `@for`
151
+ * `buildItems` callback: just the key (for reconciliation) and the data bag
152
+ * (the loop variables). Unlike a full {@link ListItem}, a spec carries no DOM
153
+ * nodes, no effects, and no sibling-chain pointers — so allocating one per row
154
+ * on every list update is cheap.
155
+ *
156
+ * The keyed-list reconciler (`runListItems`) maps each spec to either an
157
+ * existing `ListItem` (matched by key, reused wholesale) or a freshly mounted
158
+ * one (for genuinely new keys), keeping the per-update cost proportional to
159
+ * what actually changed instead of to the list size.
160
+ *
161
+ * NOTE: `data` is `any` rather than `Record<string, any>` -- when a `@for`
162
+ * body binds a single loop variable and is proxy-safe, the variable is stored
163
+ * directly (e.g. `data: page` for a number), not as a bag.
164
+ */
165
+ interface ListItemSpec {
55
166
  key: any;
167
+ data: any;
56
168
  }
57
169
  //#endregion
170
+ //#region src/types/ListItem.d.ts
171
+ interface ListItem extends Region, ListItemSpec {}
172
+ //#endregion
58
173
  //#region src/render/newListItem.d.ts
59
174
  declare function newListItem(data: Record<PropertyKey, any>, key?: any, name?: string): ListItem;
60
175
  //#endregion
@@ -63,62 +178,91 @@ declare function newRegion(name?: string): Region;
63
178
  //#endregion
64
179
  //#region src/render/nodeAnchor.d.ts
65
180
  /**
66
- * Gets the anchor node for a control statement or component.
67
- *
68
- * When mounting, this just returns the anchor node parameter (because it was
69
- * created).
70
- *
71
- * When hydrating, there should be matched <![> and <!]> comments in the HTML,
72
- * and the anchor node should be after the end comment. The matched comment
73
- * nodes will be deleted, and the hydration node set to the first node inside
74
- * the matched comments.
75
- *
76
- * @param node The potential anchor node.
77
- * @returns The anchor node.
78
- */
181
+ * Gets the anchor node for a control statement or component.
182
+ *
183
+ * When mounting, this just returns the anchor node parameter (because it was
184
+ * created).
185
+ *
186
+ * When hydrating, there should be matched <![> and <!]> comments in the HTML,
187
+ * and the anchor node should be after the end comment. The matched comment
188
+ * nodes will be deleted, and the hydration node set to the first node inside
189
+ * the matched comments.
190
+ *
191
+ * @param node The potential anchor node.
192
+ * @returns The anchor node.
193
+ */
79
194
  declare function nodeAnchor(node: ChildNode): ChildNode;
80
195
  //#endregion
81
196
  //#region src/render/nodeChild.d.ts
82
197
  /**
83
- * Gets the first child of a node.
84
- *
85
- * Sets the hydration node.
86
- *
87
- * @param parent The parent node.
88
- */
198
+ * Gets the first child of a node.
199
+ *
200
+ * Sets the hydration node.
201
+ *
202
+ * @param parent The parent node.
203
+ */
89
204
  declare function nodeChild(parent: Node): ChildNode;
90
205
  //#endregion
91
206
  //#region src/render/nodeNext.d.ts
92
207
  /**
93
- * Gets the next sibling of a node.
94
- *
95
- * When hydrating, sets the hydration node.
96
- *
97
- * @param node The node.
98
- * @param text Whether we require a text node.
99
- */
208
+ * Gets the next sibling of a node.
209
+ *
210
+ * When hydrating, sets the hydration node.
211
+ *
212
+ * @param node The node.
213
+ * @param text Whether we require a text node.
214
+ */
100
215
  declare function nodeNext(node: ChildNode, text?: boolean): ChildNode;
101
216
  //#endregion
217
+ //#region src/render/nodeRootElement.d.ts
218
+ /**
219
+ * Gets the root element of a single-root fragment built via `getElementFragment`.
220
+ *
221
+ * Companion to `nodeRoot`, for the codegen path where the compiler has emitted
222
+ * `t_fragment_el` (cloning the cached template's `firstElementChild` directly)
223
+ * instead of `t_fragment` (cloning into a `DocumentFragment`). In the
224
+ * non-hydrating case the cloned element is already the root, so this is a
225
+ * no-op pass-through. In the hydrating case we perform the same cursor walk as
226
+ * `nodeRoot`'s non-text branch so the region's `startNode` lands on the
227
+ * existing DOM node and the hydration cursor advances past any leading
228
+ * whitespace, branch-break markers, and auto-inserted `<tbody>` wrappers.
229
+ *
230
+ * @param node The cloned root element (ignored when hydrating).
231
+ */
232
+ declare function nodeRootElement(node: Element): ChildNode;
233
+ //#endregion
102
234
  //#region src/render/nodeRoot.d.ts
103
235
  /**
104
- * Gets the first child in a fragment.
105
- *
106
- * When hydrating, also sets the active range's start node, while we have it.
107
- *
108
- * @param parent The parent of the fragment.
109
- * @param text Whether we require a text node.
110
- */
236
+ * Gets the first child in a fragment.
237
+ *
238
+ * When hydrating, also sets the active region's start node, while we have it.
239
+ *
240
+ * If the hydration cursor is on a control-start marker (`<![>`), the node is
241
+ * left in place for `nodeAnchor` (called next as `t_anchor(t_root(...))`) to
242
+ * walk — it consumes the matched `<![>...<!]>` pair, removes the markers and
243
+ * sets the region's start node to the first node inside the block.
244
+ *
245
+ * For non-text fragments, leading branch-break markers (`<!^>`), empty anchor
246
+ * comments left by preceding siblings, and residual whitespace-only text nodes
247
+ * are skipped (break markers removed) so the region's start node lands on real
248
+ * content. This replaces the per-sibling `t_next` calls that the codegen used
249
+ * to emit when leading whitespace separated siblings; with whitespace trimmed
250
+ * those calls are gone, so the advancement happens here.
251
+ *
252
+ * @param parent The parent of the fragment.
253
+ * @param text Whether we require a text node.
254
+ */
111
255
  declare function nodeRoot(parent: Node, text?: boolean): ChildNode;
112
256
  //#endregion
113
257
  //#region src/render/nodeSkip.d.ts
114
258
  /**
115
- * Gets the sibling of a node, x nodes after it.
116
- *
117
- * When hydrating, sets the hydration node.
118
- *
119
- * @param node The node.
120
- * @param count The number of nodes to skip.
121
- */
259
+ * Gets the sibling of a node, x nodes after it.
260
+ *
261
+ * When hydrating, sets the hydration node.
262
+ *
263
+ * @param node The node.
264
+ * @param count The number of nodes to skip.
265
+ */
122
266
  declare function nodeSkip(node: ChildNode, count: number): ChildNode;
123
267
  //#endregion
124
268
  //#region src/render/popRegion.d.ts
@@ -127,11 +271,54 @@ declare function popRegion(oldRegion: Region): void;
127
271
  //#region src/render/pushRegion.d.ts
128
272
  declare function pushRegion(region: Region, toParent?: boolean): Region;
129
273
  //#endregion
274
+ //#region src/render/rerunRegionEffects.d.ts
275
+ /**
276
+ * Force re-runs every effect owned by `region` and its descendant regions
277
+ * that depends on at least one of the for-vars set in `changedMask`.
278
+ *
279
+ * Used by keyed-list `updateListItem` callbacks emitted by the compiler when
280
+ * the `@for` body has been classified "no-proxy safe" — i.e. the per-item
281
+ * data bag is *not* wrapped in a shallow `$watch` Proxy. Without that Proxy,
282
+ * a write such as `t_old_item.data.row = newRow` doesn't propagate through a
283
+ * signal, so any effects that read `data.row` must be re-run manually.
284
+ *
285
+ * `changedMask` is a bitmask of the for-var positions whose references
286
+ * actually changed in this update. Each effect carries `forVarMask`
287
+ * (computed at compile time) listing the for-vars its body reads; effects
288
+ * whose `forVarMask & changedMask === 0` are skipped. Mount callbacks
289
+ * (`isMountEffect` — `$onmount`/`onmount`) are always skipped: they run
290
+ * once per DOM mount and their bodies are untracked.
291
+ *
292
+ * Equivalent to what `checkEffect` does when a signal has propagated, but
293
+ * unconditional for the effects that do match: cleanup → deactivate sources
294
+ * → run → clear unused sources, for every matching effect on the region and
295
+ * on every descendant region (`depth > region.depth`, the same chain shape
296
+ * `clearRegion` walks).
297
+ */
298
+ declare function rerunRegionEffects(region: Region, changedMask: number): void;
299
+ //#endregion
300
+ //#region src/render/restoreHydration.d.ts
301
+ /**
302
+ * Restores the hydration cursor to a previously-snapshotted node. Used by
303
+ * `@try`/`@catch`: if the try branch throws partway through its hydration
304
+ * walk, the catch branch must resume hydrating from where the try group
305
+ * started, not from wherever the failed branch left the cursor.
306
+ *
307
+ * The cursor is set unconditionally: a failed try-branch build can walk the
308
+ * cursor past the last node (setting it to `null` via `nodeNext`), and the
309
+ * rewind must still restore it — otherwise the catch branch would think it
310
+ * isn't hydrating and insert fresh nodes alongside the server's. When not
311
+ * hydrating at all, the snapshot itself is `null`, so this is a no-op.
312
+ *
313
+ * @param node The snapshotted cursor node (from `saveHydration`).
314
+ */
315
+ declare function restoreHydration(node: ChildNode | null): void;
316
+ //#endregion
130
317
  //#region src/render/runControl.d.ts
131
318
  /**
132
- * Runs an `if`, `switch` or `await` control statement
133
- * @param create A function that creates the control statement's branches
134
- */
319
+ * Runs an `if`, `switch` or `await` control statement
320
+ * @param create A function that creates the control statement's branches
321
+ */
135
322
  declare function runControl(region: Region, anchor: Node | null, create: (anchor: Node | null) => void, name?: string): void;
136
323
  //#endregion
137
324
  //#region src/render/runControlBranch.d.ts
@@ -139,10 +326,103 @@ declare function runControlBranch(region: Region, oldIndex: number, index: numbe
139
326
  //#endregion
140
327
  //#region src/render/runList.d.ts
141
328
  /**
142
- * Runs a `for` control statement
143
- * @param create A function that creates the control statement's branches
144
- */
145
- declare function runList(region: Region, parent: ParentNode, anchor: Node | null, buildItems: () => ListItem[], create: (item: ListItem, anchor: Node | null) => void, update: (oldItem: ListItem, newItem: ListItem) => void): void;
329
+ * Runs a `for` control statement
330
+ * @param buildItems A function that returns the current list of lightweight
331
+ * `{key, data}` specs (one per row of the source data)
332
+ * @param create A function that creates the control statement's branches
333
+ * @param noWatch When true, the compiler has determined the `@for` body never
334
+ * writes to its loop variables, so each item's `data` bag can be left
335
+ * unwrapped (skipping the per-item shallow `$watch` Proxy + ProxyData +
336
+ * signals Map allocations). The compiler-emitted `update` callback is then
337
+ * responsible for re-running item effects when a loop variable's reference
338
+ * actually changes (via `t_rerun_region_effects`).
339
+ */
340
+ declare function runList(region: Region, parent: ParentNode, anchor: Node | null, buildItems: () => ListItemSpec[], create: (item: ListItem, anchor: Node | null) => void, update: (oldItem: ListItem, newSpec: ListItemSpec) => void, noWatch?: boolean): void;
341
+ //#endregion
342
+ //#region src/render/runAwait.d.ts
343
+ /**
344
+ * Renders an `@await` boundary. On the first run, content is rendered
345
+ * speculatively; if any read inside suspends (`didSuspend`), the boundary
346
+ * discards the partial render and shows the `with` branch instead.
347
+ *
348
+ * Fine-grained updates: on subsequent runs the boundary only decides whether
349
+ * to SWITCH branches. It does so from its `pending` set — the suspended
350
+ * computeds recorded by `suspendRead` — dropping entries that resolved and
351
+ * re-subscribing the still-suspended ones (a re-run deactivates all of the
352
+ * effect's source subscriptions, so they must be re-tracked to survive
353
+ * `clearSources`). That check is O(pending reads), not O(all sources), and
354
+ * non-suspend dependency changes inside content are left to the child
355
+ * effects that read them — the boundary isn't re-run by them at all.
356
+ *
357
+ * Stale-while-revalidate (ASYNC.md §6.2): once content has been produced
358
+ * (`hasContent`), a subsequent suspend during a refresh does NOT switch to
359
+ * the `with` branch — the boundary keeps the stale content mounted. `$async`
360
+ * retains the previous resolved value (`Computed.staleValue`) and
361
+ * `suspendRead` returns it, so child effects keep displaying the old value
362
+ * until the new promise resolves and updates them in place. The `with` branch
363
+ * is shown only on the first load, before content has ever rendered
364
+ * successfully.
365
+ *
366
+ * @param renderContent Builds the content children (may read $async getters).
367
+ * @param renderWith Builds the `with`-branch children, or null for empty.
368
+ */
369
+ declare function runAwait(region: Region, anchor: Node | null, renderContent: (anchor: Node | null) => void, renderWith: ((anchor: Node | null) => void) | null, name?: string): void;
370
+ //#endregion
371
+ //#region src/render/runTry.d.ts
372
+ /**
373
+ * Renders a `@try`/`@catch` group, or a top-level `@error` block (which the
374
+ * compiler wraps around the whole render).
375
+ *
376
+ * Like `runAwait`, the boundary is a control effect that renders one branch
377
+ * at a time into a fresh child region (`runControlBranch` clears the old
378
+ * branch on switch). Unlike the old compiled form, the try/catch lives in
379
+ * this runtime, which gives it three capabilities the compiled form lacked:
380
+ *
381
+ * - **Effect-rerun error routing.** The boundary registers itself on its
382
+ * region (`region.errorBoundary`); when an effect inside the try content
383
+ * throws on a later re-run, `triggerEffects` → `routeEffectError` stores
384
+ * the error here and force re-runs the boundary effect, which renders the
385
+ * catch branch with it.
386
+ * - **Recovery outside direct reads.** Reactive reads wrapped in nested
387
+ * `$run` effects (text/attribute interpolation) are tracked by those
388
+ * effects, not the boundary. When an error is routed, the boundary holds
389
+ * the erroring effect's source signals (`heldSignals`) and re-subscribes
390
+ * to them on every run that shows the catch branch, so a later change
391
+ * re-attempts the try branch.
392
+ * - **Top-level `@error` recovery.** Because the whole render is a
393
+ * re-runnable branch, a later re-render error (from a nested control
394
+ * re-running after a prop change) is caught by the same routing, and a
395
+ * recovery re-render clears the error content and restores the normal
396
+ * content.
397
+ *
398
+ * Semantics preserved from the compiled form:
399
+ *
400
+ * - Synchronous build errors in the try content render the catch branch
401
+ * (rewinding the hydration cursor and restoring the control region, which
402
+ * the failed partial build left active).
403
+ * - While the try branch is showing, a boundary re-run with no routed error
404
+ * does NOT rebuild it (`runControlBranch` same-index skip) — exactly like
405
+ * `@if`/`@switch` branches.
406
+ * - While the catch branch is showing, any boundary re-run re-attempts the
407
+ * try branch (the recovery path for errors read directly by the boundary
408
+ * effect, e.g. via `@const`).
409
+ * - With no catch branch, errors propagate up to the nearest outer boundary
410
+ * and no boundary is registered on the region.
411
+ *
412
+ * @param renderTry Builds the try content. May read reactive state.
413
+ * @param renderCatch Builds the catch content, or null for `@try` without
414
+ * `@catch`. Receives the error (the `@catch (err)` variable).
415
+ */
416
+ declare function runTry(region: Region, anchor: Node | null, renderTry: (anchor: Node | null) => void, renderCatch: ((anchor: Node | null, error: any) => void) | null, name?: string): void;
417
+ //#endregion
418
+ //#region src/render/saveHydration.d.ts
419
+ /**
420
+ * Snapshots the hydration cursor so a `@try` branch's partial hydration walk
421
+ * can be rewound if the branch throws and the `@catch` branch renders instead.
422
+ *
423
+ * @returns The current hydration cursor node, or `null` when not hydrating.
424
+ */
425
+ declare function saveHydration(): ChildNode | null;
146
426
  //#endregion
147
427
  //#region src/render/setAttribute.d.ts
148
428
  declare function setAttribute(el: Element, name: string, value: any): void;
@@ -150,77 +430,293 @@ declare function setAttribute(el: Element, name: string, value: any): void;
150
430
  //#region src/render/setDynamicElement.d.ts
151
431
  declare function setDynamicElement(el: HTMLElement, tag: string): HTMLElement;
152
432
  //#endregion
433
+ //#region src/types/Bindable.d.ts
434
+ /**
435
+ * Type-level marker that documents a component prop as supporting two-way
436
+ * binding via the `&` prefix at the call site.
437
+ *
438
+ * `Bindable<T>` is structurally just `T` — it has no runtime effect. It tells
439
+ * component authors and consumers "this prop is intended to be bound with
440
+ * `&prop={expr}`." Inside the component, use `$bind($state, $props, [...])`
441
+ * to wire up the actual two-way sync.
442
+ *
443
+ * Example:
444
+ * ```ts
445
+ * interface MyProps {
446
+ * value: Bindable<string>;
447
+ * }
448
+ * ```
449
+ */
450
+ type Bindable<T> = T;
451
+ //#endregion
153
452
  //#region src/watch/$batch.d.ts
154
453
  /**
155
- * Runs updates to proxy values in a batch, where the updates are stored in
156
- * context, and dependent effects are run all at once at the end.
157
- *
158
- * @param fn The function containing the batched updates to run.
159
- */
454
+ * Runs updates to proxy values in a batch, where the updates are stored in
455
+ * context, and dependent effects are run all at once at the end.
456
+ *
457
+ * @param fn The function containing the batched updates to run.
458
+ */
160
459
  declare function $batch<T>(fn: () => T): T;
161
460
  //#endregion
461
+ //#region src/watch/$async.d.ts
462
+ /**
463
+ * Caches an async computed value from a thunk that returns a Promise. A peer
464
+ * of `$cache` for async getters: the returned Computed carries a `didSuspend`
465
+ * indicator that the proxy get trap reads to suspend callers until the promise
466
+ * resolves.
467
+ *
468
+ * The thenable check and `.then` wiring live inside `computed.run` (a closure
469
+ * over the computed object), so they fire on both the initial run and every
470
+ * recalculation — `runComputed` and `checkComputed` are unchanged.
471
+ *
472
+ * @param fn A thunk returning the Promise to await. Signal reads inside `fn`
473
+ * are tracked, so the fetch re-runs when dependencies change.
474
+ */
475
+ declare function $async<T>(fn: () => Promise<T>): T;
476
+ //#endregion
477
+ //#region src/watch/$bind.d.ts
478
+ /**
479
+ * Establishes two-way reactive sync between matching keys on a state object
480
+ * and a props object.
481
+ *
482
+ * For each key, `$bind` creates:
483
+ * - **Forward sync** (`props → state`): when the parent pushes a new value via
484
+ * `$props[key]`, it flows into `$state[key]`. Skips `undefined` values so
485
+ * that defaults set in the initial `$watch(...)` are preserved when the
486
+ * parent doesn't provide a value.
487
+ * - **Backward sync** (`state → props`): when the component mutates
488
+ * `$state[key]`, the new value is written back to `$props[key]`, which the
489
+ * call site's `&key={...}` binding picks up and propagates to the parent.
490
+ *
491
+ * Same-value writes are no-ops (handled by the proxy layer), so two-way sync
492
+ * stabilises without infinite loops.
493
+ *
494
+ * `$bind` syncs same-named keys, so the key must exist on the state object.
495
+ * A state key named differently from the prop (e.g. `values` against a
496
+ * `value` prop) would silently do nothing -- the binding reads and writes
497
+ * keys that nothing else touches -- which is almost impossible to debug. The
498
+ * key is therefore required to exist on the state object, and `$bind` throws
499
+ * at setup otherwise.
500
+ *
501
+ * The prop does *not* need to exist on `props` yet: when the parent doesn't
502
+ * pass an optional prop, the compiled props object has no key for it, and
503
+ * the binding is simply inert (uncontrolled mode) until a value is pushed.
504
+ *
505
+ * @param state The component's reactive state (created via `$watch`).
506
+ * @param props The component's `$props` proxy. When `undefined` (component
507
+ * called with no props), `$bind` does nothing.
508
+ * @param keys Keys to sync. Each key must exist on `state`.
509
+ * @throws When a key does not exist on the state object.
510
+ */
511
+ declare function $bind(state: Record<PropertyKey, any>, props: Record<PropertyKey, any> | undefined, ...keys: (string | string[])[]): void;
512
+ //#endregion
162
513
  //#region src/watch/$cache.d.ts
163
514
  /**
164
- * Caches a computed value from signals accessed in a property getter.
165
- *
166
- * @param fn The function containing the signals to compute and cache.
167
- */
515
+ * Caches a computed value from signals accessed in a property getter.
516
+ *
517
+ * @param fn The function containing the signals to compute and cache.
518
+ */
168
519
  declare function $cache<T>(fn: () => T): T;
169
520
  //#endregion
170
- //#region src/watch/$mount.d.ts
521
+ //#region src/watch/$onmount.d.ts
171
522
  /**
172
- * Runs and re-runs a function on component mount
173
- *
174
- * @param fn The function to run, which may return a cleanup function
175
- */
176
- declare function $mount(fn: () => Cleanup | void): void;
523
+ * Runs `fn` once after the component is mounted to the DOM. May return a
524
+ * cleanup function that runs on unmount / region clear.
525
+ *
526
+ * The callback is **not reactive**: it runs exactly once per mount, and
527
+ * reactive values it reads are not tracked. To set up something that should
528
+ * keep updating, wrap the reactive part in `$run`:
529
+ *
530
+ * ```ts
531
+ * $onmount(() => {
532
+ * $run(() => {
533
+ * label.textContent = $state.count > 0 ? "+" : "";
534
+ * });
535
+ * });
536
+ * ```
537
+ *
538
+ * The element-level equivalent is the `onmount` attribute:
539
+ * `<input onmount={(el) => el.focus()} />`.
540
+ *
541
+ * @param fn The function to run, which may return a cleanup function
542
+ */
543
+ declare function $onmount(fn: () => Cleanup | void): void;
177
544
  //#endregion
178
545
  //#region src/watch/$peek.d.ts
546
+ /**
547
+ * Runs a function without tracking the reactive values it reads: `$watch`'d
548
+ * state accessed inside `fn` does not become a dependency of the currently
549
+ * running effect or computed. Useful for reading state inside an effect
550
+ * without re-running it when that state changes.
551
+ *
552
+ * @param fn The function to run untracked.
553
+ */
179
554
  declare function $peek<T>(fn: () => T): T;
180
555
  //#endregion
556
+ //#region src/watch/$pending.d.ts
557
+ /**
558
+ * Returns `true` if any value read inside `fn` is currently suspended in a
559
+ * "loud" way — a `$async` getter whose promise hasn't resolved yet. A reactive
560
+ * query for inline "loading…" indicators: the calling effect subscribes to the
561
+ * same computeds, so `$pending` re-evaluates when they resolve.
562
+ *
563
+ * Uses a "peek mode" internally: reads during `fn` are tracked for
564
+ * subscription but don't propagate taint or notify a `@await` boundary.
565
+ * This lets `$pending` return a plain boolean without itself suspending.
566
+ *
567
+ * Quiet-on-refresh semantics (ASYNC.md §7.4): a suspend is *quiet* — and
568
+ * therefore `$pending` returns `false` for it — when the computed has resolved
569
+ * before and the re-fetch was a *silent* `$refresh(fn, { silent: true })` (a
570
+ * bare refresh with no tracked dependency change, used for background
571
+ * revalidation). This matches Solid's stale-while-revalidate default: quietly
572
+ * re-asking the same question shouldn't ping the user. First loads and
573
+ * dependency-change refreshes are loud (`true`), as is the default (loud)
574
+ * `$refresh(fn)`. Quiet-ness is captured per computed at suspend time via
575
+ * `suspendQuiet` (computed in `$async`'s run from `hasResolved` and `recalc`).
576
+ *
577
+ * @param fn A function that reads the reactive values to check.
578
+ */
579
+ declare function $pending(fn: () => any): boolean;
580
+ //#endregion
581
+ //#region src/watch/$refresh.d.ts
582
+ /**
583
+ * Options for `$refresh`.
584
+ */
585
+ interface RefreshOptions {
586
+ /**
587
+ * Re-fetch silently — stale-while-revalidate. The suspend is *quiet*
588
+ * (`$pending` stays `false`) and subscribers aren't notified until the new
589
+ * promise resolves. For background revalidation: polling, refetch-on-
590
+ * focus. Defaults to `false` — a refresh is loud, so `$pending` reads
591
+ * `true` and inline "updating…" indicators flip on at refresh start.
592
+ */
593
+ silent?: boolean;
594
+ }
595
+ /**
596
+ * Re-fetches the `$async` getters read inside `fn` without changing a
597
+ * dependency. A companion to `$pending` (ASYNC.md §6.2): pull-to-refresh,
598
+ * refresh buttons, refetch-on-focus, polling, retry-after-error.
599
+ *
600
+ * `fn` is run in a tracking context that collects every `$async` computed it
601
+ * reads (`$cache` computeds are ignored). Each collected computed is then
602
+ * re-run with `recalc` left true — a "bare refresh" — so the suspend is
603
+ * *loud*: `$pending(fn)` returns `true` while the re-fetch is in flight and
604
+ * subscribers are notified at suspend *start*, so an inline "updating…"
605
+ * indicator appears immediately. Readers keep displaying the previous
606
+ * resolved value (`Computed.staleValue`) until the new promise resolves and
607
+ * propagates through the reactive graph; an `@await` boundary keeps its
608
+ * content mounted instead of flashing fallback.
609
+ *
610
+ * Pass `{ silent: true }` to re-fetch quietly (stale-while-revalidate):
611
+ * `$pending(fn)` stays `false` and nothing re-runs until the new promise
612
+ * resolves. For background revalidation where feedback would be noise —
613
+ * polling, refetch-on-focus:
614
+ *
615
+ * ```torp
616
+ * // poll quietly every 30s
617
+ * $run(() => {
618
+ * const id = setInterval(() => $refresh(() => $state.data, { silent: true }), 30_000);
619
+ * return () => clearInterval(id);
620
+ * });
621
+ * ```
622
+ *
623
+ * A refresh is loud regardless of `silent` when the computed has never
624
+ * resolved — e.g. retrying after an error that left `didError` set on a first
625
+ * load — or when the re-fetch is triggered by a dependency change, which
626
+ * flows through the normal `recalc` path instead of here.
627
+ *
628
+ * If `fn` reads a getter the UI has never read, the collection read
629
+ * initializes it — and that fetch IS the refresh: the computed is not re-run
630
+ * (a second fetch would be a duplicate whose resolve the generation guard
631
+ * drops). Getters already read (pending, resolved, or errored) are re-run as
632
+ * usual.
633
+ *
634
+ * The returned value of `fn` is ignored; use `fn` to reference the getters.
635
+ */
636
+ declare function $refresh(fn: () => any, options?: RefreshOptions): void;
637
+ //#endregion
181
638
  //#region src/watch/$run.d.ts
182
639
  /**
183
- * Runs and re-runs a function that depends on a watched object
184
- *
185
- * @param fn The function to run, which may return a cleanup function.
186
- */
187
- declare function $run(fn: () => Cleanup | void, name?: string): Effect;
640
+ * Runs and re-runs a function that depends on a watched object
641
+ *
642
+ * @param fn The function to run, which may return a cleanup function.
643
+ * @param options Internal fields to set on the constructed Effect (e.g.
644
+ * `isMountEffect`, `forVarDeps`). Not part of the public API.
645
+ */
646
+ declare function $run(fn: () => Cleanup | void, name?: string, options?: Pick<Effect, "isMountEffect" | "forVarMask">): Effect;
647
+ //#endregion
648
+ //#region src/watch/$stream.d.ts
649
+ /**
650
+ * Subscribes to an external source of events — server-sent events,
651
+ * WebSockets, DOM events, or any custom `StreamSource` — and calls
652
+ * `handler` for each event it pushes. Events are typically written into
653
+ * reactive state, which keeps templates, computeds and effects updating
654
+ * through the normal reactivity model:
655
+ *
656
+ * ```torp
657
+ * let $state = $watch({ messages: [] as string[] });
658
+ *
659
+ * $stream(fromServer(`/sse/${$props.id}`), (e) => {
660
+ * $state.messages.push(e.data);
661
+ * });
662
+ * ```
663
+ *
664
+ * The subscription is managed by the framework:
665
+ *
666
+ * - It starts when the component is mounted to the DOM (so `&ref`-bound
667
+ * elements are available), and is unsubscribed when the component
668
+ * unmounts or its region is cleared.
669
+ * - Reactive state read *inside* the source is tracked: when it changes,
670
+ * the source is unsubscribed and re-subscribed with fresh values (e.g.
671
+ * re-opening a connection when a user id changes). A pending debounced
672
+ * call is dropped on re-subscribe.
673
+ * - The source is never invoked during a server render, so browser-only
674
+ * APIs are safe to use.
675
+ *
676
+ * Errors are values like any other: a source that can fail should push an
677
+ * error-shaped value and own its own reconnection (e.g. `EventSource`
678
+ * reconnects automatically).
679
+ *
680
+ * @param source The stream source to subscribe to
681
+ * @param handler Called for each event the source pushes
682
+ * @param options Timing options. `debounce` delays each handler call until
683
+ * the source has been quiet for that many milliseconds, resetting on
684
+ * every event (only the last event in a burst is handled).
685
+ */
686
+ declare function $stream<T>(source: StreamSource<T>, handler: (value: T) => void, options?: {
687
+ debounce?: number;
688
+ }): void;
188
689
  //#endregion
189
690
  //#region src/watch/$unwrap.d.ts
190
691
  /**
191
- * Returns the target object of a proxy
192
- *
193
- * @param object The proxy object
194
- */
692
+ * Returns the target object of a proxy
693
+ *
694
+ * @param object The proxy object
695
+ */
195
696
  declare function $unwrap<T extends Record<PropertyKey, any>>(object: T): T;
196
697
  //#endregion
197
698
  //#region src/types/WatchOptions.d.ts
198
699
  /**
199
- * Options for $watch.
200
- */
700
+ * Options for $watch.
701
+ */
201
702
  interface WatchOptions {
202
703
  /**
203
- * Only watch top-level properties, don't recursively watch children.
204
- */
704
+ * Only watch top-level properties, don't recursively watch children.
705
+ */
205
706
  shallow?: boolean;
206
707
  }
207
708
  //#endregion
208
709
  //#region src/watch/$watch.d.ts
209
710
  /**
210
- * Watches an object and runs effects when its properties are changed
211
- *
212
- * @param object The object to watch
213
- */
214
- declare function $watch<T extends Record<PropertyKey, any>>(object: T, options?: WatchOptions): T;
215
- //#endregion
216
- //#region src/wrappers/ReactiveDate.d.ts
217
- /**
218
- * Wraps a Date object for $watching.
219
- */
220
- declare class ReactiveDate extends Date {
221
- #private;
222
- constructor(...params: any[]);
223
- }
224
- //#endregion
225
- export { $batch, $cache, $mount, $peek, $run, $unwrap, $watch, type Animation, type ClassValue, type Component, type ListItem, ReactiveDate, type SlotRender, type StyleValue, clearLayoutSlot, fillLayoutSlot, hydrate, mount, addFragment as t_add_fragment, nodeAnchor as t_anchor, addAnimation as t_animate, applyProps as t_apply_props, setAttribute as t_attribute, nodeChild as t_child, buildClasses as t_class, setDynamicElement as t_dynamic, addEvent as t_event, formatText as t_fmt, getFragment as t_fragment, newListItem as t_list_item, nodeNext as t_next, popRegion as t_pop_region, pushRegion as t_push_region, newRegion as t_region, nodeRoot as t_root, runControlBranch as t_run_branch, runControl as t_run_control, runList as t_run_list, nodeSkip as t_skip, buildStyles as t_style };
711
+ * Watches an object and runs effects when its properties are changed.
712
+ *
713
+ * Dates, Maps and Sets are supported too: their methods are reactive (reads
714
+ * track, writes notify), so `new Date()`, `new Map()` and `new Set()` can be
715
+ * used in watched state directly.
716
+ *
717
+ * @param object The object to watch
718
+ */
719
+ declare function $watch<T extends object>(object: T, options?: WatchOptions): T;
720
+ //#endregion
721
+ export { $async, $batch, $bind, $cache, $onmount, $peek, $pending, $refresh, $run, $stream, $unwrap, $watch, type Animation, type Bindable, type ClassValue, type Component, type ListItem, type ListItemSpec, type SlotRender, type StreamSource, type StyleValue, clearLayoutSlot, fillLayoutSlot, fromElement, fromServer, fromWebSocket, hydrate, mount, addElement as t_add_element, addFragment as t_add_fragment, nodeAnchor as t_anchor, addAnimation as t_animate, applyProps as t_apply_props, setAttribute as t_attribute, nodeChild as t_child, buildClasses as t_class, setDynamicElement as t_dynamic, addEvent as t_event, firstInsideNode as t_first_inside, formatText as t_fmt, getFragment as t_fragment, getElementFragment as t_fragment_el, newListItem as t_list_item, nodeNext as t_next, popRegion as t_pop_region, pushRegion as t_push_region, newRegion as t_region, rerunRegionEffects as t_rerun_region_effects, restoreHydration as t_restore_hydration, nodeRoot as t_root, nodeRootElement as t_root_el, runAwait as t_run_await, runControlBranch as t_run_branch, runControl as t_run_control, runList as t_run_list, runTry as t_run_try, saveHydration as t_save_hydration, nodeSkip as t_skip, buildStyles as t_style, unmount };
226
722
  //# sourceMappingURL=index.d.cts.map