sibujs 3.3.2 → 3.4.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 (77) hide show
  1. package/dist/browser.cjs +21 -4
  2. package/dist/browser.js +4 -4
  3. package/dist/build.cjs +3343 -3009
  4. package/dist/build.js +12 -11
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-AEOLHSSQ.js → chunk-3DVGCW7O.js} +72 -25
  7. package/dist/{chunk-6TCOWMGY.js → chunk-3Z2NGWQI.js} +1 -1
  8. package/dist/chunk-7ZHH77QA.js +9 -0
  9. package/dist/{chunk-2ARSB7NG.js → chunk-APFRCIRI.js} +2906 -2569
  10. package/dist/{chunk-62V653X2.js → chunk-AXFWGY32.js} +79 -44
  11. package/dist/{chunk-N5TQVEKE.js → chunk-BUKYCWHX.js} +1 -1
  12. package/dist/{chunk-655B7MMR.js → chunk-CEBWDD63.js} +15 -8
  13. package/dist/{chunk-YUBEOWII.js → chunk-ELXMRSVN.js} +16 -5
  14. package/dist/{chunk-FJIRS3FM.js → chunk-F7HW2NI5.js} +1 -3
  15. package/dist/{chunk-P7C7SEJV.js → chunk-FKQG7FTY.js} +5 -5
  16. package/dist/{chunk-RLTFJYDN.js → chunk-H5FI5WDP.js} +1 -1
  17. package/dist/{chunk-G6N3LMO2.js → chunk-ITWCTZYH.js} +1 -1
  18. package/dist/{chunk-YUR5SX7F.js → chunk-JCO7AHNU.js} +70 -59
  19. package/dist/{chunk-ZEUP4TUD.js → chunk-JNGGM2XE.js} +6 -6
  20. package/dist/{chunk-QCFBIVIQ.js → chunk-K35BAR4P.js} +1 -1
  21. package/dist/{chunk-JCQG2I2G.js → chunk-KZBEVFXZ.js} +1 -1
  22. package/dist/{chunk-FJO2ZL4Q.js → chunk-OAVXAFAY.js} +73 -16
  23. package/dist/{chunk-A7CZH3GN.js → chunk-ODXVQ3CS.js} +41 -20
  24. package/dist/{chunk-4NJEAPLI.js → chunk-OOUQUCNN.js} +1 -1
  25. package/dist/{chunk-5VH3GIDX.js → chunk-RT3IYFN2.js} +1 -1
  26. package/dist/{chunk-Q46YIQYW.js → chunk-S3V6ZXPI.js} +22 -5
  27. package/dist/{chunk-IQJ36UTJ.js → chunk-WSGLJYFI.js} +31 -24
  28. package/dist/{chunk-3JHCYHWN.js → chunk-WWV3SJ3L.js} +19 -13
  29. package/dist/data.cjs +16 -2
  30. package/dist/data.js +7 -6
  31. package/dist/devtools.cjs +71 -21
  32. package/dist/devtools.d.cts +12 -5
  33. package/dist/devtools.d.ts +12 -5
  34. package/dist/devtools.js +6 -5
  35. package/dist/ecosystem.cjs +11 -2
  36. package/dist/ecosystem.d.cts +1 -1
  37. package/dist/ecosystem.d.ts +1 -1
  38. package/dist/ecosystem.js +10 -9
  39. package/dist/extras.cjs +454 -250
  40. package/dist/extras.d.cts +2 -2
  41. package/dist/extras.d.ts +2 -2
  42. package/dist/extras.js +26 -22
  43. package/dist/index.cjs +3385 -3045
  44. package/dist/index.d.cts +1179 -1057
  45. package/dist/index.d.ts +1179 -1057
  46. package/dist/index.js +32 -19
  47. package/dist/motion.cjs +223 -204
  48. package/dist/motion.d.cts +8 -1
  49. package/dist/motion.d.ts +8 -1
  50. package/dist/motion.js +6 -3
  51. package/dist/patterns.cjs +13 -6
  52. package/dist/patterns.d.cts +4 -1
  53. package/dist/patterns.d.ts +4 -1
  54. package/dist/patterns.js +5 -5
  55. package/dist/performance.cjs +70 -56
  56. package/dist/performance.js +6 -5
  57. package/dist/plugins.cjs +98 -42
  58. package/dist/plugins.d.cts +2 -1
  59. package/dist/plugins.d.ts +2 -1
  60. package/dist/plugins.js +89 -36
  61. package/dist/ssr.cjs +112 -91
  62. package/dist/ssr.d.cts +8 -1
  63. package/dist/ssr.d.ts +8 -1
  64. package/dist/ssr.js +9 -8
  65. package/dist/{tagFactory-S17H2qxu.d.ts → tagFactory-Bzupt4Pj.d.cts} +1 -1
  66. package/dist/{tagFactory-S17H2qxu.d.cts → tagFactory-Bzupt4Pj.d.ts} +1 -1
  67. package/dist/testing.cjs +18 -4
  68. package/dist/testing.js +18 -7
  69. package/dist/ui.cjs +322 -281
  70. package/dist/ui.d.cts +0 -20
  71. package/dist/ui.d.ts +0 -20
  72. package/dist/ui.js +27 -21
  73. package/dist/widgets.cjs +75 -13
  74. package/dist/widgets.d.cts +6 -1
  75. package/dist/widgets.d.ts +6 -1
  76. package/dist/widgets.js +7 -6
  77. package/package.json +4 -1
