sibujs 2.1.0 → 3.0.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 (62) hide show
  1. package/dist/browser.cjs +324 -273
  2. package/dist/browser.js +4 -4
  3. package/dist/build.cjs +363 -330
  4. package/dist/build.js +10 -10
  5. package/dist/cdn.global.js +8 -8
  6. package/dist/{chunk-ZAQSMOED.js → chunk-2JQUV4Y3.js} +4 -4
  7. package/dist/{chunk-GWWURC5M.js → chunk-2KM2724A.js} +2 -2
  8. package/dist/{chunk-NASX6ST2.js → chunk-4YTVESDX.js} +1 -1
  9. package/dist/chunk-5WD7BYTZ.js +152 -0
  10. package/dist/{chunk-RDTDJCAB.js → chunk-6QZO7MMG.js} +48 -16
  11. package/dist/{chunk-DRUZZAK4.js → chunk-DF3GTP4Q.js} +7 -2
  12. package/dist/{chunk-AMK2TYNW.js → chunk-INBOWHQ3.js} +14 -11
  13. package/dist/{chunk-O6EFQ3KT.js → chunk-KH4OE6WY.js} +5 -5
  14. package/dist/{chunk-V6C4FADE.js → chunk-KZA7ANXP.js} +3 -3
  15. package/dist/chunk-L4DAT4WU.js +400 -0
  16. package/dist/{chunk-WANSMF2L.js → chunk-L52H775O.js} +4 -4
  17. package/dist/{chunk-45YP72ZQ.js → chunk-NEWH4O5U.js} +1 -1
  18. package/dist/{chunk-ON5MMR2J.js → chunk-RJIRT46U.js} +4 -4
  19. package/dist/{chunk-P2HSJDDN.js → chunk-STFTTMO2.js} +2 -2
  20. package/dist/{chunk-WIPZPFBQ.js → chunk-UKMXT5T6.js} +1 -1
  21. package/dist/{chunk-KGYT6UO6.js → chunk-V65KTDZW.js} +3 -3
  22. package/dist/{chunk-CWBVQML6.js → chunk-VSNLICTS.js} +1 -1
  23. package/dist/{chunk-3DZP6OIT.js → chunk-XDKP4T7G.js} +2 -2
  24. package/dist/{chunk-TH2ILCYW.js → chunk-XVYB3J6C.js} +27 -33
  25. package/dist/{chunk-OJ3P4ECI.js → chunk-YMOIAHWA.js} +1 -1
  26. package/dist/data.cjs +332 -298
  27. package/dist/data.js +6 -6
  28. package/dist/devtools.cjs +353 -296
  29. package/dist/devtools.d.cts +1 -1
  30. package/dist/devtools.d.ts +1 -1
  31. package/dist/devtools.js +4 -4
  32. package/dist/ecosystem.cjs +332 -298
  33. package/dist/ecosystem.js +7 -7
  34. package/dist/extras.cjs +372 -328
  35. package/dist/extras.d.cts +1 -1
  36. package/dist/extras.d.ts +1 -1
  37. package/dist/extras.js +19 -19
  38. package/dist/index.cjs +363 -330
  39. package/dist/index.d.cts +26 -36
  40. package/dist/index.d.ts +26 -36
  41. package/dist/index.js +10 -10
  42. package/dist/{introspect-DnIpHQQz.d.ts → introspect-BZWKvQUZ.d.ts} +2 -3
  43. package/dist/{introspect-2TOlQ7oa.d.cts → introspect-DsJlDD2T.d.cts} +2 -3
  44. package/dist/motion.cjs +147 -123
  45. package/dist/motion.js +3 -3
  46. package/dist/patterns.cjs +332 -298
  47. package/dist/patterns.js +5 -5
  48. package/dist/performance.cjs +315 -268
  49. package/dist/performance.js +4 -4
  50. package/dist/plugins.cjs +332 -266
  51. package/dist/plugins.js +6 -6
  52. package/dist/ssr.cjs +340 -270
  53. package/dist/ssr.js +7 -7
  54. package/dist/testing.cjs +167 -146
  55. package/dist/testing.js +2 -2
  56. package/dist/ui.cjs +324 -294
  57. package/dist/ui.js +6 -6
  58. package/dist/widgets.cjs +332 -298
  59. package/dist/widgets.js +6 -6
  60. package/package.json +1 -1
  61. package/dist/chunk-QO3WC6FS.js +0 -384
  62. package/dist/chunk-WZA53FXU.js +0 -149
