sibujs 1.2.0 → 1.3.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 (89) hide show
  1. package/README.md +29 -25
  2. package/dist/browser.cjs +804 -2
  3. package/dist/browser.d.cts +591 -1
  4. package/dist/browser.d.ts +591 -1
  5. package/dist/browser.js +50 -8
  6. package/dist/build.cjs +654 -144
  7. package/dist/build.js +14 -12
  8. package/dist/cdn.global.js +188 -7
  9. package/dist/chunk-2BYQDGN3.js +742 -0
  10. package/dist/chunk-32DY64NT.js +282 -0
  11. package/dist/chunk-3AIRKM3B.js +1263 -0
  12. package/dist/chunk-3X2YG6YM.js +505 -0
  13. package/dist/chunk-5X6PP2UK.js +28 -0
  14. package/dist/chunk-77L6NL3X.js +1097 -0
  15. package/dist/chunk-BGN5ZMP4.js +26 -0
  16. package/dist/chunk-BTU3TJDS.js +365 -0
  17. package/dist/chunk-CHF5OHIA.js +61 -0
  18. package/dist/chunk-CMBFNA7L.js +27 -0
  19. package/dist/chunk-DAHRH4ON.js +331 -0
  20. package/dist/chunk-EBGIRKQY.js +616 -0
  21. package/dist/chunk-EUZND3CB.js +27 -0
  22. package/dist/chunk-F3FA4F32.js +292 -0
  23. package/dist/chunk-JAKHTMQU.js +1000 -0
  24. package/dist/chunk-JCI5M6U6.js +956 -0
  25. package/dist/chunk-KQPDEVVS.js +398 -0
  26. package/dist/chunk-NEKUBFPT.js +60 -0
  27. package/dist/chunk-NYVAC6P5.js +37 -0
  28. package/dist/chunk-PTQJDMRT.js +146 -0
  29. package/dist/chunk-QWZG56ET.js +2744 -0
  30. package/dist/chunk-TSOKIX5Z.js +654 -0
  31. package/dist/chunk-VRW3FULF.js +725 -0
  32. package/dist/chunk-WZSPOOER.js +84 -0
  33. package/dist/chunk-YT6HQ6AM.js +14 -0
  34. package/dist/chunk-ZD6OAMTH.js +277 -0
  35. package/dist/contracts-DDrwxvJ-.d.cts +245 -0
  36. package/dist/contracts-DDrwxvJ-.d.ts +245 -0
  37. package/dist/data.cjs +35 -2
  38. package/dist/data.d.cts +7 -0
  39. package/dist/data.d.ts +7 -0
  40. package/dist/data.js +9 -8
  41. package/dist/devtools.cjs +122 -0
  42. package/dist/devtools.d.cts +69 -461
  43. package/dist/devtools.d.ts +69 -461
  44. package/dist/devtools.js +127 -6
  45. package/dist/ecosystem.cjs +23 -6
  46. package/dist/ecosystem.d.cts +1 -1
  47. package/dist/ecosystem.d.ts +1 -1
  48. package/dist/ecosystem.js +10 -9
  49. package/dist/extras.cjs +1207 -65
  50. package/dist/extras.d.cts +5 -5
  51. package/dist/extras.d.ts +5 -5
  52. package/dist/extras.js +69 -24
  53. package/dist/index.cjs +663 -144
  54. package/dist/index.d.cts +397 -17
  55. package/dist/index.d.ts +397 -17
  56. package/dist/index.js +39 -17
  57. package/dist/introspect-BumjnBKr.d.cts +477 -0
  58. package/dist/introspect-CZrlcaYy.d.ts +477 -0
  59. package/dist/introspect-Cb0zgpi2.d.cts +477 -0
  60. package/dist/introspect-Y2xNXGSf.d.ts +477 -0
  61. package/dist/motion.js +4 -4
  62. package/dist/patterns.cjs +51 -2
  63. package/dist/patterns.d.cts +18 -8
  64. package/dist/patterns.d.ts +18 -8
  65. package/dist/patterns.js +7 -7
  66. package/dist/performance.js +4 -4
  67. package/dist/plugins.cjs +428 -81
  68. package/dist/plugins.d.cts +27 -4
  69. package/dist/plugins.d.ts +27 -4
  70. package/dist/plugins.js +156 -37
  71. package/dist/ssr-4PBXAOO3.js +40 -0
  72. package/dist/ssr-Do_SiVoL.d.cts +201 -0
  73. package/dist/ssr-Do_SiVoL.d.ts +201 -0
  74. package/dist/ssr.cjs +312 -60
  75. package/dist/ssr.d.cts +10 -1
  76. package/dist/ssr.d.ts +10 -1
  77. package/dist/ssr.js +13 -10
  78. package/dist/tagFactory-DaJ0YWX6.d.cts +47 -0
  79. package/dist/tagFactory-DaJ0YWX6.d.ts +47 -0
  80. package/dist/testing.cjs +233 -2
  81. package/dist/testing.d.cts +42 -1
  82. package/dist/testing.d.ts +42 -1
  83. package/dist/testing.js +129 -2
  84. package/dist/ui.cjs +374 -3
  85. package/dist/ui.d.cts +252 -2
  86. package/dist/ui.d.ts +252 -2
  87. package/dist/ui.js +328 -8
  88. package/dist/widgets.js +7 -7
  89. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -1,7 +1,134 @@
