sibujs 3.4.1 → 4.0.1

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 (98) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +118 -15
  3. package/dist/browser.cjs +410 -101
  4. package/dist/browser.d.cts +50 -5
  5. package/dist/browser.d.ts +50 -5
  6. package/dist/browser.js +8 -6
  7. package/dist/build.cjs +784 -392
  8. package/dist/build.js +15 -15
  9. package/dist/cdn.global.js +11 -7
  10. package/dist/{chunk-PBZWJQNY.js → chunk-52ERIVFD.js} +8 -8
  11. package/dist/chunk-52XFPGSN.js +123 -0
  12. package/dist/{chunk-Y22QAKJX.js → chunk-5BVKQX2F.js} +4 -4
  13. package/dist/chunk-5INI7D2L.js +194 -0
  14. package/dist/{chunk-4I3M326N.js → chunk-AD5YSZAN.js} +19 -25
  15. package/dist/{chunk-F7HW2NI5.js → chunk-AW6HPJ3L.js} +1 -1
  16. package/dist/chunk-DHDZ7IVN.js +109 -0
  17. package/dist/{chunk-VQZDHAEK.js → chunk-E72G5JSK.js} +1 -1
  18. package/dist/{chunk-MPE75KOA.js → chunk-HPXTUPJD.js} +259 -124
  19. package/dist/{chunk-EX77FXTT.js → chunk-HYCCIYNS.js} +228 -51
  20. package/dist/{chunk-FWFEBYQ6.js → chunk-IKVUUE7D.js} +115 -41
  21. package/dist/{chunk-5MFF5EPT.js → chunk-J4WZMCIW.js} +5 -5
  22. package/dist/{chunk-BQLVTAUZ.js → chunk-JYXQCELN.js} +57 -22
  23. package/dist/{chunk-WEZ5SP7L.js → chunk-PHB3MCK4.js} +73 -34
  24. package/dist/chunk-PHRH66Y7.js +147 -0
  25. package/dist/{chunk-S2VW4NBA.js → chunk-PJDSI2K7.js} +295 -198
  26. package/dist/{chunk-QHPUFNHZ.js → chunk-PTLJ7NQX.js} +3 -3
  27. package/dist/{chunk-NXR2YFZB.js → chunk-QD4I7ZGZ.js} +24 -34
  28. package/dist/{chunk-S3NFJO6L.js → chunk-TIRZCERI.js} +36 -5
  29. package/dist/{chunk-7PNKW3FJ.js → chunk-TNEHT3NG.js} +232 -67
  30. package/dist/{chunk-335KJEN2.js → chunk-TVURNWDK.js} +5 -3
  31. package/dist/{chunk-CV7FAQ2R.js → chunk-UNAYBND2.js} +9 -3
  32. package/dist/chunk-VPP2FONR.js +142 -0
  33. package/dist/{chunk-X4JS367G.js → chunk-XDOMTQHM.js} +14 -10
  34. package/dist/chunk-XET2RUJF.js +61 -0
  35. package/dist/{chunk-3FFCUIGV.js → chunk-XZMCVZW6.js} +309 -188
  36. package/dist/{chunk-YDWP3ZOU.js → chunk-YLV26GAJ.js} +228 -86
  37. package/dist/{contracts-ey_Qh8ef.d.ts → contracts-Hg6ITAEF.d.cts} +6 -6
  38. package/dist/{contracts-ey_Qh8ef.d.cts → contracts-Hg6ITAEF.d.ts} +6 -6
  39. package/dist/{customElement-CPfIrbvg.d.cts → customElement-CKLoO63w.d.cts} +73 -11
  40. package/dist/{customElement-CPfIrbvg.d.ts → customElement-CKLoO63w.d.ts} +73 -11
  41. package/dist/data.cjs +483 -205
  42. package/dist/data.d.cts +139 -7
  43. package/dist/data.d.ts +139 -7
  44. package/dist/data.js +9 -9
  45. package/dist/devtools.cjs +222 -87
  46. package/dist/devtools.js +8 -8
  47. package/dist/dispose-4FZ6OFXR.js +19 -0
  48. package/dist/ecosystem.cjs +426 -182
  49. package/dist/ecosystem.js +11 -11
  50. package/dist/extras.cjs +1988 -772
  51. package/dist/extras.d.cts +7 -7
  52. package/dist/extras.d.ts +7 -7
  53. package/dist/extras.js +29 -26
  54. package/dist/index.cjs +791 -392
  55. package/dist/index.d.cts +299 -28
  56. package/dist/index.d.ts +299 -28
  57. package/dist/index.js +33 -18
  58. package/dist/motion.cjs +180 -50
  59. package/dist/motion.d.cts +26 -0
  60. package/dist/motion.d.ts +26 -0
  61. package/dist/motion.js +5 -5
  62. package/dist/patterns.cjs +437 -170
  63. package/dist/patterns.d.cts +60 -13
  64. package/dist/patterns.d.ts +60 -13
  65. package/dist/patterns.js +7 -7
  66. package/dist/performance.cjs +333 -148
  67. package/dist/performance.d.cts +55 -7
  68. package/dist/performance.d.ts +55 -7
  69. package/dist/performance.js +9 -9
  70. package/dist/plugins.cjs +1378 -583
  71. package/dist/plugins.d.cts +227 -9
  72. package/dist/plugins.d.ts +227 -9
  73. package/dist/plugins.js +610 -321
  74. package/dist/{ssr-D62yFwuw.d.cts → ssr-BiPRdZ6n.d.cts} +44 -15
  75. package/dist/{ssr-D62yFwuw.d.ts → ssr-BiPRdZ6n.d.ts} +44 -15
  76. package/dist/{ssr-2PPULEK2.js → ssr-JFP5535P.js} +5 -4
  77. package/dist/ssr.cjs +1111 -450
  78. package/dist/ssr.d.cts +230 -20
  79. package/dist/ssr.d.ts +230 -20
  80. package/dist/ssr.js +15 -12
  81. package/dist/{startup-0Qv6aosO.d.cts → startup-BMpaiMhP.d.cts} +1 -1
  82. package/dist/{startup-0Qv6aosO.d.ts → startup-BMpaiMhP.d.ts} +1 -1
  83. package/dist/testing.cjs +205 -63
  84. package/dist/testing.d.cts +1 -1
  85. package/dist/testing.d.ts +1 -1
  86. package/dist/testing.js +8 -10
  87. package/dist/ui.cjs +640 -199
  88. package/dist/ui.d.cts +2 -2
  89. package/dist/ui.d.ts +2 -2
  90. package/dist/ui.js +10 -10
  91. package/dist/widgets.cjs +207 -82
  92. package/dist/widgets.js +9 -9
  93. package/package.json +12 -7
  94. package/dist/chunk-5VGSK6D2.js +0 -80
  95. package/dist/chunk-6CAJU5TP.js +0 -38
  96. package/dist/chunk-COY6PUD2.js +0 -34
  97. package/dist/chunk-DLBFEAIS.js +0 -96
  98. package/dist/chunk-L3GAGWCC.js +0 -111