package/dist/index.d.cts CHANGED
@@ -762,12 +762,21 @@ declare function effect(effectFn: EffectBody | (() => void), options?: EffectOpt
762
762
  /**
763
763
  * derived creates a derived reactive signal whose value updates when dependencies change.
764
764
  *
765
- * Uses lazy pull-based evaluation with dirty flagging:
765
+ * Uses lazy pull-based evaluation with a single dirty flag:
766
766
  * - When a dependency changes, the computed is marked dirty (no re-evaluation).
767
767
  * - Dirtiness propagates downstream via propagateDirty.
768
768
  * - The getter only re-evaluates when actually read (pull-based).
769
- * - On re-evaluation, dependencies are re-tracked via track() so that
770
- * derived-of-derived chains propagate correctly.
769
+ * - On re-evaluation, dependencies are re-tracked via retrack() so that
770
+ * derived-of-derived chains propagate correctly without paying the full
771
+ * Set-delete + re-add cost of track()'s cleanup phase.
772
+ *
773
+ * NOTE: a previous revision experimented with three-color (CLEAN/CHECK/DIRTY)
774
+ * state for read-side value-change short-circuiting. It regressed every
775
+ * benchmark except Memory (Deep Chain +122%, Component Tree +20%) because
776
+ * the workloads always produce a new downstream value and CHECK had no
777
+ * work to skip — only overhead to add. Keeping the simpler boolean flag
778
+ * here; revisit CHECK propagation when we have benchmarks that exercise
779
+ * stabilisation on diamond / conditional-branch patterns.
771
780
  */
772
781
  declare function derived<T>(getter: () => T, options?: {
773
782
  name?: string;
@@ -1350,26 +1359,8 @@ interface TransitionState {
1350
1359
  declare function transition(): TransitionState;
1351
1360
 
1352
1361
  type Subscriber = () => void;
1353
- /**
1354
- * Re-run a subscriber body. Stale deps (present before but not re-read
1355
- * during this run) are pruned at end via epoch comparison — fixes the
1356
- * conditional-derived over-subscription problem without paying the
1357
- * full Set.delete + re-subscribe cost of `track()`'s cleanup phase.
1358
- *
1359
- * Used by `derived` on every pull. Uses a simple save/restore of
1360
- * `currentSubscriber` instead of the stackTop push/pop — measurably
1361
- * faster on deep chains where this function runs per-level.
1362
- */
1363
- declare function retrack(effectFn: () => void, subscriber: Subscriber): void;
1364
- /**
1365
- * Execute a function without tracking any signal reads as dependencies.
1366
- * Useful for reading signals inside effects without creating subscriptions.
1367
- *
1368
- * @param fn Function to execute without dependency tracking
1369
- * @returns The return value of fn
1370
- */
1371
1362
  declare function untracked<T>(fn: () => T): T;
1372
- /** Raise/lower the absolute drain iteration safety net. Returns previous value. */
1363
+ declare function retrack(effectFn: () => void, subscriber: Subscriber): void;
1373
1364
  declare function setMaxDrainIterations(n: number): number;
1374
1365
 
1375
1366
  /**
@@ -1431,11 +1422,7 @@ interface SuspenseProps {
1431
1422
  }
1432
1423
  declare function Suspense({ nodes, fallback }: SuspenseProps): HTMLElement;
1433
1424
 
1434
- interface ErrorBoundaryProps {
1435
- /**
1436
- * Function that renders child content or throws.
1437
- */
1438
- nodes: () => Element;
1425
+ interface ErrorBoundaryOptions {
1439
1426
  /**
1440
1427
  * Fallback renderer given an Error and retry callback.
1441
1428
  * Memoized internally — only re-created when the error changes.
@@ -1455,27 +1442,30 @@ interface ErrorBoundaryProps {
1455
1442
  * @example
1456
1443
  * ```ts
1457
1444
  * const [route, setRoute] = signal("/");
1458
- * ErrorBoundary({
1459
- * resetKeys: [route],
1460
- * nodes: () => div(riskyPageFor(route())),
1461
- * });
1445
+ * ErrorBoundary(
1446
+ * { resetKeys: [route] },
1447
+ * () => div(riskyPageFor(route())),
1448
+ * );
1462
1449
  * ```
1463
1450
  */
1464
1451
  resetKeys?: Array<() => unknown>;
1465
1452
  }
1453
+ /** @deprecated Renamed to `ErrorBoundaryOptions`; kept for typing compatibility. */
1454
+ type ErrorBoundaryProps = ErrorBoundaryOptions;
1466
1455
  /**
1467
1456
  * ErrorBoundary component using SibuJS reactive pattern.
1468
1457
  *
1469
1458
  * Features:
1470
- * - Catches sync errors thrown by nodes
1471
- * - Catches async errors (Promise rejections) from nodes
1459
+ * - Catches sync errors thrown by children
1460
+ * - Catches async errors (Promise rejections) from children
1472
1461
  * - Supports nested ErrorBoundaries (inner catches first, outer catches propagation)
1473
- * - Retry functionality to clear error and re-render nodes
1462
+ * - Retry functionality to clear error and re-render children
1474
1463
  * - Memoized fallback to avoid re-creating fallback UI on every render
1475
1464
  * - onError callback for logging/telemetry
1476
1465
  * - Improved CSS styling
1477
1466
  */
1478
- declare function ErrorBoundary({ nodes, fallback, onError, resetKeys }: ErrorBoundaryProps): Element;
1467
+ declare function ErrorBoundary(children: () => Element): Element;
1468
+ declare function ErrorBoundary(options: ErrorBoundaryOptions, children: () => Element): Element;
1479
1469
 
1480
1470
  type ErrorSeverity = "error" | "warning" | "info";
1481
1471
  interface ErrorDisplayProps {
@@ -1548,4 +1538,4 @@ interface LoadingProps {
1548
1538
  */
1549
1539
  declare function Loading(props?: LoadingProps): HTMLElement;
1550
1540
 
1551
- export { type Accessor, type ActionFn, type AnchorProps, type ArrayActions, type AsyncDerivedState, type AudioProps, type ButtonProps, type Context, DynamicComponent, type EffectBody, type EffectOptions, ErrorBoundary, type ErrorBoundaryProps, ErrorDisplay, type ErrorDisplayProps, type ErrorSeverity, type FormProps, Fragment, type ImgProps, type InputProps, type InputType, KeepAlive, type KeepAliveOptions, type LabelProps, Loading, type LoadingProps, type LongPressOptions, type MediaProps, NodeChild, NodeChildren, type OnCleanup, type OptionProps, Portal, type Ref, type SSRStore, type SelectProps, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, type TextareaProps, type TypedTagFunction, type VideoProps, __resetIdCounter, a, abbr, action, address, area, array, article, aside, asyncDerived, audio, autoResize, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, copyOnClick, createId, customElement, data, datalist, dd, deepEqual, deepSignal, defer, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getSSRStore, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, menu, meta, meter, mount, nav, nextTick, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerComponent, registerDisposer, resolveComponent, retrack, rp, rt, ruby, runInSSRContext, s, samp, script, section, select, setGlobalErrorHandler, setMaxDrainIterations, show, signal, slot, small, source, span, stop, store, strict, strictEffect, strong, style, sub, summary, sup, svg, symbol, table, takePendingError, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, transition, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
1541
+ export { type Accessor, type ActionFn, type AnchorProps, type ArrayActions, type AsyncDerivedState, type AudioProps, type ButtonProps, type Context, DynamicComponent, type EffectBody, type EffectOptions, ErrorBoundary, type ErrorBoundaryOptions, type ErrorBoundaryProps, ErrorDisplay, type ErrorDisplayProps, type ErrorSeverity, type FormProps, Fragment, type ImgProps, type InputProps, type InputType, KeepAlive, type KeepAliveOptions, type LabelProps, Loading, type LoadingProps, type LongPressOptions, type MediaProps, NodeChild, NodeChildren, type OnCleanup, type OptionProps, Portal, type Ref, type SSRStore, type SelectProps, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, type TextareaProps, type TypedTagFunction, type VideoProps, __resetIdCounter, a, abbr, action, address, area, array, article, aside, asyncDerived, audio, autoResize, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, copyOnClick, createId, customElement, data, datalist, dd, deepEqual, deepSignal, defer, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getSSRStore, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, menu, meta, meter, mount, nav, nextTick, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerComponent, registerDisposer, resolveComponent, retrack, rp, rt, ruby, runInSSRContext, s, samp, script, section, select, setGlobalErrorHandler, setMaxDrainIterations, show, signal, slot, small, source, span, stop, store, strict, strictEffect, strong, style, sub, summary, sup, svg, symbol, table, takePendingError, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, transition, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
package/dist/index.d.ts CHANGED
@@ -762,12 +762,21 @@ declare function effect(effectFn: EffectBody | (() => void), options?: EffectOpt
762
762
  /**
763
763
  * derived creates a derived reactive signal whose value updates when dependencies change.
764
764
  *
765
- * Uses lazy pull-based evaluation with dirty flagging:
765
+ * Uses lazy pull-based evaluation with a single dirty flag:
766
766
  * - When a dependency changes, the computed is marked dirty (no re-evaluation).
767
767
  * - Dirtiness propagates downstream via propagateDirty.
768
768
  * - The getter only re-evaluates when actually read (pull-based).
769
- * - On re-evaluation, dependencies are re-tracked via track() so that
770
- * derived-of-derived chains propagate correctly.
769
+ * - On re-evaluation, dependencies are re-tracked via retrack() so that
770
+ * derived-of-derived chains propagate correctly without paying the full
771
+ * Set-delete + re-add cost of track()'s cleanup phase.
772
+ *
773
+ * NOTE: a previous revision experimented with three-color (CLEAN/CHECK/DIRTY)
774
+ * state for read-side value-change short-circuiting. It regressed every
775
+ * benchmark except Memory (Deep Chain +122%, Component Tree +20%) because
776
+ * the workloads always produce a new downstream value and CHECK had no
777
+ * work to skip — only overhead to add. Keeping the simpler boolean flag
778
+ * here; revisit CHECK propagation when we have benchmarks that exercise
779
+ * stabilisation on diamond / conditional-branch patterns.
771
780
  */
772
781
  declare function derived<T>(getter: () => T, options?: {
773
782
  name?: string;
@@ -1350,26 +1359,8 @@ interface TransitionState {
1350
1359
  declare function transition(): TransitionState;
1351
1360
 
1352
1361
  type Subscriber = () => void;
1353
- /**
1354
- * Re-run a subscriber body. Stale deps (present before but not re-read
1355
- * during this run) are pruned at end via epoch comparison — fixes the
1356
- * conditional-derived over-subscription problem without paying the
1357
- * full Set.delete + re-subscribe cost of `track()`'s cleanup phase.
1358
- *
1359
- * Used by `derived` on every pull. Uses a simple save/restore of
1360
- * `currentSubscriber` instead of the stackTop push/pop — measurably
1361
- * faster on deep chains where this function runs per-level.
1362
- */
1363
- declare function retrack(effectFn: () => void, subscriber: Subscriber): void;
1364
- /**
1365
- * Execute a function without tracking any signal reads as dependencies.
1366
- * Useful for reading signals inside effects without creating subscriptions.
1367
- *
1368
- * @param fn Function to execute without dependency tracking
1369
- * @returns The return value of fn
1370
- */
1371
1362
  declare function untracked<T>(fn: () => T): T;
1372
- /** Raise/lower the absolute drain iteration safety net. Returns previous value. */
1363
+ declare function retrack(effectFn: () => void, subscriber: Subscriber): void;
1373
1364
  declare function setMaxDrainIterations(n: number): number;
1374
1365
 
1375
1366
  /**
@@ -1431,11 +1422,7 @@ interface SuspenseProps {
1431
1422
  }
1432
1423
  declare function Suspense({ nodes, fallback }: SuspenseProps): HTMLElement;
1433
1424
 
1434
- interface ErrorBoundaryProps {
1435
- /**
1436
- * Function that renders child content or throws.
1437
- */
1438
- nodes: () => Element;
1425
+ interface ErrorBoundaryOptions {
1439
1426
  /**
1440
1427
  * Fallback renderer given an Error and retry callback.
1441
1428
  * Memoized internally — only re-created when the error changes.
@@ -1455,27 +1442,30 @@ interface ErrorBoundaryProps {
1455
1442
  * @example
1456
1443
  * ```ts
1457
1444
  * const [route, setRoute] = signal("/");
1458
- * ErrorBoundary({
1459
- * resetKeys: [route],
1460
- * nodes: () => div(riskyPageFor(route())),
1461
- * });
1445
+ * ErrorBoundary(
1446
+ * { resetKeys: [route] },
1447
+ * () => div(riskyPageFor(route())),
1448
+ * );
1462
1449
  * ```
1463
1450
  */
1464
1451
  resetKeys?: Array<() => unknown>;
1465
1452
  }
1453
+ /** @deprecated Renamed to `ErrorBoundaryOptions`; kept for typing compatibility. */
1454
+ type ErrorBoundaryProps = ErrorBoundaryOptions;
1466
1455
  /**
1467
1456
  * ErrorBoundary component using SibuJS reactive pattern.
1468
1457
  *
1469
1458
  * Features:
1470
- * - Catches sync errors thrown by nodes
1471
- * - Catches async errors (Promise rejections) from nodes
1459
+ * - Catches sync errors thrown by children
1460
+ * - Catches async errors (Promise rejections) from children
1472
1461
  * - Supports nested ErrorBoundaries (inner catches first, outer catches propagation)
1473
- * - Retry functionality to clear error and re-render nodes
1462
+ * - Retry functionality to clear error and re-render children
1474
1463
  * - Memoized fallback to avoid re-creating fallback UI on every render
1475
1464
  * - onError callback for logging/telemetry
1476
1465
  * - Improved CSS styling
1477
1466
  */
1478
- declare function ErrorBoundary({ nodes, fallback, onError, resetKeys }: ErrorBoundaryProps): Element;
1467
+ declare function ErrorBoundary(children: () => Element): Element;
1468
+ declare function ErrorBoundary(options: ErrorBoundaryOptions, children: () => Element): Element;
1479
1469
 
1480
1470
  type ErrorSeverity = "error" | "warning" | "info";
1481
1471
  interface ErrorDisplayProps {
@@ -1548,4 +1538,4 @@ interface LoadingProps {
1548
1538
  */
1549
1539
  declare function Loading(props?: LoadingProps): HTMLElement;
1550
1540
 
1551
- export { type Accessor, type ActionFn, type AnchorProps, type ArrayActions, type AsyncDerivedState, type AudioProps, type ButtonProps, type Context, DynamicComponent, type EffectBody, type EffectOptions, ErrorBoundary, type ErrorBoundaryProps, ErrorDisplay, type ErrorDisplayProps, type ErrorSeverity, type FormProps, Fragment, type ImgProps, type InputProps, type InputType, KeepAlive, type KeepAliveOptions, type LabelProps, Loading, type LoadingProps, type LongPressOptions, type MediaProps, NodeChild, NodeChildren, type OnCleanup, type OptionProps, Portal, type Ref, type SSRStore, type SelectProps, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, type TextareaProps, type TypedTagFunction, type VideoProps, __resetIdCounter, a, abbr, action, address, area, array, article, aside, asyncDerived, audio, autoResize, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, copyOnClick, createId, customElement, data, datalist, dd, deepEqual, deepSignal, defer, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getSSRStore, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, menu, meta, meter, mount, nav, nextTick, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerComponent, registerDisposer, resolveComponent, retrack, rp, rt, ruby, runInSSRContext, s, samp, script, section, select, setGlobalErrorHandler, setMaxDrainIterations, show, signal, slot, small, source, span, stop, store, strict, strictEffect, strong, style, sub, summary, sup, svg, symbol, table, takePendingError, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, transition, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
1541
+ export { type Accessor, type ActionFn, type AnchorProps, type ArrayActions, type AsyncDerivedState, type AudioProps, type ButtonProps, type Context, DynamicComponent, type EffectBody, type EffectOptions, ErrorBoundary, type ErrorBoundaryOptions, type ErrorBoundaryProps, ErrorDisplay, type ErrorDisplayProps, type ErrorSeverity, type FormProps, Fragment, type ImgProps, type InputProps, type InputType, KeepAlive, type KeepAliveOptions, type LabelProps, Loading, type LoadingProps, type LongPressOptions, type MediaProps, NodeChild, NodeChildren, type OnCleanup, type OptionProps, Portal, type Ref, type SSRStore, type SelectProps, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, type TextareaProps, type TypedTagFunction, type VideoProps, __resetIdCounter, a, abbr, action, address, area, array, article, aside, asyncDerived, audio, autoResize, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, copyOnClick, createId, customElement, data, datalist, dd, deepEqual, deepSignal, defer, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getSSRStore, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, menu, meta, meter, mount, nav, nextTick, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerComponent, registerDisposer, resolveComponent, retrack, rp, rt, ruby, runInSSRContext, s, samp, script, section, select, setGlobalErrorHandler, setMaxDrainIterations, show, signal, slot, small, source, span, stop, store, strict, strictEffect, strong, style, sub, summary, sup, svg, symbol, table, takePendingError, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, transition, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
package/dist/index.js CHANGED
@@ -44,7 +44,7 @@ import {
44
44
  unregisterComponent,
45
45
  when,
46
46
  writable
47
- } from "./chunk-AMK2TYNW.js";
47
+ } from "./chunk-INBOWHQ3.js";
48
48
  import {
49
49
  __resetIdCounter,
50
50
  createId
@@ -186,26 +186,26 @@ import {
186
186
  use,
187
187
  var_,
188
188
  video
189
- } from "./chunk-CWBVQML6.js";
189
+ } from "./chunk-VSNLICTS.js";
190
190
  import {
191
191
  watch
192
- } from "./chunk-45YP72ZQ.js";
192
+ } from "./chunk-NEWH4O5U.js";
193
193
  import {
194
194
  trustHTML
195
195
  } from "./chunk-JYD2PWXH.js";
196
196
  import {
197
197
  context
198
- } from "./chunk-OJ3P4ECI.js";
198
+ } from "./chunk-YMOIAHWA.js";
199
199
  import {
200
200
  SVG_NS,
201
201
  tagFactory
202
- } from "./chunk-P2HSJDDN.js";
202
+ } from "./chunk-STFTTMO2.js";
203
203
  import {
204
204
  bindDynamic
205
- } from "./chunk-WIPZPFBQ.js";
205
+ } from "./chunk-UKMXT5T6.js";
206
206
  import {
207
207
  derived
208
- } from "./chunk-DRUZZAK4.js";
208
+ } from "./chunk-DF3GTP4Q.js";
209
209
  import {
210
210
  checkLeaks,
211
211
  dispose,
@@ -215,7 +215,7 @@ import "./chunk-UCS6AMJ7.js";
215
215
  import {
216
216
  effect,
217
217
  on
218
- } from "./chunk-WZA53FXU.js";
218
+ } from "./chunk-5WD7BYTZ.js";
219
219
  import {
220
220
  disableSSR,
221
221
  enableSSR,
@@ -229,12 +229,12 @@ import {
229
229
  enqueueBatchedSignal,
230
230
  isBatching,
231
231
  signal
232
- } from "./chunk-RDTDJCAB.js";
232
+ } from "./chunk-6QZO7MMG.js";
233
233
  import {
234
234
  retrack,
235
235
  setMaxDrainIterations,
236
236
  untracked
237
- } from "./chunk-QO3WC6FS.js";
237
+ } from "./chunk-L4DAT4WU.js";
238
238
  import "./chunk-LMLD24FC.js";
239
239
  export {
240
240
  DynamicComponent,
@@ -474,9 +474,8 @@ declare function getSubscriberCount(getter: () => unknown): number;
474
474
  * Get the dependency list of an effect or computed subscriber function.
475
475
  * Returns signal references that the subscriber depends on.
476
476
  *
477
- * Note: This reads the internal dep storage that track.ts maintains on
478
- * subscriber functions. Handles both the single-dep fast path (`_dep`)
479
- * and the multi-dep Map (`_deps`).
477
+ * Note: This reads the linked-list dep storage maintained by track.ts. Safe
478
+ * to call on any subscriber (effect or computed markDirty).
480
479
  */
481
480
  declare function getDependencies(subscriberFn: () => void): ReactiveSignal[];
482
481
  /**
@@ -474,9 +474,8 @@ declare function getSubscriberCount(getter: () => unknown): number;
474
474
  * Get the dependency list of an effect or computed subscriber function.
475
475
  * Returns signal references that the subscriber depends on.
476
476
  *
477
- * Note: This reads the internal dep storage that track.ts maintains on
478
- * subscriber functions. Handles both the single-dep fast path (`_dep`)
479
- * and the multi-dep Map (`_deps`).
477
+ * Note: This reads the linked-list dep storage maintained by track.ts. Safe
478
+ * to call on any subscriber (effect or computed markDirty).
480
479
  */
481
480
  declare function getDependencies(subscriberFn: () => void): ReactiveSignal[];
482
481
  /**
package/dist/motion.cjs CHANGED
@@ -289,10 +289,51 @@ function devWarn(message) {
289
289
 
290
290
  // src/reactivity/track.ts
291
291
  var _isDev2 = isDev();
292
- var STACK_INITIAL = 32;
293
- var subscriberStack = new Array(STACK_INITIAL);
292
+ var nodePool = [];
293
+ function createNode() {
294
+ return {
295
+ sig: null,
296
+ sub: null,
297
+ epoch: 0,
298
+ sigPrev: null,
299
+ sigNext: null,
300
+ subPrev: null,
301
+ subNext: null,
302
+ prevActive: null
303
+ };
304
+ }
305
+ function allocNode(sig, sub, epoch) {
306
+ const n = nodePool.pop();
307
+ if (n) {
308
+ n.sig = sig;
309
+ n.sub = sub;
310
+ n.epoch = epoch;
311
+ return n;
312
+ }
313
+ const fresh = createNode();
314
+ fresh.sig = sig;
315
+ fresh.sub = sub;
316
+ fresh.epoch = epoch;
317
+ return fresh;
318
+ }
319
+ function linkSignal(sig, node) {
320
+ const oldHead = sig.subsHead ?? null;
321
+ node.sigPrev = null;
322
+ node.sigNext = oldHead;
323
+ if (oldHead) oldHead.sigPrev = node;
324
+ else sig.subsTail = node;
325
+ sig.subsHead = node;
326
+ sig.__sc = (sig.__sc ?? 0) + 1;
327
+ }
328
+ function linkSub(sub, node) {
329
+ const oldTail = sub.depsTail ?? null;
330
+ node.subPrev = oldTail;
331
+ node.subNext = null;
332
+ if (oldTail) oldTail.subNext = node;
333
+ else sub.depsHead = node;
334
+ sub.depsTail = node;
335
+ }
294
336
  var currentSubscriber = null;
295
- var SUBS = "__s";
296
337
  var notifyDepth = 0;
297
338
  var pendingQueue = [];
298
339
  var pendingSet = /* @__PURE__ */ new Set();
@@ -307,40 +348,19 @@ function safeInvoke(sub) {
307
348
  function recordDependency(signal2) {
308
349
  if (!currentSubscriber) return;
309
350
  const sub = currentSubscriber;
310
- const epoch = sub._epoch;
311
- if (sub._dep === signal2) {
312
- sub._depEpoch = epoch;
313
- return;
314
- }
315
- const deps = sub._deps;
316
- if (deps) {
317
- deps.set(signal2, epoch);
318
- } else if (sub._dep !== void 0) {
319
- const map = /* @__PURE__ */ new Map();
320
- map.set(sub._dep, sub._depEpoch);
321
- map.set(signal2, epoch);
322
- sub._deps = map;
323
- sub._dep = void 0;
324
- sub._depEpoch = void 0;
325
- } else {
326
- sub._dep = signal2;
327
- sub._depEpoch = epoch;
328
- }
329
351
  const sig = signal2;
330
- let subs = sig[SUBS];
331
- if (!subs) {
332
- subs = /* @__PURE__ */ new Set();
333
- sig[SUBS] = subs;
334
- }
335
- const prevSize = subs.size;
336
- subs.add(currentSubscriber);
337
- if (subs.size !== prevSize) {
338
- if (subs.size === 1) {
339
- sig.__f = currentSubscriber;
340
- } else if (sig.__f !== void 0) {
341
- sig.__f = void 0;
342
- }
352
+ const epoch = sub._epoch ?? 0;
353
+ const active = sig.__activeNode ?? null;
354
+ if (active !== null && active.sub === sub) {
355
+ active.epoch = epoch;
356
+ return;
343
357
  }
358
+ const node = allocNode(signal2, sub, epoch);
359
+ node.prevActive = active;
360
+ sig.__activeNode = node;
361
+ linkSub(sub, node);
362
+ linkSignal(sig, node);
363
+ sub._structDirty = true;
344
364
  }
345
365
  var maxSubscriberRepeats = 50;
346
366
  var maxDrainIterations = 1e6;
@@ -352,7 +372,8 @@ function tickRepeat(sub) {
352
372
  s._runs = 1;
353
373
  return false;
354
374
  }
355
- return ++s._runs > maxSubscriberRepeats;
375
+ s._runs = (s._runs ?? 0) + 1;
376
+ return s._runs > maxSubscriberRepeats;
356
377
  }
357
378
  function cycleError(sub) {
358
379
  if (typeof console !== "undefined") {
@@ -394,93 +415,64 @@ function propagateDirty(sub) {
394
415
  stack.push(rootSig);
395
416
  while (stack.length > baseLen) {
396
417
  const sig = stack.pop();
397
- const first = sig.__f;
398
- if (first) {
399
- if (first._c) {
400
- const nSig = first._sig;
401
- if (!nSig._d) {
402
- nSig._d = true;
403
- stack.push(nSig);
404
- }
405
- } else if (!pendingSet.has(first)) {
406
- pendingSet.add(first);
407
- pendingQueue.push(first);
408
- }
409
- continue;
410
- }
411
- const subs = sig[SUBS];
412
- if (!subs) continue;
413
- for (const s of subs) {
414
- if (s._c) {
415
- const nSig = s._sig;
416
- if (nSig && !nSig._d) {
417
- nSig._d = true;
418
- stack.push(nSig);
419
- } else if (!nSig) {
420
- s();
418
+ let node = sig.subsHead ?? null;
419
+ while (node) {
420
+ const s = node.sub;
421
+ if (s) {
422
+ if (s._c) {
423
+ const nSig = s._sig;
424
+ if (nSig) {
425
+ if (!nSig._d) {
426
+ nSig._d = true;
427
+ stack.push(nSig);
428
+ }
429
+ } else {
430
+ s();
431
+ }
432
+ } else if (!pendingSet.has(s)) {
433
+ pendingSet.add(s);
434
+ pendingQueue.push(s);
421
435
  }
422
- } else if (!pendingSet.has(s)) {
423
- pendingSet.add(s);
424
- pendingQueue.push(s);
425
436
  }
437
+ node = node.sigNext;
426
438
  }
427
439
  }
428
440
  }
429
441
  function notifySubscribers(signal2) {
430
- const first = signal2.__f;
431
- if (first) {
432
- if (notifyDepth > 0) {
433
- if (first._c) {
434
- propagateDirty(first);
435
- } else if (!pendingSet.has(first)) {
436
- pendingSet.add(first);
437
- pendingQueue.push(first);
438
- }
439
- return;
440
- }
441
- notifyDepth++;
442
- drainEpoch++;
443
- try {
444
- if (first._c) {
445
- propagateDirty(first);
446
- } else if (tickRepeat(first)) {
447
- cycleError(first);
448
- } else {
449
- safeInvoke(first);
450
- }
451
- drainQueue();
452
- } finally {
453
- notifyDepth--;
454
- if (notifyDepth === 0) {
455
- pendingQueue.length = 0;
456
- pendingSet.clear();
457
- }
458
- }
459
- return;
460
- }
461
- const subs = signal2[SUBS];
462
- if (!subs || subs.size === 0) return;
442
+ const sig = signal2;
443
+ const head = sig.subsHead;
444
+ if (!head) return;
463
445
  if (notifyDepth > 0) {
464
- for (const sub of subs) {
465
- if (sub._c) {
466
- propagateDirty(sub);
467
- } else if (!pendingSet.has(sub)) {
468
- pendingSet.add(sub);
469
- pendingQueue.push(sub);
446
+ let node = head;
447
+ while (node) {
448
+ const s = node.sub;
449
+ if (s) {
450
+ if (s._c) {
451
+ propagateDirty(s);
452
+ } else if (!pendingSet.has(s)) {
453
+ pendingSet.add(s);
454
+ pendingQueue.push(s);
455
+ }
470
456
  }
457
+ node = node.sigNext;
471
458
  }
472
459
  return;
473
460
  }
474
461
  notifyDepth++;
475
462
  drainEpoch++;
476
463
  try {
477
- for (const sub of subs) {
478
- if (sub._c) {
479
- propagateDirty(sub);
480
- } else if (!pendingSet.has(sub)) {
481
- pendingSet.add(sub);
482
- pendingQueue.push(sub);
464
+ let node = head;
465
+ while (node) {
466
+ const s = node.sub;
467
+ if (s) {
468
+ if (s._c) {
469
+ propagateDirty(s);
470
+ } else if (!pendingSet.has(s)) {
471
+ pendingSet.add(s);
472
+ pendingQueue.push(s);
473
+ }
483
474
  }
475
+ node = node.sigNext;
484
476
  }
485
477
  drainQueue();
486
478
  } finally {
@@ -505,32 +497,64 @@ function enqueueBatchedSignal(signal2) {
505
497
  var _g = globalThis;
506
498
  var _isDev3 = isDev();
507
499
  function signal(initial, options) {
508
- const state = { value: initial };
500
+ const state = {
501
+ value: initial,
502
+ __v: 0,
503
+ __sc: 0,
504
+ subsHead: null,
505
+ subsTail: null,
506
+ __activeNode: null,
507
+ __name: void 0
508
+ };
509
509
  const debugName = _isDev3 ? options?.name : void 0;
510
510
  const equalsFn = options?.equals;
511
- if (debugName) {
512
- state.__name = debugName;
513
- }
511
+ if (debugName) state.__name = debugName;
514
512
  function get() {
515
513
  recordDependency(state);
516
514
  return state.value;
517
515
  }
518
516
  get.__signal = state;
519
517
  if (debugName) get.__name = debugName;
520
- function set(next) {
521
- const newValue = typeof next === "function" ? next(state.value) : next;
522
- if (equalsFn ? equalsFn(state.value, newValue) : Object.is(newValue, state.value)) return;
523
- if (_isDev3) {
524
- const oldValue = state.value;
518
+ let set;
519
+ if (equalsFn) {
520
+ set = (next) => {
521
+ const prev = state.value;
522
+ const newValue = typeof next === "function" ? next(prev) : next;
523
+ if (equalsFn(prev, newValue)) return;
524
+ state.value = newValue;
525
+ state.__v++;
526
+ if (_isDev3) {
527
+ const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
528
+ if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
529
+ }
530
+ if (!enqueueBatchedSignal(state)) {
531
+ notifySubscribers(state);
532
+ }
533
+ };
534
+ } else if (_isDev3) {
535
+ set = (next) => {
536
+ const prev = state.value;
537
+ const newValue = typeof next === "function" ? next(prev) : next;
538
+ if (Object.is(newValue, prev)) return;
525
539
  state.value = newValue;
540
+ state.__v++;
526
541
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
527
- if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue, newValue });
528
- } else {
542
+ if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
543
+ if (!enqueueBatchedSignal(state)) {
544
+ notifySubscribers(state);
545
+ }
546
+ };
547
+ } else {
548
+ set = (next) => {
549
+ const prev = state.value;
550
+ const newValue = typeof next === "function" ? next(prev) : next;
551
+ if (Object.is(newValue, prev)) return;
529
552
  state.value = newValue;
530
- }
531
- if (!enqueueBatchedSignal(state)) {
532
- notifySubscribers(state);
533
- }
553
+ state.__v++;
554
+ if (!enqueueBatchedSignal(state)) {
555
+ notifySubscribers(state);
556
+ }
557
+ };
534
558
  }
535
559
  if (_isDev3) {
536
560
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
package/dist/motion.js CHANGED
@@ -19,9 +19,9 @@ import {
19
19
  stagger,
20
20
  transition,
21
21
  viewTransition
22
- } from "./chunk-NASX6ST2.js";
23
- import "./chunk-RDTDJCAB.js";
24
- import "./chunk-QO3WC6FS.js";
22
+ } from "./chunk-4YTVESDX.js";
23
+ import "./chunk-6QZO7MMG.js";
24
+ import "./chunk-L4DAT4WU.js";
25
25
  import "./chunk-LMLD24FC.js";
26
26
  export {
27
27
  TransitionGroup,