1
- import { T as TagProps, N as NodeChildren, a as NodeChild } from './tagFactory-Dl8QCLga.js';
2
- export { S as SVG_NS, t as tagFactory } from './tagFactory-Dl8QCLga.js';
1
+ import { T as TagProps, N as NodeChildren, a as NodeChild } from './tagFactory-DaJ0YWX6.js';
2
+ export { S as SVG_NS, t as tagFactory } from './tagFactory-DaJ0YWX6.js';
3
3
  import { R as ReactiveSignal } from './signal-BnWpq6WB.js';
4
4
 
5
+ type reactive<T> = T | (() => T);
6
+ interface AnchorProps extends TagProps {
7
+ href?: reactive<string>;
8
+ target?: "_self" | "_blank" | "_parent" | "_top" | (string & {});
9
+ rel?: reactive<string>;
10
+ download?: reactive<string | boolean>;
11
+ hreflang?: reactive<string>;
12
+ referrerpolicy?: reactive<"" | "no-referrer" | "no-referrer-when-downgrade" | "origin" | "origin-when-cross-origin" | "same-origin" | "strict-origin" | "strict-origin-when-cross-origin" | "unsafe-url">;
13
+ ping?: reactive<string>;
14
+ }
15
+ type InputType = "button" | "checkbox" | "color" | "date" | "datetime-local" | "email" | "file" | "hidden" | "image" | "month" | "number" | "password" | "radio" | "range" | "reset" | "search" | "submit" | "tel" | "text" | "time" | "url" | "week";
16
+ interface InputProps extends TagProps {
17
+ type?: InputType | (string & {});
18
+ name?: reactive<string>;
19
+ value?: reactive<string | number>;
20
+ placeholder?: reactive<string>;
21
+ required?: reactive<boolean>;
22
+ disabled?: reactive<boolean>;
23
+ readonly?: reactive<boolean>;
24
+ checked?: reactive<boolean>;
25
+ min?: reactive<string | number>;
26
+ max?: reactive<string | number>;
27
+ step?: reactive<string | number>;
28
+ minlength?: reactive<number>;
29
+ maxlength?: reactive<number>;
30
+ pattern?: reactive<string>;
31
+ autocomplete?: reactive<string>;
32
+ autofocus?: reactive<boolean>;
33
+ multiple?: reactive<boolean>;
34
+ accept?: reactive<string>;
35
+ size?: reactive<number>;
36
+ form?: reactive<string>;
37
+ list?: reactive<string>;
38
+ inputmode?: reactive<"none" | "text" | "decimal" | "numeric" | "tel" | "search" | "email" | "url">;
39
+ }
40
+ interface ImgProps extends TagProps {
41
+ src?: reactive<string>;
42
+ alt?: reactive<string>;
43
+ width?: reactive<number | string>;
44
+ height?: reactive<number | string>;
45
+ loading?: reactive<"lazy" | "eager">;
46
+ decoding?: reactive<"sync" | "async" | "auto">;
47
+ srcset?: reactive<string>;
48
+ sizes?: reactive<string>;
49
+ crossorigin?: reactive<"anonymous" | "use-credentials">;
50
+ referrerpolicy?: reactive<string>;
51
+ }
52
+ interface ButtonProps extends TagProps {
53
+ type?: reactive<"button" | "submit" | "reset">;
54
+ name?: reactive<string>;
55
+ value?: reactive<string>;
56
+ disabled?: reactive<boolean>;
57
+ form?: reactive<string>;
58
+ formaction?: reactive<string>;
59
+ formenctype?: reactive<string>;
60
+ formmethod?: reactive<"get" | "post" | "dialog">;
61
+ formnovalidate?: reactive<boolean>;
62
+ formtarget?: reactive<string>;
63
+ autofocus?: reactive<boolean>;
64
+ }
65
+ interface FormProps extends TagProps {
66
+ action?: reactive<string>;
67
+ method?: reactive<"get" | "post" | "dialog">;
68
+ enctype?: reactive<"application/x-www-form-urlencoded" | "multipart/form-data" | "text/plain">;
69
+ name?: reactive<string>;
70
+ novalidate?: reactive<boolean>;
71
+ target?: reactive<string>;
72
+ autocomplete?: reactive<"on" | "off">;
73
+ acceptcharset?: reactive<string>;
74
+ }
75
+ interface SelectProps extends TagProps {
76
+ name?: reactive<string>;
77
+ value?: reactive<string>;
78
+ disabled?: reactive<boolean>;
79
+ multiple?: reactive<boolean>;
80
+ required?: reactive<boolean>;
81
+ size?: reactive<number>;
82
+ autocomplete?: reactive<string>;
83
+ autofocus?: reactive<boolean>;
84
+ form?: reactive<string>;
85
+ }
86
+ interface TextareaProps extends TagProps {
87
+ name?: reactive<string>;
88
+ value?: reactive<string>;
89
+ placeholder?: reactive<string>;
90
+ disabled?: reactive<boolean>;
91
+ readonly?: reactive<boolean>;
92
+ required?: reactive<boolean>;
93
+ rows?: reactive<number>;
94
+ cols?: reactive<number>;
95
+ minlength?: reactive<number>;
96
+ maxlength?: reactive<number>;
97
+ wrap?: reactive<"hard" | "soft" | "off">;
98
+ autocomplete?: reactive<string>;
99
+ autofocus?: reactive<boolean>;
100
+ form?: reactive<string>;
101
+ spellcheck?: reactive<boolean>;
102
+ }
103
+ interface LabelProps extends TagProps {
104
+ for?: reactive<string>;
105
+ form?: reactive<string>;
106
+ }
107
+ interface OptionProps extends TagProps {
108
+ value?: reactive<string | number>;
109
+ selected?: reactive<boolean>;
110
+ disabled?: reactive<boolean>;
111
+ label?: reactive<string>;
112
+ }
113
+ interface MediaProps extends TagProps {
114
+ src?: reactive<string>;
115
+ autoplay?: reactive<boolean>;
116
+ controls?: reactive<boolean>;
117
+ loop?: reactive<boolean>;
118
+ muted?: reactive<boolean>;
119
+ preload?: reactive<"none" | "metadata" | "auto">;
120
+ crossorigin?: reactive<"anonymous" | "use-credentials">;
121
+ }
122
+ interface VideoProps extends MediaProps {
123
+ poster?: reactive<string>;
124
+ width?: reactive<number | string>;
125
+ height?: reactive<number | string>;
126
+ playsinline?: reactive<boolean>;
127
+ }
128
+ type AudioProps = MediaProps;
129
+
130
+ type TypedTagFunction<Props extends TagProps, El extends Element> = (first?: Props | NodeChildren, second?: NodeChildren) => El;
131
+
5
132
  declare const head: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
