@fictjs/runtime 0.3.0 → 0.5.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 (70) hide show
  1. package/dist/advanced.cjs +10 -8
  2. package/dist/advanced.cjs.map +1 -1
  3. package/dist/advanced.d.cts +4 -3
  4. package/dist/advanced.d.ts +4 -3
  5. package/dist/advanced.js +10 -8
  6. package/dist/advanced.js.map +1 -1
  7. package/dist/{chunk-TWELIZRY.js → chunk-5AA7HP4S.js} +5 -3
  8. package/dist/{chunk-TWELIZRY.js.map → chunk-5AA7HP4S.js.map} +1 -1
  9. package/dist/chunk-6SOPF5LZ.cjs +2363 -0
  10. package/dist/chunk-6SOPF5LZ.cjs.map +1 -0
  11. package/dist/{chunk-SO6X7G5S.js → chunk-BQG7VEBY.js} +501 -1880
  12. package/dist/chunk-BQG7VEBY.js.map +1 -0
  13. package/dist/chunk-FKDMDAUR.js +2363 -0
  14. package/dist/chunk-FKDMDAUR.js.map +1 -0
  15. package/dist/{chunk-L4DIV3RC.cjs → chunk-GHUV2FLD.cjs} +9 -7
  16. package/dist/chunk-GHUV2FLD.cjs.map +1 -0
  17. package/dist/{chunk-XLIZJMMJ.js → chunk-KKKYW54Z.js} +8 -6
  18. package/dist/{chunk-XLIZJMMJ.js.map → chunk-KKKYW54Z.js.map} +1 -1
  19. package/dist/{chunk-M2TSXZ4C.cjs → chunk-KYLNC4CD.cjs} +18 -16
  20. package/dist/chunk-KYLNC4CD.cjs.map +1 -0
  21. package/dist/chunk-TKWN42TA.cjs +2259 -0
  22. package/dist/chunk-TKWN42TA.cjs.map +1 -0
  23. package/dist/{context-B25xyQrJ.d.cts → context-CTBE00S_.d.cts} +1 -1
  24. package/dist/{context-CGdP7_Jb.d.ts → context-lkLhbkFJ.d.ts} +1 -1
  25. package/dist/{effect-D6kaLM2-.d.cts → effect-BpSNEJJz.d.cts} +7 -67
  26. package/dist/{effect-D6kaLM2-.d.ts → effect-BpSNEJJz.d.ts} +7 -67
  27. package/dist/index.cjs +40 -38
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +5 -4
  30. package/dist/index.d.ts +5 -4
  31. package/dist/index.dev.js +92 -4
  32. package/dist/index.dev.js.map +1 -1
  33. package/dist/index.js +19 -17
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal.cjs +189 -202
  36. package/dist/internal.cjs.map +1 -1
  37. package/dist/internal.d.cts +13 -23
  38. package/dist/internal.d.ts +13 -23
  39. package/dist/internal.js +195 -208
  40. package/dist/internal.js.map +1 -1
  41. package/dist/loader.cjs +280 -0
  42. package/dist/loader.cjs.map +1 -0
  43. package/dist/loader.d.cts +57 -0
  44. package/dist/loader.d.ts +57 -0
  45. package/dist/loader.js +280 -0
  46. package/dist/loader.js.map +1 -0
  47. package/dist/{props-BIfromL0.d.cts → props-XTHYD19o.d.cts} +13 -2
  48. package/dist/{props-BEgIVMRx.d.ts → props-x-HbI-jX.d.ts} +13 -2
  49. package/dist/resume-BrAkmSTY.d.cts +79 -0
  50. package/dist/resume-Dx8_l72o.d.ts +79 -0
  51. package/dist/{scope-CzNkn587.d.ts → scope-CdbGmsFf.d.ts} +1 -1
  52. package/dist/{scope-Cx_3CjIZ.d.cts → scope-DfcP9I-A.d.cts} +1 -1
  53. package/dist/signal-C4ISF17w.d.cts +66 -0
  54. package/dist/signal-C4ISF17w.d.ts +66 -0
  55. package/package.json +8 -3
  56. package/src/binding.ts +254 -5
  57. package/src/dom.ts +103 -5
  58. package/src/hooks.ts +15 -2
  59. package/src/hydration.ts +75 -0
  60. package/src/internal.ts +34 -2
  61. package/src/list-helpers.ts +113 -12
  62. package/src/loader.ts +437 -0
  63. package/src/node-ops.ts +65 -0
  64. package/src/resume.ts +517 -0
  65. package/src/store.ts +8 -0
  66. package/dist/chunk-ID3WBWNO.cjs +0 -3638
  67. package/dist/chunk-ID3WBWNO.cjs.map +0 -1
  68. package/dist/chunk-L4DIV3RC.cjs.map +0 -1
  69. package/dist/chunk-M2TSXZ4C.cjs.map +0 -1
  70. package/dist/chunk-SO6X7G5S.js.map +0 -1
