@fictjs/runtime 0.2.0 → 0.2.2

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 (37) hide show
  1. package/dist/advanced.cjs +8 -8
  2. package/dist/advanced.js +3 -3
  3. package/dist/{chunk-BSUMPMKX.cjs → chunk-3A4VW6AK.cjs} +7 -7
  4. package/dist/{chunk-BSUMPMKX.cjs.map → chunk-3A4VW6AK.cjs.map} +1 -1
  5. package/dist/{chunk-J74L7UYP.cjs → chunk-3U7EBKEU.cjs} +5 -3
  6. package/dist/chunk-3U7EBKEU.cjs.map +1 -0
  7. package/dist/{chunk-QV5GOCR5.js → chunk-LU2LD2WJ.js} +2 -2
  8. package/dist/{chunk-FG3M7EBL.js → chunk-TEYUDPTA.js} +2 -2
  9. package/dist/{chunk-FG3M7EBL.js.map → chunk-TEYUDPTA.js.map} +1 -1
  10. package/dist/{chunk-527QSKFM.cjs → chunk-URDFDRHR.cjs} +16 -16
  11. package/dist/{chunk-527QSKFM.cjs.map → chunk-URDFDRHR.cjs.map} +1 -1
  12. package/dist/{chunk-5KXEEQUO.js → chunk-YVS4WJ2W.js} +5 -3
  13. package/dist/chunk-YVS4WJ2W.js.map +1 -0
  14. package/dist/index.cjs +46 -50
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +1 -1
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.dev.js +12 -14
  19. package/dist/index.dev.js.map +1 -1
  20. package/dist/index.js +10 -14
  21. package/dist/index.js.map +1 -1
  22. package/dist/internal.cjs +64 -42
  23. package/dist/internal.cjs.map +1 -1
  24. package/dist/internal.js +32 -10
  25. package/dist/internal.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/context.ts +1 -1
  28. package/src/dom.ts +4 -1
  29. package/src/error-boundary.ts +9 -9
  30. package/src/signal.ts +2 -1
  31. package/src/store.ts +42 -20
  32. package/src/suspense.ts +0 -5
  33. package/dist/chunk-5KXEEQUO.js.map +0 -1
  34. package/dist/chunk-J74L7UYP.cjs.map +0 -1
  35. package/dist/jsx-runtime.d.cts +0 -671
  36. package/dist/jsx-runtime.d.ts +0 -671
  37. /package/dist/{chunk-QV5GOCR5.js.map → chunk-LU2LD2WJ.js.map} +0 -0
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  createContext,
3
3
  hasContext,
4
4
  useContext
5
- } from "./chunk-FG3M7EBL.js";
5
+ } from "./chunk-TEYUDPTA.js";
6
6
  import {
7
7
  Fragment,
8
8
  batch2 as batch,
@@ -34,7 +34,7 @@ import {
34
34
  untrack2 as untrack,
35
35
  useDeferredValue,
36
36
  useTransition
37
- } from "./chunk-5KXEEQUO.js";
37
+ } from "./chunk-YVS4WJ2W.js";
38
38
 
39
39
  // src/ref.ts
