sibujs 4.0.0 → 4.1.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 (55) hide show
  1. package/README.md +5 -1
  2. package/dist/browser.cjs +9 -2
  3. package/dist/browser.js +4 -4
  4. package/dist/build.cjs +93 -14
  5. package/dist/build.js +10 -10
  6. package/dist/cdn.global.js +10 -10
  7. package/dist/{chunk-F64ZPCFE.js → chunk-4RH6D7GR.js} +3 -3
  8. package/dist/{chunk-WOOMUJFT.js → chunk-4U7KD3RY.js} +3 -3
  9. package/dist/{chunk-O3QQ3XOL.js → chunk-5GJ5RTHA.js} +1 -1
  10. package/dist/{chunk-GCSGGA3Q.js → chunk-ANGSYNPX.js} +77 -14
  11. package/dist/{chunk-VFHIVEPF.js → chunk-BMSN6NWQ.js} +3 -3
  12. package/dist/{chunk-ACBT6UZS.js → chunk-D3SZ4LVS.js} +9 -2
  13. package/dist/{chunk-EWEE7NBF.js → chunk-DAKLOMKS.js} +2 -2
  14. package/dist/{chunk-Z2CE42DB.js → chunk-DCDS2PQ6.js} +1 -1
  15. package/dist/{chunk-WN6WDFCB.js → chunk-FB7KQXZI.js} +4 -4
  16. package/dist/{chunk-6LG2T7LO.js → chunk-FMHIQNMP.js} +4 -4
  17. package/dist/{chunk-DQVUBVNX.js → chunk-I3VI34DP.js} +10 -11
  18. package/dist/{chunk-E62UADKL.js → chunk-IM7N5WR4.js} +1 -1
  19. package/dist/{chunk-RRIDJQ5C.js → chunk-KSOEJGFO.js} +1 -1
  20. package/dist/{chunk-3EKJK5FZ.js → chunk-LOFZHP6V.js} +2 -2
  21. package/dist/{chunk-ES2GERY2.js → chunk-MRAMKDHQ.js} +1 -1
  22. package/dist/{chunk-PBQEW5VW.js → chunk-PFTDGEPZ.js} +1 -1
  23. package/dist/{chunk-4MFZMLUU.js → chunk-SHDVWATN.js} +1 -1
  24. package/dist/{chunk-W55YHPEP.js → chunk-UFSQEO7P.js} +14 -2
  25. package/dist/{chunk-DR7H6UGM.js → chunk-XIHMS2Y6.js} +5 -5
  26. package/dist/{chunk-NF3LYCQH.js → chunk-XSZRJW76.js} +4 -4
  27. package/dist/data.cjs +9 -2
  28. package/dist/data.js +6 -6
  29. package/dist/devtools.cjs +9 -2
  30. package/dist/devtools.js +4 -4
  31. package/dist/ecosystem.cjs +16 -9
  32. package/dist/ecosystem.js +7 -7
  33. package/dist/extras.cjs +16 -9
  34. package/dist/extras.js +19 -19
  35. package/dist/index.cjs +94 -14
  36. package/dist/index.d.cts +133 -1
  37. package/dist/index.d.ts +133 -1
  38. package/dist/index.js +12 -10
  39. package/dist/motion.cjs +9 -2
  40. package/dist/motion.js +3 -3
  41. package/dist/patterns.cjs +9 -2
  42. package/dist/patterns.js +5 -5
  43. package/dist/performance.cjs +9 -2
  44. package/dist/performance.js +4 -4
  45. package/dist/plugins.cjs +16 -9
  46. package/dist/plugins.js +6 -6
  47. package/dist/ssr.cjs +16 -9
  48. package/dist/ssr.js +7 -7
  49. package/dist/testing.cjs +9 -2
  50. package/dist/testing.js +2 -2
  51. package/dist/ui.cjs +9 -2
  52. package/dist/ui.js +6 -6
  53. package/dist/widgets.cjs +9 -2
  54. package/dist/widgets.js +6 -6
  55. package/package.json +7 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SibuJS
2
2
 