6
133
  declare const body: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
7
134
  declare const title: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
@@ -33,7 +160,7 @@ declare const li: (first?: TagProps | NodeChildren, second?: NodeChildren) => El
33
160
  declare const ol: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
34
161
  declare const ul: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
35
162
  declare const pre: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
36
- declare const a: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
163
+ declare const a: TypedTagFunction<AnchorProps, HTMLAnchorElement>;
37
164
  declare const abbr: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
38
165
  declare const b: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
39
166
  declare const bdi: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
@@ -61,11 +188,11 @@ declare const time: (first?: TagProps | NodeChildren, second?: NodeChildren) =>
61
188
  declare const u: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
62
189
  declare const var_: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
63
190
  declare const area: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
64
- declare const audio: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
65
- declare const img: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
191
+ declare const audio: TypedTagFunction<AudioProps, HTMLAudioElement>;
192
+ declare const img: TypedTagFunction<ImgProps, HTMLImageElement>;
66
193
  declare const map: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
67
194
  declare const track: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
68
- declare const video: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
195
+ declare const video: TypedTagFunction<VideoProps, HTMLVideoElement>;
69
196
  declare const embed: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
70
197
  declare const iframe: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
71
198
  declare const object: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
@@ -90,20 +217,20 @@ declare const tfoot: (first?: TagProps | NodeChildren, second?: NodeChildren) =>
90
217
  declare const th: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