40
40
  function createRef() {
@@ -46,14 +46,15 @@ function ErrorBoundary(props) {
46
46
  const fragment = document.createDocumentFragment();
47
47
  const marker = document.createComment("fict:error-boundary");
48
48
  fragment.appendChild(marker);
49
- const currentView = signal(props.children ?? null);
50
49
  const hostRoot = getCurrentRoot();
51
50
  let cleanup;
52
51
  let activeNodes = [];
53
52
  let renderingFallback = false;
53
+ let reset = () => {
54
+ };
54
55
  const toView = (err) => {
55
56
  if (err != null) {
56
- return typeof props.fallback === "function" ? props.fallback(err) : props.fallback;
57
+ return typeof props.fallback === "function" ? props.fallback(err, reset) : props.fallback;
57
58
  }
58
59
  return props.children ?? null;
59
60
  };
@@ -81,7 +82,6 @@ function ErrorBoundary(props) {
81
82
  }
82
83
  } catch (err) {
83
84
  popRoot(prev);
84
- flushOnMount(root);
85
85
  destroyRoot(root);
86
86
  if (renderingFallback) {
87
87
  throw err;
@@ -105,10 +105,11 @@ function ErrorBoundary(props) {
105
105
  };
106
106
  activeNodes = nodes;
107
107
  };
108
- createEffect(() => {
109
- const value = currentView();
110
- renderValue(value);
111
- });
108
+ reset = () => {
109
+ renderingFallback = false;
110
+ renderValue(toView(null));
111
+ };
112
+ renderValue(props.children ?? null);
112
113
  registerErrorHandler((err) => {
113
114
  renderValue(toView(err));
114
115
  props.onError?.(err);
@@ -147,7 +148,6 @@ function createSuspenseToken() {
147
148
  }
148
149
  var isThenable = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
149
150
  function Suspense(props) {
150
- const currentView = signal(props.children ?? null);
151
151
  const pending = signal(0);
152
152
  let resolvedOnce = false;
153
153
  let epoch = 0;
@@ -183,7 +183,6 @@ function Suspense(props) {
183
183
  }
184
184
  } catch (err) {
185
185
  popRoot(prev);
186
- flushOnMount(root);
187
186
  destroyRoot(root);
188
187
  if (!handleError(err, { source: "render" }, hostRoot)) {
189
188
  throw err;
@@ -212,7 +211,6 @@ function Suspense(props) {
212
211
  registerSuspenseHandler((token) => {
213
212
  const tokenEpoch = epoch;
214
213
  pending(pending() + 1);
215
- currentView(toFallback());
216
214
  renderView(toFallback());
217
215
  const thenable = token.then ? token : isThenable(token) ? token : null;
218
216
  if (thenable) {
@@ -224,7 +222,6 @@ function Suspense(props) {
224
222
  const newPending = Math.max(0, pending() - 1);
225
223
  pending(newPending);
226
224
  if (newPending === 0) {
227
- currentView(props.children ?? null);
228
225
  renderView(props.children ?? null);
229
226
  onResolveMaybe();
230
227
  }
@@ -256,7 +253,6 @@ function Suspense(props) {
256
253
  prev = next;
257
254
  epoch++;
258
255
  pending(0);
259
- currentView(props.children ?? null);
260
256
  renderView(props.children ?? null);
261
257
  }
262
258
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ref.ts","../src/error-boundary.ts","../src/suspense.ts"],"sourcesContent":["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 { createSignal } from './signal'\nimport type { BaseProps, FictNode } from './types'\n\ninterface ErrorBoundaryProps extends BaseProps {\n fallback: FictNode | ((err: unknown) => 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 currentView = createSignal<FictNode | null>(props.children ?? null)\n const hostRoot = getCurrentRoot()\n\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n let renderingFallback = false\n\n const toView = (err: unknown | null): FictNode | null => {\n if (err != null) {\n return typeof props.fallback === 'function'\n ? (props.fallback as (e: unknown) => FictNode)(err)\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 flushOnMount(root)\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 createEffect(() => {\n const value = currentView()\n renderValue(value)\n })\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 currentView = createSignal<FictNode | null>(props.children ?? null)\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 flushOnMount(root)\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 currentView(toFallback())\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 currentView(props.children ?? null)\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 currentView(props.children ?? null)\n renderView(props.children ?? null)\n }\n })\n }\n\n return fragment\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/ref.ts","../src/error-boundary.ts","../src/suspense.ts"],"sourcesContent":["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"],"mappings":"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","names":[]}
package/dist/internal.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
- var _chunkBSUMPMKXcjs = require('./chunk-BSUMPMKX.cjs');
3
+ var _chunk3A4VW6AKcjs = require('./chunk-3A4VW6AK.cjs');
4
4
 
5
5
 
6
6
 
@@ -66,7 +66,7 @@ var _chunkBSUMPMKXcjs = require('./chunk-BSUMPMKX.cjs');
66
66
 
67
67
 
68
68
 
69
- var _chunkJ74L7UYPcjs = require('./chunk-J74L7UYP.cjs');
69
+ var _chunk3U7EBKEUcjs = require('./chunk-3U7EBKEU.cjs');
70
70
 
71
71
  // src/store.ts
72
72
  var PROXY = Symbol("fict:store-proxy");
@@ -76,7 +76,7 @@ function createStore(initialValue) {
76
76
  const unwrapped = unwrap2(initialValue);
77
77
  const wrapped = wrap(unwrapped);
78
78
  function setStore(fn) {
79
- _chunkJ74L7UYPcjs.batch.call(void 0, () => {
79
+ _chunk3U7EBKEUcjs.batch.call(void 0, () => {
80
80
  const result = fn(wrapped);
81
81
  if (result !== void 0) {
82
82
  reconcile(wrapped, result);
@@ -89,7 +89,7 @@ var proxyCache = /* @__PURE__ */ new WeakMap();
89
89
  var signalCache = /* @__PURE__ */ new WeakMap();
90
90
  function wrap(value) {
91
91
  if (value === null || typeof value !== "object") return value;
92
- if (value[PROXY]) return value;
92
+ if (Reflect.get(value, PROXY)) return value;
93
93
  if (proxyCache.has(value)) return proxyCache.get(value);
94
94
  const handler = {
95
95
  get(target, prop2, receiver) {
@@ -114,6 +114,8 @@ function wrap(value) {
114
114
  },
115
115
  set(target, prop2, value2, receiver) {
116
116
  if (prop2 === PROXY || prop2 === TARGET) return false;
117
+ const isArrayLength = Array.isArray(target) && prop2 === "length";
118
+ const oldLength = isArrayLength ? target.length : void 0;
117
119
  const hadKey = Object.prototype.hasOwnProperty.call(target, prop2);
118
120
  const oldValue = Reflect.get(target, prop2, receiver);
119
121
  if (oldValue === value2) return true;
@@ -123,6 +125,23 @@ function wrap(value) {
123
125
  if (!hadKey) {
124
126
  trigger(target, ITERATE_KEY);
125
127
  }
128
+ if (isArrayLength) {
129
+ const nextLength = target.length;
130
+ if (typeof oldLength === "number" && nextLength < oldLength) {
131
+ const signals = signalCache.get(target);
132
+ if (signals) {
133
+ for (const key of signals.keys()) {
134
+ if (typeof key !== "string") continue;
135
+ const index = Number(key);
136
+ if (!Number.isInteger(index) || String(index) !== key) continue;
137
+ if (index >= nextLength && index < oldLength) {
138
+ trigger(target, key);
139
+ }
140
+ }
141
+ }
142
+ }
143
+ trigger(target, ITERATE_KEY);
144
+ }
126
145
  }
127
146
  return result;
128
147
  },
@@ -143,8 +162,8 @@ function wrap(value) {
143
162
  return proxy;
144
163
  }
145
164
  function unwrap2(value) {
146
- if (value && typeof value === "object" && value[PROXY]) {
147
- return value[TARGET];
165
+ if (value && typeof value === "object" && Reflect.get(value, PROXY)) {
166
+ return Reflect.get(value, TARGET);
148
167
  }
149
168
  return value;
150
169
  }
@@ -157,7 +176,7 @@ function track(target, prop2) {
157
176
  let s = signals.get(prop2);
158
177
  if (!s) {
159
178
  const initial = prop2 === ITERATE_KEY ? Reflect.ownKeys(target).length : getLastValue(target, prop2);
160
- s = _chunkJ74L7UYPcjs.signal.call(void 0, initial);
179
+ s = _chunk3U7EBKEUcjs.signal.call(void 0, initial);
161
180
  signals.set(prop2, s);
162
181
  }
163
182
  s();
@@ -176,7 +195,7 @@ function trigger(target, prop2) {
176
195
  }
177
196
  }
178
197
  function getLastValue(target, prop2) {
179
- return target[prop2];
198
+ return Reflect.get(target, prop2);
180
199
  }
181
200
  function reconcile(target, value) {
182
201
  if (target === value) return;
@@ -191,13 +210,16 @@ function reconcile(target, value) {
191
210
  const realValue = unwrap2(value);
192
211
  const keys = /* @__PURE__ */ new Set([...Object.keys(realTarget), ...Object.keys(realValue)]);
193
212
  for (const key of keys) {
194
- if (realValue[key] === void 0 && realTarget[key] !== void 0) {
213
+ const rTarget = realTarget;
214
+ const rValue = realValue;
215
+ if (rValue[key] === void 0 && rTarget[key] !== void 0) {
195
216
  delete target[key];
196
- } else if (realTarget[key] !== realValue[key]) {
197
- target[key] = realValue[key];
217
+ } else if (rTarget[key] !== rValue[key]) {
218
+ ;
219
+ target[key] = rValue[key];
198
220
  }
199
221
  }
200
- if (Array.isArray(target) && target.length !== realValue.length) {
222
+ if (Array.isArray(target) && Array.isArray(realValue) && target.length !== realValue.length) {
201
223
  target.length = realValue.length;
202
224
  }
203
225
  }
@@ -329,7 +351,7 @@ var MAX_SAFE_VERSION = 9007199254740991;
329
351
  function createVersionedSignalAccessor(initialValue) {
330
352
  let current = initialValue;
331
353
  let version = 0;
332
- const track2 = _chunkJ74L7UYPcjs.signal.call(void 0, version);
354
+ const track2 = _chunk3U7EBKEUcjs.signal.call(void 0, version);
333
355
  function accessor(value) {
334
356
  if (arguments.length === 0) {
335
357
  track2();
@@ -346,7 +368,7 @@ function createKeyedListContainer() {
346
368
  const endMarker = document.createComment("fict:list:end");
347
369
  const dispose = () => {
348
370
  for (const block of container.blocks.values()) {
349
- _chunkJ74L7UYPcjs.destroyRoot.call(void 0, block.root);
371
+ _chunk3U7EBKEUcjs.destroyRoot.call(void 0, block.root);
350
372
  }
351
373
  container.blocks.clear();
352
374
  container.nextBlocks.clear();
@@ -385,32 +407,32 @@ function createKeyedListContainer() {
385
407
  }
386
408
  function createKeyedBlock(key, item, index, render, needsIndex = true, hostRoot) {
387
409
  const itemSig = createVersionedSignalAccessor(item);
388
- const indexSig = needsIndex ? _chunkJ74L7UYPcjs.signal.call(void 0, index) : ((next) => {
410
+ const indexSig = needsIndex ? _chunk3U7EBKEUcjs.signal.call(void 0, index) : ((next) => {
389
411
  if (arguments.length === 0) return index;
390
412
  index = next;
391
413
  return index;
392
414
  });
393
- const root = _chunkJ74L7UYPcjs.createRootContext.call(void 0, hostRoot);
394
- const prevRoot = _chunkJ74L7UYPcjs.pushRoot.call(void 0, root);
415
+ const root = _chunk3U7EBKEUcjs.createRootContext.call(void 0, hostRoot);
416
+ const prevRoot = _chunk3U7EBKEUcjs.pushRoot.call(void 0, root);
395
417
  let nodes = [];
396
418
  let scopeDispose;
397
- const prevSub = _chunkJ74L7UYPcjs.setActiveSub.call(void 0, void 0);
419
+ const prevSub = _chunk3U7EBKEUcjs.setActiveSub.call(void 0, void 0);
398
420
  try {
399
- scopeDispose = _chunkJ74L7UYPcjs.effectScope.call(void 0, () => {
421
+ scopeDispose = _chunk3U7EBKEUcjs.effectScope.call(void 0, () => {
400
422
  const rendered = render(itemSig, indexSig, key);
401
423
  if (rendered instanceof Node || Array.isArray(rendered) && rendered.every((n) => n instanceof Node)) {
402
- nodes = _chunkJ74L7UYPcjs.toNodeArray.call(void 0, rendered);
424
+ nodes = _chunk3U7EBKEUcjs.toNodeArray.call(void 0, rendered);
403
425
  } else {
404
- const element = _chunkJ74L7UYPcjs.createElement.call(void 0, rendered);
405
- nodes = _chunkJ74L7UYPcjs.toNodeArray.call(void 0, element);
426
+ const element = _chunk3U7EBKEUcjs.createElement.call(void 0, rendered);
427
+ nodes = _chunk3U7EBKEUcjs.toNodeArray.call(void 0, element);
406
428
  }
407
429
  });
408
430
  if (scopeDispose) {
409
431
  root.cleanups.push(scopeDispose);
410
432
  }
411
433
  } finally {
412
- _chunkJ74L7UYPcjs.setActiveSub.call(void 0, prevSub);
413
- _chunkJ74L7UYPcjs.popRoot.call(void 0, prevRoot);
434
+ _chunk3U7EBKEUcjs.setActiveSub.call(void 0, prevSub);
435
+ _chunk3U7EBKEUcjs.popRoot.call(void 0, prevRoot);
414
436
  }
415
437
  return {
416
438
  key,
@@ -516,7 +538,7 @@ function createKeyedList(getItems, keyFn, renderItem, needsIndex) {
516
538
  }
517
539
  function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
518
540
  const container = createKeyedListContainer();
519
- const hostRoot = _chunkJ74L7UYPcjs.getCurrentRoot.call(void 0, );
541
+ const hostRoot = _chunk3U7EBKEUcjs.getCurrentRoot.call(void 0, );
520
542
  const fragment = document.createDocumentFragment();
521
543
  fragment.append(container.startMarker, container.endMarker);
522
544
  let disposed = false;
@@ -538,7 +560,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
538
560
  if (disposed) return;
539
561
  const parent = getConnectedParent();
540
562
  if (!parent) return;
541
- _chunkJ74L7UYPcjs.batch2.call(void 0, () => {
563
+ _chunk3U7EBKEUcjs.batch2.call(void 0, () => {
542
564
  const oldBlocks = container.blocks;
543
565
  const newBlocks = container.nextBlocks;
544
566
  const prevOrderedBlocks = container.orderedBlocks;
@@ -548,7 +570,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
548
570
  if (newItems.length === 0) {
549
571
  if (oldBlocks.size > 0) {
550
572
  for (const block of oldBlocks.values()) {
551
- _chunkJ74L7UYPcjs.destroyRoot.call(void 0, block.root);
573
+ _chunk3U7EBKEUcjs.destroyRoot.call(void 0, block.root);
552
574
  }
553
575
  const range = document.createRange();
554
576
  range.setStartAfter(container.startMarker);
@@ -629,8 +651,8 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
629
651
  `[fict] Duplicate key "${String(key)}" detected in list rendering. Each item should have a unique key. The previous item with this key will be replaced.`
630
652
  );
631
653
  }
632
- _chunkJ74L7UYPcjs.destroyRoot.call(void 0, existingBlock.root);
633
- _chunkJ74L7UYPcjs.removeNodes.call(void 0, existingBlock.nodes);
654
+ _chunk3U7EBKEUcjs.destroyRoot.call(void 0, existingBlock.root);
655
+ _chunk3U7EBKEUcjs.removeNodes.call(void 0, existingBlock.nodes);
634
656
  }
635
657
  block = createKeyedBlock(key, item, index, renderItem, needsIndex, hostRoot);
636
658
  createdBlocks.push(block);
@@ -643,8 +665,8 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
643
665
  hasDuplicateKey = true;
644
666
  const prior = nextOrderedBlocks[position];
645
667
  if (prior && prior !== resolvedBlock) {
646
- _chunkJ74L7UYPcjs.destroyRoot.call(void 0, prior.root);
647
- _chunkJ74L7UYPcjs.removeNodes.call(void 0, prior.nodes);
668
+ _chunk3U7EBKEUcjs.destroyRoot.call(void 0, prior.root);
669
+ _chunk3U7EBKEUcjs.removeNodes.call(void 0, prior.nodes);
648
670
  }
649
671
  nextOrderedBlocks[position] = resolvedBlock;
650
672
  } else {
@@ -682,7 +704,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
682
704
  }
683
705
  }
684
706
  if (appendedNodes.length > 0) {
685
- _chunkJ74L7UYPcjs.insertNodesBefore.call(void 0, parent, appendedNodes, container.endMarker);
707
+ _chunk3U7EBKEUcjs.insertNodesBefore.call(void 0, parent, appendedNodes, container.endMarker);
686
708
  const currentNodes = container.currentNodes;
687
709
  currentNodes.pop();
688
710
  for (let i = 0; i < appendedNodes.length; i++) {
@@ -696,15 +718,15 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
696
718
  container.nextOrderedBlocks = prevOrderedBlocks;
697
719
  for (const block of createdBlocks) {
698
720
  if (newBlocks.get(block.key) === block) {
699
- _chunkJ74L7UYPcjs.flushOnMount.call(void 0, block.root);
721
+ _chunk3U7EBKEUcjs.flushOnMount.call(void 0, block.root);
700
722
  }
701
723
  }
702
724
  return;
703
725
  }
704
726
  if (oldBlocks.size > 0) {
705
727
  for (const block of oldBlocks.values()) {
706
- _chunkJ74L7UYPcjs.destroyRoot.call(void 0, block.root);
707
- _chunkJ74L7UYPcjs.removeNodes.call(void 0, block.nodes);
728
+ _chunk3U7EBKEUcjs.destroyRoot.call(void 0, block.root);
729
+ _chunk3U7EBKEUcjs.removeNodes.call(void 0, block.nodes);
708
730
  }
709
731
  oldBlocks.clear();
710
732
  }
@@ -763,7 +785,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
763
785
  container.nextOrderedBlocks = prevOrderedBlocks;
764
786
  for (const block of createdBlocks) {
765
787
  if (newBlocks.get(block.key) === block) {
766
- _chunkJ74L7UYPcjs.flushOnMount.call(void 0, block.root);
788
+ _chunk3U7EBKEUcjs.flushOnMount.call(void 0, block.root);
767
789
  }
768
790
  }
769
791
  });
@@ -777,15 +799,15 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
777
799
  const parent = getConnectedParent();
778
800
  if (!parent) return false;
779
801
  const start = () => {
780
- effectDispose = _chunkJ74L7UYPcjs.createRenderEffect.call(void 0, performDiff);
802
+ effectDispose = _chunk3U7EBKEUcjs.createRenderEffect.call(void 0, performDiff);
781
803
  effectStarted = true;
782
804
  };
783
805
  if (hostRoot) {
784
- const prev = _chunkJ74L7UYPcjs.pushRoot.call(void 0, hostRoot);
806
+ const prev = _chunk3U7EBKEUcjs.pushRoot.call(void 0, hostRoot);
785
807
  try {
786
808
  start();
787
809
  } finally {
788
- _chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
810
+ _chunk3U7EBKEUcjs.popRoot.call(void 0, prev);
789
811
  }
790
812
  } else {
791
813
  start();
@@ -799,7 +821,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
799
821
  if (getConnectedParent()) {
800
822
  disconnectObserver();
801
823
  if (ensureEffectStarted()) {
802
- _chunkJ74L7UYPcjs.flush.call(void 0, );
824
+ _chunk3U7EBKEUcjs.flush.call(void 0, );
803
825
  }
804
826
  }
805
827
  });
@@ -833,7 +855,7 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
833
855
  if (disposed) return;
834
856
  scheduleStart();
835
857
  if (ensureEffectStarted()) {
836
- _chunkJ74L7UYPcjs.flush.call(void 0, );
858
+ _chunk3U7EBKEUcjs.flush.call(void 0, );
837
859
  } else {
838
860
  waitForConnection();
839
861
  }
@@ -906,5 +928,5 @@ function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex) {
906
928
 
907
929
 
908
930
 
909
- exports.Aliases = _chunkJ74L7UYPcjs.Aliases; exports.BooleanAttributes = _chunkJ74L7UYPcjs.BooleanAttributes; exports.ChildProperties = _chunkJ74L7UYPcjs.ChildProperties; exports.DelegatedEvents = _chunkJ74L7UYPcjs.DelegatedEvents; exports.Fragment = _chunkJ74L7UYPcjs.Fragment; exports.Properties = _chunkJ74L7UYPcjs.Properties; exports.SVGElements = _chunkJ74L7UYPcjs.SVGElements; exports.SVGNamespace = _chunkJ74L7UYPcjs.SVGNamespace; exports.UnitlessStyles = _chunkJ74L7UYPcjs.UnitlessStyles; exports.__fictPopContext = _chunkJ74L7UYPcjs.__fictPopContext; exports.__fictProp = _chunkJ74L7UYPcjs.__fictProp; exports.__fictPropsRest = _chunkJ74L7UYPcjs.__fictPropsRest; exports.__fictPushContext = _chunkJ74L7UYPcjs.__fictPushContext; exports.__fictRender = _chunkJ74L7UYPcjs.__fictRender; exports.__fictResetContext = _chunkJ74L7UYPcjs.__fictResetContext; exports.__fictUseContext = _chunkJ74L7UYPcjs.__fictUseContext; exports.__fictUseEffect = _chunkJ74L7UYPcjs.__fictUseEffect; exports.__fictUseMemo = _chunkJ74L7UYPcjs.__fictUseMemo; exports.__fictUseSignal = _chunkJ74L7UYPcjs.__fictUseSignal; exports.addEventListener = _chunkJ74L7UYPcjs.addEventListener; exports.assign = _chunkJ74L7UYPcjs.assign; exports.bindAttribute = _chunkJ74L7UYPcjs.bindAttribute; exports.bindClass = _chunkJ74L7UYPcjs.bindClass; exports.bindEvent = _chunkJ74L7UYPcjs.bindEvent; exports.bindProperty = _chunkJ74L7UYPcjs.bindProperty; exports.bindRef = _chunkJ74L7UYPcjs.bindRef; exports.bindStyle = _chunkJ74L7UYPcjs.bindStyle; exports.bindText = _chunkJ74L7UYPcjs.bindText; exports.callEventHandler = _chunkJ74L7UYPcjs.callEventHandler; exports.classList = _chunkJ74L7UYPcjs.classList; exports.clearDelegatedEvents = _chunkJ74L7UYPcjs.clearDelegatedEvents; exports.createConditional = _chunkJ74L7UYPcjs.createConditional; exports.createEffect = _chunkJ74L7UYPcjs.createEffect; exports.createElement = _chunkJ74L7UYPcjs.createElement; exports.createKeyedList = createKeyedList; exports.createMemo = _chunkJ74L7UYPcjs.createMemo; exports.createPortal = _chunkJ74L7UYPcjs.createPortal; exports.createPropsProxy = _chunkJ74L7UYPcjs.createPropsProxy; exports.createRenderEffect = _chunkJ74L7UYPcjs.createRenderEffect; exports.createSelector = _chunkJ74L7UYPcjs.createSelector; exports.createSignal = _chunkJ74L7UYPcjs.signal; exports.createStore = createStore; exports.delegateEvents = _chunkJ74L7UYPcjs.delegateEvents; exports.getPropAlias = _chunkJ74L7UYPcjs.getPropAlias; exports.insert = _chunkJ74L7UYPcjs.insert; exports.insertNodesBefore = _chunkJ74L7UYPcjs.insertNodesBefore; exports.isNodeBetweenMarkers = isNodeBetweenMarkers; exports.isReactive = _chunkJ74L7UYPcjs.isReactive; exports.mergeProps = _chunkJ74L7UYPcjs.mergeProps; exports.moveNodesBefore = moveNodesBefore; exports.onDestroy = _chunkJ74L7UYPcjs.onDestroy; exports.prop = _chunkJ74L7UYPcjs.prop; exports.reconcileArrays = reconcileArrays; exports.removeNodes = _chunkJ74L7UYPcjs.removeNodes; exports.runInScope = _chunkBSUMPMKXcjs.runInScope; exports.spread = _chunkJ74L7UYPcjs.spread; exports.template = _chunkJ74L7UYPcjs.template; exports.toNodeArray = _chunkJ74L7UYPcjs.toNodeArray; exports.unwrap = _chunkJ74L7UYPcjs.unwrap;
931
+ exports.Aliases = _chunk3U7EBKEUcjs.Aliases; exports.BooleanAttributes = _chunk3U7EBKEUcjs.BooleanAttributes; exports.ChildProperties = _chunk3U7EBKEUcjs.ChildProperties; exports.DelegatedEvents = _chunk3U7EBKEUcjs.DelegatedEvents; exports.Fragment = _chunk3U7EBKEUcjs.Fragment; exports.Properties = _chunk3U7EBKEUcjs.Properties; exports.SVGElements = _chunk3U7EBKEUcjs.SVGElements; exports.SVGNamespace = _chunk3U7EBKEUcjs.SVGNamespace; exports.UnitlessStyles = _chunk3U7EBKEUcjs.UnitlessStyles; exports.__fictPopContext = _chunk3U7EBKEUcjs.__fictPopContext; exports.__fictProp = _chunk3U7EBKEUcjs.__fictProp; exports.__fictPropsRest = _chunk3U7EBKEUcjs.__fictPropsRest; exports.__fictPushContext = _chunk3U7EBKEUcjs.__fictPushContext; exports.__fictRender = _chunk3U7EBKEUcjs.__fictRender; exports.__fictResetContext = _chunk3U7EBKEUcjs.__fictResetContext; exports.__fictUseContext = _chunk3U7EBKEUcjs.__fictUseContext; exports.__fictUseEffect = _chunk3U7EBKEUcjs.__fictUseEffect; exports.__fictUseMemo = _chunk3U7EBKEUcjs.__fictUseMemo; exports.__fictUseSignal = _chunk3U7EBKEUcjs.__fictUseSignal; exports.addEventListener = _chunk3U7EBKEUcjs.addEventListener; exports.assign = _chunk3U7EBKEUcjs.assign; exports.bindAttribute = _chunk3U7EBKEUcjs.bindAttribute; exports.bindClass = _chunk3U7EBKEUcjs.bindClass; exports.bindEvent = _chunk3U7EBKEUcjs.bindEvent; exports.bindProperty = _chunk3U7EBKEUcjs.bindProperty; exports.bindRef = _chunk3U7EBKEUcjs.bindRef; exports.bindStyle = _chunk3U7EBKEUcjs.bindStyle; exports.bindText = _chunk3U7EBKEUcjs.bindText; exports.callEventHandler = _chunk3U7EBKEUcjs.callEventHandler; exports.classList = _chunk3U7EBKEUcjs.classList; exports.clearDelegatedEvents = _chunk3U7EBKEUcjs.clearDelegatedEvents; exports.createConditional = _chunk3U7EBKEUcjs.createConditional; exports.createEffect = _chunk3U7EBKEUcjs.createEffect; exports.createElement = _chunk3U7EBKEUcjs.createElement; exports.createKeyedList = createKeyedList; exports.createMemo = _chunk3U7EBKEUcjs.createMemo; exports.createPortal = _chunk3U7EBKEUcjs.createPortal; exports.createPropsProxy = _chunk3U7EBKEUcjs.createPropsProxy; exports.createRenderEffect = _chunk3U7EBKEUcjs.createRenderEffect; exports.createSelector = _chunk3U7EBKEUcjs.createSelector; exports.createSignal = _chunk3U7EBKEUcjs.signal; exports.createStore = createStore; exports.delegateEvents = _chunk3U7EBKEUcjs.delegateEvents; exports.getPropAlias = _chunk3U7EBKEUcjs.getPropAlias; exports.insert = _chunk3U7EBKEUcjs.insert; exports.insertNodesBefore = _chunk3U7EBKEUcjs.insertNodesBefore; exports.isNodeBetweenMarkers = isNodeBetweenMarkers; exports.isReactive = _chunk3U7EBKEUcjs.isReactive; exports.mergeProps = _chunk3U7EBKEUcjs.mergeProps; exports.moveNodesBefore = moveNodesBefore; exports.onDestroy = _chunk3U7EBKEUcjs.onDestroy; exports.prop = _chunk3U7EBKEUcjs.prop; exports.reconcileArrays = reconcileArrays; exports.removeNodes = _chunk3U7EBKEUcjs.removeNodes; exports.runInScope = _chunk3A4VW6AKcjs.runInScope; exports.spread = _chunk3U7EBKEUcjs.spread; exports.template = _chunk3U7EBKEUcjs.template; exports.toNodeArray = _chunk3U7EBKEUcjs.toNodeArray; exports.unwrap = _chunk3U7EBKEUcjs.unwrap;
910
932
  //# sourceMappingURL=internal.cjs.map