sibujs 3.0.0 → 3.2.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 (78) hide show
  1. package/README.md +6 -0
  2. package/dist/browser.cjs +16 -8
  3. package/dist/browser.js +6 -5
  4. package/dist/build.cjs +276 -150
  5. package/dist/build.js +35 -24
  6. package/dist/cdn.global.js +7 -7
  7. package/dist/{chunk-RJIRT46U.js → chunk-2C4E3HBM.js} +5 -5
  8. package/dist/{chunk-XDKP4T7G.js → chunk-4JCAUOLN.js} +45 -23
  9. package/dist/{chunk-VSNLICTS.js → chunk-5N74TKLD.js} +1 -1
  10. package/dist/{chunk-XVYB3J6C.js → chunk-7XDYVJLE.js} +19 -9
  11. package/dist/{chunk-L52H775O.js → chunk-BGNLPNGV.js} +20 -12
  12. package/dist/{chunk-6QZO7MMG.js → chunk-C427DVQF.js} +1 -1
  13. package/dist/{chunk-5WD7BYTZ.js → chunk-FDY42FIU.js} +3 -2
  14. package/dist/{chunk-4YTVESDX.js → chunk-FOI23UJL.js} +11 -1
  15. package/dist/{chunk-2RA7SHDA.js → chunk-GOJMFRBL.js} +20 -4
  16. package/dist/{chunk-2KM2724A.js → chunk-GOUM4JCT.js} +6 -6
  17. package/dist/chunk-H3SRKIYX.js +17 -0
  18. package/dist/{chunk-NEWH4O5U.js → chunk-H6PCHJZQ.js} +2 -2
  19. package/dist/{chunk-UCS6AMJ7.js → chunk-HMJFCBRR.js} +26 -3
  20. package/dist/{chunk-JYD2PWXH.js → chunk-HXMS4SNP.js} +22 -15
  21. package/dist/{chunk-DF3GTP4Q.js → chunk-JYXOEYI4.js} +12 -18
  22. package/dist/{chunk-KZA7ANXP.js → chunk-NFYWLRUO.js} +11 -18
  23. package/dist/{chunk-KH4OE6WY.js → chunk-NPIEEKPT.js} +20 -11
  24. package/dist/{chunk-V65KTDZW.js → chunk-OYLPZO4N.js} +33 -15
  25. package/dist/{chunk-LYTCUZ7H.js → chunk-RDRSWYNP.js} +1 -1
  26. package/dist/{chunk-UKMXT5T6.js → chunk-RLUJL2MV.js} +7 -12
  27. package/dist/{chunk-INBOWHQ3.js → chunk-V2MTG5FT.js} +99 -36
  28. package/dist/{chunk-CNZ35WI2.js → chunk-VJE6DDYM.js} +2 -2
  29. package/dist/{chunk-2JQUV4Y3.js → chunk-VOCE4NNK.js} +157 -75
  30. package/dist/{chunk-STFTTMO2.js → chunk-X67UYC74.js} +31 -12
  31. package/dist/{chunk-YMOIAHWA.js → chunk-YFDGQWDA.js} +1 -1
  32. package/dist/{chunk-L4DAT4WU.js → chunk-Z2FWAE4B.js} +28 -1
  33. package/dist/data.cjs +211 -93
  34. package/dist/data.d.cts +7 -1
  35. package/dist/data.d.ts +7 -1
  36. package/dist/data.js +8 -8
  37. package/dist/devtools.cjs +38 -10
  38. package/dist/devtools.d.cts +1 -1
  39. package/dist/devtools.d.ts +1 -1
  40. package/dist/devtools.js +6 -6
  41. package/dist/ecosystem.cjs +163 -65
  42. package/dist/ecosystem.js +9 -9
  43. package/dist/extras.cjs +420 -198
  44. package/dist/extras.d.cts +2 -2
  45. package/dist/extras.d.ts +2 -2
  46. package/dist/extras.js +27 -24
  47. package/dist/index.cjs +255 -139
  48. package/dist/index.d.cts +15 -2
  49. package/dist/index.d.ts +15 -2
  50. package/dist/index.js +15 -13
  51. package/dist/{introspect-BZWKvQUZ.d.ts → introspect-DOZfmC-4.d.ts} +1 -1
  52. package/dist/{introspect-DsJlDD2T.d.cts → introspect-RjLfIFpL.d.cts} +1 -1
  53. package/dist/motion.cjs +10 -0
  54. package/dist/motion.js +3 -3
  55. package/dist/patterns.cjs +66 -39
  56. package/dist/patterns.js +8 -7
  57. package/dist/performance.cjs +101 -25
  58. package/dist/performance.d.cts +2 -2
  59. package/dist/performance.d.ts +2 -2
  60. package/dist/performance.js +8 -7
  61. package/dist/plugins.cjs +243 -138
  62. package/dist/plugins.d.cts +1 -1
  63. package/dist/plugins.d.ts +1 -1
  64. package/dist/plugins.js +96 -45
  65. package/dist/{ssr-FXD2PPMC.js → ssr-2QDQ27EV.js} +5 -3
  66. package/dist/{ssr-CrVNy6Pa.d.cts → ssr-D62yFwuw.d.cts} +8 -1
  67. package/dist/{ssr-CrVNy6Pa.d.ts → ssr-D62yFwuw.d.ts} +8 -1
  68. package/dist/ssr.cjs +185 -68
  69. package/dist/ssr.d.cts +1 -1
  70. package/dist/ssr.d.ts +1 -1
  71. package/dist/ssr.js +12 -10
  72. package/dist/testing.cjs +9 -4
  73. package/dist/testing.js +3 -3
  74. package/dist/ui.cjs +76 -39
  75. package/dist/ui.js +10 -9
  76. package/dist/widgets.cjs +61 -23
  77. package/dist/widgets.js +8 -8
  78. package/package.json +3 -1