91
218
  declare const thead: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
92
219
  declare const tr: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
93
- declare const button: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
220
+ declare const button: TypedTagFunction<ButtonProps, HTMLButtonElement>;
94
221
  declare const datalist: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
95
222
  declare const fieldset: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
96
- declare const form: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
97
- declare const input: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
98
- declare const label: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
223
+ declare const form: TypedTagFunction<FormProps, HTMLFormElement>;
224
+ declare const input: TypedTagFunction<InputProps, HTMLInputElement>;
225
+ declare const label: TypedTagFunction<LabelProps, HTMLLabelElement>;
99
226
  declare const legend: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
100
227
  declare const meter: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
101
228
  declare const optgroup: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
102
- declare const option: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
229
+ declare const option: TypedTagFunction<OptionProps, HTMLOptionElement>;
103
230
  declare const output: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
104
231
  declare const progress: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
105
- declare const select: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
106
- declare const textarea: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
232
+ declare const select: TypedTagFunction<SelectProps, HTMLSelectElement>;
233
+ declare const textarea: TypedTagFunction<TextareaProps, HTMLTextAreaElement>;
107
234
  declare const details: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
108
235
  declare const dialog: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
109
236
  declare const menu: (first?: TagProps | NodeChildren, second?: NodeChildren) => Element;
@@ -493,6 +620,38 @@ declare function catchErrorAsync<T>(fn: () => Promise<T>, onError?: ErrorHandler
493
620
  */
494
621
  declare function setGlobalErrorHandler(handler: ErrorHandler): void;
495
622
 
623
+ /**
624
+ * Generate a stable, framework-unique ID string suitable for a11y pairing
625
+ * (`aria-labelledby`, `htmlFor` + `id`, etc.).
626
+ *
627
+ * Each call returns a fresh incrementing id. Optionally accepts a prefix.
628
+ *
629
+ * IDs are plain strings (not reactive) — call once per component instance
630
+ * and reuse the returned value for both sides of the association.
631
+ *
632
+ * @param prefix Optional prefix, default "sibu"
633
+ * @returns A unique id like `"sibu-1"` or `"my-input-2"`
634
+ *
635
+ * @example
636
+ * ```ts
637
+ * function Field(labelText: string) {
638
+ * const id = createId("field");
639
+ * return div({ nodes: [
640
+ * label({ for: id, nodes: labelText }),
641
+ * input({ id }),
642
+ * ]});
643
+ * }
644
+ * ```
645
+ */
646
+ declare function createId(prefix?: string): string;
647
+ /**
648
+ * Reset the id counter. Intended for tests and SSR setups that want
649
+ * deterministic ids across runs.
650
+ *
651
+ * @internal
652
+ */
653
+ declare function __resetIdCounter(): void;
654
+
496
655
  /**
497
656
  * Register a teardown function for a DOM node.
498
657
  * When dispose(node) is called, all registered teardowns run.
@@ -823,6 +982,46 @@ declare function writable<T>(get: () => T, set: (value: T) => void, options?: {
823
982
  name?: string;
824
983
  }): [Accessor<T>, (value: T) => void];
825
984
 
985
+ interface AsyncDerivedState<T> {
986
+ /** Resolved value, or `initial` while loading. */
987
+ value: () => T;
988
+ /** True while the underlying promise is in-flight. */
989
+ loading: () => boolean;
990
+ /** The last caught error, or `null`. */
991
+ error: () => unknown | null;
992
+ /** Manually re-run the async computation. */
993
+ refresh: () => void;
994
+ }
995
+ /**
996
+ * `asyncDerived` is the async counterpart of `derived`: it takes a factory
997
+ * that returns a Promise and re-runs whenever its reactive dependencies
998
+ * change. The returned object exposes reactive `value`, `loading`, and
999
+ * `error` getters, plus a `refresh()` trigger.
1000
+ *
1001
+ * Stale responses are dropped: if a new run starts before an older one
1002
+ * resolves, the older one's result is ignored. This prevents flicker when
1003
+ * dependencies change rapidly (e.g. typing in a search box).
1004
+ *
1005
+ * Unlike `query()` or `resource()`, `asyncDerived` has no caching or retry
1006
+ * logic — it's a minimal async-reactivity primitive suited for ad-hoc
1007
+ * derivations (parsing, formatting, validation against a server).
1008
+ *
1009
+ * @param factory Async function returning the derived value
1010
+ * @param initial Value used while the first computation is pending
1011
+ *
1012
+ * @example
1013
+ * ```ts
1014
+ * const [query, setQuery] = signal("");
1015
+ * const results = asyncDerived(async () => {
1016
+ * const q = query();
1017
+ * if (!q) return [];
1018
+ * const r = await fetch(`/api/search?q=${encodeURIComponent(q)}`);
1019
+ * return r.json();
1020
+ * }, []);
1021
+ * ```
1022
+ */
1023
+ declare function asyncDerived<T>(factory: () => Promise<T>, initial: T): AsyncDerivedState<T>;
1024
+
826
1025
  /**
827
1026
  * Lifecycle hooks for SibuJS components.
828
1027
  *
@@ -889,8 +1088,6 @@ declare function onCleanup(callback: CleanupFn, element: Node): void;
889
1088
  * Context API for SibuJS — provides dependency injection across
890
1089
  * component trees without prop drilling.
891
1090
  *
892
- * Inspired by React's Context and Vue's provide/inject patterns.
893
- *
894
1091
  * @example
895
1092
  * ```ts
896
1093
  * // Create a context with a default value
@@ -927,6 +1124,46 @@ interface Context<T> {
927
1124
  */
