sibujs 4.4.0 → 4.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 (74) hide show
  1. package/README.md +11 -0
  2. package/dist/browser.cjs +31 -2
  3. package/dist/browser.d.cts +15 -2
  4. package/dist/browser.d.ts +15 -2
  5. package/dist/browser.js +4 -4
  6. package/dist/build.cjs +92 -13
  7. package/dist/build.js +10 -10
  8. package/dist/cdn.dev.global.js +9 -9
  9. package/dist/cdn.full.dev.global.js +10 -10
  10. package/dist/cdn.full.global.js +9 -9
  11. package/dist/cdn.global.js +9 -9
  12. package/dist/{chunk-XLO7SLIX.js → chunk-2DCGACUU.js} +16 -9
  13. package/dist/{chunk-6GSIXTWX.js → chunk-3JZ4L5TJ.js} +10 -4
  14. package/dist/{chunk-UCALUKB5.js → chunk-4PMLNECI.js} +4 -4
  15. package/dist/{chunk-RR7M3FHM.js → chunk-7LN645I6.js} +1 -1
  16. package/dist/{chunk-SKPTERHP.js → chunk-B3WHI2QA.js} +1 -1
  17. package/dist/{chunk-4Z3SPQ67.js → chunk-FTIR4QW2.js} +13 -3
  18. package/dist/{chunk-HFCOH2GN.js → chunk-GW3SCCZG.js} +4 -4
  19. package/dist/{chunk-PNIRUQ4C.js → chunk-KEISJXBU.js} +2 -2
  20. package/dist/{chunk-LYVUX7NT.js → chunk-OMJJM3KM.js} +2 -2
  21. package/dist/{chunk-VCTAEPSB.js → chunk-ONOHFDLG.js} +9 -1
  22. package/dist/{chunk-36S2YPP4.js → chunk-PCT43HW3.js} +1 -1
  23. package/dist/{chunk-W2EQ7X2L.js → chunk-RBTPLM32.js} +46 -8
  24. package/dist/{chunk-7GIHSAWB.js → chunk-RIXRAYIU.js} +1 -1
  25. package/dist/{chunk-HQSEH5F6.js → chunk-RJE2BNI4.js} +3 -3
  26. package/dist/{chunk-ADM46X22.js → chunk-S373NSMK.js} +18 -13
  27. package/dist/{chunk-M2F7TZHH.js → chunk-TBYTO6BS.js} +2 -2
  28. package/dist/{chunk-3BTTCZ5J.js → chunk-UGRX3S57.js} +31 -2
  29. package/dist/{chunk-7NBDXVHS.js → chunk-VUF4ALSW.js} +1 -1
  30. package/dist/{chunk-LQFGQNMV.js → chunk-VZKNK2V7.js} +9 -4
  31. package/dist/{chunk-NVNJH22U.js → chunk-XZZOBQAY.js} +1 -1
  32. package/dist/{customElement-CNZxEB9G.d.ts → customElement-OB9CIsc5.d.cts} +38 -10
  33. package/dist/{customElement-CNZxEB9G.d.cts → customElement-OB9CIsc5.d.ts} +38 -10
  34. package/dist/data.cjs +81 -9
  35. package/dist/data.js +6 -6
  36. package/dist/devtools.cjs +41 -2
  37. package/dist/devtools.js +4 -4
  38. package/dist/ecosystem.cjs +83 -9
  39. package/dist/ecosystem.d.cts +13 -5
  40. package/dist/ecosystem.d.ts +13 -5
  41. package/dist/ecosystem.js +7 -7
  42. package/dist/extras.cjs +115 -14
  43. package/dist/extras.d.cts +2 -2
  44. package/dist/extras.d.ts +2 -2
  45. package/dist/extras.js +19 -19
  46. package/dist/index.cjs +92 -13
  47. package/dist/index.d.cts +24 -151
  48. package/dist/index.d.ts +24 -151
  49. package/dist/index.js +10 -10
  50. package/dist/motion.cjs +31 -2
  51. package/dist/motion.js +3 -3
  52. package/dist/patterns.cjs +81 -10
  53. package/dist/patterns.d.cts +5 -0
  54. package/dist/patterns.d.ts +5 -0
  55. package/dist/patterns.js +5 -5
  56. package/dist/performance.cjs +31 -2
  57. package/dist/performance.js +4 -4
  58. package/dist/plugins.cjs +39 -2
  59. package/dist/plugins.js +6 -6
  60. package/dist/ssr.cjs +39 -2
  61. package/dist/ssr.js +7 -7
  62. package/dist/tagFactory-DVoDpHye.d.cts +215 -0
  63. package/dist/tagFactory-DVoDpHye.d.ts +215 -0
  64. package/dist/testing.cjs +31 -2
  65. package/dist/testing.js +2 -2
  66. package/dist/ui.cjs +93 -13
  67. package/dist/ui.d.cts +1 -1
  68. package/dist/ui.d.ts +1 -1
  69. package/dist/ui.js +6 -6
  70. package/dist/widgets.cjs +75 -9
  71. package/dist/widgets.js +6 -6
  72. package/package.json +2 -2
  73. package/dist/tagFactory-Bzupt4Pj.d.cts +0 -55
  74. package/dist/tagFactory-Bzupt4Pj.d.ts +0 -55