package/dist/ui.cjs CHANGED
@@ -107,8 +107,69 @@ function devWarn(message) {
107
107
  }
108
108
  }
109
109
 
110
- // src/reactivity/track-core.ts
110
+ // src/core/rendering/dispose.ts
111
+ var elementDisposers = /* @__PURE__ */ new WeakMap();
111
112
  var _isDev2 = isDev();
113
+ var activeBindingCount = 0;
114
+ function registerDisposer(node, teardown) {
115
+ let disposers = elementDisposers.get(node);
116
+ if (!disposers) {
117
+ disposers = [];
118
+ elementDisposers.set(node, disposers);
119
+ }
120
+ disposers.push(teardown);
121
+ if (_isDev2) activeBindingCount++;
122
+ }
123
+ function dispose(node) {
124
+ const stack = [node];
125
+ const order = [];
126
+ while (stack.length > 0) {
127
+ const current = stack.pop();
128
+ order.push(current);
129
+ const children = Array.from(current.childNodes);
130
+ for (let i = 0; i < children.length; i++) {
131
+ stack.push(children[i]);
132
+ }
133
+ }
134
+ for (let i = order.length - 1; i >= 0; i--) {
135
+ const current = order[i];
136
+ const disposers = elementDisposers.get(current);
137
+ if (disposers) {
138
+ const snapshot = disposers.slice();
139
+ elementDisposers.delete(current);
140
+ if (_isDev2) activeBindingCount -= snapshot.length;
141
+ for (const d of snapshot) {
142
+ try {
143
+ d();
144
+ } catch (err) {
145
+ if (_isDev2 && typeof console !== "undefined") {
146
+ console.warn("[SibuJS] Disposer threw during cleanup:", err);
147
+ }
148
+ }
149
+ }
150
+ let extraPasses = 0;
151
+ while (extraPasses++ < 8) {
152
+ const added = elementDisposers.get(current);
153
+ if (!added || added.length === 0) break;
154
+ const moreSnapshot = added.slice();
155
+ elementDisposers.delete(current);
156
+ if (_isDev2) activeBindingCount -= moreSnapshot.length;
157
+ for (const d of moreSnapshot) {
158
+ try {
159
+ d();
160
+ } catch (err) {
161
+ if (_isDev2 && typeof console !== "undefined") {
162
+ console.warn("[SibuJS] Disposer threw during cleanup:", err);
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ // src/reactivity/track-core.ts
172
+ var _isDev3 = isDev();
112
173
  var POOL_MAX = 4096;
113
174
  var nodePool = [];
114
175
  function createNode() {
@@ -200,7 +261,7 @@ function safeInvoke(sub) {
200
261
  try {
201
262
  sub();
202
263
  } catch (err) {
203
- if (_isDev2) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
264
+ if (_isDev3) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
204
265
  }
205
266
  }
206
267
  var suspendDepth = 0;
@@ -522,14 +583,14 @@ function forEachSubscriber(signal2, visit) {
522
583
  }
523
584
 
524
585
  // src/reactivity/track.ts
525
- var _isDev3 = isDev();
526
- var _runtimeVersion = true ? "3.3.2" : "dev";
586
+ var _isDev4 = isDev();
587
+ var _runtimeVersion = true ? "3.4.0" : "dev";
527
588
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
528
589
  function resolveReactiveApi() {
529
590
  const g = globalThis;
530
591
  const existing = g[REGISTRY_KEY];
531
592
  if (existing) {
532
- if (_isDev3 && !existing.__dupWarned) {
593
+ if (_isDev4 && !existing.__dupWarned) {
533
594
  existing.__dupWarned = true;
534
595
  devWarn(
535
596
  `Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity still works \u2014 all copies share the first one \u2014 but de-duplicate sibujs in your bundler (e.g. Vite optimizeDeps.exclude: ['sibujs'] or resolve.dedupe: ['sibujs']).`
@@ -658,6 +719,162 @@ function derived(getter, options) {
658
719
  return computedGetter;
659
720
  }
660
721
 
722
+ // src/core/ssr-context.ts
723
+ var SSR_KEY = /* @__PURE__ */ Symbol.for("sibujs.ssr.v1");
724
+ function detectSSRShared() {
725
+ let detected = null;
726
+ try {
727
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
728
+ let mod = null;
729
+ const getBuiltin = process.getBuiltinModule;
730
+ if (typeof getBuiltin === "function") {
731
+ mod = getBuiltin("node:async_hooks");
732
+ } else {
733
+ const req = Function("return typeof require==='function'?require:null")();
734
+ if (req) mod = req("node:async_hooks");
735
+ }
736
+ if (mod) detected = new mod.AsyncLocalStorage();
737
+ }
738
+ } catch {
739
+ detected = null;
740
+ }
741
+ return { als: detected, fallbackStore: { ssr: false, suspenseIdCounter: 0 } };
742
+ }
743
+ var _shared = globalThis[SSR_KEY] ?? (globalThis[SSR_KEY] = detectSSRShared());
744
+ var als = _shared.als;
745
+ var fallbackStore = _shared.fallbackStore;
746
+ function getSSRStore() {
747
+ if (als) {
748
+ const s = als.getStore();
749
+ if (s) return s;
750
+ }
751
+ return fallbackStore;
752
+ }
753
+ function isSSR() {
754
+ return getSSRStore().ssr;
755
+ }
756
+
757
+ // src/core/signals/effect.ts
758
+ var _g = globalThis;
759
+ var MAX_RERUNS = 100;
760
+ function flushUserCleanups(ctx) {
761
+ const list = ctx.userCleanups;
762
+ if (list.length === 0) return;
763
+ ctx.userCleanups = [];
764
+ for (let i = list.length - 1; i >= 0; i--) {
765
+ try {
766
+ list[i]();
767
+ } catch (err) {
768
+ if (typeof console !== "undefined") console.warn("[SibuJS effect] onCleanup threw:", err);
769
+ }
770
+ }
771
+ }
772
+ function drainReruns(ctx) {
773
+ let reruns = 1;
774
+ do {
775
+ ctx.rerunPending = false;
776
+ if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
777
+ retrack2(ctx.bodyFn, ctx.subscriber);
778
+ } while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
779
+ if (ctx.rerunPending) {
780
+ ctx.rerunPending = false;
781
+ if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
782
+ console.error(
783
+ `[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
784
+ );
785
+ }
786
+ }
787
+ }
788
+ function disposeEffect(ctx) {
789
+ if (ctx.disposed) return;
790
+ ctx.disposed = true;
791
+ const h = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
792
+ if (h) {
793
+ try {
794
+ h.emit("effect:destroy", { effectFn: ctx.fn });
795
+ } catch {
796
+ }
797
+ }
798
+ try {
799
+ if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
800
+ } catch (err) {
801
+ if (typeof console !== "undefined") {
802
+ console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
803
+ }
804
+ }
805
+ try {
806
+ cleanup2(ctx.subscriber);
807
+ } catch (err) {
808
+ if (typeof console !== "undefined") {
809
+ console.warn("[SibuJS effect] dispose threw:", err);
810
+ }
811
+ }
812
+ }
813
+ function effect(effectFn, options) {
814
+ devAssert(typeof effectFn === "function", "effect: argument must be a function.");
815
+ if (isSSR()) return () => {
816
+ };
817
+ const ctx = {
818
+ fn: effectFn,
819
+ onError: options?.onError,
820
+ userCleanups: [],
821
+ running: false,
822
+ rerunPending: false,
823
+ disposed: false,
824
+ onCleanup: null,
825
+ subscriber: null,
826
+ bodyFn: null
827
+ };
828
+ ctx.onCleanup = (fn) => {
829
+ ctx.userCleanups.push(fn);
830
+ };
831
+ const onErrorCaptured = ctx.onError;
832
+ ctx.bodyFn = onErrorCaptured ? () => {
833
+ try {
834
+ ctx.fn(ctx.onCleanup);
835
+ } catch (err) {
836
+ onErrorCaptured(err);
837
+ }
838
+ } : () => {
839
+ ctx.fn(ctx.onCleanup);
840
+ };
841
+ const sub = (() => {
842
+ if (ctx.disposed) return;
843
+ if (ctx.running) {
844
+ ctx.rerunPending = true;
845
+ return;
846
+ }
847
+ ctx.running = true;
848
+ try {
849
+ ctx.rerunPending = false;
850
+ if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
851
+ retrack2(ctx.bodyFn, sub);
852
+ if (ctx.rerunPending) drainReruns(ctx);
853
+ } finally {
854
+ ctx.running = false;
855
+ ctx.rerunPending = false;
856
+ }
857
+ });
858
+ sub.depsHead = null;
859
+ sub.depsTail = null;
860
+ sub._epoch = 0;
861
+ sub._structDirty = false;
862
+ sub._runEpoch = 0;
863
+ sub._runs = 0;
864
+ ctx.subscriber = sub;
865
+ ctx.running = true;
866
+ try {
867
+ retrack2(ctx.bodyFn, ctx.subscriber);
868
+ if (ctx.rerunPending) drainReruns(ctx);
869
+ } finally {
870
+ ctx.running = false;
871
+ ctx.rerunPending = false;
872
+ }
873
+ const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
874
+ if (hook) hook.emit("effect:create", { effectFn });
875
+ return () => disposeEffect(ctx);
876
+ }
877
+
661
878
  // src/reactivity/batch.ts
662
879
  var batchDepth = 0;
663
880
  var pendingSignals = /* @__PURE__ */ new Set();
@@ -709,8 +926,8 @@ var enqueueBatchedSignal = API2.enqueueBatchedSignal;
709
926
  var isBatching = API2.isBatching;
710
927
 
711
928
  // src/core/signals/signal.ts
712
- var _g = globalThis;
713
- var _isDev4 = isDev();
929
+ var _g2 = globalThis;
930
+ var _isDev5 = isDev();
714
931
  function signal(initial, options) {
715
932
  const state = {
716
933
  value: initial,
@@ -721,7 +938,7 @@ function signal(initial, options) {
721
938
  __activeNode: null,
722
939
  __name: void 0
723
940
  };
724
- const debugName = _isDev4 ? options?.name : void 0;
941
+ const debugName = _isDev5 ? options?.name : void 0;
725
942
  const equalsFn = options?.equals;
726
943
  if (debugName) state.__name = debugName;
727
944
  function get() {
@@ -738,22 +955,22 @@ function signal(initial, options) {
738
955
  if (equalsFn(prev, newValue)) return;
739
956
  state.value = newValue;
740
957
  state.__v++;
741
- if (_isDev4) {
742
- const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
958
+ if (_isDev5) {
959
+ const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
743
960
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
744
961
  }
745
962
  if (!enqueueBatchedSignal(state)) {
746
963
  notifySubscribers2(state);
747
964
  }
748
965
  };
749
- } else if (_isDev4) {
966
+ } else if (_isDev5) {
750
967
  set = (next) => {
751
968
  const prev = state.value;
752
969
  const newValue = typeof next === "function" ? next(prev) : next;
753
970
  if (Object.is(newValue, prev)) return;
754
971
  state.value = newValue;
755
972
  state.__v++;
756
- const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
973
+ const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
757
974
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
758
975
  if (!enqueueBatchedSignal(state)) {
759
976
  notifySubscribers2(state);
@@ -771,8 +988,8 @@ function signal(initial, options) {
771
988
  }
772
989
  };
773
990
  }
774
- if (_isDev4) {
775
- const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
991
+ if (_isDev5) {
992
+ const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
776
993
  if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
777
994
  }
778
995
  return [get, set];
@@ -848,11 +1065,32 @@ function bindField(field, extras) {
848
1065
  change: (e) => field.set(readControlValue(e.target)),
849
1066
  blur: () => field.touch()
850
1067
  };
851
- const { on: extraOn, value: _ignoreValue, ...restExtras } = extras ?? {};
1068
+ const {
1069
+ on: extraOn,
1070
+ value: _ignoreValue,
1071
+ onElement: extraOnElement,
1072
+ ...restExtras
1073
+ } = extras ?? {};
852
1074
  const mergedOn = extraOn && typeof extraOn === "object" ? { ...extraOn, ...fieldOn } : fieldOn;
1075
+ const onElement = (el) => {
1076
+ if (el instanceof HTMLSelectElement && el.multiple) {
1077
+ const stop = effect(() => {
1078
+ const v = field.value();
1079
+ const selected = Array.isArray(v) ? v.map(String) : [];
1080
+ for (const opt of Array.from(el.options)) {
1081
+ opt.selected = selected.includes(opt.value);
1082
+ }
1083
+ });
1084
+ registerDisposer(el, stop);
1085
+ }
1086
+ if (typeof extraOnElement === "function") {
1087
+ extraOnElement(el);
1088
+ }
1089
+ };
853
1090
  return {
854
1091
  value: field.value,
855
1092
  on: mergedOn,
1093
+ onElement,
856
1094
  ...restExtras
857
1095
  };
858
1096
  }
@@ -909,9 +1147,21 @@ function form(config) {
909
1147
  }
910
1148
  return true;
911
1149
  });
1150
+ const valueEquals = (a, b) => {
1151
+ if (Object.is(a, b)) return true;
1152
+ if (Array.isArray(a) && Array.isArray(b)) {
1153
+ return a.length === b.length && a.every((v, i) => Object.is(v, b[i]));
1154
+ }
1155
+ if (a && b && typeof a === "object" && typeof b === "object") {
1156
+ const ak = Object.keys(a);
1157
+ const bk = Object.keys(b);
1158
+ return ak.length === bk.length && ak.every((k) => Object.is(a[k], b[k]));
1159
+ }
1160
+ return false;
1161
+ };
912
1162
  const isDirty = derived(() => {
913
1163
  for (const [name, cfg] of fieldEntries) {
914
- if (!Object.is(fieldMap[name].value(), cfg.initial)) return true;
1164
+ if (!valueEquals(fieldMap[name].value(), cfg.initial)) return true;
915
1165
  }
916
1166
  return false;
917
1167
  });
@@ -1006,223 +1256,6 @@ function formAction(fn) {
1006
1256
  return { run, pending, error, result, reset, onSubmit };
1007
1257
  }
1008
1258
 
1009
- // src/core/rendering/dispose.ts
1010
- var elementDisposers = /* @__PURE__ */ new WeakMap();
1011
- var _isDev5 = isDev();
1012
- var activeBindingCount = 0;
1013
- function registerDisposer(node, teardown) {
1014
- let disposers = elementDisposers.get(node);
1015
- if (!disposers) {
1016
- disposers = [];
1017
- elementDisposers.set(node, disposers);
1018
- }
1019
- disposers.push(teardown);
1020
- if (_isDev5) activeBindingCount++;
1021
- }
1022
- function dispose(node) {
1023
- const stack = [node];
1024
- const order = [];
1025
- while (stack.length > 0) {
1026
- const current = stack.pop();
1027
- order.push(current);
1028
- const children = Array.from(current.childNodes);
1029
- for (let i = 0; i < children.length; i++) {
1030
- stack.push(children[i]);
1031
- }
1032
- }
1033
- for (let i = order.length - 1; i >= 0; i--) {
1034
- const current = order[i];
1035
- const disposers = elementDisposers.get(current);
1036
- if (disposers) {
1037
- const snapshot = disposers.slice();
1038
- elementDisposers.delete(current);
1039
- if (_isDev5) activeBindingCount -= snapshot.length;
1040
- for (const d of snapshot) {
1041
- try {
1042
- d();
1043
- } catch (err) {
1044
- if (_isDev5 && typeof console !== "undefined") {
1045
- console.warn("[SibuJS] Disposer threw during cleanup:", err);
1046
- }
1047
- }
1048
- }
1049
- let extraPasses = 0;
1050
- while (extraPasses++ < 8) {
1051
- const added = elementDisposers.get(current);
1052
- if (!added || added.length === 0) break;
1053
- const moreSnapshot = added.slice();
1054
- elementDisposers.delete(current);
1055
- if (_isDev5) activeBindingCount -= moreSnapshot.length;
1056
- for (const d of moreSnapshot) {
1057
- try {
1058
- d();
1059
- } catch (err) {
1060
- if (_isDev5 && typeof console !== "undefined") {
1061
- console.warn("[SibuJS] Disposer threw during cleanup:", err);
1062
- }
1063
- }
1064
- }
1065
- }
1066
- }
1067
- }
1068
- }
1069
-
1070
- // src/core/ssr-context.ts
1071
- var SSR_KEY = /* @__PURE__ */ Symbol.for("sibujs.ssr.v1");
1072
- function detectSSRShared() {
1073
- let detected = null;
1074
- try {
1075
- if (typeof process !== "undefined" && process.versions && process.versions.node) {
1076
- let mod = null;
1077
- const getBuiltin = process.getBuiltinModule;
1078
- if (typeof getBuiltin === "function") {
1079
- mod = getBuiltin("node:async_hooks");
1080
- } else {
1081
- const req = Function("return typeof require==='function'?require:null")();
1082
- if (req) mod = req("node:async_hooks");
1083
- }
1084
- if (mod) detected = new mod.AsyncLocalStorage();
1085
- }
1086
- } catch {
1087
- detected = null;
1088
- }
1089
- return { als: detected, fallbackStore: { ssr: false, suspenseIdCounter: 0 } };
1090
- }
1091
- var _shared = globalThis[SSR_KEY] ?? (globalThis[SSR_KEY] = detectSSRShared());
1092
- var als = _shared.als;
1093
- var fallbackStore = _shared.fallbackStore;
1094
- function getSSRStore() {
1095
- if (als) {
1096
- const s = als.getStore();
1097
- if (s) return s;
1098
- }
1099
- return fallbackStore;
1100
- }
1101
- function isSSR() {
1102
- return getSSRStore().ssr;
1103
- }
1104
-
1105
- // src/core/signals/effect.ts
1106
- var _g2 = globalThis;
1107
- var MAX_RERUNS = 100;
1108
- function flushUserCleanups(ctx) {
1109
- const list = ctx.userCleanups;
1110
- if (list.length === 0) return;
1111
- ctx.userCleanups = [];
1112
- for (let i = list.length - 1; i >= 0; i--) {
1113
- try {
1114
- list[i]();
1115
- } catch (err) {
1116
- if (typeof console !== "undefined") console.warn("[SibuJS effect] onCleanup threw:", err);
1117
- }
1118
- }
1119
- }
1120
- function drainReruns(ctx) {
1121
- let reruns = 1;
1122
- do {
1123
- ctx.rerunPending = false;
1124
- if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1125
- retrack2(ctx.bodyFn, ctx.subscriber);
1126
- } while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
1127
- if (ctx.rerunPending) {
1128
- ctx.rerunPending = false;
1129
- if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
1130
- console.error(
1131
- `[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
1132
- );
1133
- }
1134
- }
1135
- }
1136
- function disposeEffect(ctx) {
1137
- if (ctx.disposed) return;
1138
- ctx.disposed = true;
1139
- const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1140
- if (h) {
1141
- try {
1142
- h.emit("effect:destroy", { effectFn: ctx.fn });
1143
- } catch {
1144
- }
1145
- }
1146
- try {
1147
- if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1148
- } catch (err) {
1149
- if (typeof console !== "undefined") {
1150
- console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
1151
- }
1152
- }
1153
- try {
1154
- cleanup2(ctx.subscriber);
1155
- } catch (err) {
1156
- if (typeof console !== "undefined") {
1157
- console.warn("[SibuJS effect] dispose threw:", err);
1158
- }
1159
- }
1160
- }
1161
- function effect(effectFn, options) {
1162
- devAssert(typeof effectFn === "function", "effect: argument must be a function.");
1163
- if (isSSR()) return () => {
1164
- };
1165
- const ctx = {
1166
- fn: effectFn,
1167
- onError: options?.onError,
1168
- userCleanups: [],
1169
- running: false,
1170
- rerunPending: false,
1171
- disposed: false,
1172
- onCleanup: null,
1173
- subscriber: null,
1174
- bodyFn: null
1175
- };
1176
- ctx.onCleanup = (fn) => {
1177
- ctx.userCleanups.push(fn);
1178
- };
1179
- const onErrorCaptured = ctx.onError;
1180
- ctx.bodyFn = onErrorCaptured ? () => {
1181
- try {
1182
- ctx.fn(ctx.onCleanup);
1183
- } catch (err) {
1184
- onErrorCaptured(err);
1185
- }
1186
- } : () => {
1187
- ctx.fn(ctx.onCleanup);
1188
- };
1189
- const sub = (() => {
1190
- if (ctx.disposed) return;
1191
- if (ctx.running) {
1192
- ctx.rerunPending = true;
1193
- return;
1194
- }
1195
- ctx.running = true;
1196
- try {
1197
- ctx.rerunPending = false;
1198
- if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1199
- retrack2(ctx.bodyFn, sub);
1200
- if (ctx.rerunPending) drainReruns(ctx);
1201
- } finally {
1202
- ctx.running = false;
1203
- ctx.rerunPending = false;
1204
- }
1205
- });
1206
- sub.depsHead = null;
1207
- sub.depsTail = null;
1208
- sub._epoch = 0;
1209
- sub._structDirty = false;
1210
- sub._runEpoch = 0;
1211
- sub._runs = 0;
1212
- ctx.subscriber = sub;
1213
- ctx.running = true;
1214
- try {
1215
- retrack2(ctx.bodyFn, ctx.subscriber);
1216
- if (ctx.rerunPending) drainReruns(ctx);
1217
- } finally {
1218
- ctx.running = false;
1219
- ctx.rerunPending = false;
1220
- }
1221
- const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1222
- if (hook) hook.emit("effect:create", { effectFn });
1223
- return () => disposeEffect(ctx);
1224
- }
1225
-
1226
1259
  // src/ui/virtualList.ts
1227
1260
  function VirtualList(props) {
1228
1261
  const overscan = props.overscan ?? 3;
@@ -1379,7 +1412,6 @@ function inputMask(options) {
1379
1412
  return /[^a-zA-Z0-9]/g;
1380
1413
  }
1381
1414
  const stripRegex = buildStripRegex();
1382
- const rawCharTest = options.pattern.includes("*") ? () => true : (c) => /[a-zA-Z0-9]/.test(c);
1383
1415
  function bind(input) {
1384
1416
  const onInput = () => {
1385
1417
  const cursorBefore = input.selectionStart ?? input.value.length;
@@ -1389,20 +1421,14 @@ function inputMask(options) {
1389
1421
  setValue(masked);
1390
1422
  setRawValue(extractRaw(masked));
1391
1423
  input.value = masked;
1392
- let rawBefore = 0;
1393
- for (let i = 0; i < cursorBefore && i < oldValue.length; i++) {
1394
- if (rawCharTest(oldValue[i])) rawBefore++;
1395
- }
1424
+ const rawBefore = oldValue.slice(0, cursorBefore).replace(stripRegex, "").length;
1396
1425
  let newCursor = 0;
1397
1426
  let counted = 0;
1398
- for (; newCursor < masked.length; newCursor++) {
1427
+ while (newCursor < masked.length && counted < rawBefore) {
1399
1428
  if (newCursor < options.pattern.length && isSlot(options.pattern[newCursor])) {
1400
1429
  counted++;
1401
- if (counted >= rawBefore) {
1402
- newCursor++;
1403
- break;
1404
- }
1405
1430
  }
1431
+ newCursor++;
1406
1432
  }
1407
1433
  try {
1408
1434
  input.setSelectionRange(newCursor, newCursor);
@@ -1443,6 +1469,12 @@ function zipMask() {
1443
1469
  return { pattern: "99999" };
1444
1470
  }
1445
1471
 
1472
+ // src/utils/globalSingleton.ts
1473
+ function globalSingleton(key, create) {
1474
+ const g = globalThis;
1475
+ return g[key] ?? (g[key] = create());
1476
+ }
1477
+
1446
1478
  // src/ui/a11y.ts
1447
1479
  function aria(element, attrs) {
1448
1480
  for (const [key, value] of Object.entries(attrs)) {
@@ -1601,14 +1633,12 @@ function hotkey(combo, handler, options = {}) {
1601
1633
  document.addEventListener("keydown", listener);
1602
1634
  return () => document.removeEventListener("keydown", listener);
1603
1635
  }
1604
- var announceQueues = {
1605
- polite: [],
1606
- assertive: []
1607
- };
1608
- var announceDraining = {
1609
- polite: false,
1610
- assertive: false
1611
- };
1636
+ var _announce = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.a11y.announce.v1"), () => ({
1637
+ queues: { polite: [], assertive: [] },
1638
+ draining: { polite: false, assertive: false }
1639
+ }));
1640
+ var announceQueues = _announce.queues;
1641
+ var announceDraining = _announce.draining;
1612
1642
  var ANNOUNCE_INTERVAL_MS = 150;
1613
1643
  function ensureLiveRegion(priority) {
1614
1644
  let region = document.getElementById(`sibu-announce-${priority}`);
@@ -1835,7 +1865,7 @@ function createDialogAria(element, options = {}) {
1835
1865
  }
1836
1866
 
1837
1867
  // src/ui/scopedStyle.ts
1838
- var scopeCounter = 0;
1868
+ var _scope = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.scopedStyle.v1"), () => ({ n: 0 }));
1839
1869
  function decodeCssEscapes(css) {
1840
1870
  return css.replace(/\\([0-9a-f]{1,6})[ \t\n\r\f]?|\\([^\n])/gi, (_match, hex, ch) => {
1841
1871
  if (hex) {
@@ -1862,7 +1892,7 @@ function sanitizeCSS(css) {
1862
1892
  return sanitized;
1863
1893
  }
1864
1894
  function scopedStyle(css) {
1865
- const id = `sibu-s${scopeCounter++}`;
1895
+ const id = `sibu-s${_scope.n++}`;
1866
1896
  const attr = `data-${id}`;
1867
1897
  const safeCss = sanitizeCSS(css);
1868
1898
  const scopedCSS = safeCss.replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/g, (match, selector, delimiter) => {
@@ -2076,13 +2106,16 @@ function bindData(el, key, getter) {
2076
2106
  }
2077
2107
 
2078
2108
  // src/ui/dialog.ts
2079
- var dialogStack = [];
2080
- var globalListenerAttached = false;
2109
+ var _dlg = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.dialog.v1"), () => ({
2110
+ stack: [],
2111
+ listenerAttached: false
2112
+ }));
2113
+ var dialogStack = _dlg.stack;
2081
2114
  function __resetDialogStack() {
2082
2115
  while (dialogStack.length > 0) dialogStack.pop();
2083
- if (typeof window !== "undefined" && globalListenerAttached) {
2116
+ if (typeof window !== "undefined" && _dlg.listenerAttached) {
2084
2117
  window.removeEventListener("keydown", handleGlobalKeydown);
2085
- globalListenerAttached = false;
2118
+ _dlg.listenerAttached = false;
2086
2119
  }
2087
2120
  }
2088
2121
  function handleGlobalKeydown(event) {
@@ -2091,16 +2124,16 @@ function handleGlobalKeydown(event) {
2091
2124
  if (top) top.close();
2092
2125
  }
2093
2126
  function ensureGlobalListener() {
2094
- if (typeof window === "undefined" || globalListenerAttached) return;
2127
+ if (typeof window === "undefined" || _dlg.listenerAttached) return;
2095
2128
  window.addEventListener("keydown", handleGlobalKeydown);
2096
- globalListenerAttached = true;
2129
+ _dlg.listenerAttached = true;
2097
2130
  }
2098
2131
  function removeGlobalListenerIfIdle() {
2099
2132
  if (typeof window === "undefined") return;
2100
- if (!globalListenerAttached) return;
2133
+ if (!_dlg.listenerAttached) return;
2101
2134
  if (dialogStack.length > 0) return;
2102
2135
  window.removeEventListener("keydown", handleGlobalKeydown);
2103
- globalListenerAttached = false;
2136
+ _dlg.listenerAttached = false;
2104
2137
  }
2105
2138
  function dialog() {
2106
2139
  const [isOpen, setIsOpen] = signal(false);
@@ -2226,6 +2259,10 @@ function infiniteScroll(options) {
2226
2259
  await onLoadMore();
2227
2260
  } finally {
2228
2261
  setLoading(false);
2262
+ if (!disposed && observer && _current && hasMore()) {
2263
+ observer.unobserve(_current);
2264
+ observer.observe(_current);
2265
+ }
2229
2266
  }
2230
2267
  }
2231
2268
  const originalRef = sentinelRef;
@@ -2265,29 +2302,30 @@ function pagination(options) {
2265
2302
  const total = options.totalItems();
2266
2303
  return Math.max(1, Math.ceil(total / pageSizeValue));
2267
2304
  });
2305
+ const currentPage = derived(() => Math.min(Math.max(1, page()), totalPages()));
2268
2306
  const startIndex = derived(() => {
2269
- return (page() - 1) * pageSizeValue;
2307
+ return (currentPage() - 1) * pageSizeValue;
2270
2308
  });
2271
2309
  const endIndex = derived(() => {
2272
- const end = page() * pageSizeValue;
2310
+ const end = currentPage() * pageSizeValue;
2273
2311
  const total = options.totalItems();
2274
2312
  return Math.min(end, total);
2275
2313
  });
2276
2314
  function next() {
2277
- if (page() < totalPages()) {
2278
- setPage((p) => p + 1);
2315
+ if (currentPage() < totalPages()) {
2316
+ setPage(currentPage() + 1);
2279
2317
  }
2280
2318
  }
2281
2319
  function prev() {
2282
- if (page() > 1) {
2283
- setPage((p) => p - 1);
2320
+ if (currentPage() > 1) {
2321
+ setPage(currentPage() - 1);
2284
2322
  }
2285
2323
  }
2286
2324
  function goTo(target) {
2287
2325
  const clamped = Math.max(1, Math.min(target, totalPages()));
2288
2326
  setPage(clamped);
2289
2327
  }
2290
- return { page, pageSize, totalPages, next, prev, goTo, startIndex, endIndex };
2328
+ return { page: currentPage, pageSize, totalPages, next, prev, goTo, startIndex, endIndex };
2291
2329
  }
2292
2330
 
2293
2331
  // src/ui/eventBus.ts
@@ -2414,24 +2452,27 @@ function hover(target) {
2414
2452
  target.removeEventListener("pointerenter", onEnter);
2415
2453
  target.removeEventListener("pointerleave", onLeave);
2416
2454
  }
2455
+ registerDisposer(target, dispose2);
2417
2456
  return { hovered, dispose: dispose2 };
2418
2457
  }
2419
2458
 
2420
2459
  // src/ui/scrollLock.ts
2421
- var lockCount = 0;
2422
- var savedOverflow = null;
2423
- var savedPaddingRight = null;
2460
+ var _lock = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.scrollLock.v1"), () => ({
2461
+ count: 0,
2462
+ savedOverflow: null,
2463
+ savedPaddingRight: null
2464
+ }));
2424
2465
  function scrollLock() {
2425
2466
  let owned = false;
2426
2467
  function lock() {
2427
2468
  if (owned) return;
2428
2469
  owned = true;
2429
- lockCount++;
2430
- if (lockCount !== 1 || typeof document === "undefined") return;
2470
+ _lock.count++;
2471
+ if (_lock.count !== 1 || typeof document === "undefined") return;
2431
2472
  const body = document.body;
2432
2473
  const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;
2433
- savedOverflow = body.style.overflow;
2434
- savedPaddingRight = body.style.paddingRight;
2474
+ _lock.savedOverflow = body.style.overflow;
2475
+ _lock.savedPaddingRight = body.style.paddingRight;
2435
2476
  body.style.overflow = "hidden";
2436
2477
  if (scrollBarWidth > 0) {
2437
2478
  body.style.paddingRight = `${scrollBarWidth}px`;
@@ -2440,13 +2481,13 @@ function scrollLock() {
2440
2481
  function unlock() {
2441
2482
  if (!owned) return;
2442
2483
  owned = false;
2443
- lockCount = Math.max(0, lockCount - 1);
2444
- if (lockCount !== 0 || typeof document === "undefined") return;
2484
+ _lock.count = Math.max(0, _lock.count - 1);
2485
+ if (_lock.count !== 0 || typeof document === "undefined") return;
2445
2486
  const body = document.body;
2446
- body.style.overflow = savedOverflow ?? "";
2447
- body.style.paddingRight = savedPaddingRight ?? "";
2448
- savedOverflow = null;
2449
- savedPaddingRight = null;
2487
+ body.style.overflow = _lock.savedOverflow ?? "";
2488
+ body.style.paddingRight = _lock.savedPaddingRight ?? "";
2489
+ _lock.savedOverflow = null;
2490
+ _lock.savedPaddingRight = null;
2450
2491
  }
2451
2492
  return { lock, unlock };
2452
2493
  }