928
1125
  declare function context<T>(defaultValue: T): Context<T>;
929
1126
 
1127
+ /**
1128
+ * Dev-only wrapper that runs `fn` twice — once now, once on the next
1129
+ * microtask. Any hidden side effect (duplicate event listener, missing
1130
+ * cleanup, stale closure) shows up immediately.
1131
+ *
1132
+ * In production builds the helper inlines to a single call.
1133
+ *
1134
+ * @example
1135
+ * ```ts
1136
+ * strict(() => {
1137
+ * // Any effect here is invoked twice in dev. If the second run
1138
+ * // causes duplicated listeners or DOM nodes, you have a cleanup bug.
1139
+ * effect(() => {
1140
+ * document.addEventListener("keydown", onKey);
1141
+ * // Forgot to return a disposer — strict() makes this obvious.
1142
+ * });
1143
+ * });
1144
+ * ```
1145
+ */
1146
+ declare function strict<T>(fn: () => T): T;
1147
+ /**
1148
+ * Dev-only wrapper that re-runs an effect twice the first time to catch
1149
+ * accidental side-effect bleeding. The returned teardown disposes both
1150
+ * invocations.
1151
+ *
1152
+ * This is a thin wrapper around `effect()` — use it instead of `effect()`
1153
+ * in any place where you suspect a cleanup bug.
1154
+ *
1155
+ * @example
1156
+ * ```ts
1157
+ * const dispose = strictEffect(() => {
1158
+ * const handler = () => { ... };
1159
+ * window.addEventListener("resize", handler);
1160
+ * // Missing `return () => removeEventListener(...)` — strictEffect
1161
+ * // will double-attach in dev and you'll see two log lines.
1162
+ * });
1163
+ * ```
1164
+ */
1165
+ declare function strictEffect(fn: () => void): () => void;
1166
+
930
1167
  /**
931
1168
  * SSR context for SibuJS.
932
1169
  *
@@ -950,6 +1187,11 @@ declare function disableSSR(): void;
950
1187
  /**
951
1188
  * Run a function in SSR mode. Automatically enables/disables SSR around the callback.
952
1189
  * Returns whatever the callback returns.
1190
+ *
1191
+ * Nesting-safe: saves the prior SSR flag and restores it in the `finally`
1192
+ * block. A nested `withSSR(...)` call cannot prematurely flip the outer
1193
+ * scope's SSR flag back to `false`, and an exception thrown inside `fn`
1194
+ * still leaves the flag in its original state.
953
1195
  */
954
1196
  declare function withSSR<T>(fn: () => T): T;
955
1197
 
@@ -986,6 +1228,77 @@ declare function enqueueBatchedSignal(signal: ReactiveSignal): boolean;
986
1228
  */
987
1229
  declare function isBatching(): boolean;
988
1230
 