@@ -194,6 +194,11 @@ declare function classList(node: Element, value: Record<string, boolean> | null
194
194
  * @param createElementFn - Optional function to create DOM elements (when marker is provided)
195
195
  */
196
196
  declare function insert(parent: ParentNode & Node, getValue: () => FictNode, markerOrCreateElement?: Node | CreateElementFn, createElementFn?: CreateElementFn): Cleanup;
197
+ /**
198
+ * Insert reactive content between two marker comments.
199
+ * Supports hydration by claiming existing nodes between markers.
200
+ */
201
+ declare function insertBetween(start: Comment, end: Comment, getValue: () => FictNode, createElementFn?: CreateElementFn): Cleanup;
197
202
  /**
198
203
  * Create a reactive child binding that updates when the child value changes.
199
204
  * This is used for dynamic expressions like `{show && <Modal />}` or `{items.map(...)}`.
@@ -333,7 +338,7 @@ declare function assign(node: Element, props: Record<string, unknown>, isSVG?: b
333
338
  * )
334
339
  * ```
335
340
  */
336
- declare function createConditional(condition: () => boolean, renderTrue: () => FictNode, createElementFn: CreateElementFn, renderFalse?: () => FictNode): BindingHandle;
341
+ declare function createConditional(condition: () => boolean, renderTrue: () => FictNode, createElementFn: CreateElementFn, renderFalse?: () => FictNode, startOverride?: Comment, endOverride?: Comment): BindingHandle;
337
342
  /**
338
343
  * Create a show/hide binding that uses CSS display instead of DOM manipulation.
339
344
  * More efficient than conditional when the content is expensive to create.
@@ -374,71 +379,6 @@ declare function createRoot<T>(fn: () => T, options?: CreateRootOptions): {
374
379
  };
375
380
  declare function registerErrorHandler(fn: ErrorHandler): void;
376
381
 
377
- /**
378
- * Options for creating a signal
379
- */
380
- interface SignalOptions<T> {
381
- /** Custom equality check */
382
- equals?: false | ((prev: T, next: T) => boolean);
383
- /** Debug name */
384
- name?: string;
385
- /** Source location */
386
- devToolsSource?: string;
387
- }
388
- /**
389
- * Options for creating a memo
390
- */
391
- interface MemoOptions<T> {
392
- /** Custom equality check */
393
- equals?: false | ((prev: T, next: T) => boolean);
394
- /** Debug name */
395
- name?: string;
396
- /** Source location */
397
- devToolsSource?: string;
398
- }
399
- /**
400
- * Signal accessor - function to get/set signal value
401
- */
402
- interface SignalAccessor<T> {
403
- (): T;
404
- (value: T): void;
405
- }
406
- /**
407
- * Computed accessor - function to get computed value
408
- */
409
- type ComputedAccessor<T> = () => T;
410
- /**
411
- * Effect scope disposer - function to dispose an effect scope
412
- */
413
- type EffectScopeDisposer = () => void;
414
- /**
415
- * Create a reactive signal
416
- * @param initialValue - The initial value
417
- * @returns A signal accessor function
418
- */
419
- declare function signal<T>(initialValue: T, options?: SignalOptions<T>): SignalAccessor<T>;
420
- /**
421
- * Create a reactive effect scope
422
- * @param fn - The scope function
423
- * @returns An effect scope disposer function
424
- */
425
- declare function effectScope(fn: () => void): EffectScopeDisposer;
426
- /**
427
- * Reset all global reactive state for test isolation.
428
- * ONLY use this in test setup/teardown - never in production code.
429
- * This clears effect queues, resets batch depth, and clears pending flushes.
430
- */
431
- declare function __resetReactiveState(): void;
432
- /**
433
- * Create a selector signal that efficiently updates only when the selected key matches.
434
- * Useful for large lists where only one item is selected.
435
- *
436
- * @param source - The source signal returning the current key
437
- * @param equalityFn - Optional equality function
438
- * @returns A selector function that takes a key and returns a boolean signal accessor
439
- */
440
- declare function createSelector<T>(source: () => T, equalityFn?: (a: T, b: T) => boolean): (key: T) => boolean;
441
-
442
382
  /**
443
383
  * Effect callback run synchronously; async callbacks are not tracked after the first await.
444
384
  * TypeScript will reject `async () => {}` here—split async work or read signals before awaiting.
@@ -447,4 +387,4 @@ type Effect = () => void | Cleanup;
447
387
  declare function createEffect(fn: Effect): () => void;
448
388
  declare function createRenderEffect(fn: Effect): () => void;
449
389
 
450
- export { delegateEvents as $, type EventHandler as A, type BaseProps as B, type Cleanup as C, type DOMElement as D, type Effect as E, type FictNode as F, type ErrorInfo as G, type SignalOptions as H, type ComputedAccessor as I, bindText as J, bindAttribute as K, bindStyle as L, type MemoOptions as M, bindClass as N, bindEvent as O, type PropsWithChildren as P, callEventHandler as Q, type RefObject as R, type SignalAccessor as S, bindProperty as T, bindRef as U, insert as V, createConditional as W, spread as X, assign as Y, classList as Z, __resetReactiveState as _, createTextBinding as a, clearDelegatedEvents as a0, addEventListener as a1, type MaybeReactive as a2, type BindingHandle as a3, type CreateElementFn as a4, type AttributeSetter as a5, createChildBinding as b, createSelector as c, createAttributeBinding as d, effectScope as e, createStyleBinding as f, createClassBinding as g, createShow as h, isReactive as i, createRenderEffect as j, type SuspenseToken as k, createEffect as l, onDestroy as m, onCleanup as n, onMount as o, createRoot as p, createPortal as q, registerErrorHandler as r, signal as s, type FictVNode as t, unwrap as u, type Component as v, type Ref as w, type RefCallback as x, type StyleProp as y, type ClassProp as z };
390
+ export { bindStyle as A, type BaseProps as B, type Cleanup as C, type DOMElement as D, type Effect as E, type FictNode as F, bindClass as G, bindEvent as H, callEventHandler as I, bindProperty as J, bindRef as K, insert as L, insertBetween as M, createConditional as N, spread as O, type PropsWithChildren as P, assign as Q, type RefObject as R, type SuspenseToken as S, classList as T, delegateEvents as U, clearDelegatedEvents as V, addEventListener as W, type MaybeReactive as X, type BindingHandle as Y, type CreateElementFn as Z, type AttributeSetter as _, createChildBinding as a, createAttributeBinding as b, createTextBinding as c, createStyleBinding as d, createClassBinding as e, createShow as f, createRenderEffect as g, createEffect as h, isReactive as i, onDestroy as j, onCleanup as k, createRoot as l, createPortal as m, type FictVNode as n, onMount as o, type Component as p, type Ref as q, registerErrorHandler as r, type RefCallback as s, type StyleProp as t, unwrap as u, type ClassProp as v, type EventHandler as w, type ErrorInfo as x, bindText as y, bindAttribute as z };
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkM2TSXZ4Ccjs = require('./chunk-M2TSXZ4C.cjs');
5
+ var _chunkKYLNC4CDcjs = require('./chunk-KYLNC4CD.cjs');
6
6
 
7
7
 
8
8
 
@@ -19,6 +19,7 @@ var _chunkM2TSXZ4Ccjs = require('./chunk-M2TSXZ4C.cjs');
19
19
 
20
20
 
21
21
 
22
+ var _chunkTKWN42TAcjs = require('./chunk-TKWN42TA.cjs');
22
23
 
23
24
 
24
25
 
@@ -35,7 +36,8 @@ var _chunkM2TSXZ4Ccjs = require('./chunk-M2TSXZ4C.cjs');
35
36
 
36
37
 
37
38
 
38
- var _chunkID3WBWNOcjs = require('./chunk-ID3WBWNO.cjs');
39
+
40
+ var _chunk6SOPF5LZcjs = require('./chunk-6SOPF5LZ.cjs');
39
41
 
40
42
  // src/ref.ts
41
43
  function createRef() {
@@ -47,7 +49,7 @@ function ErrorBoundary(props) {
47
49
  const fragment = document.createDocumentFragment();
48
50
  const marker = document.createComment("fict:error-boundary");
49
51
  fragment.appendChild(marker);
50
- const hostRoot = _chunkID3WBWNOcjs.getCurrentRoot.call(void 0, );
52
+ const hostRoot = _chunk6SOPF5LZcjs.getCurrentRoot.call(void 0, );
51
53
  let cleanup;
52
54
  let activeNodes = [];
53
55
  let renderingFallback = false;
@@ -65,25 +67,25 @@ function ErrorBoundary(props) {
65
67
  cleanup = void 0;
66
68
  }
67
69
  if (activeNodes.length) {
68
- _chunkID3WBWNOcjs.removeNodes.call(void 0, activeNodes);
70
+ _chunkTKWN42TAcjs.removeNodes.call(void 0, activeNodes);
69
71
  activeNodes = [];
70
72
  }
71
73
  if (value == null || value === false) {
72
74
  return;
73
75
  }
74
- const root = _chunkID3WBWNOcjs.createRootContext.call(void 0, hostRoot);
75
- const prev = _chunkID3WBWNOcjs.pushRoot.call(void 0, root);
76
+ const root = _chunk6SOPF5LZcjs.createRootContext.call(void 0, hostRoot);
77
+ const prev = _chunk6SOPF5LZcjs.pushRoot.call(void 0, root);
76
78
  let nodes = [];
77
79
  try {
78
- const output = _chunkID3WBWNOcjs.createElement.call(void 0, value);
79
- nodes = _chunkID3WBWNOcjs.toNodeArray.call(void 0, output);
80
+ const output = _chunkTKWN42TAcjs.createElement.call(void 0, value);
81
+ nodes = _chunkTKWN42TAcjs.toNodeArray.call(void 0, output);
80
82
  const parentNode = marker.parentNode;
81
83
  if (parentNode) {
82
- _chunkID3WBWNOcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
84
+ _chunkTKWN42TAcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
83
85
  }
84
86
  } catch (err) {
85
- _chunkID3WBWNOcjs.popRoot.call(void 0, prev);
86
- _chunkID3WBWNOcjs.destroyRoot.call(void 0, root);
87
+ _chunk6SOPF5LZcjs.popRoot.call(void 0, prev);
88
+ _chunk6SOPF5LZcjs.destroyRoot.call(void 0, root);
87
89
  if (renderingFallback) {
88
90
  throw err;
89
91
  }
@@ -98,11 +100,11 @@ function ErrorBoundary(props) {
98
100
  }
99
101
  return;
100
102
  }
101
- _chunkID3WBWNOcjs.popRoot.call(void 0, prev);
102
- _chunkID3WBWNOcjs.flushOnMount.call(void 0, root);
103
+ _chunk6SOPF5LZcjs.popRoot.call(void 0, prev);
104
+ _chunk6SOPF5LZcjs.flushOnMount.call(void 0, root);
103
105
  cleanup = () => {
104
- _chunkID3WBWNOcjs.destroyRoot.call(void 0, root);
105
- _chunkID3WBWNOcjs.removeNodes.call(void 0, nodes);
106
+ _chunk6SOPF5LZcjs.destroyRoot.call(void 0, root);
107
+ _chunkTKWN42TAcjs.removeNodes.call(void 0, nodes);
106
108
  };
107
109
  activeNodes = nodes;
108
110
  };
@@ -111,7 +113,7 @@ function ErrorBoundary(props) {
111
113
  renderValue(toView(null));
112
114
  };
113
115
  renderValue(_nullishCoalesce(props.children, () => ( null)));
114
- _chunkID3WBWNOcjs.registerErrorHandler.call(void 0, (err) => {
116
+ _chunk6SOPF5LZcjs.registerErrorHandler.call(void 0, (err) => {
115
117
  renderValue(toView(err));
116
118
  _optionalChain([props, 'access', _5 => _5.onError, 'optionalCall', _6 => _6(err)]);
117
119
  return true;
@@ -120,7 +122,7 @@ function ErrorBoundary(props) {
120
122
  const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
121
123
  const getter = isGetter ? props.resetKeys : void 0;
122
124
  let prev = isGetter ? getter() : props.resetKeys;
123
- _chunkID3WBWNOcjs.createEffect.call(void 0, () => {
125
+ _chunk6SOPF5LZcjs.createEffect.call(void 0, () => {
124
126
  const next = getter ? getter() : props.resetKeys;
125
127
  if (prev !== next) {
126
128
  prev = next;
@@ -149,10 +151,10 @@ function createSuspenseToken() {
149
151
  }
150
152
  var isThenable = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
151
153
  function Suspense(props) {
152
- const pending = _chunkID3WBWNOcjs.signal.call(void 0, 0);
154
+ const pending = _chunk6SOPF5LZcjs.signal.call(void 0, 0);
153
155
  let resolvedOnce = false;
154
156
  let epoch = 0;
155
- const hostRoot = _chunkID3WBWNOcjs.getCurrentRoot.call(void 0, );
157
+ const hostRoot = _chunk6SOPF5LZcjs.getCurrentRoot.call(void 0, );
156
158
  const toFallback = (err) => typeof props.fallback === "function" ? props.fallback(err) : props.fallback;
157
159
  const renderView = (view) => {
158
160
  if (cleanup) {
@@ -160,41 +162,41 @@ function Suspense(props) {
160
162
  cleanup = void 0;
161
163
  }
162
164
  if (activeNodes.length) {
163
- _chunkID3WBWNOcjs.removeNodes.call(void 0, activeNodes);
165
+ _chunkTKWN42TAcjs.removeNodes.call(void 0, activeNodes);
164
166
  activeNodes = [];
165
167
  }
166
168
  if (view == null || view === false) {
167
169
  return;
168
170
  }
169
- const root = _chunkID3WBWNOcjs.createRootContext.call(void 0, hostRoot);
170
- const prev = _chunkID3WBWNOcjs.pushRoot.call(void 0, root);
171
+ const root = _chunk6SOPF5LZcjs.createRootContext.call(void 0, hostRoot);
172
+ const prev = _chunk6SOPF5LZcjs.pushRoot.call(void 0, root);
171
173
  let nodes = [];
172
174
  try {
173
- const output = _chunkID3WBWNOcjs.createElement.call(void 0, view);
174
- nodes = _chunkID3WBWNOcjs.toNodeArray.call(void 0, output);
175
+ const output = _chunkTKWN42TAcjs.createElement.call(void 0, view);
176
+ nodes = _chunkTKWN42TAcjs.toNodeArray.call(void 0, output);
175
177
  const suspendedAttempt = root.suspended || nodes.length > 0 && nodes.every((node) => node instanceof Comment && node.data === "fict:suspend");
176
178
  if (suspendedAttempt) {
177
- _chunkID3WBWNOcjs.popRoot.call(void 0, prev);
178
- _chunkID3WBWNOcjs.destroyRoot.call(void 0, root);
179
+ _chunk6SOPF5LZcjs.popRoot.call(void 0, prev);
180
+ _chunk6SOPF5LZcjs.destroyRoot.call(void 0, root);
179
181
  return;
180
182
  }
181
183
  const parentNode = marker.parentNode;
182
184
  if (parentNode) {
183
- _chunkID3WBWNOcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
185
+ _chunkTKWN42TAcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
184
186
  }
185
187
  } catch (err) {
186
- _chunkID3WBWNOcjs.popRoot.call(void 0, prev);
187
- _chunkID3WBWNOcjs.destroyRoot.call(void 0, root);
188
- if (!_chunkID3WBWNOcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
188
+ _chunk6SOPF5LZcjs.popRoot.call(void 0, prev);
189
+ _chunk6SOPF5LZcjs.destroyRoot.call(void 0, root);
190
+ if (!_chunk6SOPF5LZcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
189
191
  throw err;
190
192
  }
191
193
  return;
192
194
  }
193
- _chunkID3WBWNOcjs.popRoot.call(void 0, prev);
194
- _chunkID3WBWNOcjs.flushOnMount.call(void 0, root);
195
+ _chunk6SOPF5LZcjs.popRoot.call(void 0, prev);
196
+ _chunk6SOPF5LZcjs.flushOnMount.call(void 0, root);
195
197
  cleanup = () => {
196
- _chunkID3WBWNOcjs.destroyRoot.call(void 0, root);
197
- _chunkID3WBWNOcjs.removeNodes.call(void 0, nodes);
198
+ _chunk6SOPF5LZcjs.destroyRoot.call(void 0, root);
199
+ _chunkTKWN42TAcjs.removeNodes.call(void 0, nodes);
198
200
  };
199
201
  activeNodes = nodes;
200
202
  };
@@ -209,7 +211,7 @@ function Suspense(props) {
209
211
  _optionalChain([props, 'access', _7 => _7.onResolve, 'optionalCall', _8 => _8()]);
210
212
  }
211
213
  };
212
- _chunkID3WBWNOcjs.registerSuspenseHandler.call(void 0, (token) => {
214
+ _chunk6SOPF5LZcjs.registerSuspenseHandler.call(void 0, (token) => {
213
215
  const tokenEpoch = epoch;
214
216
  pending(pending() + 1);
215
217
  renderView(toFallback());
@@ -234,7 +236,7 @@ function Suspense(props) {
234
236
  const newPending = Math.max(0, pending() - 1);
235
237
  pending(newPending);
236
238
  _optionalChain([props, 'access', _9 => _9.onReject, 'optionalCall', _10 => _10(err)]);
237
- if (!_chunkID3WBWNOcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
239
+ if (!_chunk6SOPF5LZcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
238
240
  throw err;
239
241
  }
240
242
  }
@@ -248,7 +250,7 @@ function Suspense(props) {
248
250
  const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
249
251
  const getter = isGetter ? props.resetKeys : void 0;
250
252
  let prev = isGetter ? getter() : props.resetKeys;
251
- _chunkID3WBWNOcjs.createEffect.call(void 0, () => {
253
+ _chunk6SOPF5LZcjs.createEffect.call(void 0, () => {
252
254
  const next = getter ? getter() : props.resetKeys;
253
255
  if (prev !== next) {
254
256
  prev = next;
@@ -286,5 +288,5 @@ function Suspense(props) {
286
288
 
287
289
 
288
290
 
289
- exports.ErrorBoundary = ErrorBoundary; exports.Fragment = _chunkID3WBWNOcjs.Fragment; exports.Suspense = Suspense; exports.batch = _chunkID3WBWNOcjs.batch2; exports.createContext = _chunkM2TSXZ4Ccjs.createContext; exports.createEffect = _chunkID3WBWNOcjs.createEffect; exports.createElement = _chunkID3WBWNOcjs.createElement; exports.createMemo = _chunkID3WBWNOcjs.createMemo; exports.createPortal = _chunkID3WBWNOcjs.createPortal; exports.createRef = createRef; exports.createRoot = _chunkID3WBWNOcjs.createRoot; exports.createSuspenseToken = createSuspenseToken; exports.hasContext = _chunkM2TSXZ4Ccjs.hasContext; exports.keyed = _chunkID3WBWNOcjs.keyed; exports.mergeProps = _chunkID3WBWNOcjs.mergeProps; exports.onCleanup = _chunkID3WBWNOcjs.onCleanup; exports.onDestroy = _chunkID3WBWNOcjs.onDestroy; exports.onMount = _chunkID3WBWNOcjs.onMount; exports.prop = _chunkID3WBWNOcjs.prop; exports.render = _chunkID3WBWNOcjs.render; exports.startTransition = _chunkID3WBWNOcjs.startTransition; exports.untrack = _chunkID3WBWNOcjs.untrack2; exports.useContext = _chunkM2TSXZ4Ccjs.useContext; exports.useDeferredValue = _chunkID3WBWNOcjs.useDeferredValue; exports.useTransition = _chunkID3WBWNOcjs.useTransition;
291
+ exports.ErrorBoundary = ErrorBoundary; exports.Fragment = _chunkTKWN42TAcjs.Fragment; exports.Suspense = Suspense; exports.batch = _chunkTKWN42TAcjs.batch; exports.createContext = _chunkKYLNC4CDcjs.createContext; exports.createEffect = _chunk6SOPF5LZcjs.createEffect; exports.createElement = _chunkTKWN42TAcjs.createElement; exports.createMemo = _chunk6SOPF5LZcjs.createMemo; exports.createPortal = _chunkTKWN42TAcjs.createPortal; exports.createRef = createRef; exports.createRoot = _chunk6SOPF5LZcjs.createRoot; exports.createSuspenseToken = createSuspenseToken; exports.hasContext = _chunkKYLNC4CDcjs.hasContext; exports.keyed = _chunkTKWN42TAcjs.keyed; exports.mergeProps = _chunkTKWN42TAcjs.mergeProps; exports.onCleanup = _chunk6SOPF5LZcjs.onCleanup; exports.onDestroy = _chunk6SOPF5LZcjs.onDestroy; exports.onMount = _chunk6SOPF5LZcjs.onMount; exports.prop = _chunkTKWN42TAcjs.prop; exports.render = _chunkTKWN42TAcjs.render; exports.startTransition = _chunkTKWN42TAcjs.startTransition; exports.untrack = _chunkTKWN42TAcjs.untrack; exports.useContext = _chunkKYLNC4CDcjs.useContext; exports.useDeferredValue = _chunkTKWN42TAcjs.useDeferredValue; exports.useTransition = _chunkTKWN42TAcjs.useTransition;
290
292
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","../src/ref.ts","../src/error-boundary.ts","../src/suspense.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","sourcesContent":[null,"import type { RefObject } from './types'\n\n/**\n * Create a ref object for DOM element references.\n *\n * @returns A ref object with a `current` property initialized to `null`\n *\n * @example\n * ```tsx\n * import { createRef } from 'fict'\n *\n * function Component() {\n * const inputRef = createRef<HTMLInputElement>()\n *\n * $effect(() => {\n * inputRef.current?.focus()\n * })\n *\n * return <input ref={inputRef} />\n * }\n * ```\n */\nexport function createRef<T extends Element = HTMLElement>(): RefObject<T> {\n return { current: null }\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n pushRoot,\n popRoot,\n registerErrorHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport type { BaseProps, FictNode } from './types'\n\ninterface ErrorBoundaryProps extends BaseProps {\n fallback: FictNode | ((err: unknown, reset?: () => void) => FictNode)\n onError?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): FictNode {\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:error-boundary')\n fragment.appendChild(marker)\n\n const hostRoot = getCurrentRoot()\n\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n let renderingFallback = false\n\n let reset = () => {}\n const toView = (err: unknown | null): FictNode | null => {\n if (err != null) {\n return typeof props.fallback === 'function'\n ? (props.fallback as (e: unknown, reset?: () => void) => FictNode)(err, reset)\n : props.fallback\n }\n return props.children ?? null\n }\n\n const renderValue = (value: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (value == null || value === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(value)\n nodes = toNodeArray(output)\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n destroyRoot(root)\n // Fall back immediately on render errors, avoid infinite recursion\n if (renderingFallback) {\n throw err\n }\n // nested errors. If fallback rendering also throws, we should NOT reset\n // the flag until we're sure no more recursion is happening.\n renderingFallback = true\n try {\n renderValue(toView(err))\n // Only reset if successful - if renderValue threw, we want to keep\n // renderingFallback = true to prevent infinite recursion\n renderingFallback = false\n props.onError?.(err)\n } catch (fallbackErr) {\n // Fallback rendering failed - keep renderingFallback = true\n // to prevent further attempts, then rethrow\n // If fallback fails, report both errors\n props.onError?.(err)\n throw fallbackErr\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n reset = () => {\n renderingFallback = false\n renderValue(toView(null))\n }\n\n renderValue(props.children ?? null)\n\n registerErrorHandler(err => {\n renderValue(toView(err))\n props.onError?.(err)\n return true\n })\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n renderValue(toView(null))\n }\n })\n }\n\n return fragment\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n handleError,\n pushRoot,\n popRoot,\n registerSuspenseHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode, SuspenseToken } from './types'\n\nexport interface SuspenseProps extends BaseProps {\n fallback: FictNode | ((err?: unknown) => FictNode)\n onResolve?: () => void\n onReject?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport interface SuspenseHandle {\n token: SuspenseToken\n resolve: () => void\n reject: (err: unknown) => void\n}\n\nexport function createSuspenseToken(): SuspenseHandle {\n let resolve!: () => void\n let reject!: (err: unknown) => void\n const promise = new Promise<void>((res, rej) => {\n resolve = res\n reject = rej\n })\n return {\n token: {\n then: promise.then.bind(promise),\n },\n resolve,\n reject,\n }\n}\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as PromiseLike<unknown>).then === 'function'\n\nexport function Suspense(props: SuspenseProps): FictNode {\n const pending = createSignal(0)\n let resolvedOnce = false\n let epoch = 0\n const hostRoot = getCurrentRoot()\n\n const toFallback = (err?: unknown) =>\n typeof props.fallback === 'function'\n ? (props.fallback as (e?: unknown) => FictNode)(err)\n : props.fallback\n\n const renderView = (view: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (view == null || view === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(view)\n nodes = toNodeArray(output)\n // Suspended view: child threw a suspense token and was handled upstream.\n // Avoid replacing existing fallback content; tear down this attempt.\n const suspendedAttempt =\n root.suspended ||\n (nodes.length > 0 &&\n nodes.every(node => node instanceof Comment && (node as Comment).data === 'fict:suspend'))\n if (suspendedAttempt) {\n popRoot(prev)\n destroyRoot(root)\n return\n }\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n destroyRoot(root)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:suspense')\n fragment.appendChild(marker)\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n\n const onResolveMaybe = () => {\n if (!resolvedOnce) {\n resolvedOnce = true\n props.onResolve?.()\n }\n }\n\n registerSuspenseHandler(token => {\n const tokenEpoch = epoch\n pending(pending() + 1)\n // Directly render fallback instead of using switchView to avoid\n // triggering the effect which would cause duplicate renders\n renderView(toFallback())\n\n const thenable = (token as SuspenseToken).then\n ? (token as SuspenseToken)\n : isThenable(token)\n ? token\n : null\n\n if (thenable) {\n thenable.then(\n () => {\n // This prevents stale token resolutions from affecting state after\n // a reset. The order is important: check epoch first, then update state.\n if (epoch !== tokenEpoch) {\n // Token is stale (from before a reset), ignore it completely\n return\n }\n // Use Math.max as a defensive measure - pending should never go below 0,\n // but this protects against edge cases where a token might resolve twice\n // or after the component has been reset.\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n if (newPending === 0) {\n // Directly render children instead of using switchView\n renderView(props.children ?? null)\n onResolveMaybe()\n }\n },\n err => {\n // Same epoch check - ignore stale tokens\n if (epoch !== tokenEpoch) {\n return\n }\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n props.onReject?.(err)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n },\n )\n return true\n }\n\n return false\n })\n\n // Initial render - render children directly\n // Note: This will be called synchronously during component creation.\n // If children suspend, the handler above will be called and switch to fallback.\n renderView(props.children ?? null)\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n epoch++\n pending(0)\n // Directly render children instead of using switchView\n renderView(props.children ?? null)\n }\n })\n }\n\n return fragment\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","../src/ref.ts","../src/error-boundary.ts","../src/suspense.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","sourcesContent":[null,"import type { RefObject } from './types'\n\n/**\n * Create a ref object for DOM element references.\n *\n * @returns A ref object with a `current` property initialized to `null`\n *\n * @example\n * ```tsx\n * import { createRef } from 'fict'\n *\n * function Component() {\n * const inputRef = createRef<HTMLInputElement>()\n *\n * $effect(() => {\n * inputRef.current?.focus()\n * })\n *\n * return <input ref={inputRef} />\n * }\n * ```\n */\nexport function createRef<T extends Element = HTMLElement>(): RefObject<T> {\n return { current: null }\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n pushRoot,\n popRoot,\n registerErrorHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport type { BaseProps, FictNode } from './types'\n\ninterface ErrorBoundaryProps extends BaseProps {\n fallback: FictNode | ((err: unknown, reset?: () => void) => FictNode)\n onError?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): FictNode {\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:error-boundary')\n fragment.appendChild(marker)\n\n const hostRoot = getCurrentRoot()\n\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n let renderingFallback = false\n\n let reset = () => {}\n const toView = (err: unknown | null): FictNode | null => {\n if (err != null) {\n return typeof props.fallback === 'function'\n ? (props.fallback as (e: unknown, reset?: () => void) => FictNode)(err, reset)\n : props.fallback\n }\n return props.children ?? null\n }\n\n const renderValue = (value: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (value == null || value === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(value)\n nodes = toNodeArray(output)\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n destroyRoot(root)\n // Fall back immediately on render errors, avoid infinite recursion\n if (renderingFallback) {\n throw err\n }\n // nested errors. If fallback rendering also throws, we should NOT reset\n // the flag until we're sure no more recursion is happening.\n renderingFallback = true\n try {\n renderValue(toView(err))\n // Only reset if successful - if renderValue threw, we want to keep\n // renderingFallback = true to prevent infinite recursion\n renderingFallback = false\n props.onError?.(err)\n } catch (fallbackErr) {\n // Fallback rendering failed - keep renderingFallback = true\n // to prevent further attempts, then rethrow\n // If fallback fails, report both errors\n props.onError?.(err)\n throw fallbackErr\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n reset = () => {\n renderingFallback = false\n renderValue(toView(null))\n }\n\n renderValue(props.children ?? null)\n\n registerErrorHandler(err => {\n renderValue(toView(err))\n props.onError?.(err)\n return true\n })\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n renderValue(toView(null))\n }\n })\n }\n\n return fragment\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n handleError,\n pushRoot,\n popRoot,\n registerSuspenseHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode, SuspenseToken } from './types'\n\nexport interface SuspenseProps extends BaseProps {\n fallback: FictNode | ((err?: unknown) => FictNode)\n onResolve?: () => void\n onReject?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport interface SuspenseHandle {\n token: SuspenseToken\n resolve: () => void\n reject: (err: unknown) => void\n}\n\nexport function createSuspenseToken(): SuspenseHandle {\n let resolve!: () => void\n let reject!: (err: unknown) => void\n const promise = new Promise<void>((res, rej) => {\n resolve = res\n reject = rej\n })\n return {\n token: {\n then: promise.then.bind(promise),\n },\n resolve,\n reject,\n }\n}\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as PromiseLike<unknown>).then === 'function'\n\nexport function Suspense(props: SuspenseProps): FictNode {\n const pending = createSignal(0)\n let resolvedOnce = false\n let epoch = 0\n const hostRoot = getCurrentRoot()\n\n const toFallback = (err?: unknown) =>\n typeof props.fallback === 'function'\n ? (props.fallback as (e?: unknown) => FictNode)(err)\n : props.fallback\n\n const renderView = (view: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (view == null || view === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(view)\n nodes = toNodeArray(output)\n // Suspended view: child threw a suspense token and was handled upstream.\n // Avoid replacing existing fallback content; tear down this attempt.\n const suspendedAttempt =\n root.suspended ||\n (nodes.length > 0 &&\n nodes.every(node => node instanceof Comment && (node as Comment).data === 'fict:suspend'))\n if (suspendedAttempt) {\n popRoot(prev)\n destroyRoot(root)\n return\n }\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n destroyRoot(root)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:suspense')\n fragment.appendChild(marker)\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n\n const onResolveMaybe = () => {\n if (!resolvedOnce) {\n resolvedOnce = true\n props.onResolve?.()\n }\n }\n\n registerSuspenseHandler(token => {\n const tokenEpoch = epoch\n pending(pending() + 1)\n // Directly render fallback instead of using switchView to avoid\n // triggering the effect which would cause duplicate renders\n renderView(toFallback())\n\n const thenable = (token as SuspenseToken).then\n ? (token as SuspenseToken)\n : isThenable(token)\n ? token\n : null\n\n if (thenable) {\n thenable.then(\n () => {\n // This prevents stale token resolutions from affecting state after\n // a reset. The order is important: check epoch first, then update state.\n if (epoch !== tokenEpoch) {\n // Token is stale (from before a reset), ignore it completely\n return\n }\n // Use Math.max as a defensive measure - pending should never go below 0,\n // but this protects against edge cases where a token might resolve twice\n // or after the component has been reset.\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n if (newPending === 0) {\n // Directly render children instead of using switchView\n renderView(props.children ?? null)\n onResolveMaybe()\n }\n },\n err => {\n // Same epoch check - ignore stale tokens\n if (epoch !== tokenEpoch) {\n return\n }\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n props.onReject?.(err)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n },\n )\n return true\n }\n\n return false\n })\n\n // Initial render - render children directly\n // Note: This will be called synchronously during component creation.\n // If children suspend, the handler above will be called and switch to fallback.\n renderView(props.children ?? null)\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n epoch++\n pending(0)\n // Directly render children instead of using switchView\n renderView(props.children ?? null)\n }\n })\n }\n\n return fragment\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,7 +1,8 @@
1
- export { F as Fragment, J as JSX, M as Memo, a as createElement, c as createMemo, k as keyed, m as mergeProps, p as prop, r as render } from './props-BIfromL0.cjs';
2
- import { R as RefObject, B as BaseProps, F as FictNode, k as SuspenseToken } from './effect-D6kaLM2-.cjs';
3
- export { z as ClassProp, C as Cleanup, v as Component, D as DOMElement, E as Effect, G as ErrorInfo, A as EventHandler, t as FictVNode, P as PropsWithChildren, w as Ref, x as RefCallback, y as StyleProp, l as createEffect, q as createPortal, p as createRoot, n as onCleanup, m as onDestroy, o as onMount } from './effect-D6kaLM2-.cjs';
4
- export { C as Context, F as FictDevtoolsHook, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-B25xyQrJ.cjs';
1
+ export { F as Fragment, J as JSX, M as Memo, a as createElement, c as createMemo, k as keyed, m as mergeProps, p as prop, r as render } from './props-XTHYD19o.cjs';
2
+ import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-BpSNEJJz.cjs';
3
+ export { v as ClassProp, C as Cleanup, p as Component, D as DOMElement, E as Effect, x as ErrorInfo, w as EventHandler, n as FictVNode, P as PropsWithChildren, q as Ref, s as RefCallback, t as StyleProp, h as createEffect, m as createPortal, l as createRoot, k as onCleanup, j as onDestroy, o as onMount } from './effect-BpSNEJJz.cjs';
4
+ export { C as Context, F as FictDevtoolsHook, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-CTBE00S_.cjs';
5
+ import './signal-C4ISF17w.cjs';
5
6
 
6
7
  /**
7
8
  * Create a ref object for DOM element references.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- export { F as Fragment, J as JSX, M as Memo, a as createElement, c as createMemo, k as keyed, m as mergeProps, p as prop, r as render } from './props-BEgIVMRx.js';
2
- import { R as RefObject, B as BaseProps, F as FictNode, k as SuspenseToken } from './effect-D6kaLM2-.js';
3
- export { z as ClassProp, C as Cleanup, v as Component, D as DOMElement, E as Effect, G as ErrorInfo, A as EventHandler, t as FictVNode, P as PropsWithChildren, w as Ref, x as RefCallback, y as StyleProp, l as createEffect, q as createPortal, p as createRoot, n as onCleanup, m as onDestroy, o as onMount } from './effect-D6kaLM2-.js';
4
- export { C as Context, F as FictDevtoolsHook, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-CGdP7_Jb.js';
1
+ export { F as Fragment, J as JSX, M as Memo, a as createElement, c as createMemo, k as keyed, m as mergeProps, p as prop, r as render } from './props-x-HbI-jX.js';
2
+ import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-BpSNEJJz.js';
3
+ export { v as ClassProp, C as Cleanup, p as Component, D as DOMElement, E as Effect, x as ErrorInfo, w as EventHandler, n as FictVNode, P as PropsWithChildren, q as Ref, s as RefCallback, t as StyleProp, h as createEffect, m as createPortal, l as createRoot, k as onCleanup, j as onDestroy, o as onMount } from './effect-BpSNEJJz.js';
4
+ export { C as Context, F as FictDevtoolsHook, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-lkLhbkFJ.js';
5
+ import './signal-C4ISF17w.js';
5
6
 
6
7
  /**
7
8
  * Create a ref object for DOM element references.
package/dist/index.dev.js CHANGED
@@ -495,8 +495,10 @@ function createRenderEffect(fn) {
495
495
  // src/hooks.ts
496
496
  var isDev3 = true ? true : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
497
497
  var ctxStack = [];
498
+ var preparedContext = null;
498
499
  function __fictPushContext() {
499
- const ctx = { slots: [], cursor: 0 };
500
+ const ctx = preparedContext ?? { slots: [], cursor: 0 };
501
+ preparedContext = null;
500
502
  ctxStack.push(ctx);
501
503
  return ctx;
502
504
  }
@@ -1673,6 +1675,22 @@ var unitlessList = isDev5 ? [
1673
1675
  ] : ["opacity", "zIndex"];
1674
1676
  var UnitlessStyles = new Set(unitlessList);
1675
1677
 
1678
+ // src/hydration.ts
1679
+ var hydrationStack = [];
1680
+ function withHydration(root, fn) {
1681
+ const owner = root.ownerDocument ?? document;
1682
+ hydrationStack.push({
1683
+ cursor: root.firstChild,
1684
+ boundary: null,
1685
+ owner
1686
+ });
1687
+ try {
1688
+ fn();
1689
+ } finally {
1690
+ hydrationStack.pop();
1691
+ }
1692
+ }
1693
+
1676
1694
  // src/node-ops.ts
1677
1695
  function toNodeArray(node) {
1678
1696
  try {
@@ -1816,6 +1834,40 @@ function removeNodes(nodes) {
1816
1834
  }
1817
1835
  }
1818
1836
 
1837
+ // src/resume.ts
1838
+ var ssrEnabled = false;
1839
+ var resumableEnabled = false;
1840
+ var hydrating = false;
1841
+ var scopeCounter = 0;
1842
+ var scopeRegistry = /* @__PURE__ */ new Map();
1843
+ function __fictIsResumable() {
1844
+ return ssrEnabled || resumableEnabled;
1845
+ }
1846
+ function __fictIsHydrating() {
1847
+ return hydrating;
1848
+ }
1849
+ function __fictRegisterScope(ctx, host, type, props) {
1850
+ if (!__fictIsResumable()) return "";
1851
+ const id = `s${++scopeCounter}`;
1852
+ ctx.scopeId = id;
1853
+ if (type !== void 0) {
1854
+ ctx.scopeType = type;
1855
+ }
1856
+ host.setAttribute("data-fict-s", id);
1857
+ if (type) {
1858
+ host.setAttribute("data-fict-t", type);
1859
+ }
1860
+ const record = { id, ctx, host };
1861
+ if (type !== void 0) {
1862
+ record.type = type;
1863
+ }
1864
+ if (props !== void 0) {
1865
+ record.props = props;
1866
+ }
1867
+ scopeRegistry.set(id, record);
1868
+ return id;
1869
+ }
1870
+
1819
1871
  // src/binding.ts
1820
1872
  var isDev6 = true ? true : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
1821
1873
  function isReactive(value) {
@@ -2400,14 +2452,22 @@ var nextComponentId = 1;
2400
2452
  function render(view, container) {
2401
2453
  const root = createRootContext();
2402
2454
  const prev = pushRoot(root);
2403
- let dom;
2455
+ let dom = void 0;
2404
2456
  try {
2405
2457
  const output = view();
2406
- dom = createElement(output);
2458
+ if (__fictIsHydrating()) {
2459
+ withHydration(container, () => {
2460
+ dom = createElement(output);
2461
+ });
2462
+ } else {
2463
+ dom = createElement(output);
2464
+ }
2407
2465
  } finally {
2408
2466
  popRoot(prev);
2409
2467
  }
2410
- container.replaceChildren(dom);
2468
+ if (!__fictIsHydrating()) {
2469
+ container.replaceChildren(dom);
2470
+ }
2411
2471
  container.setAttribute("data-fict-fine-grained", "1");
2412
2472
  flushOnMount(root);
2413
2473
  const teardown = () => {
@@ -2434,6 +2494,13 @@ function createElementWithContext(node, namespace) {
2434
2494
  if (node === null || node === void 0 || node === false) {
2435
2495
  return document.createTextNode("");
2436
2496
  }
2497
+ if (isReactive(node)) {
2498
+ const resolved = node();
2499
+ if (resolved === node) {
2500
+ return document.createTextNode("");
2501
+ }
2502
+ return createElementWithContext(resolved, namespace);
2503
+ }
2437
2504
  if (typeof node === "object" && node !== null && !(node instanceof Node)) {
2438
2505
  if ("marker" in node) {
2439
2506
  const handle = node;
@@ -2510,6 +2577,27 @@ function createElementWithContext(node, namespace) {
2510
2577
  });
2511
2578
  onCleanup(() => hook.componentUnmount?.(componentId));
2512
2579
  }
2580
+ if (__fictIsResumable() && !__fictIsHydrating()) {
2581
+ const content = createElementWithContext(rendered, namespace);
2582
+ const host = namespace === "svg" ? document.createElementNS(SVG_NS, "fict-host") : namespace === "mathml" ? document.createElementNS(MATHML_NS, "fict-host") : document.createElement("fict-host");
2583
+ host.setAttribute("data-fict-host", "");
2584
+ if (namespace === null && host.style) {
2585
+ ;
2586
+ host.style.display = "contents";
2587
+ }
2588
+ const meta = vnode.type.__fictMeta;
2589
+ const typeKey = (meta?.id ?? vnode.type.name) || "Anonymous";
2590
+ __fictRegisterScope(ctx, host, typeKey, rawProps);
2591
+ if (meta?.resume) {
2592
+ host.setAttribute("data-fict-h", meta.resume);
2593
+ }
2594
+ if (content instanceof DocumentFragment) {
2595
+ host.append(...Array.from(content.childNodes));
2596
+ } else {
2597
+ host.appendChild(content);
2598
+ }
2599
+ return host;
2600
+ }
2513
2601
  return createElementWithContext(rendered, namespace);
2514
2602
  } catch (err) {
2515
2603
  if (handleSuspend(err)) {