package/dist/ui.cjs CHANGED
@@ -230,7 +230,7 @@ function retrack(effectFn, subscriber) {
230
230
  }
231
231
  }
232
232
  function track(effectFn, subscriber) {
233
- if (!subscriber) subscriber = effectFn;
233
+ if (!subscriber) return reactiveBinding(effectFn);
234
234
  cleanup(subscriber);
235
235
  const prev = currentSubscriber;
236
236
  currentSubscriber = subscriber;
@@ -248,6 +248,32 @@ function track(effectFn, subscriber) {
248
248
  const sub = subscriber;
249
249
  return sub._dispose ?? (sub._dispose = () => cleanup(subscriber));
250
250
  }
251
+ function reactiveBinding(commit) {
252
+ const run = () => {
253
+ const s = subscriber;
254
+ if (s._disposed || s._reentrant) return;
255
+ s._reentrant = true;
256
+ try {
257
+ retrack(commit, subscriber);
258
+ } finally {
259
+ s._reentrant = false;
260
+ }
261
+ };
262
+ const subscriber = run;
263
+ subscriber.depsHead = null;
264
+ subscriber.depsTail = null;
265
+ subscriber._epoch = 0;
266
+ subscriber._structDirty = false;
267
+ subscriber._runEpoch = 0;
268
+ subscriber._runs = 0;
269
+ subscriber._reentrant = false;
270
+ subscriber._disposed = false;
271
+ run();
272
+ return subscriber._dispose ?? (subscriber._dispose = () => {
273
+ subscriber._disposed = true;
274
+ cleanup(subscriber);
275
+ });
276
+ }
251
277
  function recordDependency(signal2) {
252
278
  if (!currentSubscriber) return;
253
279
  const sub = currentSubscriber;
@@ -406,6 +432,7 @@ function derived(getter, options) {
406
432
  const equals = options?.equals;
407
433
  const cs = {};
408
434
  cs._d = false;
435
+ cs._init = false;
409
436
  cs._g = getter;
410
437
  cs.__v = 0;
411
438
  const markDirty = () => {
@@ -414,11 +441,18 @@ function derived(getter, options) {
414
441
  };
415
442
  markDirty._c = 1;
416
443
  markDirty._sig = cs;
444
+ const recompute = () => {
445
+ const next = getter();
446
+ cs._v = equals && cs._init ? equals(cs._v, next) ? cs._v : next : next;
447
+ cs._d = false;
448
+ cs._init = true;
449
+ };
417
450
  track(() => {
418
451
  let threw = true;
419
452
  try {
420
453
  cs._v = getter();
421
454
  cs._d = false;
455
+ cs._init = true;
422
456
  threw = false;
423
457
  } finally {
424
458
  if (threw) cs._d = true;
@@ -434,20 +468,13 @@ function derived(getter, options) {
434
468
  }
435
469
  if (trackingSuspended) {
436
470
  if (cs._d) {
471
+ const prev = cs._v;
437
472
  evaluating = true;
438
- let threw = true;
439
473
  try {
440
- const prev = cs._v;
441
- retrack(() => {
442
- const next = getter();
443
- cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
444
- cs._d = false;
445
- threw = false;
446
- }, markDirty);
474
+ retrack(recompute, markDirty);
447
475
  if (!Object.is(prev, cs._v)) cs.__v++;
448
476
  } finally {
449
477
  evaluating = false;
450
- if (threw) cs._d = true;
451
478
  }
452
479
  }
453
480
  return cs._v;
@@ -456,18 +483,11 @@ function derived(getter, options) {
456
483
  if (cs._d) {
457
484
  const oldValue = cs._v;
458
485
  evaluating = true;
459
- let threw = true;
460
486
  try {
461
- retrack(() => {
462
- const next = getter();
463
- cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
464
- cs._d = false;
465
- threw = false;
466
- }, markDirty);
487
+ retrack(recompute, markDirty);
467
488
  if (!Object.is(oldValue, cs._v)) cs.__v++;
468
489
  } finally {
469
490
  evaluating = false;
470
- if (threw) cs._d = true;
471
491
  }
472
492
  if (hook && oldValue !== cs._v) {
473
493
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
@@ -861,11 +881,15 @@ function dispose(node) {
861
881
  var als = null;
862
882
  try {
863
883
  if (typeof process !== "undefined" && process.versions && process.versions.node) {
864
- const req = Function("return typeof require==='function'?require:null")();
865
- if (req) {
866
- const mod = req("node:async_hooks");
867
- als = new mod.AsyncLocalStorage();
884
+ let mod = null;
885
+ const getBuiltin = process.getBuiltinModule;
886
+ if (typeof getBuiltin === "function") {
887
+ mod = getBuiltin("node:async_hooks");
888
+ } else {
889
+ const req = Function("return typeof require==='function'?require:null")();
890
+ if (req) mod = req("node:async_hooks");
868
891
  }
892
+ if (mod) als = new mod.AsyncLocalStorage();
869
893
  }
870
894
  } catch {
871
895
  als = null;
@@ -967,6 +991,7 @@ function effect(effectFn, options) {
967
991
  ctx.fn(ctx.onCleanup);
968
992
  };
969
993
  const sub = (() => {
994
+ if (ctx.disposed) return;
970
995
  if (ctx.running) {
971
996
  ctx.rerunPending = true;
972
997
  return;
@@ -1031,7 +1056,10 @@ function VirtualList(props) {
1031
1056
  const visibleCount = Math.ceil(props.containerHeight / props.itemHeight) + 2 * overscan;
1032
1057
  const endIndex = Math.min(items.length, startIndex + visibleCount);
1033
1058
  content.style.top = `${startIndex * props.itemHeight}px`;
1034
- content.innerHTML = "";
1059
+ while (content.firstChild) {
1060
+ dispose(content.firstChild);
1061
+ content.removeChild(content.firstChild);
1062
+ }
1035
1063
  for (let i = startIndex; i < endIndex; i++) {
1036
1064
  const itemEl = props.renderItem(items[i], i);
1037
1065
  itemEl.style.height = `${props.itemHeight}px`;
@@ -1039,7 +1067,7 @@ function VirtualList(props) {
1039
1067
  content.appendChild(itemEl);
1040
1068
  }
1041
1069
  };
1042
- effect(update);
1070
+ registerDisposer(container, effect(update));
1043
1071
  return container;
1044
1072
  }
1045
1073
 
@@ -1180,7 +1208,10 @@ function inputMask(options) {
1180
1208
  }
1181
1209
  }
1182
1210
  }
1183
- input.setSelectionRange(newCursor, newCursor);
1211
+ try {
1212
+ input.setSelectionRange(newCursor, newCursor);
1213
+ } catch {
1214
+ }
1184
1215
  };
1185
1216
  const onFocus = () => {
1186
1217
  if (!input.value) {
@@ -1222,9 +1253,12 @@ function aria(element, attrs) {
1222
1253
  const ariaKey = key.startsWith("aria-") ? key : `aria-${key}`;
1223
1254
  if (typeof value === "function") {
1224
1255
  const getter = value;
1225
- track(() => {
1226
- element.setAttribute(ariaKey, String(getter()));
1227
- });
1256
+ registerDisposer(
1257
+ element,
1258
+ track(() => {
1259
+ element.setAttribute(ariaKey, String(getter()));
1260
+ })
1261
+ );
1228
1262
  } else {
1229
1263
  element.setAttribute(ariaKey, String(value));
1230
1264
  }
@@ -1487,6 +1521,7 @@ function createListbox(container, options = {}) {
1487
1521
  const opts = Array.from(container.querySelectorAll(optionSelector));
1488
1522
  for (const opt of opts) {
1489
1523
  if (!opt.id) opt.id = createId("listbox-option");
1524
+ if (!opt.hasAttribute("aria-selected")) opt.setAttribute("aria-selected", "false");
1490
1525
  }
1491
1526
  }
1492
1527
  stampIds();
@@ -1677,9 +1712,17 @@ function removeScopedStyle(scopeId) {
1677
1712
  }
1678
1713
 
1679
1714
  // src/utils/sanitize.ts
1715
+ function stripControlChars(value) {
1716
+ return value.replace(/[\x00-\x20\x7f-\x9f]+/g, "");
1717
+ }
1718
+ function isEventHandlerAttr(name) {
1719
+ if (name.length < 3) return false;
1720
+ const lower = name.toLowerCase();
1721
+ return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
1722
+ }
1680
1723
  var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
1681
1724
  function sanitizeUrl(url) {
1682
- const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
1725
+ const trimmed = stripControlChars(url).trim();
1683
1726
  if (!trimmed) return "";
1684
1727
  const lower = trimmed.toLowerCase();
1685
1728
  let schemeEnd = -1;
@@ -1712,7 +1755,7 @@ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
1712
1755
  "data"
1713
1756
  ]);
1714
1757
  function isUrlAttribute(attr) {
1715
- return URL_ATTRIBUTES.has(attr);
1758
+ return URL_ATTRIBUTES.has(attr.toLowerCase());
1716
1759
  }
1717
1760
 
1718
1761
  // src/reactivity/bindAttribute.ts
@@ -1720,11 +1763,6 @@ var _isDev5 = isDev();
1720
1763
  function setProp(el, key, val) {
1721
1764
  el[key] = val;
1722
1765
  }
1723
- function isEventHandlerAttr(name) {
1724
- if (name.length < 3) return false;
1725
- const lower = name.toLowerCase();
1726
- return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
1727
- }
1728
1766
  function bindAttribute(el, attr, getter) {
1729
1767
  if (isEventHandlerAttr(attr)) {
1730
1768
  if (_isDev5)
@@ -1760,8 +1798,7 @@ function bindAttribute(el, attr, getter) {
1760
1798
  el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
1761
1799
  }
1762
1800
  }
1763
- const teardown = track(commit);
1764
- return teardown;
1801
+ return reactiveBinding(commit);
1765
1802
  }
1766
1803
 
1767
1804
  // src/ui/reactiveAttr.ts
@@ -2302,7 +2339,7 @@ function withBoundary(name, component) {
2302
2339
  function createSlots(slots) {
2303
2340
  return {
2304
2341
  renderSlot(name, fallback) {
2305
- const slotFn = slots[name];
2342
+ const slotFn = Object.hasOwn(slots, name) ? slots[name] : void 0;
2306
2343
  if (slotFn) {
2307
2344
  const result = slotFn();
2308
2345
  if (Array.isArray(result)) {
@@ -2316,7 +2353,7 @@ function createSlots(slots) {
2316
2353
  return fallback ? fallback() : null;
2317
2354
  },
2318
2355
  hasSlot(name) {
2319
- return name in slots;
2356
+ return Object.hasOwn(slots, name);
2320
2357
  }
2321
2358
  };
2322
2359
  }
package/dist/ui.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  toast,
39
39
  withScopedStyle,
40
40
  zipMask
41
- } from "./chunk-KH4OE6WY.js";
41
+ } from "./chunk-NPIEEKPT.js";
42
42
  import {
43
43
  RenderProp,
44
44
  assertType,
@@ -54,24 +54,24 @@ import {
54
54
  withDefaults,
55
55
  withProps,
56
56
  withWrapper
57
- } from "./chunk-CNZ35WI2.js";
57
+ } from "./chunk-VJE6DDYM.js";
58
58
  import {
59
59
  createId
60
60
  } from "./chunk-YT6HQ6AM.js";
61
- import "./chunk-UKMXT5T6.js";
62
- import "./chunk-DF3GTP4Q.js";
61
+ import "./chunk-RLUJL2MV.js";
62
+ import "./chunk-JYXOEYI4.js";
63
63
  import {
64
64
  registerDisposer
65
65
  } from "./chunk-2UPRY23K.js";
66
- import "./chunk-UCS6AMJ7.js";
66
+ import "./chunk-HMJFCBRR.js";
67
67
  import {
68
68
  effect
69
- } from "./chunk-5WD7BYTZ.js";
70
- import "./chunk-2RA7SHDA.js";
69
+ } from "./chunk-FDY42FIU.js";
70
+ import "./chunk-GOJMFRBL.js";
71
71
  import {
72
72
  signal
73
- } from "./chunk-6QZO7MMG.js";
74
- import "./chunk-L4DAT4WU.js";
73
+ } from "./chunk-C427DVQF.js";
74
+ import "./chunk-Z2FWAE4B.js";
75
75
  import "./chunk-LMLD24FC.js";
76
76
 
77
77
  // src/ui/formAction.ts
@@ -170,6 +170,7 @@ function createListbox(container, options = {}) {
170
170
  const opts = Array.from(container.querySelectorAll(optionSelector));
171
171
  for (const opt of opts) {
172
172
  if (!opt.id) opt.id = createId("listbox-option");
173
+ if (!opt.hasAttribute("aria-selected")) opt.setAttribute("aria-selected", "false");
173
174
  }
174
175
  }
175
176
  stampIds();
package/dist/widgets.cjs CHANGED
@@ -177,7 +177,7 @@ function retrack(effectFn, subscriber) {
177
177
  }
178
178
  }
179
179
  function track(effectFn, subscriber) {
180
- if (!subscriber) subscriber = effectFn;
180
+ if (!subscriber) return reactiveBinding(effectFn);
181
181
  cleanup(subscriber);
182
182
  const prev = currentSubscriber;
183
183
  currentSubscriber = subscriber;
@@ -195,6 +195,32 @@ function track(effectFn, subscriber) {
195
195
  const sub = subscriber;
196
196
  return sub._dispose ?? (sub._dispose = () => cleanup(subscriber));
197
197
  }
198
+ function reactiveBinding(commit) {
199
+ const run = () => {
200
+ const s = subscriber;
201
+ if (s._disposed || s._reentrant) return;
202
+ s._reentrant = true;
203
+ try {
204
+ retrack(commit, subscriber);
205
+ } finally {
206
+ s._reentrant = false;
207
+ }
208
+ };
209
+ const subscriber = run;
210
+ subscriber.depsHead = null;
211
+ subscriber.depsTail = null;
212
+ subscriber._epoch = 0;
213
+ subscriber._structDirty = false;
214
+ subscriber._runEpoch = 0;
215
+ subscriber._runs = 0;
216
+ subscriber._reentrant = false;
217
+ subscriber._disposed = false;
218
+ run();
219
+ return subscriber._dispose ?? (subscriber._dispose = () => {
220
+ subscriber._disposed = true;
221
+ cleanup(subscriber);
222
+ });
223
+ }
198
224
  function recordDependency(signal2) {
199
225
  if (!currentSubscriber) return;
200
226
  const sub = currentSubscriber;
@@ -383,6 +409,7 @@ function derived(getter, options) {
383
409
  const equals = options?.equals;
384
410
  const cs = {};
385
411
  cs._d = false;
412
+ cs._init = false;
386
413
  cs._g = getter;
387
414
  cs.__v = 0;
388
415
  const markDirty = () => {
@@ -391,11 +418,18 @@ function derived(getter, options) {
391
418
  };
392
419
  markDirty._c = 1;
393
420
  markDirty._sig = cs;
421
+ const recompute = () => {
422
+ const next = getter();
423
+ cs._v = equals && cs._init ? equals(cs._v, next) ? cs._v : next : next;
424
+ cs._d = false;
425
+ cs._init = true;
426
+ };
394
427
  track(() => {
395
428
  let threw = true;
396
429
  try {
397
430
  cs._v = getter();
398
431
  cs._d = false;
432
+ cs._init = true;
399
433
  threw = false;
400
434
  } finally {
401
435
  if (threw) cs._d = true;
@@ -411,20 +445,13 @@ function derived(getter, options) {
411
445
  }
412
446
  if (trackingSuspended) {
413
447
  if (cs._d) {
448
+ const prev = cs._v;
414
449
  evaluating = true;
415
- let threw = true;
416
450
  try {
417
- const prev = cs._v;
418
- retrack(() => {
419
- const next = getter();
420
- cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
421
- cs._d = false;
422
- threw = false;
423
- }, markDirty);
451
+ retrack(recompute, markDirty);
424
452
  if (!Object.is(prev, cs._v)) cs.__v++;
425
453
  } finally {
426
454
  evaluating = false;
427
- if (threw) cs._d = true;
428
455
  }
429
456
  }
430
457
  return cs._v;
@@ -433,18 +460,11 @@ function derived(getter, options) {
433
460
  if (cs._d) {
434
461
  const oldValue = cs._v;
435
462
  evaluating = true;
436
- let threw = true;
437
463
  try {
438
- retrack(() => {
439
- const next = getter();
440
- cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
441
- cs._d = false;
442
- threw = false;
443
- }, markDirty);
464
+ retrack(recompute, markDirty);
444
465
  if (!Object.is(oldValue, cs._v)) cs.__v++;
445
466
  } finally {
446
467
  evaluating = false;
447
- if (threw) cs._d = true;
448
468
  }
449
469
  if (hook && oldValue !== cs._v) {
450
470
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
@@ -465,11 +485,15 @@ function derived(getter, options) {
465
485
  var als = null;
466
486
  try {
467
487
  if (typeof process !== "undefined" && process.versions && process.versions.node) {
468
- const req = Function("return typeof require==='function'?require:null")();
469
- if (req) {
470
- const mod = req("node:async_hooks");
471
- als = new mod.AsyncLocalStorage();
488
+ let mod = null;
489
+ const getBuiltin = process.getBuiltinModule;
490
+ if (typeof getBuiltin === "function") {
491
+ mod = getBuiltin("node:async_hooks");
492
+ } else {
493
+ const req = Function("return typeof require==='function'?require:null")();
494
+ if (req) mod = req("node:async_hooks");
472
495
  }
496
+ if (mod) als = new mod.AsyncLocalStorage();
473
497
  }
474
498
  } catch {
475
499
  als = null;
@@ -571,6 +595,7 @@ function effect(effectFn, options) {
571
595
  ctx.fn(ctx.onCleanup);
572
596
  };
573
597
  const sub = (() => {
598
+ if (ctx.disposed) return;
574
599
  if (ctx.running) {
575
600
  ctx.rerunPending = true;
576
601
  return;
@@ -1750,7 +1775,20 @@ function fileUpload(options) {
1750
1775
 
1751
1776
  // src/utils/sanitize.ts
1752
1777
  function stripHtml(html) {
1753
- return String(html).replace(/<[^>]*>/g, "");
1778
+ const input = String(html);
1779
+ if (typeof DOMParser !== "undefined") {
1780
+ try {
1781
+ return new DOMParser().parseFromString(input, "text/html").body.textContent ?? "";
1782
+ } catch {
1783
+ }
1784
+ }
1785
+ let prev;
1786
+ let out = input;
1787
+ do {
1788
+ prev = out;
1789
+ out = out.replace(/<[^>]*>/g, "");
1790
+ } while (out !== prev);
1791
+ return out.replace(/<[^>]*$/, "");
1754
1792
  }
1755
1793
 
1756
1794
  // src/widgets/contentEditable.ts
package/dist/widgets.js CHANGED
@@ -8,14 +8,14 @@ import {
8
8
  select,
9
9
  tabs,
10
10
  tooltip
11
- } from "./chunk-RJIRT46U.js";
12
- import "./chunk-NEWH4O5U.js";
13
- import "./chunk-DF3GTP4Q.js";
14
- import "./chunk-UCS6AMJ7.js";
15
- import "./chunk-5WD7BYTZ.js";
16
- import "./chunk-2RA7SHDA.js";
17
- import "./chunk-6QZO7MMG.js";
18
- import "./chunk-L4DAT4WU.js";
11
+ } from "./chunk-2C4E3HBM.js";
12
+ import "./chunk-H6PCHJZQ.js";
13
+ import "./chunk-JYXOEYI4.js";
14
+ import "./chunk-HMJFCBRR.js";
15
+ import "./chunk-FDY42FIU.js";
16
+ import "./chunk-GOJMFRBL.js";
17
+ import "./chunk-C427DVQF.js";
18
+ import "./chunk-Z2FWAE4B.js";
19
19
  import "./chunk-LMLD24FC.js";
20
20
  export {
21
21
  accordion,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sibujs",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "A lightweight, function-based frontend framework that combines the best of React, Svelte, and Vue — with zero VDOM and maximum simplicity. Designed for developers who want fine-grained reactivity and full control without compilation or magic.",
5
5
  "keywords": [
6
6
  "frontend",
@@ -136,7 +136,9 @@
136
136
  "devDependencies": {
137
137
  "@biomejs/biome": "2.4.7",
138
138
  "@types/node": "^25.5.0",
139
+ "@vitest/coverage-v8": "^3.1.3",
139
140
  "@vitest/ui": "^3.1.3",
141
+ "fake-indexeddb": "^6.2.5",
140
142
  "jsdom": "^26.1.0",
141
143
  "tsup": "^8.5.1",
142
144
  "typescript": "^5.8.3",