@@ -3,7 +3,7 @@ interface FieldConfig<T = unknown> {
3
3
  initial: T;
4
4
  validators?: ValidatorFn<T>[];
5
5
  }
6
- type FormConfig<T extends Record<string, unknown>> = {
6
+ type FormConfig<T extends object> = {
7
7
  [K in keyof T]: FieldConfig<T[K]>;
8
8
  };
9
9
  interface FormField<T = unknown> {
@@ -14,7 +14,7 @@ interface FormField<T = unknown> {
14
14
  touch: () => void;
15
15
  reset: () => void;
16
16
  }
17
- interface FormReturn<T extends Record<string, unknown>> {
17
+ interface FormReturn<T extends object> {
18
18
  fields: {
19
19
  [K in keyof T]: FormField<T[K]>;
20
20
  };
@@ -40,8 +40,18 @@ declare function custom<T>(fn: (value: T) => boolean, message: string): Validato
40
40
  /**
41
41
  * Props returned by bindField, ready to spread into an input tag factory.
42
42
  */
43
- interface BoundFieldProps {
44
- value: () => unknown;
43
+ /**
44
+ * Props produced by {@link bindField}, ready to spread onto a tag factory.
45
+ *
46
+ * Generic over the field's value type. `value: () => unknown` forced every
47
+ * consumer to cast, because `unknown` does not satisfy the typed tag factories'
48
+ * `reactive<string>` — so the declaration contradicted this helper's own
49
+ * documented purpose ("props object ready to pass directly to a tag factory").
50
+ * The parameter defaults to `unknown`, so existing annotations of the bare
51
+ * `BoundFieldProps` keep compiling. (TYPE-010)
52
+ */
53
+ interface BoundFieldProps<T = unknown> {
54
+ value: () => T;
45
55
  on: {
46
56
  input: (e: Event) => void;
47
57
  change: (e: Event) => void;
@@ -69,8 +79,8 @@ interface BoundFieldProps {
69
79
  * input(bindField(f.fields.email, { type: "email", placeholder: "Email" }))
70
80
  * ```
71
81
  */
72
- declare function bindField<T>(field: FormField<T>, extras?: Record<string, unknown>): BoundFieldProps;
73
- declare function form<T extends Record<string, unknown>>(config: FormConfig<T>): FormReturn<T>;
82
+ declare function bindField<T>(field: FormField<T>, extras?: Record<string, unknown>): BoundFieldProps<T>;
83
+ declare function form<T extends object>(config: FormConfig<T>): FormReturn<T>;
74
84
 
75
85
  interface VirtualListProps<T> {
76
86
  items: () => T[];
@@ -195,25 +205,58 @@ declare function withScopedStyle<P>(css: string, component: (props: P) => HTMLEl
195
205
  */
196
206
  declare function removeScopedStyle(scopeId: string): void;
197
207
 
208
+ /**
209
+ * Every value the shared attribute primitive accepts, and nothing more.
210
+ *
211
+ * `null` / `undefined` are part of the contract, not an oversight: they REMOVE
212
+ * the attribute. That is what makes the ordinary optional-value getter —
213
+ * `() => user?.label` typed `string | null | undefined` — expressible without a
214
+ * cast. The declared type used to exclude both while the runtime handled them,
215
+ * so the documented behaviour was unreachable from type-checked code.
216
+ *
217
+ * Deliberately NOT widened to `unknown`: the runtime only defines behaviour for
218
+ * these, and a public signature should describe the runtime exactly rather than
219
+ * inviting values whose handling is incidental.
220
+ */
221
+ type AttributeValue = string | number | boolean | null | undefined;
222
+ /** An attribute value, or a reactive getter producing one. */
223
+ type AttributeSource = AttributeValue | (() => AttributeValue);
198
224
  /**
199
225
  * Bind multiple reactive attributes to an element.
200
226
  * Each attribute value can be a static value or a reactive getter.
201
227
  * Returns a single teardown function that stops all bindings.
228
+ *
229
+ * Static and reactive values share ONE security policy. They previously did
230
+ * not: a getter went through `bindAttribute` (which refuses `on*` and sanitizes
231
+ * URL/style/srcset), while a plain string went straight to `setAttribute`. So
232
+ * `bindAttrs(a, { href: "javascript:…" })` was live XSS while the identical
233
+ * `bindAttrs(a, { href: () => "javascript:…" })` was blocked — the same
234
+ * authoring intent with two different verdicts. Both now commit through
235
+ * `setSafeAttribute`.
202
236
  */
203
- declare function bindAttrs(el: HTMLElement, attrs: Record<string, string | number | boolean | (() => string | number | boolean)>): () => void;
237
+ declare function bindAttrs(el: HTMLElement, attrs: Record<string, AttributeSource>): () => void;
204
238
  /**
205
239
  * Reactively toggle a boolean attribute (like disabled, readonly, hidden).
206
240
  * When the value is truthy the attribute is present (set to ""),
207
241
  * when falsy the attribute is removed entirely.
208
242
  * Returns a teardown function to stop reactive tracking.
243
+ *
244
+ * The attribute NAME is policed too: `bindBoolAttr(el, "onclick", true)` would
245
+ * otherwise create a live `onclick=""` handler slot through a helper whose
246
+ * whole purpose is inert presence toggling.
209
247
  */
210
248
  declare function bindBoolAttr(el: HTMLElement, attr: string, getter: boolean | (() => boolean)): () => void;
211
249
  /**
212
250
  * Bind a data-* attribute reactively.
213
251
  * Shorthand for `bindAttribute(el, "data-<key>", getter)`.
214
252
  * Returns a teardown function to stop reactive tracking.
253
+ *
254
+ * Shares the removal semantics of every other attribute writer: `null` /
255
+ * `undefined` remove `data-<key>` rather than writing the text "null". The
256
+ * value is handed to the primitive unstringified so that decision is made in
257
+ * one place.
215
258
  */
216
- declare function bindData(el: HTMLElement, key: string, getter: string | (() => string)): () => void;
259
+ declare function bindData(el: HTMLElement, key: string, getter: AttributeValue | (() => AttributeValue)): () => void;
217
260
 
218
261
  /**
219
262
  * Test-only helper to reset the module-level stack between specs. Client-only:
@@ -261,6 +304,15 @@ declare function toast(options?: {
261
304
  /**
262
305
  * infiniteScroll combines IntersectionObserver with a data-fetching trigger
263
306
  * to implement infinite scroll behavior.
307
+ *
308
+ * ERROR CONTRACT: `onLoadMore` is user code and may reject. The observer
309
+ * callback cannot `await` it, so the promise it starts is floating — and a
310
+ * floating rejection is an unhandled rejection, which crashes a Node SSR
311
+ * process and fires `window.onunhandledrejection` in a browser, for what is
312
+ * really just a failed page of data. `loadMore()` therefore CONTAINS its own
313
+ * failure: it reports through the framework's central error pipeline
314
+ * (`reportError`, phase `"async"`) and never rejects to its caller. The
315
+ * `loading` flag is always cleared, so a failed page does not wedge the list.
264
316
  */
265
317
  declare function infiniteScroll(options: {
266
318
  onLoadMore: () => Promise<void>;
@@ -296,7 +348,7 @@ declare function pagination(options: {
296
348
  * eventBus creates a typed publish/subscribe event system.
297
349
  * No reactive state needed -- pure event dispatching.
298
350
  */
299
- declare function eventBus<T extends Record<string, unknown>>(): {
351
+ declare function eventBus<T extends object>(): {
300
352
  on: <K extends keyof T>(event: K, handler: (data: T[K]) => void) => () => void;
301
353
  emit: <K extends keyof T>(event: K, data: T[K]) => void;
302
354
  off: <K extends keyof T>(event: K, handler: (data: T[K]) => void) => void;
@@ -308,7 +360,6 @@ interface CustomElementOptions {
308
360
  mode?: "open" | "closed";
309
361
  styles?: string;
310
362
  observedAttributes?: string[];
311
- extends?: string;
312
363
  }
313
364
  /**
314
365
  * defineElement creates a Web Component wrapping a SibuJS component function.
@@ -316,7 +367,18 @@ interface CustomElementOptions {
316
367
  declare function defineElement(name: string, component: (props: Record<string, unknown>, element: HTMLElement) => HTMLElement, options?: CustomElementOptions): void;
317
368
  /**
318
369
  * Creates an SVG element with proper namespace.
370
+ *
371
+ * Attribute writes go through the framework's shared commit primitive, so the
372
+ * SVG helper enforces exactly the policy the HTML tag factory and the reactive
373
+ * bindings enforce: `on*` strings are refused, `href` / `xlink:href` go through
374
+ * the URL allowlist, and `style` goes through the declaration-list sanitizer.
375
+ * Previously every non-function prop was a raw `setAttribute`, so
376
+ * `svgElement("svg", { onload: "alert(1)" })` installed a live handler that the
377
+ * equivalent HTML call had always refused.
378
+ *
379
+ * Function-valued `on*` props keep their existing meaning — `addEventListener`,
380
+ * never an attribute.
319
381
  */
320
382
  declare function svgElement(tag: string, props?: Record<string, unknown>, ...nodes: (SVGElement | string)[]): SVGElement;
321
383
 
322
- export { lazyLoad as A, type BoundFieldProps as B, type CustomElementOptions as C, matchesPattern as D, max as E, type FieldConfig as F, maxLength as G, min as H, type IntersectionResult as I, minLength as J, pagination as K, phoneMask as L, type MaskOptions as M, removeScopedStyle as N, required as O, scopedStyle as P, ssnMask as Q, svgElement as R, timeMask as S, type Toast as T, toast as U, type ValidatorFn as V, withScopedStyle as W, zipMask as X, __resetDialogStack as _, FocusTrap as a, type FormConfig as b, type FormField as c, type FormReturn as d, type ToastInstance as e, VirtualList as f, type VirtualListProps as g, announce as h, aria as i, bindAttrs as j, bindBoolAttr as k, bindData as l, bindField as m, creditCardMask as n, custom as o, dateMask as p, defineElement as q, dialog as r, email as s, eventBus as t, focus as u, form as v, hotkey as w, infiniteScroll as x, inputMask as y, intersection as z };
384
+ export { type AttributeSource as A, type BoundFieldProps as B, type CustomElementOptions as C, intersection as D, lazyLoad as E, type FieldConfig as F, matchesPattern as G, max as H, type IntersectionResult as I, maxLength as J, min as K, minLength as L, type MaskOptions as M, pagination as N, phoneMask as O, removeScopedStyle as P, required as Q, scopedStyle as R, ssnMask as S, type Toast as T, svgElement as U, type ValidatorFn as V, timeMask as W, toast as X, withScopedStyle as Y, zipMask as Z, __resetDialogStack as _, type AttributeValue as a, FocusTrap as b, type FormConfig as c, type FormField as d, type FormReturn as e, type ToastInstance as f, VirtualList as g, type VirtualListProps as h, announce as i, aria as j, bindAttrs as k, bindBoolAttr as l, bindData as m, bindField as n, creditCardMask as o, custom as p, dateMask as q, defineElement as r, dialog as s, email as t, eventBus as u, focus as v, form as w, hotkey as x, infiniteScroll as y, inputMask as z };