1231
+ /**
1232
+ * Wait for the next microtask — after any currently-pending reactive updates
1233
+ * have been flushed. Useful in imperative code that needs to read DOM state
1234
+ * right after changing a signal.
1235
+ *
1236
+ * Under the hood this resolves on a microtask and again on an animation frame
1237
+ * so both synchronous reactive passes and layout side-effects have settled.
1238
+ *
1239
+ * @returns Promise that resolves after the next DOM flush
1240
+ *
1241
+ * @example
1242
+ * ```ts
1243
+ * setMenuOpen(true);
1244
+ * await nextTick();
1245
+ * menuRef.current?.focus(); // DOM has the new menu rendered
1246
+ * ```
1247
+ */
1248
+ declare function nextTick(): Promise<void>;
1249
+
1250
+ /**
1251
+ * Create a deferred mirror of a reactive getter. The returned accessor
1252
+ * eventually converges to the source value, but updates on a microtask
1253
+ * + `requestAnimationFrame` pair — so if the source changes repeatedly
1254
+ * in the same frame, only the latest value is ever surfaced.
1255
+ *
1256
+ * Use this for expensive derived views (filtered lists, rich charts)
1257
+ * that should not block fast state changes (typing, cursor movement).
1258
+ *
1259
+ * @example
1260
+ * ```ts
1261
+ * const [query, setQuery] = signal("");
1262
+ * const deferredQuery = defer(query);
1263
+ *
1264
+ * // input stays instant — it reads query()
1265
+ * input({ on: { input: e => setQuery(e.target.value) } });
1266
+ *
1267
+ * // heavy list reads deferredQuery() and updates one frame later
1268
+ * each(() => heavyFilter(items, deferredQuery()), row => li({ nodes: row.name }));
1269
+ * ```
1270
+ */
1271
+ declare function defer<T>(getter: () => T): () => T;
1272
+ interface TransitionState {
1273
+ pending: () => boolean;
1274
+ start: (fn: () => void | Promise<void>) => void;
1275
+ }
1276
+ /**
1277
+ * Create a transition handle. `start(fn)` runs `fn` on the next idle
1278
+ * callback so expensive reactive updates do not block immediate input
1279
+ * events. `pending()` is a reactive boolean that is `true` while a
1280
+ * transition is in flight.
1281
+ *
1282
+ * There is no "interruption" — the runtime has no concept of partial
1283
+ * renders. The transition is cooperative: its body runs when the browser
1284
+ * reports spare time via `requestIdleCallback`. That is sufficient for
1285
+ * the 90% case (defer a heavy update so a click handler can finish first)
1286
+ * and avoids the complexity of an interruptible reconciler.
1287
+ *
1288
+ * Async callbacks are supported: `pending()` stays `true` until the
1289
+ * returned promise resolves OR rejects.
1290
+ *
1291
+ * @example
1292
+ * ```ts
1293
+ * const t = transition();
1294
+ * button({
1295
+ * disabled: t.pending,
1296
+ * on: { click: () => t.start(() => setFilter(nextFilter)) },
1297
+ * });
1298
+ * ```
1299
+ */
1300
+ declare function transition(): TransitionState;
1301
+
989
1302
  /**
990
1303
  * Execute a function without tracking any signal reads as dependencies.
991
1304
  * Useful for reading signals inside effects without creating subscriptions.
@@ -1067,6 +1380,23 @@ interface ErrorBoundaryProps {
1067
1380
  * Called when an error is caught (sync or async).
1068
1381
  */
1069
1382
  onError?: (error: Error) => void;
1383
+ /**
1384
+ * A list of reactive getters. Whenever any of these values change
1385
+ * after an error has been caught, the boundary automatically resets
1386
+ * (clears the error and re-renders). Useful for recovering from a
1387
+ * failed render after the user navigates, changes filters, or
1388
+ * otherwise picks a new input that might not fail this time.
1389
+ *
1390
+ * @example
1391
+ * ```ts
1392
+ * const [route, setRoute] = signal("/");
1393
+ * ErrorBoundary({
1394
+ * resetKeys: [route],
1395
+ * nodes: () => div({ nodes: riskyPageFor(route()) }),
1396
+ * });
1397
+ * ```
1398
+ */
1399
+ resetKeys?: Array<() => unknown>;
1070
1400
  }
1071
1401
  /**
1072
1402
  * ErrorBoundary component using SibuJS reactive pattern.
@@ -1080,7 +1410,57 @@ interface ErrorBoundaryProps {
1080
1410
  * - onError callback for logging/telemetry
1081
1411
  * - Improved CSS styling
1082
1412
  */