@@ -0,0 +1,215 @@
1
+ declare const __accessor: unique symbol;
2
+ /**
3
+ * A reactive signal getter returned by signal(), derived(), and similar primitives.
4
+ *
5
+ * Pass an Accessor directly into reactive prop positions — never call it there:
6
+ * ```ts
7
+ * const [count, setCount] = signal(0);
8
+ *
9
+ * div(count) // ✓ reactive — Accessor passed directly
10
+ * div(() => count()) // ✓ reactive — explicit arrow wrapper
11
+ * div(count()) // ✗ static — evaluated once, not reactive
12
+ * ```
13
+ */
14
+ type Accessor<T> = (() => T) & {
15
+ readonly [__accessor]?: never;
16
+ };
17
+ type SetState<T> = (next: T | ((prev: T) => T)) => void;
18
+ type StateTuple<T> = [Accessor<T>, SetState<T>];
19
+ /** Options for signal */
20
+ interface SignalOptions<T = unknown> {
21
+ /** Debug name for devtools inspection. Only used in development. */
22
+ name?: string;
23
+ /** Custom equality function. Defaults to Object.is(). */
24
+ equals?: (prev: T, next: T) => boolean;
25
+ }
26
+ /**
27
+ * signal creates a reactive signal that holds a value of type T.
28
+ * Returns a tuple: [getter, setter].
29
+ *
30
+ * @param initial Initial value
31
+ * @param options Optional config: `{ name: "count" }` for devtools labeling
32
+ * @returns A `[getter, setter]` tuple. Calling the getter inside a reactive
33
+ * context subscribes to the signal; the setter accepts a value or an updater.
34
+ */
35
+ declare function signal<T>(initial: T, options?: SignalOptions<T>): StateTuple<T>;
36
+ /**
37
+ * A valueless reactive token standing in for state SibuJS does not own.
38
+ *
39
+ * See {@link external}.
40
+ */
41
+ interface ExternalSource {
42
+ /**
43
+ * Declare, from inside a reactive computation, that it reads the external
44
+ * state this source represents. Call it in the same places you would read a
45
+ * signal — the top of a binding getter, a `derived()` body, an `effect()`.
46
+ *
47
+ * Outside a tracking context it is a no-op, exactly like reading a signal.
48
+ */
49
+ track(): void;
50
+ /**
51
+ * Declare that the external state changed. Every consumer that called
52
+ * {@link ExternalSource.track} is invalidated.
53
+ *
54
+ * Participates in `batch()` like any signal write: inside a batch, consumers
55
+ * are notified once when the outermost batch flushes.
56
+ */
57
+ invalidate(): void;
58
+ }
59
+ /**
60
+ * Create a reactive source for state that lives outside SibuJS — a domain
61
+ * engine, a media element, a canvas scene, an editor document, a cache a
62
+ * socket writes into.
63
+ *
64
+ * The pattern is two lines: `track()` where you read, `invalidate()` after you
65
+ * mutate.
66
+ *
67
+ * ```ts
68
+ * import { Chess } from "chess.js";
69
+ * import { external } from "sibujs";
70
+ *
71
+ * const game = new Chess(); // owns the rules and the mutable state
72
+ * const moved = external(); // owns "something changed"
73
+ *
74
+ * ctx.text("@status", () => {
75
+ * moved.track(); // this binding reads the engine
76
+ * return game.isCheckmate() ? "Checkmate" : `${game.turn()} to move`;
77
+ * });
78
+ *
79
+ * game.move({ from: "e2", to: "e4" });
80
+ * moved.invalidate(); // every consumer above re-reads
81
+ * ```
82
+ *
83
+ * **One source is one invalidation domain.** Every consumer of a source
84
+ * re-runs on every `invalidate()`, so the granularity of your updates is
85
+ * exactly the granularity of your sources: one for a whole engine is the
86
+ * cheapest to write, several (`board`, `clock`, `history`) let an update touch
87
+ * only what it affects. See `docs/architecture/external-state.md` for the
88
+ * trade-offs and when subdividing is worth it.
89
+ *
90
+ * Ownership, disposal and error routing are the consumer's, not the source's:
91
+ * a disposed binding or effect is never invalidated, and a consumer that
92
+ * throws is reported through the normal runtime error pipeline with its own
93
+ * phase and node.
94
+ *
95
+ * @param options `name` labels the source in devtools (development only).
96
+ */
97
+ declare function external(options?: {
98
+ name?: string;
99
+ }): ExternalSource;
100
+
101
+ /**
102
+ * derived creates a derived reactive signal whose value updates when dependencies change.
103
+ *
104
+ * Uses lazy pull-based evaluation with a single dirty flag:
105
+ * - When a dependency changes, the computed is marked dirty (no re-evaluation).
106
+ * - Dirtiness propagates downstream via propagateDirty.
107
+ * - The getter only re-evaluates when actually read (pull-based).
108
+ * - On re-evaluation, dependencies are re-tracked via retrack() so that
109
+ * derived-of-derived chains propagate correctly without paying the full
110
+ * Set-delete + re-add cost of track()'s cleanup phase.
111
+ *
112
+ * STABILIZATION — why a dirty flag is enough:
113
+ *
114
+ * A dirty computed does NOT imply a changed value. Downstream effects are
115
+ * enqueued by `propagateDirty` at write time, before this computed has had a
116
+ * chance to recompute and compare. Rather than adding a three-color
117
+ * (CLEAN/CHECK/DIRTY) propagation pass — which an earlier revision measured as
118
+ * a regression on every benchmark, because the extra state has nothing to skip
119
+ * when values genuinely change — the engine settles the question lazily at
120
+ * DRAIN time: `cs._validate` recomputes a dirty computed and `cs.__v` is bumped
121
+ * ONLY when the new value differs under this computed's comparator. The
122
+ * scheduler compares that version against what each subscriber last observed
123
+ * and suppresses the run when nothing changed (see `depsChanged` in
124
+ * ../../reactivity/track-core.ts).
125
+ *
126
+ * That keeps the cheap boolean dirty flag AND makes `equals` actually stop
127
+ * propagation, with recomputation still fully lazy: `_validate` only ever runs
128
+ * when an effect is genuinely about to observe the value.
129
+ *
130
+ * DISPOSAL — a derived subscribes to its sources when it is created, and those
131
+ * edges live as long as the sources do. A derived created per mount (one per
132
+ * virtualized row, say) must be released when its owner goes away:
133
+ * `flag.dispose()`, or `onCleanup(flag.dispose, rowNode)` to tie it to a node.
134
+ * A disposed accessor is inert: it keeps returning the last value it settled,
135
+ * never recomputes, never re-subscribes, and never wakes downstream readers.
136
+ * Disposal is idempotent.
137
+ *
138
+ * ERRORS — a recomputation that throws is thrown to the next reader, in that
139
+ * reader's context: a binding reports it with its node (so the nearest
140
+ * `ErrorBoundary` can claim it), an effect reports it, a direct caller can catch
141
+ * it, and a derived reading another derived passes it on. A live derived stays
142
+ * dirty and recomputes on the following read; a derived that disposed itself
143
+ * during the failing run returns its frozen value afterwards.
144
+ *
145
+ * @returns An accessor for the computed value. It recomputes lazily on read
146
+ * after any dependency changes, and carries `dispose()` to release its source
147
+ * subscriptions.
148
+ */
149
+ declare function derived<T>(getter: () => T, options?: {
150
+ name?: string;
151
+ /** Custom equality — when the recomputed value equals the previous,
152
+ * downstream subscribers are not notified. Defaults to `Object.is`. */
153
+ equals?: (a: T, b: T) => boolean;
154
+ }): DerivedAccessor<T>;
155
+ /** Accessor returned by {@link derived}: read it like any getter, release it with `dispose()`. */
156
+ type DerivedAccessor<T> = Accessor<T> & {
157
+ /** Release every source subscription. The accessor then returns its last settled value. Idempotent. */
158
+ dispose: () => void;
159
+ };
160
+
161
+ /**
162
+ * Canonical disposer/teardown signature used across the framework.
163
+ *
164
+ * Returned by `effect()`, `track()`, widget `bind()` methods, and other
165
+ * subscription/lifecycle helpers. All disposers MUST be idempotent — calling
166
+ * twice should be a no-op rather than an error.
167
+ */
168
+ type Dispose = () => void;
169
+ type NodeChild = Node | Element | Text | Comment | string | number | boolean | (() => NodeChild) | null | undefined;
170
+ type NodeChildren = NodeChild | NodeChild[] | NodeChild[][] | (() => NodeChild | NodeChild[]);
171
+
172
+ declare const SVG_NS = "http://www.w3.org/2000/svg";
173
+ interface TagProps {
174
+ id?: string;
175
+ class?: string | (() => string) | Record<string, boolean | (() => boolean)>;
176
+ style?: Record<string, string | number | (() => string | number)> | string | (() => string);
177
+ ref?: {
178
+ current: Element | null;
179
+ };
180
+ nodes?: NodeChildren;
181
+ on?: Record<string, (ev: Event) => void>;
182
+ /** Called with the element after creation — useful for imperative bindings */
183
+ onElement?: (el: HTMLElement) => void;
184
+ [attr: string]: unknown;
185
+ }
186
+ /**
187
+ * Factory for creating HTML or SVG elements with reactive props and nodes.
188
+ *
189
+ * Calling conventions:
190
+ *
191
+ * tag() empty element
192
+ * tag("text") element with text content
193
+ * tag(42) element with numeric text content
194
+ * tag([childA, childB]) element with children (array)
195
+ * tag(node) element wrapping a single existing node
196
+ * tag(getter) element with a reactive child
197
+ * tag("className", children) positional: class + children
198
+ * tag({ ...props }) full props object (children via props.nodes)
199
+ * tag({ ...props }, children) props + children (no need for `nodes:` key!)
200
+ *
201
+ * The last form is the "deeply-nested shorthand" the codebase favours:
202
+ *
203
+ * div({ class: "card" }, [
204
+ * h1({ class: "title" }, "Hello"),
205
+ * p({ class: "body" }, "World"),
206
+ * div({ class: "row" }, [
207
+ * span({ id: "x" }, "child"),
208
+ * ]),
209
+ * ])
210
+ *
211
+ * `children` overrides `props.nodes` when both are present.
212
+ */
213
+ declare const tagFactory: (tag: string, ns?: string) => (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
214
+
215
+ export { type Accessor as A, type DerivedAccessor as D, type ExternalSource as E, type NodeChild as N, SVG_NS as S, type TagProps as T, type NodeChildren as a, type Dispose as b, type SignalOptions as c, derived as d, external as e, signal as s, tagFactory as t };
@@ -0,0 +1,215 @@
1
+ declare const __accessor: unique symbol;
2
+ /**
3
+ * A reactive signal getter returned by signal(), derived(), and similar primitives.
4
+ *
5
+ * Pass an Accessor directly into reactive prop positions — never call it there:
6
+ * ```ts
7
+ * const [count, setCount] = signal(0);
8
+ *
9
+ * div(count) // ✓ reactive — Accessor passed directly
10
+ * div(() => count()) // ✓ reactive — explicit arrow wrapper
11
+ * div(count()) // ✗ static — evaluated once, not reactive
12
+ * ```
13
+ */
14
+ type Accessor<T> = (() => T) & {
15
+ readonly [__accessor]?: never;
16
+ };
17
+ type SetState<T> = (next: T | ((prev: T) => T)) => void;
18
+ type StateTuple<T> = [Accessor<T>, SetState<T>];
19
+ /** Options for signal */
20
+ interface SignalOptions<T = unknown> {
21
+ /** Debug name for devtools inspection. Only used in development. */
22
+ name?: string;
23
+ /** Custom equality function. Defaults to Object.is(). */
24
+ equals?: (prev: T, next: T) => boolean;
25
+ }
26
+ /**
27
+ * signal creates a reactive signal that holds a value of type T.
28
+ * Returns a tuple: [getter, setter].
29
+ *
30
+ * @param initial Initial value
31
+ * @param options Optional config: `{ name: "count" }` for devtools labeling
32
+ * @returns A `[getter, setter]` tuple. Calling the getter inside a reactive
33
+ * context subscribes to the signal; the setter accepts a value or an updater.
34
+ */
35
+ declare function signal<T>(initial: T, options?: SignalOptions<T>): StateTuple<T>;
36
+ /**
37
+ * A valueless reactive token standing in for state SibuJS does not own.
38
+ *
39
+ * See {@link external}.
40
+ */
41
+ interface ExternalSource {
42
+ /**
43
+ * Declare, from inside a reactive computation, that it reads the external
44
+ * state this source represents. Call it in the same places you would read a
45
+ * signal — the top of a binding getter, a `derived()` body, an `effect()`.
46
+ *
47
+ * Outside a tracking context it is a no-op, exactly like reading a signal.
48
+ */
49
+ track(): void;
50
+ /**
51
+ * Declare that the external state changed. Every consumer that called
52
+ * {@link ExternalSource.track} is invalidated.
53
+ *
54
+ * Participates in `batch()` like any signal write: inside a batch, consumers
55
+ * are notified once when the outermost batch flushes.
56
+ */
57
+ invalidate(): void;
58
+ }
59
+ /**
60
+ * Create a reactive source for state that lives outside SibuJS — a domain
61
+ * engine, a media element, a canvas scene, an editor document, a cache a
62
+ * socket writes into.
63
+ *
64
+ * The pattern is two lines: `track()` where you read, `invalidate()` after you
65
+ * mutate.
66
+ *
67
+ * ```ts
68
+ * import { Chess } from "chess.js";
69
+ * import { external } from "sibujs";
70
+ *
71
+ * const game = new Chess(); // owns the rules and the mutable state
72
+ * const moved = external(); // owns "something changed"
73
+ *
74
+ * ctx.text("@status", () => {
75
+ * moved.track(); // this binding reads the engine
76
+ * return game.isCheckmate() ? "Checkmate" : `${game.turn()} to move`;
77
+ * });
78
+ *
79
+ * game.move({ from: "e2", to: "e4" });
80
+ * moved.invalidate(); // every consumer above re-reads
81
+ * ```
82
+ *
83
+ * **One source is one invalidation domain.** Every consumer of a source
84
+ * re-runs on every `invalidate()`, so the granularity of your updates is
85
+ * exactly the granularity of your sources: one for a whole engine is the
86
+ * cheapest to write, several (`board`, `clock`, `history`) let an update touch
87
+ * only what it affects. See `docs/architecture/external-state.md` for the
88
+ * trade-offs and when subdividing is worth it.
89
+ *
90
+ * Ownership, disposal and error routing are the consumer's, not the source's:
91
+ * a disposed binding or effect is never invalidated, and a consumer that
92
+ * throws is reported through the normal runtime error pipeline with its own
93
+ * phase and node.
94
+ *
95
+ * @param options `name` labels the source in devtools (development only).
96
+ */
97
+ declare function external(options?: {
98
+ name?: string;
99
+ }): ExternalSource;
100
+
101
+ /**
102
+ * derived creates a derived reactive signal whose value updates when dependencies change.
103
+ *
104
+ * Uses lazy pull-based evaluation with a single dirty flag:
105
+ * - When a dependency changes, the computed is marked dirty (no re-evaluation).
106
+ * - Dirtiness propagates downstream via propagateDirty.
107
+ * - The getter only re-evaluates when actually read (pull-based).
108
+ * - On re-evaluation, dependencies are re-tracked via retrack() so that
109
+ * derived-of-derived chains propagate correctly without paying the full
110
+ * Set-delete + re-add cost of track()'s cleanup phase.
111
+ *
112
+ * STABILIZATION — why a dirty flag is enough:
113
+ *
114
+ * A dirty computed does NOT imply a changed value. Downstream effects are
115
+ * enqueued by `propagateDirty` at write time, before this computed has had a
116
+ * chance to recompute and compare. Rather than adding a three-color
117
+ * (CLEAN/CHECK/DIRTY) propagation pass — which an earlier revision measured as
118
+ * a regression on every benchmark, because the extra state has nothing to skip
119
+ * when values genuinely change — the engine settles the question lazily at
120
+ * DRAIN time: `cs._validate` recomputes a dirty computed and `cs.__v` is bumped
121
+ * ONLY when the new value differs under this computed's comparator. The
122
+ * scheduler compares that version against what each subscriber last observed
123
+ * and suppresses the run when nothing changed (see `depsChanged` in
124
+ * ../../reactivity/track-core.ts).
125
+ *
126
+ * That keeps the cheap boolean dirty flag AND makes `equals` actually stop
127
+ * propagation, with recomputation still fully lazy: `_validate` only ever runs
128
+ * when an effect is genuinely about to observe the value.
129
+ *
130
+ * DISPOSAL — a derived subscribes to its sources when it is created, and those
131
+ * edges live as long as the sources do. A derived created per mount (one per
132
+ * virtualized row, say) must be released when its owner goes away:
133
+ * `flag.dispose()`, or `onCleanup(flag.dispose, rowNode)` to tie it to a node.
134
+ * A disposed accessor is inert: it keeps returning the last value it settled,
135
+ * never recomputes, never re-subscribes, and never wakes downstream readers.
136
+ * Disposal is idempotent.
137
+ *
138
+ * ERRORS — a recomputation that throws is thrown to the next reader, in that
139
+ * reader's context: a binding reports it with its node (so the nearest
140
+ * `ErrorBoundary` can claim it), an effect reports it, a direct caller can catch
141
+ * it, and a derived reading another derived passes it on. A live derived stays
142
+ * dirty and recomputes on the following read; a derived that disposed itself
143
+ * during the failing run returns its frozen value afterwards.
144
+ *
145
+ * @returns An accessor for the computed value. It recomputes lazily on read
146
+ * after any dependency changes, and carries `dispose()` to release its source
147
+ * subscriptions.
148
+ */
149
+ declare function derived<T>(getter: () => T, options?: {
150
+ name?: string;
151
+ /** Custom equality — when the recomputed value equals the previous,
152
+ * downstream subscribers are not notified. Defaults to `Object.is`. */
153
+ equals?: (a: T, b: T) => boolean;
154
+ }): DerivedAccessor<T>;
155
+ /** Accessor returned by {@link derived}: read it like any getter, release it with `dispose()`. */
156
+ type DerivedAccessor<T> = Accessor<T> & {
157
+ /** Release every source subscription. The accessor then returns its last settled value. Idempotent. */
158
+ dispose: () => void;
159
+ };
160
+
161
+ /**
162
+ * Canonical disposer/teardown signature used across the framework.
163
+ *
164
+ * Returned by `effect()`, `track()`, widget `bind()` methods, and other
165
+ * subscription/lifecycle helpers. All disposers MUST be idempotent — calling
166
+ * twice should be a no-op rather than an error.
167
+ */
168
+ type Dispose = () => void;
169
+ type NodeChild = Node | Element | Text | Comment | string | number | boolean | (() => NodeChild) | null | undefined;
170
+ type NodeChildren = NodeChild | NodeChild[] | NodeChild[][] | (() => NodeChild | NodeChild[]);
171
+
172
+ declare const SVG_NS = "http://www.w3.org/2000/svg";
173
+ interface TagProps {
174
+ id?: string;
175
+ class?: string | (() => string) | Record<string, boolean | (() => boolean)>;
176
+ style?: Record<string, string | number | (() => string | number)> | string | (() => string);
177
+ ref?: {
178
+ current: Element | null;
179
+ };
180
+ nodes?: NodeChildren;
181
+ on?: Record<string, (ev: Event) => void>;
182
+ /** Called with the element after creation — useful for imperative bindings */
183
+ onElement?: (el: HTMLElement) => void;
184
+ [attr: string]: unknown;
185
+ }
186
+ /**
187
+ * Factory for creating HTML or SVG elements with reactive props and nodes.
188
+ *
189
+ * Calling conventions:
190
+ *
191
+ * tag() empty element
192
+ * tag("text") element with text content
193
+ * tag(42) element with numeric text content
194
+ * tag([childA, childB]) element with children (array)
195
+ * tag(node) element wrapping a single existing node
196
+ * tag(getter) element with a reactive child
197
+ * tag("className", children) positional: class + children
198
+ * tag({ ...props }) full props object (children via props.nodes)
199
+ * tag({ ...props }, children) props + children (no need for `nodes:` key!)
200
+ *
201
+ * The last form is the "deeply-nested shorthand" the codebase favours:
202
+ *
203
+ * div({ class: "card" }, [
204
+ * h1({ class: "title" }, "Hello"),
205
+ * p({ class: "body" }, "World"),
206
+ * div({ class: "row" }, [
207
+ * span({ id: "x" }, "child"),
208
+ * ]),
209
+ * ])
210
+ *
211
+ * `children` overrides `props.nodes` when both are present.
212
+ */
213
+ declare const tagFactory: (tag: string, ns?: string) => (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
214
+
215
+ export { type Accessor as A, type DerivedAccessor as D, type ExternalSource as E, type NodeChild as N, SVG_NS as S, type TagProps as T, type NodeChildren as a, type Dispose as b, type SignalOptions as c, derived as d, external as e, signal as s, tagFactory as t };
package/dist/testing.cjs CHANGED
@@ -1821,6 +1821,15 @@ function untracked(fn) {
1821
1821
  var subscriberEpochCounter = 0;
1822
1822
  function retrack(effectFn, subscriber) {
1823
1823
  const prev = currentSubscriber;
1824
+ let savedDepth = 0;
1825
+ let savedSuspendSub = null;
1826
+ if (trackingSuspended) {
1827
+ savedDepth = suspendDepth;
1828
+ savedSuspendSub = suspendSavedSub;
1829
+ suspendDepth = 0;
1830
+ suspendSavedSub = null;
1831
+ trackingSuspended = false;
1832
+ }
1824
1833
  currentSubscriber = subscriber;
1825
1834
  const sub = subscriber;
1826
1835
  const epoch = ++subscriberEpochCounter;
@@ -1835,6 +1844,11 @@ function retrack(effectFn, subscriber) {
1835
1844
  effectFn();
1836
1845
  } finally {
1837
1846
  currentSubscriber = prev;
1847
+ if (savedDepth !== 0) {
1848
+ suspendDepth = savedDepth;
1849
+ suspendSavedSub = savedSuspendSub;
1850
+ trackingSuspended = true;
1851
+ }
1838
1852
  let node = sub.depsHead ?? null;
1839
1853
  while (node !== null) {
1840
1854
  const next = node.subNext;
@@ -1854,11 +1868,25 @@ function track(effectFn, subscriber) {
1854
1868
  if (!subscriber) return reactiveBinding(effectFn);
1855
1869
  cleanup(subscriber);
1856
1870
  const prev = currentSubscriber;
1871
+ let savedDepth = 0;
1872
+ let savedSuspendSub = null;
1873
+ if (trackingSuspended) {
1874
+ savedDepth = suspendDepth;
1875
+ savedSuspendSub = suspendSavedSub;
1876
+ suspendDepth = 0;
1877
+ suspendSavedSub = null;
1878
+ trackingSuspended = false;
1879
+ }
1857
1880
  currentSubscriber = subscriber;
1858
1881
  try {
1859
1882
  effectFn();
1860
1883
  } finally {
1861
1884
  currentSubscriber = prev;
1885
+ if (savedDepth !== 0) {
1886
+ suspendDepth = savedDepth;
1887
+ suspendSavedSub = savedSuspendSub;
1888
+ trackingSuspended = true;
1889
+ }
1862
1890
  const sub2 = subscriber;
1863
1891
  for (let n = sub2.depsHead ?? null; n !== null; n = n.subNext) {
1864
1892
  const sig = n.sig;
@@ -2029,8 +2057,9 @@ function propagateDirty(sub) {
2029
2057
  if (s._c) {
2030
2058
  const nSig = s._sig;
2031
2059
  if (nSig) {
2032
- if (!nSig._d) {
2060
+ if (!nSig._d || nSig._f === true) {
2033
2061
  nSig._d = true;
2062
+ nSig._f = false;
2034
2063
  stack.push(nSig);
2035
2064
  }
2036
2065
  } else {
@@ -2130,7 +2159,7 @@ function forEachSubscriber(signal, visit) {
2130
2159
  }
2131
2160
 
2132
2161
  // src/reactivity/track.ts
2133
- var _runtimeVersion = true ? "4.4.0" : "dev";
2162
+ var _runtimeVersion = true ? "4.5.0" : "dev";
2134
2163
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
2135
2164
  function resolveReactiveApi() {
2136
2165
  const g = globalThis;
package/dist/testing.js CHANGED
@@ -3,12 +3,12 @@ import {
3
3
  } from "./chunk-7ZHH77QA.js";
4
4
  import {
5
5
  effect
6
- } from "./chunk-7GIHSAWB.js";
6
+ } from "./chunk-RIXRAYIU.js";
7
7
  import "./chunk-5DXA2J44.js";
8
8
  import {
9
9
  replaceChildrenSafely
10
10
  } from "./chunk-QKRPLZ2V.js";
11
- import "./chunk-3BTTCZ5J.js";
11
+ import "./chunk-UGRX3S57.js";
12
12
  import "./chunk-2WLZ6757.js";
13
13
 
14
14
  // src/testing/a11y.ts