sibujs 3.1.0 → 3.2.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 (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 +235 -147
  5. package/dist/build.js +35 -24
  6. package/dist/cdn.global.js +7 -7
  7. package/dist/{chunk-WYU7CYJ3.js → chunk-2C4E3HBM.js} +5 -5
  8. package/dist/{chunk-3DYB5B3S.js → chunk-4JCAUOLN.js} +45 -23
  9. package/dist/{chunk-2HAGQWDV.js → chunk-5N74TKLD.js} +1 -1
  10. package/dist/{chunk-SVVAUX7J.js → chunk-7XDYVJLE.js} +19 -9
  11. package/dist/{chunk-2N2UL7O4.js → chunk-BGNLPNGV.js} +20 -12
  12. package/dist/{chunk-RK4BQG25.js → chunk-C427DVQF.js} +1 -1
  13. package/dist/{chunk-ZIBE2SAT.js → chunk-FDY42FIU.js} +3 -2
  14. package/dist/{chunk-GQ7RRFPU.js → chunk-FOI23UJL.js} +11 -1
  15. package/dist/{chunk-2RA7SHDA.js → chunk-GOJMFRBL.js} +20 -4
  16. package/dist/{chunk-IVOUCSZL.js → chunk-GOUM4JCT.js} +6 -6
  17. package/dist/chunk-H3SRKIYX.js +17 -0
  18. package/dist/{chunk-3DJH25UO.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-SC437AMI.js → chunk-JYXOEYI4.js} +12 -18
  22. package/dist/{chunk-KB3BA2XK.js → chunk-NFYWLRUO.js} +11 -18
  23. package/dist/{chunk-QNQY5DUS.js → chunk-NPIEEKPT.js} +20 -11
  24. package/dist/{chunk-UYX2NDOH.js → chunk-OYLPZO4N.js} +33 -15
  25. package/dist/{chunk-LYTCUZ7H.js → chunk-RDRSWYNP.js} +1 -1
  26. package/dist/{chunk-2ZJ7TSW4.js → chunk-RLUJL2MV.js} +4 -8
  27. package/dist/{chunk-CR4MXPHB.js → chunk-V2MTG5FT.js} +99 -36
  28. package/dist/{chunk-CNZ35WI2.js → chunk-VJE6DDYM.js} +2 -2
  29. package/dist/{chunk-PMSDFTK3.js → chunk-VOCE4NNK.js} +157 -75
  30. package/dist/{chunk-WKUXSE7V.js → chunk-X67UYC74.js} +12 -11
  31. package/dist/{chunk-EFOAE5NC.js → chunk-YFDGQWDA.js} +1 -1
  32. package/dist/{chunk-3U4ZVXVD.js → chunk-Z2FWAE4B.js} +6 -2
  33. package/dist/data.cjs +190 -94
  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 +123 -63
  42. package/dist/ecosystem.js +9 -9
  43. package/dist/extras.cjs +380 -196
  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 +214 -136
  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 +45 -40
  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 +234 -160
  62. package/dist/plugins.d.cts +1 -1
  63. package/dist/plugins.d.ts +1 -1
  64. package/dist/plugins.js +127 -69
  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 +145 -66
  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 +54 -38
  75. package/dist/ui.js +10 -9
  76. package/dist/widgets.cjs +40 -24
  77. package/dist/widgets.js +8 -8
  78. package/package.json +3 -1
package/dist/data.d.ts CHANGED
@@ -133,7 +133,7 @@ interface MutationResult<TData, TVariables> {
133
133
  /** Reset state to idle */
134
134
  reset: () => void;
135
135
  }
136
- declare function mutation<TData, TVariables = void, TContext = unknown>(mutationFn: (variables: TVariables) => Promise<TData>, options?: MutationOptions<TData, TVariables, TContext>): MutationResult<TData, TVariables>;
136
+ declare function mutation<TData, TVariables = void, TContext = unknown>(mutationFn: (variables: TVariables, signal?: AbortSignal) => Promise<TData>, options?: MutationOptions<TData, TVariables, TContext>): MutationResult<TData, TVariables>;
137
137
 
138
138
  interface InfiniteQueryOptions<TData, TPageParam = number> {
139
139
  /** Get the param for the next page. Return undefined to signal end. */
@@ -142,6 +142,12 @@ interface InfiniteQueryOptions<TData, TPageParam = number> {
142
142
  getPreviousPageParam?: (firstPage: TData, allPages: TData[]) => TPageParam | undefined;
143
143
  /** Initial page param. Default: 0 (for number) */
144
144
  initialPageParam?: TPageParam;
145
+ /**
146
+ * Maximum number of pages to retain. When exceeded, the oldest page is
147
+ * dropped from the opposite end (sliding window) to bound memory. Unset =
148
+ * unbounded.
149
+ */
150
+ maxPages?: number;
145
151
  /** Whether to fetch on creation. Default: true */
146
152
  enabled?: boolean;
147
153
  /** Retry options */
package/dist/data.js CHANGED
@@ -20,14 +20,14 @@ import {
20
20
  syncAdapter,
21
21
  throttle,
22
22
  withRetry
23
- } from "./chunk-PMSDFTK3.js";
24
- import "./chunk-EFOAE5NC.js";
25
- import "./chunk-SC437AMI.js";
26
- import "./chunk-UCS6AMJ7.js";
27
- import "./chunk-ZIBE2SAT.js";
28
- import "./chunk-2RA7SHDA.js";
29
- import "./chunk-RK4BQG25.js";
30
- import "./chunk-3U4ZVXVD.js";
23
+ } from "./chunk-VOCE4NNK.js";
24
+ import "./chunk-YFDGQWDA.js";
25
+ import "./chunk-JYXOEYI4.js";
26
+ import "./chunk-HMJFCBRR.js";
27
+ import "./chunk-FDY42FIU.js";
28
+ import "./chunk-GOJMFRBL.js";
29
+ import "./chunk-C427DVQF.js";
30
+ import "./chunk-Z2FWAE4B.js";
31
31
  import "./chunk-LMLD24FC.js";
32
32
  export {
33
33
  __resetQueryCache,
package/dist/devtools.cjs CHANGED
@@ -65,6 +65,7 @@ module.exports = __toCommonJS(devtools_exports);
65
65
  // src/devtools/debug.ts
66
66
  var debugEnabled = false;
67
67
  var perfMarks = /* @__PURE__ */ new Map();
68
+ var MAX_PERF_SAMPLES = 1e3;
68
69
  function enableDebug() {
69
70
  debugEnabled = true;
70
71
  console.log("[SibuJS] Debug mode enabled");
@@ -89,7 +90,11 @@ function perfTracker(label) {
89
90
  }
90
91
  function endMeasure() {
91
92
  const elapsed = globalThis.performance.now() - startTime;
92
- perfMarks.get(label)?.push(elapsed);
93
+ const marks = perfMarks.get(label);
94
+ if (marks) {
95
+ marks.push(elapsed);
96
+ if (marks.length > MAX_PERF_SAMPLES) marks.shift();
97
+ }
93
98
  if (debugEnabled) {
94
99
  debugLog("Perf", `${label}: ${elapsed.toFixed(2)}ms`);
95
100
  }
@@ -562,7 +567,20 @@ function signal(initial, options) {
562
567
 
563
568
  // src/utils/sanitize.ts
564
569
  function stripHtml(html) {
565
- return String(html).replace(/<[^>]*>/g, "");
570
+ const input = String(html);
571
+ if (typeof DOMParser !== "undefined") {
572
+ try {
573
+ return new DOMParser().parseFromString(input, "text/html").body.textContent ?? "";
574
+ } catch {
575
+ }
576
+ }
577
+ let prev;
578
+ let out = input;
579
+ do {
580
+ prev = out;
581
+ out = out.replace(/<[^>]*>/g, "");
582
+ } while (out !== prev);
583
+ return out.replace(/<[^>]*$/, "");
566
584
  }
567
585
 
568
586
  // src/devtools/devtools.ts
@@ -1494,7 +1512,7 @@ function withErrorTracking(name, component, reporter) {
1494
1512
  }
1495
1513
  };
1496
1514
  }
1497
- function formatError(error, context) {
1515
+ function formatError(error, context, seen = /* @__PURE__ */ new Set([error])) {
1498
1516
  const lines = [];
1499
1517
  const componentLabel = context?.component ?? (error instanceof SibuError ? error.component : void 0);
1500
1518
  if (componentLabel) {
@@ -1519,10 +1537,11 @@ function formatError(error, context) {
1519
1537
  lines.push(stackBody);
1520
1538
  }
1521
1539
  const cause = error.cause;
1522
- if (cause instanceof Error) {
1540
+ if (cause instanceof Error && !seen.has(cause)) {
1541
+ seen.add(cause);
1523
1542
  lines.push("");
1524
1543
  lines.push("Caused by:");
1525
- lines.push(formatError(cause));
1544
+ lines.push(formatError(cause, context, seen));
1526
1545
  }
1527
1546
  return lines.join("\n");
1528
1547
  }
@@ -1531,11 +1550,15 @@ function formatError(error, context) {
1531
1550
  var als = null;
1532
1551
  try {
1533
1552
  if (typeof process !== "undefined" && process.versions && process.versions.node) {
1534
- const req = Function("return typeof require==='function'?require:null")();
1535
- if (req) {
1536
- const mod = req("node:async_hooks");
1537
- als = new mod.AsyncLocalStorage();
1553
+ let mod = null;
1554
+ const getBuiltin = process.getBuiltinModule;
1555
+ if (typeof getBuiltin === "function") {
1556
+ mod = getBuiltin("node:async_hooks");
1557
+ } else {
1558
+ const req = Function("return typeof require==='function'?require:null")();
1559
+ if (req) mod = req("node:async_hooks");
1538
1560
  }
1561
+ if (mod) als = new mod.AsyncLocalStorage();
1539
1562
  }
1540
1563
  } catch {
1541
1564
  als = null;
@@ -1637,6 +1660,7 @@ function effect(effectFn, options) {
1637
1660
  ctx.fn(ctx.onCleanup);
1638
1661
  };
1639
1662
  const sub = (() => {
1663
+ if (ctx.disposed) return;
1640
1664
  if (ctx.running) {
1641
1665
  ctx.rerunPending = true;
1642
1666
  return;
@@ -1681,7 +1705,11 @@ function debugValue(value, formatter) {
1681
1705
  const dispose2 = effect(() => {
1682
1706
  const resolved = value();
1683
1707
  entry.value = resolved;
1684
- entry.label = format(resolved);
1708
+ try {
1709
+ entry.label = format(resolved);
1710
+ } catch (err) {
1711
+ entry.label = `<format error: ${err instanceof Error ? err.message : String(err)}>`;
1712
+ }
1685
1713
  });
1686
1714
  return () => {
1687
1715
  dispose2();
@@ -1,4 +1,4 @@
1
- export { D as DevToolsEvent, a as DevtoolsOverlayOptions, P as ProfilerResult, R as ReactiveNodeInfo, S as SibuError, c as checkLeaks, b as clearDebugValues, d as clearHMRModule, e as clearHMRState, f as clearPerformanceData, g as createDevtoolsOverlay, h as createErrorReporter, i as createHMRBoundary, j as createProfiler, k as debugLog, l as debugValue, m as devState, n as disableDebug, o as enableDebug, p as exposeHMR, q as formatError, r as getActiveDevTools, s as getDebugValues, t as getDependencies, u as getPerformanceReport, v as getSignalName, w as getSubscriberCount, x as hmrState, y as initDevTools, z as inspectSignal, A as isDebugEnabled, B as isHMRAvailable, C as measureRender, E as perfTracker, F as registerHMR, G as runCleanups, H as startMeasure, I as trackCleanup, J as walkDependencyGraph, K as withErrorTracking } from './introspect-DsJlDD2T.cjs';
1
+ export { D as DevToolsEvent, a as DevtoolsOverlayOptions, P as ProfilerResult, R as ReactiveNodeInfo, S as SibuError, c as checkLeaks, b as clearDebugValues, d as clearHMRModule, e as clearHMRState, f as clearPerformanceData, g as createDevtoolsOverlay, h as createErrorReporter, i as createHMRBoundary, j as createProfiler, k as debugLog, l as debugValue, m as devState, n as disableDebug, o as enableDebug, p as exposeHMR, q as formatError, r as getActiveDevTools, s as getDebugValues, t as getDependencies, u as getPerformanceReport, v as getSignalName, w as getSubscriberCount, x as hmrState, y as initDevTools, z as inspectSignal, A as isDebugEnabled, B as isHMRAvailable, C as measureRender, E as perfTracker, F as registerHMR, G as runCleanups, H as startMeasure, I as trackCleanup, J as walkDependencyGraph, K as withErrorTracking } from './introspect-RjLfIFpL.cjs';
2
2
  import './signal-BnWpq6WB.cjs';
3
3
 
4
4
  interface SignalNodeSnapshot {
@@ -1,4 +1,4 @@
1
- export { D as DevToolsEvent, a as DevtoolsOverlayOptions, P as ProfilerResult, R as ReactiveNodeInfo, S as SibuError, c as checkLeaks, b as clearDebugValues, d as clearHMRModule, e as clearHMRState, f as clearPerformanceData, g as createDevtoolsOverlay, h as createErrorReporter, i as createHMRBoundary, j as createProfiler, k as debugLog, l as debugValue, m as devState, n as disableDebug, o as enableDebug, p as exposeHMR, q as formatError, r as getActiveDevTools, s as getDebugValues, t as getDependencies, u as getPerformanceReport, v as getSignalName, w as getSubscriberCount, x as hmrState, y as initDevTools, z as inspectSignal, A as isDebugEnabled, B as isHMRAvailable, C as measureRender, E as perfTracker, F as registerHMR, G as runCleanups, H as startMeasure, I as trackCleanup, J as walkDependencyGraph, K as withErrorTracking } from './introspect-BZWKvQUZ.js';
1
+ export { D as DevToolsEvent, a as DevtoolsOverlayOptions, P as ProfilerResult, R as ReactiveNodeInfo, S as SibuError, c as checkLeaks, b as clearDebugValues, d as clearHMRModule, e as clearHMRState, f as clearPerformanceData, g as createDevtoolsOverlay, h as createErrorReporter, i as createHMRBoundary, j as createProfiler, k as debugLog, l as debugValue, m as devState, n as disableDebug, o as enableDebug, p as exposeHMR, q as formatError, r as getActiveDevTools, s as getDebugValues, t as getDependencies, u as getPerformanceReport, v as getSignalName, w as getSubscriberCount, x as hmrState, y as initDevTools, z as inspectSignal, A as isDebugEnabled, B as isHMRAvailable, C as measureRender, E as perfTracker, F as registerHMR, G as runCleanups, H as startMeasure, I as trackCleanup, J as walkDependencyGraph, K as withErrorTracking } from './introspect-DOZfmC-4.js';
2
2
  import './signal-BnWpq6WB.js';
3
3
 
4
4
  interface SignalNodeSnapshot {
package/dist/devtools.js CHANGED
@@ -35,13 +35,13 @@ import {
35
35
  trackCleanup,
36
36
  walkDependencyGraph,
37
37
  withErrorTracking
38
- } from "./chunk-SVVAUX7J.js";
38
+ } from "./chunk-7XDYVJLE.js";
39
39
  import "./chunk-2UPRY23K.js";
40
- import "./chunk-UCS6AMJ7.js";
41
- import "./chunk-ZIBE2SAT.js";
42
- import "./chunk-2RA7SHDA.js";
43
- import "./chunk-RK4BQG25.js";
44
- import "./chunk-3U4ZVXVD.js";
40
+ import "./chunk-HMJFCBRR.js";
41
+ import "./chunk-FDY42FIU.js";
42
+ import "./chunk-GOJMFRBL.js";
43
+ import "./chunk-C427DVQF.js";
44
+ import "./chunk-Z2FWAE4B.js";
45
45
  import {
46
46
  isDev
47
47
  } from "./chunk-LMLD24FC.js";
@@ -197,7 +197,7 @@ function track(effectFn, subscriber) {
197
197
  function reactiveBinding(commit) {
198
198
  const run = () => {
199
199
  const s = subscriber;
200
- if (s._reentrant) return;
200
+ if (s._disposed || s._reentrant) return;
201
201
  s._reentrant = true;
202
202
  try {
203
203
  retrack(commit, subscriber);
@@ -213,8 +213,12 @@ function reactiveBinding(commit) {
213
213
  subscriber._runEpoch = 0;
214
214
  subscriber._runs = 0;
215
215
  subscriber._reentrant = false;
216
+ subscriber._disposed = false;
216
217
  run();
217
- return subscriber._dispose ?? (subscriber._dispose = () => cleanup(subscriber));
218
+ return subscriber._dispose ?? (subscriber._dispose = () => {
219
+ subscriber._disposed = true;
220
+ cleanup(subscriber);
221
+ });
218
222
  }
219
223
  function recordDependency(signal2) {
220
224
  if (!currentSubscriber) return;
@@ -401,11 +405,15 @@ function notifySubscribers(signal2) {
401
405
  var als = null;
402
406
  try {
403
407
  if (typeof process !== "undefined" && process.versions && process.versions.node) {
404
- const req = Function("return typeof require==='function'?require:null")();
405
- if (req) {
406
- const mod = req("node:async_hooks");
407
- als = new mod.AsyncLocalStorage();
408
+ let mod = null;
409
+ const getBuiltin = process.getBuiltinModule;
410
+ if (typeof getBuiltin === "function") {
411
+ mod = getBuiltin("node:async_hooks");
412
+ } else {
413
+ const req = Function("return typeof require==='function'?require:null")();
414
+ if (req) mod = req("node:async_hooks");
408
415
  }
416
+ if (mod) als = new mod.AsyncLocalStorage();
409
417
  }
410
418
  } catch {
411
419
  als = null;
@@ -507,6 +515,7 @@ function effect(effectFn, options) {
507
515
  ctx.fn(ctx.onCleanup);
508
516
  };
509
517
  const sub = (() => {
518
+ if (ctx.disposed) return;
510
519
  if (ctx.running) {
511
520
  ctx.rerunPending = true;
512
521
  return;
@@ -731,6 +740,18 @@ function mobXAdapter(options) {
731
740
  return createPlugin("sibu-mobx", (ctx) => {
732
741
  const { autorun } = options;
733
742
  const disposers = [];
743
+ function trackDisposer(rawDispose) {
744
+ let done = false;
745
+ const wrapped = () => {
746
+ if (done) return;
747
+ done = true;
748
+ const i = disposers.indexOf(wrapped);
749
+ if (i >= 0) disposers.splice(i, 1);
750
+ rawDispose();
751
+ };
752
+ disposers.push(wrapped);
753
+ return wrapped;
754
+ }
734
755
  function fromMobX(expression) {
735
756
  const [getValue, setValue] = signal(void 0);
736
757
  const disposer = autorun(() => {
@@ -739,22 +760,18 @@ function mobXAdapter(options) {
739
760
  setValue(newValue);
740
761
  });
741
762
  });
742
- disposers.push(disposer);
743
763
  const getter = (() => getValue());
744
- getter.dispose = () => {
745
- const i = disposers.indexOf(disposer);
746
- if (i >= 0) disposers.splice(i, 1);
747
- disposer();
748
- };
764
+ getter.dispose = trackDisposer(disposer);
749
765
  return getter;
750
766
  }
751
767
  function toMobX(sibuGetter, callback) {
752
- return effect(() => {
768
+ const stop = effect(() => {
753
769
  callback(sibuGetter());
754
770
  });
771
+ return trackDisposer(stop);
755
772
  }
756
773
  function destroy() {
757
- for (const disposer of disposers) {
774
+ for (const disposer of [...disposers]) {
758
775
  disposer();
759
776
  }
760
777
  disposers.length = 0;
@@ -771,6 +788,7 @@ function derived(getter, options) {
771
788
  const equals = options?.equals;
772
789
  const cs = {};
773
790
  cs._d = false;
791
+ cs._init = false;
774
792
  cs._g = getter;
775
793
  cs.__v = 0;
776
794
  const markDirty = () => {
@@ -779,11 +797,18 @@ function derived(getter, options) {
779
797
  };
780
798
  markDirty._c = 1;
781
799
  markDirty._sig = cs;
800
+ const recompute = () => {
801
+ const next = getter();
802
+ cs._v = equals && cs._init ? equals(cs._v, next) ? cs._v : next : next;
803
+ cs._d = false;
804
+ cs._init = true;
805
+ };
782
806
  track(() => {
783
807
  let threw = true;
784
808
  try {
785
809
  cs._v = getter();
786
810
  cs._d = false;
811
+ cs._init = true;
787
812
  threw = false;
788
813
  } finally {
789
814
  if (threw) cs._d = true;
@@ -799,20 +824,13 @@ function derived(getter, options) {
799
824
  }
800
825
  if (trackingSuspended) {
801
826
  if (cs._d) {
827
+ const prev = cs._v;
802
828
  evaluating = true;
803
- let threw = true;
804
829
  try {
805
- const prev = cs._v;
806
- retrack(() => {
807
- const next = getter();
808
- cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
809
- cs._d = false;
810
- threw = false;
811
- }, markDirty);
830
+ retrack(recompute, markDirty);
812
831
  if (!Object.is(prev, cs._v)) cs.__v++;
813
832
  } finally {
814
833
  evaluating = false;
815
- if (threw) cs._d = true;
816
834
  }
817
835
  }
818
836
  return cs._v;
@@ -821,18 +839,11 @@ function derived(getter, options) {
821
839
  if (cs._d) {
822
840
  const oldValue = cs._v;
823
841
  evaluating = true;
824
- let threw = true;
825
842
  try {
826
- retrack(() => {
827
- const next = getter();
828
- cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
829
- cs._d = false;
830
- threw = false;
831
- }, markDirty);
843
+ retrack(recompute, markDirty);
832
844
  if (!Object.is(oldValue, cs._v)) cs.__v++;
833
845
  } finally {
834
846
  evaluating = false;
835
- if (threw) cs._d = true;
836
847
  }
837
848
  if (hook && oldValue !== cs._v) {
838
849
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
@@ -899,9 +910,17 @@ function zustandAdapter(options) {
899
910
  }
900
911
 
901
912
  // src/utils/sanitize.ts
913
+ function stripControlChars(value) {
914
+ return value.replace(/[\x00-\x20\x7f-\x9f]+/g, "");
915
+ }
916
+ function isEventHandlerAttr(name) {
917
+ if (name.length < 3) return false;
918
+ const lower = name.toLowerCase();
919
+ return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
920
+ }
902
921
  var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
903
922
  function sanitizeUrl(url) {
904
- const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
923
+ const trimmed = stripControlChars(url).trim();
905
924
  if (!trimmed) return "";
906
925
  const lower = trimmed.toLowerCase();
907
926
  let schemeEnd = -1;
@@ -964,7 +983,7 @@ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
964
983
  "data"
965
984
  ]);
966
985
  function isUrlAttribute(attr) {
967
- return URL_ATTRIBUTES.has(attr);
986
+ return URL_ATTRIBUTES.has(attr.toLowerCase());
968
987
  }
969
988
 
970
989
  // src/reactivity/bindAttribute.ts
@@ -972,11 +991,6 @@ var _isDev4 = isDev();
972
991
  function setProp(el, key, val) {
973
992
  el[key] = val;
974
993
  }
975
- function isEventHandlerAttr(name) {
976
- if (name.length < 3) return false;
977
- const lower = name.toLowerCase();
978
- return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
979
- }
980
994
  function bindAttribute(el, attr, getter) {
981
995
  if (isEventHandlerAttr(attr)) {
982
996
  if (_isDev4)
@@ -1015,8 +1029,69 @@ function bindAttribute(el, attr, getter) {
1015
1029
  return reactiveBinding(commit);
1016
1030
  }
1017
1031
 
1018
- // src/reactivity/bindChildNode.ts
1032
+ // src/core/rendering/dispose.ts
1033
+ var elementDisposers = /* @__PURE__ */ new WeakMap();
1019
1034
  var _isDev5 = isDev();
1035
+ var activeBindingCount = 0;
1036
+ function registerDisposer(node, teardown) {
1037
+ let disposers = elementDisposers.get(node);
1038
+ if (!disposers) {
1039
+ disposers = [];
1040
+ elementDisposers.set(node, disposers);
1041
+ }
1042
+ disposers.push(teardown);
1043
+ if (_isDev5) activeBindingCount++;
1044
+ }
1045
+ function dispose(node) {
1046
+ const stack = [node];
1047
+ const order = [];
1048
+ while (stack.length > 0) {
1049
+ const current = stack.pop();
1050
+ order.push(current);
1051
+ const children = Array.from(current.childNodes);
1052
+ for (let i = 0; i < children.length; i++) {
1053
+ stack.push(children[i]);
1054
+ }
1055
+ }
1056
+ for (let i = order.length - 1; i >= 0; i--) {
1057
+ const current = order[i];
1058
+ const disposers = elementDisposers.get(current);
1059
+ if (disposers) {
1060
+ const snapshot = disposers.slice();
1061
+ elementDisposers.delete(current);
1062
+ if (_isDev5) activeBindingCount -= snapshot.length;
1063
+ for (const d of snapshot) {
1064
+ try {
1065
+ d();
1066
+ } catch (err) {
1067
+ if (_isDev5 && typeof console !== "undefined") {
1068
+ console.warn("[SibuJS] Disposer threw during cleanup:", err);
1069
+ }
1070
+ }
1071
+ }
1072
+ let extraPasses = 0;
1073
+ while (extraPasses++ < 8) {
1074
+ const added = elementDisposers.get(current);
1075
+ if (!added || added.length === 0) break;
1076
+ const moreSnapshot = added.slice();
1077
+ elementDisposers.delete(current);
1078
+ if (_isDev5) activeBindingCount -= moreSnapshot.length;
1079
+ for (const d of moreSnapshot) {
1080
+ try {
1081
+ d();
1082
+ } catch (err) {
1083
+ if (_isDev5 && typeof console !== "undefined") {
1084
+ console.warn("[SibuJS] Disposer threw during cleanup:", err);
1085
+ }
1086
+ }
1087
+ }
1088
+ }
1089
+ }
1090
+ }
1091
+ }
1092
+
1093
+ // src/reactivity/bindChildNode.ts
1094
+ var _isDev6 = isDev();
1020
1095
  function bindChildNode(placeholder, getter) {
1021
1096
  let lastNodes = [];
1022
1097
  function commit() {
@@ -1024,12 +1099,13 @@ function bindChildNode(placeholder, getter) {
1024
1099
  try {
1025
1100
  result = getter();
1026
1101
  } catch (err) {
1027
- if (_isDev5) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
1102
+ if (_isDev6) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
1028
1103
  return;
1029
1104
  }
1030
1105
  if (result == null || typeof result === "boolean") {
1031
1106
  for (let i = 0; i < lastNodes.length; i++) {
1032
1107
  const node = lastNodes[i];
1108
+ dispose(node);
1033
1109
  if (node.parentNode) node.parentNode.removeChild(node);
1034
1110
  }
1035
1111
  lastNodes.length = 0;
@@ -1049,7 +1125,7 @@ function bindChildNode(placeholder, getter) {
1049
1125
  if (item == null || typeof item === "boolean") continue;
1050
1126
  const node = item instanceof Node ? item : document.createTextNode(String(item));
1051
1127
  if (seen.has(node)) {
1052
- if (_isDev5)
1128
+ if (_isDev6)
1053
1129
  devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
1054
1130
  continue;
1055
1131
  }
@@ -1071,38 +1147,22 @@ function bindChildNode(placeholder, getter) {
1071
1147
  for (let i = 0; i < lastNodes.length; i++) {
1072
1148
  const node = lastNodes[i];
1073
1149
  if (reused?.has(node)) continue;
1150
+ dispose(node);
1074
1151
  if (node.parentNode) node.parentNode.removeChild(node);
1075
1152
  }
1076
- const anchor = placeholder.nextSibling;
1153
+ let prev = placeholder;
1077
1154
  for (let i = 0; i < newNodes.length; i++) {
1078
1155
  const node = newNodes[i];
1079
- if (reused?.has(node) && node.parentNode === parent) {
1080
- if (node.nextSibling !== anchor) {
1081
- parent.insertBefore(node, anchor);
1082
- }
1083
- } else {
1084
- parent.insertBefore(node, anchor);
1156
+ if (prev.nextSibling !== node) {
1157
+ parent.insertBefore(node, prev.nextSibling);
1085
1158
  }
1159
+ prev = node;
1086
1160
  }
1087
1161
  lastNodes = newNodes;
1088
1162
  }
1089
1163
  return reactiveBinding(commit);
1090
1164
  }
1091
1165
 
1092
- // src/core/rendering/dispose.ts
1093
- var elementDisposers = /* @__PURE__ */ new WeakMap();
1094
- var _isDev6 = isDev();
1095
- var activeBindingCount = 0;
1096
- function registerDisposer(node, teardown) {
1097
- let disposers = elementDisposers.get(node);
1098
- if (!disposers) {
1099
- disposers = [];
1100
- elementDisposers.set(node, disposers);
1101
- }
1102
- disposers.push(teardown);
1103
- if (_isDev6) activeBindingCount++;
1104
- }
1105
-
1106
1166
  // src/core/rendering/tagFactory.ts
1107
1167
  var _isDev7 = isDev();
1108
1168
  var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
@@ -1337,7 +1397,7 @@ var tagFactory = (tag, ns) => {
1337
1397
  const value = props[key];
1338
1398
  if (value == null) continue;
1339
1399
  const lkey = key.toLowerCase();
1340
- if (lkey[0] === "o" && lkey[1] === "n") continue;
1400
+ if (isEventHandlerAttr(key)) continue;
1341
1401
  if (typeof value === "function") {
1342
1402
  registerDisposer(el, bindAttribute(el, key, value));
1343
1403
  } else if (typeof value === "boolean") {
package/dist/ecosystem.js CHANGED
@@ -7,17 +7,17 @@ import {
7
7
  mobXAdapter,
8
8
  reduxAdapter,
9
9
  zustandAdapter
10
- } from "./chunk-2N2UL7O4.js";
10
+ } from "./chunk-BGNLPNGV.js";
11
11
  import "./chunk-3JHCYHWN.js";
12
- import "./chunk-WKUXSE7V.js";
13
- import "./chunk-2ZJ7TSW4.js";
14
- import "./chunk-SC437AMI.js";
12
+ import "./chunk-X67UYC74.js";
13
+ import "./chunk-RLUJL2MV.js";
14
+ import "./chunk-JYXOEYI4.js";
15
15
  import "./chunk-2UPRY23K.js";
16
- import "./chunk-UCS6AMJ7.js";
17
- import "./chunk-ZIBE2SAT.js";
18
- import "./chunk-2RA7SHDA.js";
19
- import "./chunk-RK4BQG25.js";
20
- import "./chunk-3U4ZVXVD.js";
16
+ import "./chunk-HMJFCBRR.js";
17
+ import "./chunk-FDY42FIU.js";
18
+ import "./chunk-GOJMFRBL.js";
19
+ import "./chunk-C427DVQF.js";
20
+ import "./chunk-Z2FWAE4B.js";
21
21
  import "./chunk-LMLD24FC.js";
22
22
  export {
23
23
  antdAdapter,