1083
- declare function ErrorBoundary({ nodes, fallback, onError }: ErrorBoundaryProps): Element;
1413
+ declare function ErrorBoundary({ nodes, fallback, onError, resetKeys }: ErrorBoundaryProps): Element;
1414
+
1415
+ type ErrorSeverity = "error" | "warning" | "info";
1416
+ interface ErrorDisplayProps {
1417
+ /** The Error (or error-like value) to show. */
1418
+ error: unknown;
1419
+ /** Severity colour. Default `"error"`. */
1420
+ severity?: ErrorSeverity;
1421
+ /** Optional headline override. By default `error.message` is used. */
1422
+ title?: string;
1423
+ /**
1424
+ * Label for the primary action. Shown next to a Reload button.
1425
+ * Leave unset to hide the retry action.
1426
+ */
1427
+ retryLabel?: string;
1428
+ /** Callback for the retry button. */
1429
+ onRetry?: () => void;
1430
+ /**
1431
+ * If `true`, the Reload button is hidden. Useful for embedded
1432
+ * error panels where a full page reload is inappropriate.
1433
+ */
1434
+ hideReload?: boolean;
1435
+ /**
1436
+ * If `true`, the stack trace and metadata are always shown even in
1437
+ * production builds. Default: only shown in dev.
1438
+ */
1439
+ alwaysShowDetails?: boolean;
1440
+ /**
1441
+ * Extra metadata rendered as a key/value list under the message.
1442
+ * Useful for attaching request IDs, user IDs, etc.
1443
+ */
1444
+ metadata?: Record<string, string | number | boolean | null | undefined>;
1445
+ }
1446
+ /**
1447
+ * Rich error display component. Wire an error-like value in and get
1448
+ * a colored panel back with copy, retry, reload, stack, cause chain,
1449
+ * and metadata — all built from tag factories. Reusable anywhere
1450
+ * (inside `ErrorBoundary`, from a fetch failure, from a form submit).
1451
+ *
1452
+ * @example
1453
+ * ```ts
1454
+ * button({
1455
+ * on: { click: async () => {
1456
+ * try { await save(); }
1457
+ * catch (err) { mount(ErrorDisplay({ error: err, onRetry: save }), errorHost); }
1458
+ * }},
1459
+ * nodes: "Save",
1460
+ * });
1461
+ * ```
1462
+ */
1463
+ declare function ErrorDisplay(props: ErrorDisplayProps): Element;
1084
1464
 