3
- A lightweight, function-based frontend framework with fine-grained reactivity, direct DOM rendering, and zero compilation. **No Virtual DOM. No magic.**
3
+ A function-based frontend framework with fine-grained reactivity, direct DOM rendering, and zero compilation. **No Virtual DOM. No magic.**
4
4
 
5
5
  [NPM](https://www.npmjs.com/package/sibujs) · [License](https://github.com/hexplus/sibujs/blob/main/LICENSE)
6
6
 
@@ -147,6 +147,10 @@ The lean core: reactivity, rendering, and components. Everything below imports f
147
147
  ### Islands & Progressive Enhancement
148
148
  - **`enhance` / `enhanceAll`** — attach fine-grained reactivity to existing server-rendered HTML with no build step (the third rendering mode alongside `mount` and `hydrate`).
149
149
  - **`island` / `registerIsland` / `hydrateIslands`** — hydrate isolated interactive regions on demand.
150
+ - **`ctx.each`** — bind many elements the server already rendered (a board, a table, a keyboard) from one descriptor, with no new DOM.
151
+ - **`external`** — reactive integration with state SibuJS does not own: a domain engine, a canvas, an editor, a socket cache. `track()` where you read, `invalidate()` where you mutate.
152
+
153
+ Guides: [islands & progressive enhancement](docs/islands.md) · [external mutable state and update granularity](docs/architecture/external-state.md) · [running islands inside another framework's page](docs/interop.md). Reference application: [`examples/chess/`](examples/chess/).
150
154
 
151
155
  ---
152
156
 
package/dist/browser.cjs CHANGED
@@ -387,7 +387,14 @@ function reactiveBinding(commit, ownerNode) {
387
387
  subscriber._disposed = false;
388
388
  subscriber._errorPhase = "binding";
389
389
  subscriber._errorNode = ownerNode;
390
- run();
390
+ try {
391
+ run();
392
+ } catch (err) {
393
+ subscriber._disposed = true;
394
+ subscriber._errorNode = void 0;
395
+ cleanup(subscriber);
396
+ throw err;
397
+ }
391
398
  return subscriber._dispose ?? (subscriber._dispose = () => {
392
399
  subscriber._disposed = true;
393
400
  subscriber._errorNode = void 0;
@@ -619,7 +626,7 @@ function forEachSubscriber(signal2, visit) {
619
626
 
620
627
  // src/reactivity/track.ts
621
628
  var _isDev2 = isDev();
622
- var _runtimeVersion = true ? "4.0.0" : "dev";
629
+ var _runtimeVersion = true ? "4.1.0" : "dev";
623
630
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
624
631
  function resolveReactiveApi() {
625
632
  const g = globalThis;
package/dist/browser.js CHANGED
@@ -35,14 +35,14 @@ import {
35
35
  visibility,
36
36
  wakeLock,
37
37
  windowSize
38
- } from "./chunk-EWEE7NBF.js";
38
+ } from "./chunk-DAKLOMKS.js";
39
39
  import "./chunk-H3SRKIYX.js";
40
40
  import "./chunk-52XFPGSN.js";
41
41
  import "./chunk-7ZHH77QA.js";
42
- import "./chunk-PBQEW5VW.js";
42
+ import "./chunk-PFTDGEPZ.js";
43
43
  import "./chunk-TIRZCERI.js";
44
- import "./chunk-W55YHPEP.js";
45
- import "./chunk-ACBT6UZS.js";
44
+ import "./chunk-UFSQEO7P.js";
45
+ import "./chunk-D3SZ4LVS.js";
46
46
  import "./chunk-VPP2FONR.js";
47
47
  export {
48
48
  animationFrame,
package/dist/build.cjs CHANGED
@@ -1132,6 +1132,7 @@ __export(index_exports, {
1132
1132
  enhance: () => enhance,
1133
1133
  enhanceAll: () => enhanceAll,
1134
1134
  enqueueBatchedSignal: () => enqueueBatchedSignal,
1135
+ external: () => external,
1135
1136
  fieldset: () => fieldset,
1136
1137
  figcaption: () => figcaption,
1137
1138
  figure: () => figure,
@@ -1945,7 +1946,14 @@ function reactiveBinding(commit, ownerNode) {
1945
1946
  subscriber._disposed = false;
1946
1947
  subscriber._errorPhase = "binding";
1947
1948
  subscriber._errorNode = ownerNode;
1948
- run();
1949
+ try {
1950
+ run();
1951
+ } catch (err) {
1952
+ subscriber._disposed = true;
1953
+ subscriber._errorNode = void 0;
1954
+ cleanup(subscriber);
1955
+ throw err;
1956
+ }
1949
1957
  return subscriber._dispose ?? (subscriber._dispose = () => {
1950
1958
  subscriber._disposed = true;
1951
1959
  subscriber._errorNode = void 0;
@@ -2177,7 +2185,7 @@ function forEachSubscriber(signal2, visit) {
2177
2185
 
2178
2186
  // src/reactivity/track.ts
2179
2187
  var _isDev4 = isDev();
2180
- var _runtimeVersion = true ? "4.0.0" : "dev";
2188
+ var _runtimeVersion = true ? "4.1.0" : "dev";
2181
2189
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
2182
2190
  function resolveReactiveApi() {
2183
2191
  const g2 = globalThis;
@@ -2400,9 +2408,9 @@ function toKebab(prop) {
2400
2408
  }
2401
2409
  function applyStyle(el, style2) {
2402
2410
  if (typeof style2 === "function") {
2403
- const teardown = track2(() => {
2411
+ const teardown = reactiveBinding2(() => {
2404
2412
  el.setAttribute("style", sanitizeStyleAttribute(String(style2())));
2405
- });
2413
+ }, el);
2406
2414
  registerDisposer(el, teardown);
2407
2415
  return;
2408
2416
  }
@@ -2416,9 +2424,9 @@ function applyStyle(el, style2) {
2416
2424
  const name = toKebab(prop);
2417
2425
  if (typeof val === "function") {
2418
2426
  const getter = val;
2419
- const teardown = track2(() => {
2427
+ const teardown = reactiveBinding2(() => {
2420
2428
  htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
2421
- });
2429
+ }, el);
2422
2430
  registerDisposer(el, teardown);
2423
2431
  } else {
2424
2432
  htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
@@ -2431,9 +2439,9 @@ function applyClass(el, cls) {
2431
2439
  return;
2432
2440
  }
2433
2441
  if (typeof cls === "function") {
2434
- const teardown = track2(() => {
2442
+ const teardown = reactiveBinding2(() => {
2435
2443
  el.setAttribute("class", cls());
2436
- });
2444
+ }, el);
2437
2445
  registerDisposer(el, teardown);
2438
2446
  return;
2439
2447
  }
@@ -2458,7 +2466,7 @@ function applyClass(el, cls) {
2458
2466
  }
2459
2467
  el.setAttribute("class", r);
2460
2468
  };
2461
- const teardown = track2(update);
2469
+ const teardown = reactiveBinding2(update, el);
2462
2470
  registerDisposer(el, teardown);
2463
2471
  } else {
2464
2472
  el.setAttribute("class", result);
@@ -3432,6 +3440,17 @@ function signal(initial, options) {
3432
3440
  }
3433
3441
  return [get, set];
3434
3442
  }
3443
+ function external(options) {
3444
+ const [version, bump] = signal(0, options?.name ? { name: options.name } : void 0);
3445
+ return {
3446
+ track() {
3447
+ version();
3448
+ },
3449
+ invalidate() {
3450
+ bump((n) => n + 1);
3451
+ }
3452
+ };
3453
+ }
3435
3454
 
3436
3455
  // src/components/ErrorDisplay.ts
3437
3456
  var STYLES = `
@@ -5996,6 +6015,7 @@ function drainTeardowns(teardowns, label2) {
5996
6015
  }
5997
6016
  }
5998
6017
  }
6018
+ var EACH_KEYS = ["text", "attr", "class", "show", "on", "cleanup"];
5999
6019
  function resolveTarget(root, target) {
6000
6020
  if (target == null) return root;
6001
6021
  if (typeof target !== "string") return target;
@@ -6006,6 +6026,11 @@ function resolveTarget(root, target) {
6006
6026
  return null;
6007
6027
  }
6008
6028
  }
6029
+ function bindNode(el, commit) {
6030
+ if (isSSR()) return () => {
6031
+ };
6032
+ return reactiveBinding2(commit, el);
6033
+ }
6009
6034
  function readControlValue(el) {
6010
6035
  if (el instanceof HTMLInputElement) {
6011
6036
  if (el.type === "checkbox") return el.checked;
@@ -6029,6 +6054,50 @@ function writeControlValue(el, value) {
6029
6054
  const next = value == null ? "" : String(value);
6030
6055
  if (el.value !== next) el.value = next;
6031
6056
  }
6057
+ function applyEachBindings(ctx, el, spec, index) {
6058
+ const where = `ctx.each[${index}]`;
6059
+ if (isDev()) {
6060
+ for (const key of Object.keys(spec)) {
6061
+ devAssert(
6062
+ EACH_KEYS.includes(key),
6063
+ `${where}: unknown binding "${key}". Expected one of: ${EACH_KEYS.join(", ")}.`
6064
+ );
6065
+ }
6066
+ }
6067
+ if (spec.text !== void 0) {
6068
+ devAssert(typeof spec.text === "function", `${where}: "text" must be a function returning the value.`);
6069
+ ctx.text(el, spec.text);
6070
+ }
6071
+ if (spec.attr !== void 0) {
6072
+ for (const name of Object.keys(spec.attr)) {
6073
+ const value = spec.attr[name];
6074
+ devAssert(typeof value === "function", `${where}: attr["${name}"] must be a function returning the value.`);
6075
+ ctx.attr(el, name, value);
6076
+ }
6077
+ }
6078
+ if (spec.class !== void 0) {
6079
+ for (const name of Object.keys(spec.class)) {
6080
+ const on2 = spec.class[name];
6081
+ devAssert(typeof on2 === "function", `${where}: class["${name}"] must be a function returning a boolean.`);
6082
+ ctx.classed(el, name, on2);
6083
+ }
6084
+ }
6085
+ if (spec.show !== void 0) {
6086
+ devAssert(typeof spec.show === "function", `${where}: "show" must be a function returning a boolean.`);
6087
+ ctx.show(el, spec.show);
6088
+ }
6089
+ if (spec.on !== void 0) {
6090
+ for (const event of Object.keys(spec.on)) {
6091
+ const handler = spec.on[event];
6092
+ devAssert(typeof handler === "function", `${where}: on["${String(event)}"] must be a function.`);
6093
+ ctx.on(el, event, handler);
6094
+ }
6095
+ }
6096
+ if (spec.cleanup !== void 0) {
6097
+ devAssert(typeof spec.cleanup === "function", `${where}: "cleanup" must be a function.`);
6098
+ ctx.cleanup(spec.cleanup);
6099
+ }
6100
+ }
6032
6101
  function enhance(target, setup) {
6033
6102
  const root = typeof target === "string" ? typeof document !== "undefined" ? document.querySelector(target) : null : target;
6034
6103
  if (!root) {
@@ -6079,7 +6148,7 @@ function enhance(target, setup) {
6079
6148
  text: (t, value) => {
6080
6149
  bind(t, (el) => {
6081
6150
  teardowns.push(
6082
- effect(() => {
6151
+ bindNode(el, () => {
6083
6152
  const v = value();
6084
6153
  const next = v == null ? "" : String(v);
6085
6154
  if (el.textContent !== next) el.textContent = next;
@@ -6090,7 +6159,7 @@ function enhance(target, setup) {
6090
6159
  attr: (t, name, value) => {
6091
6160
  bind(t, (el) => {
6092
6161
  teardowns.push(
6093
- effect(() => {
6162
+ bindNode(el, () => {
6094
6163
  const v = value();
6095
6164
  const next = v == null ? null : String(v);
6096
6165
  setSafeAttribute(el, name, next, { syncValueProperty: false, label: "enhance attr()" });
@@ -6101,7 +6170,7 @@ function enhance(target, setup) {
6101
6170
  classed: (t, name, on2) => {
6102
6171
  bind(t, (el) => {
6103
6172
  teardowns.push(
6104
- effect(() => {
6173
+ bindNode(el, () => {
6105
6174
  el.classList.toggle(name, Boolean(on2()));
6106
6175
  })
6107
6176
  );
@@ -6111,7 +6180,7 @@ function enhance(target, setup) {
6111
6180
  bind(t, (el) => {
6112
6181
  const prevHidden = el.hidden;
6113
6182
  teardowns.push(
6114
- effect(() => {
6183
+ bindNode(el, () => {
6115
6184
  el.hidden = !when2();
6116
6185
  })
6117
6186
  );
@@ -6126,7 +6195,7 @@ function enhance(target, setup) {
6126
6195
  const [get, set] = state2;
6127
6196
  const evt = options?.event ?? (control instanceof HTMLSelectElement || control instanceof HTMLInputElement && (control.type === "checkbox" || control.type === "radio") ? "change" : "input");
6128
6197
  teardowns.push(
6129
- effect(() => {
6198
+ bindNode(el, () => {
6130
6199
  writeControlValue(control, get());
6131
6200
  })
6132
6201
  );
@@ -6135,6 +6204,16 @@ function enhance(target, setup) {
6135
6204
  teardowns.push(() => control.removeEventListener(evt, onInput));
6136
6205
  });
6137
6206
  },
6207
+ each: (target_, describe2) => {
6208
+ devAssert(typeof describe2 === "function", "ctx.each: second argument must be a function.");
6209
+ const elements = typeof target_ === "string" ? ctx.refs(target_) : Array.from(target_);
6210
+ for (let i2 = 0; i2 < elements.length; i2++) {
6211
+ const el = elements[i2];
6212
+ const spec = describe2(el, i2);
6213
+ if (spec == null) continue;
6214
+ applyEachBindings(ctx, el, spec, i2);
6215
+ }
6216
+ },
6138
6217
  cleanup: (fn) => {
6139
6218
  teardowns.push(fn);
6140
6219
  }
package/dist/build.js CHANGED
@@ -1,21 +1,21 @@
1
1
  import {
2
2
  index_exports
3
- } from "./chunk-GCSGGA3Q.js";
4
- import "./chunk-ES2GERY2.js";
3
+ } from "./chunk-ANGSYNPX.js";
4
+ import "./chunk-MRAMKDHQ.js";
5
5
  import "./chunk-HYCCIYNS.js";
6
- import "./chunk-RRIDJQ5C.js";
6
+ import "./chunk-KSOEJGFO.js";
7
7
  import "./chunk-CCSJMTRN.js";
8
- import "./chunk-O3QQ3XOL.js";
9
- import "./chunk-DQVUBVNX.js";
10
- import "./chunk-4MFZMLUU.js";
11
- import "./chunk-Z2CE42DB.js";
8
+ import "./chunk-5GJ5RTHA.js";
9
+ import "./chunk-I3VI34DP.js";
10
+ import "./chunk-SHDVWATN.js";
11
+ import "./chunk-DCDS2PQ6.js";
12
12
  import "./chunk-5INI7D2L.js";
13
13
  import "./chunk-7ZHH77QA.js";
14
- import "./chunk-PBQEW5VW.js";
14
+ import "./chunk-PFTDGEPZ.js";
15
15
  import "./chunk-TIRZCERI.js";
16
16
  import "./chunk-DHDZ7IVN.js";
17
- import "./chunk-W55YHPEP.js";
18
- import "./chunk-ACBT6UZS.js";
17
+ import "./chunk-UFSQEO7P.js";
18
+ import "./chunk-D3SZ4LVS.js";
19
19
  import "./chunk-VPP2FONR.js";
20
20
 
21
21
  // src/build/compileTemplates.ts