1085
1465
  interface LoadingProps {
1086
1466
  /** Text to show alongside the spinner */
@@ -1103,4 +1483,4 @@ interface LoadingProps {
1103
1483
  */
1104
1484
  declare function Loading(props?: LoadingProps): HTMLElement;
1105
1485
 
1106
- export { type Accessor, type ActionFn, type ArrayActions, type Context, DynamicComponent, type EffectOptions, ErrorBoundary, type ErrorBoundaryProps, Fragment, KeepAlive, type KeepAliveOptions, Loading, type LoadingProps, type LongPressOptions, NodeChild, NodeChildren, Portal, type Ref, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, a, abbr, action, address, area, array, article, aside, 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, customElement, data, datalist, dd, deepEqual, deepSignal, 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, 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, memo, memoFn, menu, meta, meter, mount, nav, 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, rp, rt, ruby, s, samp, script, section, select, setGlobalErrorHandler, show, signal, slot, small, source, span, stop, store, strong, style, sub, summary, sup, svg, symbol, table, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
1486
+ export { type Accessor, type ActionFn, type AnchorProps, type ArrayActions, type AsyncDerivedState, type AudioProps, type ButtonProps, type Context, DynamicComponent, 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 OptionProps, Portal, type Ref, 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, 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, memo, memoFn, 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, rp, rt, ruby, s, samp, script, section, select, setGlobalErrorHandler, show, signal, slot, small, source, span, stop, store, strict, strictEffect, strong, style, sub, summary, sup, svg, symbol, table, 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
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  DynamicComponent,
3
3
  ErrorBoundary,
4
+ ErrorDisplay,
4
5
  Fragment,
5
6
  KeepAlive,
6
7
  Loading,
@@ -8,6 +9,7 @@ import {
8
9
  Suspense,
9
10
  action,
10
11
  array,
12
+ asyncDerived,
11
13
  autoResize,
12
14
  catchError,
13
15
  catchErrorAsync,
@@ -15,6 +17,7 @@ import {
15
17
  copyOnClick,
16
18
  deepEqual,
17
19
  deepSignal,
20
+ defer,
18
21
  each,
19
22
  getSlot,
20
23
  html,
@@ -24,6 +27,7 @@ import {
24
27
  memo,
25
28
  memoFn,
26
29
  mount,
30
+ nextTick,
27
31
  onCleanup,
28
32
  onMount,
29
33
  onUnmount,
@@ -34,11 +38,18 @@ import {
34
38
  setGlobalErrorHandler,
35
39
  show,
36
40
  store,
41
+ strict,
42
+ strictEffect,
43
+ transition,
37
44
  trapFocus,
38
45
  unregisterComponent,
39
46
  when,
40
47
  writable
41
- } from "./chunk-P6W3STU4.js";
48
+ } from "./chunk-QWZG56ET.js";
49
+ import {
50
+ __resetIdCounter,
51
+ createId
52
+ } from "./chunk-YT6HQ6AM.js";
42
53
  import {
43
54
  a,
44
55
  abbr,
@@ -176,54 +187,58 @@ import {
176
187
  use,
177
188
  var_,
178
189
  video
179
- } from "./chunk-GCOK2LC3.js";
190
+ } from "./chunk-32DY64NT.js";
180
191
  import {
181
192
  watch
182
- } from "./chunk-TNQWPPE6.js";
193
+ } from "./chunk-NYVAC6P5.js";
183
194
  import {
184
195
  context
185
- } from "./chunk-WR5D4EGH.js";
196
+ } from "./chunk-BGN5ZMP4.js";
186
197
  import {
187
198
  SVG_NS,
188
- checkLeaks,
189
- dispose,
190
- registerDisposer,
191
199
  tagFactory
192
- } from "./chunk-B7SWRFUT.js";
200
+ } from "./chunk-F3FA4F32.js";
193
201
  import {
194
- bindDynamic
195
- } from "./chunk-23VV7YD3.js";
202
+ bindDynamic,
203
+ checkLeaks,
204
+ dispose,
205
+ registerDisposer
206
+ } from "./chunk-PTQJDMRT.js";
196
207
  import {
197
208
  derived
198
- } from "./chunk-L6JRBDNS.js";
209
+ } from "./chunk-NEKUBFPT.js";
210
+ import "./chunk-CMBFNA7L.js";
199
211
  import {
200
212
  effect,
201
213
  on
202
- } from "./chunk-6SA3QQES.js";
214
+ } from "./chunk-CHF5OHIA.js";
203
215
  import {
204
216
  disableSSR,
205
217
  enableSSR,
206
218
  isSSR,
207
219
  withSSR
208
- } from "./chunk-CHJ27IGK.js";
220
+ } from "./chunk-EUZND3CB.js";
209
221
  import {
210
222
  batch,
211
223
  enqueueBatchedSignal,
212
224
  isBatching,
213
- signal,
225
+ signal
226
+ } from "./chunk-WZSPOOER.js";
227
+ import {
214
228
  untracked
215
- } from "./chunk-V2XTI523.js";
216
- import "./chunk-UNXCEF6S.js";
217
- import "./chunk-MLKGABMK.js";
229
+ } from "./chunk-ZD6OAMTH.js";
230
+ import "./chunk-5X6PP2UK.js";
218
231
  export {
219
232
  DynamicComponent,
220
233
  ErrorBoundary,
234
+ ErrorDisplay,
221
235
  Fragment,
222
236
  KeepAlive,
223
237
  Loading,
224
238
  Portal,
225
239
  SVG_NS,
226
240
  Suspense,
241
+ __resetIdCounter,
227
242
  a,
228
243
  abbr,
229
244
  action,
@@ -232,6 +247,7 @@ export {
232
247
  array,
233
248
  article,
234
249
  aside,
250
+ asyncDerived,
235
251
  audio,
236
252
  autoResize,
237
253
  b,
@@ -259,12 +275,14 @@ export {
259
275
  colgroup,
260
276
  context,
261
277
  copyOnClick,
278
+ createId,
262
279
  customElement,
263
280
  data,
264
281
  datalist,
265
282
  dd,
266
283
  deepEqual,
267
284
  deepSignal,
285
+ defer,
268
286
  defs,
269
287
  del,
270
288
  derived,
@@ -332,6 +350,7 @@ export {
332
350
  meter,
333
351
  mount,
334
352
  nav,
353
+ nextTick,
335
354
  noscript,
336
355
  object,
337
356
  ol,
@@ -377,6 +396,8 @@ export {
377
396
  span,
378
397
  stop,
379
398
  store,
399
+ strict,
400
+ strictEffect,
380
401
  strong,
381
402
  style,
382
403
  sub,
@@ -398,6 +419,7 @@ export {
398
419
  title,
399
420
  tr,
400
421
  track,
422
+ transition,
401
423
  trapFocus,
402
424
  tspan,
403
425
  u,