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/extras.cjs CHANGED
@@ -209,6 +209,7 @@ __export(extras_exports, {
209
209
  pointerLock: () => pointerLock,
210
210
  popover: () => popover,
211
211
  precompile: () => precompile,
212
+ prefersReducedMotion: () => prefersReducedMotion,
212
213
  prefetch: () => prefetch,
213
214
  preloadCritical: () => preloadCritical,
214
215
  preloadImage: () => preloadImage,
@@ -753,7 +754,7 @@ function forEachSubscriber(signal2, visit) {
753
754
 
754
755
  // src/reactivity/track.ts
755
756
  var _isDev3 = isDev();
756
- var _runtimeVersion = true ? "3.3.2" : "dev";
757
+ var _runtimeVersion = true ? "3.4.0" : "dev";
757
758
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
758
759
  function resolveReactiveApi() {
759
760
  const g2 = globalThis;
@@ -1175,6 +1176,12 @@ function signal(initial, options) {
1175
1176
  return [get, set];
1176
1177
  }
1177
1178
 
1179
+ // src/utils/globalSingleton.ts
1180
+ function globalSingleton(key, create) {
1181
+ const g2 = globalThis;
1182
+ return g2[key] ?? (g2[key] = create());
1183
+ }
1184
+
1178
1185
  // src/data/retry.ts
1179
1186
  function calculateDelay(attempt, strategy, baseDelay, maxDelay, jitter) {
1180
1187
  let delay;
@@ -1236,7 +1243,7 @@ async function withRetry(fn, options, onRetry, signal2) {
1236
1243
  }
1237
1244
 
1238
1245
  // src/data/query.ts
1239
- var globalQueryCache = /* @__PURE__ */ new Map();
1246
+ var globalQueryCache = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.query.cache.v1"), () => /* @__PURE__ */ new Map());
1240
1247
  function getActiveQueryCache() {
1241
1248
  return getRequestScopedCache("query") ?? globalQueryCache;
1242
1249
  }
@@ -2258,6 +2265,10 @@ function socket(url, options) {
2258
2265
  }
2259
2266
  function connect() {
2260
2267
  if (disposed) return;
2268
+ if (typeof WebSocket === "undefined") {
2269
+ setStatus("closed");
2270
+ return;
2271
+ }
2261
2272
  const safeUrl = validateWsUrl(getUrl());
2262
2273
  if (safeUrl === null) {
2263
2274
  setStatus("closed");
@@ -2451,6 +2462,10 @@ function stream(url, options) {
2451
2462
  let attempts = 0;
2452
2463
  function connect() {
2453
2464
  if (disposed) return;
2465
+ if (typeof EventSource === "undefined") {
2466
+ setStatus("closed");
2467
+ return;
2468
+ }
2454
2469
  const safeUrl = validateSseUrl(url);
2455
2470
  if (safeUrl === null) {
2456
2471
  setStatus("closed");
@@ -2687,7 +2702,7 @@ function battery() {
2687
2702
  let disposed = false;
2688
2703
  if (typeof navigator !== "undefined" && "getBattery" in navigator) {
2689
2704
  setSupported(true);
2690
- navigator.getBattery().then((bm) => {
2705
+ const batteryPromise = navigator.getBattery().then((bm) => {
2691
2706
  if (disposed) return;
2692
2707
  battery2 = bm;
2693
2708
  batch(() => {
@@ -2705,6 +2720,9 @@ function battery() {
2705
2720
  bm.addEventListener("chargingtimechange", onChargingTimeChange);
2706
2721
  bm.addEventListener("dischargingtimechange", onDischargingTimeChange);
2707
2722
  });
2723
+ batteryPromise.catch(() => {
2724
+ if (!disposed) setSupported(false);
2725
+ });
2708
2726
  }
2709
2727
  function dispose2() {
2710
2728
  disposed = true;
@@ -3269,9 +3287,17 @@ function wakeLock() {
3269
3287
  }
3270
3288
  const api = navigator.wakeLock;
3271
3289
  let sentinel = null;
3290
+ let disposed = false;
3272
3291
  async function request() {
3292
+ if (disposed) return;
3273
3293
  try {
3274
- sentinel = await api.request("screen");
3294
+ const s2 = await api.request("screen");
3295
+ if (disposed) {
3296
+ s2.release().catch(() => {
3297
+ });
3298
+ return;
3299
+ }
3300
+ sentinel = s2;
3275
3301
  setActive(true);
3276
3302
  sentinel.addEventListener("release", () => {
3277
3303
  setActive(false);
@@ -3298,6 +3324,7 @@ function wakeLock() {
3298
3324
  };
3299
3325
  document.addEventListener("visibilitychange", onVisibility);
3300
3326
  function dispose2() {
3327
+ disposed = true;
3301
3328
  document.removeEventListener("visibilitychange", onVisibility);
3302
3329
  release().catch((err) => {
3303
3330
  if (typeof console !== "undefined") {
@@ -3329,6 +3356,7 @@ function animationFrame(options = {}) {
3329
3356
  let id = null;
3330
3357
  let prev = -1;
3331
3358
  let start = -1;
3359
+ let disposed = false;
3332
3360
  const minFrameMs = options.fpsLimit ? 1e3 / options.fpsLimit : 0;
3333
3361
  const step = (now) => {
3334
3362
  if (start < 0) start = now;
@@ -3342,7 +3370,7 @@ function animationFrame(options = {}) {
3342
3370
  id = requestAnimationFrame(step);
3343
3371
  };
3344
3372
  function resume() {
3345
- if (id !== null) return;
3373
+ if (disposed || id !== null) return;
3346
3374
  setRunning(true);
3347
3375
  id = requestAnimationFrame(step);
3348
3376
  }
@@ -3356,6 +3384,7 @@ function animationFrame(options = {}) {
3356
3384
  start = -1;
3357
3385
  }
3358
3386
  function dispose2() {
3387
+ disposed = true;
3359
3388
  pause();
3360
3389
  }
3361
3390
  if (options.immediate !== false) resume();
@@ -3414,7 +3443,9 @@ function bounds(target) {
3414
3443
  }
3415
3444
  };
3416
3445
  }
3446
+ let disposed = false;
3417
3447
  function refresh() {
3448
+ if (disposed) return;
3418
3449
  setRect(readRect(target));
3419
3450
  }
3420
3451
  refresh();
@@ -3426,6 +3457,7 @@ function bounds(target) {
3426
3457
  const onScroll = () => refresh();
3427
3458
  window.addEventListener("scroll", onScroll, { passive: true, capture: true });
3428
3459
  function dispose2() {
3460
+ disposed = true;
3429
3461
  resizeObserver?.disconnect();
3430
3462
  window.removeEventListener("scroll", onScroll, { capture: true });
3431
3463
  }
@@ -3871,7 +3903,14 @@ function machine(config) {
3871
3903
 
3872
3904
  // src/patterns/persist.ts
3873
3905
  function persisted(key, initial, options = {}) {
3874
- const storage = options.session ? sessionStorage : localStorage;
3906
+ const storage = (() => {
3907
+ try {
3908
+ if (options.session) return typeof sessionStorage !== "undefined" ? sessionStorage : null;
3909
+ return typeof localStorage !== "undefined" ? localStorage : null;
3910
+ } catch {
3911
+ return null;
3912
+ }
3913
+ })();
3875
3914
  const serialize = options.serialize || JSON.stringify;
3876
3915
  const safeReviver = (k, v) => isUnsafeKey(k) ? void 0 : v;
3877
3916
  const deserialize = options.deserialize || ((raw) => JSON.parse(raw, safeReviver));
@@ -3880,7 +3919,7 @@ function persisted(key, initial, options = {}) {
3880
3919
  const syncTabs = options.session ? false : options.syncTabs ?? true;
3881
3920
  let restored = initial;
3882
3921
  try {
3883
- let raw = storage.getItem(key);
3922
+ let raw = storage ? storage.getItem(key) : null;
3884
3923
  if (raw !== null) {
3885
3924
  if (decrypt) raw = decrypt(raw);
3886
3925
  const parsed = deserialize(raw);
@@ -3896,12 +3935,12 @@ function persisted(key, initial, options = {}) {
3896
3935
  try {
3897
3936
  let serialized = serialize(current);
3898
3937
  if (encrypt) serialized = encrypt(serialized);
3899
- storage.setItem(key, serialized);
3938
+ storage?.setItem(key, serialized);
3900
3939
  } catch {
3901
3940
  }
3902
3941
  });
3903
3942
  let storageListener = null;
3904
- if (syncTabs && typeof window !== "undefined") {
3943
+ if (syncTabs && storage && typeof window !== "undefined") {
3905
3944
  storageListener = (e) => {
3906
3945
  if (e.storageArea !== storage || e.key !== key) return;
3907
3946
  if (e.newValue === null) {
@@ -4204,7 +4243,7 @@ function globalStore(config) {
4204
4243
  next();
4205
4244
  }
4206
4245
  function select3(selector) {
4207
- return derived(() => selector(getState()));
4246
+ return () => selector(getState());
4208
4247
  }
4209
4248
  function subscribe(callback) {
4210
4249
  listeners.add(callback);
@@ -4381,6 +4420,67 @@ function createGuard(validator) {
4381
4420
  };
4382
4421
  }
4383
4422
 
4423
+ // src/core/rendering/dispose.ts
4424
+ var elementDisposers = /* @__PURE__ */ new WeakMap();
4425
+ var _isDev5 = isDev();
4426
+ var activeBindingCount = 0;
4427
+ function registerDisposer(node, teardown) {
4428
+ let disposers = elementDisposers.get(node);
4429
+ if (!disposers) {
4430
+ disposers = [];
4431
+ elementDisposers.set(node, disposers);
4432
+ }
4433
+ disposers.push(teardown);
4434
+ if (_isDev5) activeBindingCount++;
4435
+ }
4436
+ function dispose(node) {
4437
+ const stack = [node];
4438
+ const order = [];
4439
+ while (stack.length > 0) {
4440
+ const current = stack.pop();
4441
+ order.push(current);
4442
+ const children = Array.from(current.childNodes);
4443
+ for (let i2 = 0; i2 < children.length; i2++) {
4444
+ stack.push(children[i2]);
4445
+ }
4446
+ }
4447
+ for (let i2 = order.length - 1; i2 >= 0; i2--) {
4448
+ const current = order[i2];
4449
+ const disposers = elementDisposers.get(current);
4450
+ if (disposers) {
4451
+ const snapshot = disposers.slice();
4452
+ elementDisposers.delete(current);
4453
+ if (_isDev5) activeBindingCount -= snapshot.length;
4454
+ for (const d of snapshot) {
4455
+ try {
4456
+ d();
4457
+ } catch (err) {
4458
+ if (_isDev5 && typeof console !== "undefined") {
4459
+ console.warn("[SibuJS] Disposer threw during cleanup:", err);
4460
+ }
4461
+ }
4462
+ }
4463
+ let extraPasses = 0;
4464
+ while (extraPasses++ < 8) {
4465
+ const added = elementDisposers.get(current);
4466
+ if (!added || added.length === 0) break;
4467
+ const moreSnapshot = added.slice();
4468
+ elementDisposers.delete(current);
4469
+ if (_isDev5) activeBindingCount -= moreSnapshot.length;
4470
+ for (const d of moreSnapshot) {
4471
+ try {
4472
+ d();
4473
+ } catch (err) {
4474
+ if (_isDev5 && typeof console !== "undefined") {
4475
+ console.warn("[SibuJS] Disposer threw during cleanup:", err);
4476
+ }
4477
+ }
4478
+ }
4479
+ }
4480
+ }
4481
+ }
4482
+ }
4483
+
4384
4484
  // src/ui/transition.ts
4385
4485
  function transition(element, options = {}) {
4386
4486
  const {
@@ -4453,6 +4553,7 @@ function transition(element, options = {}) {
4453
4553
  }
4454
4554
  });
4455
4555
  }
4556
+ registerDisposer(element, cancelPending);
4456
4557
  return { enter, leave };
4457
4558
  }
4458
4559
  function spring(element, keyframes, options = {}) {
@@ -4468,8 +4569,29 @@ function spring(element, keyframes, options = {}) {
4468
4569
  });
4469
4570
  }
4470
4571
 
4572
+ // src/ui/reducedMotion.ts
4573
+ function prefersReducedMotion() {
4574
+ return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
4575
+ }
4576
+ function reducedMotion() {
4577
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
4578
+ const [reduced2] = signal(false);
4579
+ return { reduced: reduced2, dispose: () => {
4580
+ } };
4581
+ }
4582
+ const mql = window.matchMedia("(prefers-reduced-motion: reduce)");
4583
+ const [reduced, setReduced] = signal(mql.matches);
4584
+ const handler = (event) => {
4585
+ setReduced(event.matches);
4586
+ };
4587
+ mql.addEventListener("change", handler);
4588
+ function dispose2() {
4589
+ mql.removeEventListener("change", handler);
4590
+ }
4591
+ return { reduced, dispose: dispose2 };
4592
+ }
4593
+
4471
4594
  // src/ui/animationPresets.ts
4472
- var prefersReducedMotion = () => typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
4473
4595
  function createPreset(keyframes, defaults, overrides) {
4474
4596
  const opts = {
4475
4597
  ...defaults,
@@ -4638,6 +4760,7 @@ function TransitionGroup(options) {
4638
4760
  if (options.leave) {
4639
4761
  await options.leave(el);
4640
4762
  }
4763
+ positions.delete(el);
4641
4764
  setElements((prev) => prev.filter((e) => e !== el));
4642
4765
  }
4643
4766
  function track4(newElements) {
@@ -4704,27 +4827,7 @@ function viewTransition(callback) {
4704
4827
  return { start, isTransitioning };
4705
4828
  }
4706
4829
 
4707
- // src/ui/reducedMotion.ts
4708
- function reducedMotion() {
4709
- if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
4710
- const [reduced2] = signal(false);
4711
- return { reduced: reduced2, dispose: () => {
4712
- } };
4713
- }
4714
- const mql = window.matchMedia("(prefers-reduced-motion: reduce)");
4715
- const [reduced, setReduced] = signal(mql.matches);
4716
- const handler = (event) => {
4717
- setReduced(event.matches);
4718
- };
4719
- mql.addEventListener("change", handler);
4720
- function dispose2() {
4721
- mql.removeEventListener("change", handler);
4722
- }
4723
- return { reduced, dispose: dispose2 };
4724
- }
4725
-
4726
4830
  // src/ui/springSignal.ts
4727
- var prefersReducedMotion2 = () => typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
4728
4831
  function springSignal(initial, options) {
4729
4832
  const stiffness = options?.stiffness ?? 0.15;
4730
4833
  const damping = options?.damping ?? 0.8;
@@ -4760,7 +4863,7 @@ function springSignal(initial, options) {
4760
4863
  }
4761
4864
  function set(newTarget) {
4762
4865
  target = newTarget;
4763
- if (prefersReducedMotion2()) {
4866
+ if (prefersReducedMotion()) {
4764
4867
  current = newTarget;
4765
4868
  velocity = 0;
4766
4869
  if (rafId !== null) {
@@ -4856,11 +4959,32 @@ function bindField(field, extras) {
4856
4959
  change: (e) => field.set(readControlValue(e.target)),
4857
4960
  blur: () => field.touch()
4858
4961
  };
4859
- const { on: extraOn, value: _ignoreValue, ...restExtras } = extras ?? {};
4962
+ const {
4963
+ on: extraOn,
4964
+ value: _ignoreValue,
4965
+ onElement: extraOnElement,
4966
+ ...restExtras
4967
+ } = extras ?? {};
4860
4968
  const mergedOn = extraOn && typeof extraOn === "object" ? { ...extraOn, ...fieldOn } : fieldOn;
4969
+ const onElement = (el) => {
4970
+ if (el instanceof HTMLSelectElement && el.multiple) {
4971
+ const stop2 = effect(() => {
4972
+ const v = field.value();
4973
+ const selected = Array.isArray(v) ? v.map(String) : [];
4974
+ for (const opt of Array.from(el.options)) {
4975
+ opt.selected = selected.includes(opt.value);
4976
+ }
4977
+ });
4978
+ registerDisposer(el, stop2);
4979
+ }
4980
+ if (typeof extraOnElement === "function") {
4981
+ extraOnElement(el);
4982
+ }
4983
+ };
4861
4984
  return {
4862
4985
  value: field.value,
4863
4986
  on: mergedOn,
4987
+ onElement,
4864
4988
  ...restExtras
4865
4989
  };
4866
4990
  }
@@ -4917,9 +5041,21 @@ function form(config) {
4917
5041
  }
4918
5042
  return true;
4919
5043
  });
5044
+ const valueEquals = (a2, b2) => {
5045
+ if (Object.is(a2, b2)) return true;
5046
+ if (Array.isArray(a2) && Array.isArray(b2)) {
5047
+ return a2.length === b2.length && a2.every((v, i2) => Object.is(v, b2[i2]));
5048
+ }
5049
+ if (a2 && b2 && typeof a2 === "object" && typeof b2 === "object") {
5050
+ const ak = Object.keys(a2);
5051
+ const bk = Object.keys(b2);
5052
+ return ak.length === bk.length && ak.every((k) => Object.is(a2[k], b2[k]));
5053
+ }
5054
+ return false;
5055
+ };
4920
5056
  const isDirty = derived(() => {
4921
5057
  for (const [name, cfg] of fieldEntries) {
4922
- if (!Object.is(fieldMap[name].value(), cfg.initial)) return true;
5058
+ if (!valueEquals(fieldMap[name].value(), cfg.initial)) return true;
4923
5059
  }
4924
5060
  return false;
4925
5061
  });
@@ -4979,67 +5115,6 @@ function form(config) {
4979
5115
  };
4980
5116
  }
4981
5117
 
4982
- // src/core/rendering/dispose.ts
4983
- var elementDisposers = /* @__PURE__ */ new WeakMap();
4984
- var _isDev5 = isDev();
4985
- var activeBindingCount = 0;
4986
- function registerDisposer(node, teardown) {
4987
- let disposers = elementDisposers.get(node);
4988
- if (!disposers) {
4989
- disposers = [];
4990
- elementDisposers.set(node, disposers);
4991
- }
4992
- disposers.push(teardown);
4993
- if (_isDev5) activeBindingCount++;
4994
- }
4995
- function dispose(node) {
4996
- const stack = [node];
4997
- const order = [];
4998
- while (stack.length > 0) {
4999
- const current = stack.pop();
5000
- order.push(current);
5001
- const children = Array.from(current.childNodes);
5002
- for (let i2 = 0; i2 < children.length; i2++) {
5003
- stack.push(children[i2]);
5004
- }
5005
- }
5006
- for (let i2 = order.length - 1; i2 >= 0; i2--) {
5007
- const current = order[i2];
5008
- const disposers = elementDisposers.get(current);
5009
- if (disposers) {
5010
- const snapshot = disposers.slice();
5011
- elementDisposers.delete(current);
5012
- if (_isDev5) activeBindingCount -= snapshot.length;
5013
- for (const d of snapshot) {
5014
- try {
5015
- d();
5016
- } catch (err) {
5017
- if (_isDev5 && typeof console !== "undefined") {
5018
- console.warn("[SibuJS] Disposer threw during cleanup:", err);
5019
- }
5020
- }
5021
- }
5022
- let extraPasses = 0;
5023
- while (extraPasses++ < 8) {
5024
- const added = elementDisposers.get(current);
5025
- if (!added || added.length === 0) break;
5026
- const moreSnapshot = added.slice();
5027
- elementDisposers.delete(current);
5028
- if (_isDev5) activeBindingCount -= moreSnapshot.length;
5029
- for (const d of moreSnapshot) {
5030
- try {
5031
- d();
5032
- } catch (err) {
5033
- if (_isDev5 && typeof console !== "undefined") {
5034
- console.warn("[SibuJS] Disposer threw during cleanup:", err);
5035
- }
5036
- }
5037
- }
5038
- }
5039
- }
5040
- }
5041
- }
5042
-
5043
5118
  // src/ui/virtualList.ts
5044
5119
  function VirtualList(props) {
5045
5120
  const overscan = props.overscan ?? 3;
@@ -5196,7 +5271,6 @@ function inputMask(options) {
5196
5271
  return /[^a-zA-Z0-9]/g;
5197
5272
  }
5198
5273
  const stripRegex = buildStripRegex();
5199
- const rawCharTest = options.pattern.includes("*") ? () => true : (c) => /[a-zA-Z0-9]/.test(c);
5200
5274
  function bind(input2) {
5201
5275
  const onInput = () => {
5202
5276
  const cursorBefore = input2.selectionStart ?? input2.value.length;
@@ -5206,20 +5280,14 @@ function inputMask(options) {
5206
5280
  setValue(masked);
5207
5281
  setRawValue(extractRaw(masked));
5208
5282
  input2.value = masked;
5209
- let rawBefore = 0;
5210
- for (let i2 = 0; i2 < cursorBefore && i2 < oldValue.length; i2++) {
5211
- if (rawCharTest(oldValue[i2])) rawBefore++;
5212
- }
5283
+ const rawBefore = oldValue.slice(0, cursorBefore).replace(stripRegex, "").length;
5213
5284
  let newCursor = 0;
5214
5285
  let counted = 0;
5215
- for (; newCursor < masked.length; newCursor++) {
5286
+ while (newCursor < masked.length && counted < rawBefore) {
5216
5287
  if (newCursor < options.pattern.length && isSlot(options.pattern[newCursor])) {
5217
5288
  counted++;
5218
- if (counted >= rawBefore) {
5219
- newCursor++;
5220
- break;
5221
- }
5222
5289
  }
5290
+ newCursor++;
5223
5291
  }
5224
5292
  try {
5225
5293
  input2.setSelectionRange(newCursor, newCursor);
@@ -5418,14 +5486,12 @@ function hotkey(combo, handler, options = {}) {
5418
5486
  document.addEventListener("keydown", listener);
5419
5487
  return () => document.removeEventListener("keydown", listener);
5420
5488
  }
5421
- var announceQueues = {
5422
- polite: [],
5423
- assertive: []
5424
- };
5425
- var announceDraining = {
5426
- polite: false,
5427
- assertive: false
5428
- };
5489
+ var _announce = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.a11y.announce.v1"), () => ({
5490
+ queues: { polite: [], assertive: [] },
5491
+ draining: { polite: false, assertive: false }
5492
+ }));
5493
+ var announceQueues = _announce.queues;
5494
+ var announceDraining = _announce.draining;
5429
5495
  var ANNOUNCE_INTERVAL_MS = 150;
5430
5496
  function ensureLiveRegion(priority) {
5431
5497
  let region = document.getElementById(`sibu-announce-${priority}`);
@@ -5467,7 +5533,7 @@ function announce(message, priority = "polite") {
5467
5533
  }
5468
5534
 
5469
5535
  // src/ui/scopedStyle.ts
5470
- var scopeCounter = 0;
5536
+ var _scope = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.scopedStyle.v1"), () => ({ n: 0 }));
5471
5537
  function decodeCssEscapes(css) {
5472
5538
  return css.replace(/\\([0-9a-f]{1,6})[ \t\n\r\f]?|\\([^\n])/gi, (_match, hex, ch) => {
5473
5539
  if (hex) {
@@ -5494,7 +5560,7 @@ function sanitizeCSS(css) {
5494
5560
  return sanitized;
5495
5561
  }
5496
5562
  function scopedStyle(css) {
5497
- const id = `sibu-s${scopeCounter++}`;
5563
+ const id = `sibu-s${_scope.n++}`;
5498
5564
  const attr = `data-${id}`;
5499
5565
  const safeCss = sanitizeCSS(css);
5500
5566
  const scopedCSS = safeCss.replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/g, (match, selector, delimiter) => {
@@ -5644,13 +5710,16 @@ function bindData(el, key, getter) {
5644
5710
  }
5645
5711
 
5646
5712
  // src/ui/dialog.ts
5647
- var dialogStack = [];
5648
- var globalListenerAttached = false;
5713
+ var _dlg = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.dialog.v1"), () => ({
5714
+ stack: [],
5715
+ listenerAttached: false
5716
+ }));
5717
+ var dialogStack = _dlg.stack;
5649
5718
  function __resetDialogStack() {
5650
5719
  while (dialogStack.length > 0) dialogStack.pop();
5651
- if (typeof window !== "undefined" && globalListenerAttached) {
5720
+ if (typeof window !== "undefined" && _dlg.listenerAttached) {
5652
5721
  window.removeEventListener("keydown", handleGlobalKeydown);
5653
- globalListenerAttached = false;
5722
+ _dlg.listenerAttached = false;
5654
5723
  }
5655
5724
  }
5656
5725
  function handleGlobalKeydown(event) {
@@ -5659,16 +5728,16 @@ function handleGlobalKeydown(event) {
5659
5728
  if (top) top.close();
5660
5729
  }
5661
5730
  function ensureGlobalListener() {
5662
- if (typeof window === "undefined" || globalListenerAttached) return;
5731
+ if (typeof window === "undefined" || _dlg.listenerAttached) return;
5663
5732
  window.addEventListener("keydown", handleGlobalKeydown);
5664
- globalListenerAttached = true;
5733
+ _dlg.listenerAttached = true;
5665
5734
  }
5666
5735
  function removeGlobalListenerIfIdle() {
5667
5736
  if (typeof window === "undefined") return;
5668
- if (!globalListenerAttached) return;
5737
+ if (!_dlg.listenerAttached) return;
5669
5738
  if (dialogStack.length > 0) return;
5670
5739
  window.removeEventListener("keydown", handleGlobalKeydown);
5671
- globalListenerAttached = false;
5740
+ _dlg.listenerAttached = false;
5672
5741
  }
5673
5742
  function dialog() {
5674
5743
  const [isOpen, setIsOpen] = signal(false);
@@ -5794,6 +5863,10 @@ function infiniteScroll(options) {
5794
5863
  await onLoadMore();
5795
5864
  } finally {
5796
5865
  setLoading(false);
5866
+ if (!disposed && observer && _current && hasMore()) {
5867
+ observer.unobserve(_current);
5868
+ observer.observe(_current);
5869
+ }
5797
5870
  }
5798
5871
  }
5799
5872
  const originalRef = sentinelRef;
@@ -5833,29 +5906,30 @@ function pagination(options) {
5833
5906
  const total = options.totalItems();
5834
5907
  return Math.max(1, Math.ceil(total / pageSizeValue));
5835
5908
  });
5909
+ const currentPage = derived(() => Math.min(Math.max(1, page()), totalPages()));
5836
5910
  const startIndex = derived(() => {
5837
- return (page() - 1) * pageSizeValue;
5911
+ return (currentPage() - 1) * pageSizeValue;
5838
5912
  });
5839
5913
  const endIndex = derived(() => {
5840
- const end = page() * pageSizeValue;
5914
+ const end = currentPage() * pageSizeValue;
5841
5915
  const total = options.totalItems();
5842
5916
  return Math.min(end, total);
5843
5917
  });
5844
5918
  function next() {
5845
- if (page() < totalPages()) {
5846
- setPage((p2) => p2 + 1);
5919
+ if (currentPage() < totalPages()) {
5920
+ setPage(currentPage() + 1);
5847
5921
  }
5848
5922
  }
5849
5923
  function prev() {
5850
- if (page() > 1) {
5851
- setPage((p2) => p2 - 1);
5924
+ if (currentPage() > 1) {
5925
+ setPage(currentPage() - 1);
5852
5926
  }
5853
5927
  }
5854
5928
  function goTo(target) {
5855
5929
  const clamped = Math.max(1, Math.min(target, totalPages()));
5856
5930
  setPage(clamped);
5857
5931
  }
5858
- return { page, pageSize, totalPages, next, prev, goTo, startIndex, endIndex };
5932
+ return { page: currentPage, pageSize, totalPages, next, prev, goTo, startIndex, endIndex };
5859
5933
  }
5860
5934
 
5861
5935
  // src/ui/eventBus.ts
@@ -5901,12 +5975,15 @@ var Priority = {
5901
5975
  LOW: 3,
5902
5976
  IDLE: 4
5903
5977
  };
5904
- var taskIdCounter = 0;
5905
- var taskQueue = [];
5906
- var isProcessing = false;
5907
- var scheduledKind = null;
5908
- var scheduledHandle = null;
5909
- var microtaskScheduled = false;
5978
+ var _sched = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.scheduler.v1"), () => ({
5979
+ taskIdCounter: 0,
5980
+ taskQueue: [],
5981
+ isProcessing: false,
5982
+ scheduledKind: null,
5983
+ scheduledHandle: null,
5984
+ microtaskScheduled: false
5985
+ }));
5986
+ var taskQueue = _sched.taskQueue;
5910
5987
  function insertTask(task) {
5911
5988
  let i2 = taskQueue.length;
5912
5989
  while (i2 > 0 && taskQueue[i2 - 1].priority > task.priority) {
@@ -5915,8 +5992,8 @@ function insertTask(task) {
5915
5992
  taskQueue.splice(i2, 0, task);
5916
5993
  }
5917
5994
  function processQueue() {
5918
- if (isProcessing || taskQueue.length === 0) return;
5919
- isProcessing = true;
5995
+ if (_sched.isProcessing || taskQueue.length === 0) return;
5996
+ _sched.isProcessing = true;
5920
5997
  const startTime = performance.now();
5921
5998
  const timeSlice = 5;
5922
5999
  while (taskQueue.length > 0) {
@@ -5935,64 +6012,69 @@ function processQueue() {
5935
6012
  console.error("[Scheduler] Task error:", e);
5936
6013
  }
5937
6014
  }
5938
- isProcessing = false;
6015
+ _sched.isProcessing = false;
5939
6016
  if (taskQueue.length > 0) {
5940
6017
  scheduleFrame();
5941
6018
  }
5942
6019
  }
5943
6020
  var TIER_SPEED = { microtask: 0, frame: 1, timeout: 2, idle: 3 };
5944
6021
  function cancelScheduled() {
5945
- if (scheduledHandle !== null) {
5946
- if (scheduledKind === "frame") cancelAnimationFrame(scheduledHandle);
5947
- else if (scheduledKind === "idle" && typeof cancelIdleCallback !== "undefined") cancelIdleCallback(scheduledHandle);
5948
- else if (scheduledKind === "timeout") clearTimeout(scheduledHandle);
6022
+ if (_sched.scheduledHandle !== null) {
6023
+ if (_sched.scheduledKind === "frame") cancelAnimationFrame(_sched.scheduledHandle);
6024
+ else if (_sched.scheduledKind === "idle" && typeof cancelIdleCallback !== "undefined")
6025
+ cancelIdleCallback(_sched.scheduledHandle);
6026
+ else if (_sched.scheduledKind === "timeout") clearTimeout(_sched.scheduledHandle);
5949
6027
  }
5950
- scheduledHandle = null;
5951
- scheduledKind = null;
6028
+ _sched.scheduledHandle = null;
6029
+ _sched.scheduledKind = null;
5952
6030
  }
5953
6031
  function scheduleFrame() {
5954
6032
  const nextTask = taskQueue.find((t) => !t.cancelled);
5955
6033
  if (!nextTask) return;
5956
- const desired = nextTask.priority <= Priority.USER_BLOCKING ? "microtask" : nextTask.priority === Priority.IDLE ? typeof requestIdleCallback !== "undefined" ? "idle" : "timeout" : "frame";
5957
- if (microtaskScheduled) return;
5958
- if (scheduledKind !== null) {
5959
- if (TIER_SPEED[scheduledKind] <= TIER_SPEED[desired]) return;
6034
+ const desired = nextTask.priority <= Priority.USER_BLOCKING ? "microtask" : nextTask.priority === Priority.IDLE ? typeof requestIdleCallback !== "undefined" ? "idle" : "timeout" : (
6035
+ // NORMAL/LOW prefer a frame, but rAF is absent under SSR — fall back
6036
+ // to a timeout so startTransition()/deferredValue() don't throw.
6037
+ typeof requestAnimationFrame !== "undefined" ? "frame" : "timeout"
6038
+ );
6039
+ if (_sched.microtaskScheduled) return;
6040
+ if (_sched.scheduledKind !== null) {
6041
+ if (TIER_SPEED[_sched.scheduledKind] <= TIER_SPEED[desired]) return;
5960
6042
  cancelScheduled();
5961
6043
  }
5962
6044
  if (desired === "microtask") {
5963
- microtaskScheduled = true;
5964
- scheduledKind = "microtask";
6045
+ _sched.microtaskScheduled = true;
6046
+ _sched.scheduledKind = "microtask";
5965
6047
  queueMicrotask(() => {
5966
- microtaskScheduled = false;
5967
- scheduledKind = null;
6048
+ _sched.microtaskScheduled = false;
6049
+ _sched.scheduledKind = null;
5968
6050
  processQueue();
5969
6051
  });
5970
6052
  } else if (desired === "idle") {
5971
- scheduledKind = "idle";
5972
- scheduledHandle = requestIdleCallback(() => {
5973
- scheduledKind = null;
5974
- scheduledHandle = null;
6053
+ _sched.scheduledKind = "idle";
6054
+ _sched.scheduledHandle = requestIdleCallback(() => {
6055
+ _sched.scheduledKind = null;
6056
+ _sched.scheduledHandle = null;
5975
6057
  processQueue();
5976
6058
  });
5977
6059
  } else if (desired === "timeout") {
5978
- scheduledKind = "timeout";
5979
- scheduledHandle = setTimeout(() => {
5980
- scheduledKind = null;
5981
- scheduledHandle = null;
6060
+ _sched.scheduledKind = "timeout";
6061
+ _sched.scheduledHandle = setTimeout(() => {
6062
+ _sched.scheduledKind = null;
6063
+ _sched.scheduledHandle = null;
5982
6064
  processQueue();
5983
6065
  }, 50);
5984
6066
  } else {
5985
- scheduledKind = "frame";
5986
- scheduledHandle = requestAnimationFrame(() => {
5987
- scheduledKind = null;
5988
- scheduledHandle = null;
6067
+ _sched.scheduledKind = "frame";
6068
+ _sched.scheduledHandle = requestAnimationFrame(() => {
6069
+ _sched.scheduledKind = null;
6070
+ _sched.scheduledHandle = null;
5989
6071
  processQueue();
5990
6072
  });
5991
6073
  }
5992
6074
  }
5993
6075
  function scheduleUpdate(priority, callback) {
5994
6076
  const task = {
5995
- id: taskIdCounter++,
6077
+ id: _sched.taskIdCounter++,
5996
6078
  priority,
5997
6079
  callback,
5998
6080
  cancelled: false
@@ -6013,15 +6095,15 @@ function scheduleUpdate(priority, callback) {
6013
6095
  };
6014
6096
  }
6015
6097
  function flushScheduler() {
6016
- if (scheduledHandle !== null) {
6017
- if (scheduledKind === "frame") cancelAnimationFrame(scheduledHandle);
6018
- else if (scheduledKind === "idle" && typeof cancelIdleCallback !== "undefined") {
6019
- cancelIdleCallback(scheduledHandle);
6020
- } else if (scheduledKind === "timeout") clearTimeout(scheduledHandle);
6021
- }
6022
- scheduledHandle = null;
6023
- scheduledKind = null;
6024
- microtaskScheduled = false;
6098
+ if (_sched.scheduledHandle !== null) {
6099
+ if (_sched.scheduledKind === "frame") cancelAnimationFrame(_sched.scheduledHandle);
6100
+ else if (_sched.scheduledKind === "idle" && typeof cancelIdleCallback !== "undefined") {
6101
+ cancelIdleCallback(_sched.scheduledHandle);
6102
+ } else if (_sched.scheduledKind === "timeout") clearTimeout(_sched.scheduledHandle);
6103
+ }
6104
+ _sched.scheduledHandle = null;
6105
+ _sched.scheduledKind = null;
6106
+ _sched.microtaskScheduled = false;
6025
6107
  while (taskQueue.length > 0) {
6026
6108
  const task = taskQueue.shift();
6027
6109
  if (!task) break;
@@ -6029,7 +6111,7 @@ function flushScheduler() {
6029
6111
  task.callback();
6030
6112
  }
6031
6113
  }
6032
- isProcessing = false;
6114
+ _sched.isProcessing = false;
6033
6115
  }
6034
6116
  function pendingTasks() {
6035
6117
  return taskQueue.filter((t) => !t.cancelled).length;
@@ -6077,16 +6159,18 @@ function transitionState() {
6077
6159
  }
6078
6160
  return [isPending, transition2];
6079
6161
  }
6080
- var idCounter = 0;
6081
- var idPrefix = "sibu";
6162
+ var _ids = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.uniqueId.v1"), () => ({
6163
+ counter: 0,
6164
+ prefix: "sibu"
6165
+ }));
6082
6166
  function resetIdCounter() {
6083
- idCounter = 0;
6167
+ _ids.counter = 0;
6084
6168
  }
6085
6169
  function setIdPrefix(prefix) {
6086
- idPrefix = prefix;
6170
+ _ids.prefix = prefix;
6087
6171
  }
6088
6172
  function uniqueId(suffix) {
6089
- const id = `${idPrefix}-${idCounter++}`;
6173
+ const id = `${_ids.prefix}-${_ids.counter++}`;
6090
6174
  return suffix ? `${id}-${suffix}` : id;
6091
6175
  }
6092
6176
 
@@ -6834,7 +6918,6 @@ function normalizedStore(schema) {
6834
6918
  }
6835
6919
  function normalize(data2, schema) {
6836
6920
  const entities = {};
6837
- const idKey = schema.idKey || "id";
6838
6921
  function ensureTable(name) {
6839
6922
  if (!entities[name]) {
6840
6923
  entities[name] = {};
@@ -6850,7 +6933,7 @@ function normalize(data2, schema) {
6850
6933
  for (const [field, relationType] of Object.entries(entitySchema.relations)) {
6851
6934
  const value = entity[field];
6852
6935
  if (value == null) continue;
6853
- const relSchema = { name: relationType, idKey };
6936
+ const relSchema = { name: relationType };
6854
6937
  if (Array.isArray(value)) {
6855
6938
  flat[field] = value.map((item) => normalizeEntity(item, relSchema));
6856
6939
  } else if (typeof value === "object") {
@@ -6873,13 +6956,12 @@ function denormalize(id, entities, schema) {
6873
6956
  if (!table2) return void 0;
6874
6957
  const entity = table2[id];
6875
6958
  if (!entity) return void 0;
6876
- const idKey = schema.idKey || "id";
6877
6959
  const result = { ...entity };
6878
6960
  if (schema.relations) {
6879
6961
  for (const [field, relationType] of Object.entries(schema.relations)) {
6880
6962
  const value = entity[field];
6881
6963
  if (value == null) continue;
6882
- const relSchema = { name: relationType, idKey };
6964
+ const relSchema = { name: relationType };
6883
6965
  if (Array.isArray(value)) {
6884
6966
  result[field] = value.map((relId) => denormalize(relId, entities, relSchema));
6885
6967
  } else if (typeof value === "string") {
@@ -7212,6 +7294,7 @@ function Head(props) {
7212
7294
  }
7213
7295
  };
7214
7296
  apply();
7297
+ registerDisposer(anchor, cleanup3);
7215
7298
  return anchor;
7216
7299
  }
7217
7300
  function setStructuredData(data2) {
@@ -7526,8 +7609,14 @@ function createWorkerPool(workerFn2, poolSize) {
7526
7609
  }
7527
7610
 
7528
7611
  // src/platform/wasm.ts
7529
- var moduleCache = /* @__PURE__ */ new Map();
7530
- var instanceCache = /* @__PURE__ */ new Map();
7612
+ var moduleCache = globalSingleton(
7613
+ /* @__PURE__ */ Symbol.for("sibujs.wasm.moduleCache.v1"),
7614
+ () => /* @__PURE__ */ new Map()
7615
+ );
7616
+ var instanceCache = globalSingleton(
7617
+ /* @__PURE__ */ Symbol.for("sibujs.wasm.instanceCache.v1"),
7618
+ () => /* @__PURE__ */ new Map()
7619
+ );
7531
7620
  function wasm(source2, config = {}) {
7532
7621
  const [instance, setInstance] = signal(null);
7533
7622
  const [loading, setLoading] = signal(true);
@@ -8157,7 +8246,10 @@ var font = tagFactory("font");
8157
8246
  var marquee = tagFactory("marquee");
8158
8247
 
8159
8248
  // src/platform/microfrontend.ts
8160
- var moduleCache2 = /* @__PURE__ */ new Map();
8249
+ var moduleCache2 = globalSingleton(
8250
+ /* @__PURE__ */ Symbol.for("sibujs.microfrontend.moduleCache.v1"),
8251
+ () => /* @__PURE__ */ new Map()
8252
+ );
8161
8253
  function createMicroApp(config) {
8162
8254
  const host = config.container ?? document.createElement("div");
8163
8255
  host.setAttribute("data-micro-app", config.name);
@@ -8428,24 +8520,30 @@ function createAction(actionFn) {
8428
8520
  const [data2, setData] = signal(void 0);
8429
8521
  const [error, setError] = signal(void 0);
8430
8522
  const [loading, setLoading] = signal(false);
8523
+ let activeRun = 0;
8431
8524
  const submit = async (input2) => {
8525
+ const runId = ++activeRun;
8432
8526
  batch(() => {
8433
8527
  setLoading(true);
8434
8528
  setError(void 0);
8435
8529
  });
8436
8530
  try {
8437
8531
  const result = await actionFn(input2);
8438
- batch(() => {
8439
- setData(result);
8440
- setLoading(false);
8441
- });
8532
+ if (runId === activeRun) {
8533
+ batch(() => {
8534
+ setData(result);
8535
+ setLoading(false);
8536
+ });
8537
+ }
8442
8538
  return result;
8443
8539
  } catch (err) {
8444
8540
  const actionError = err instanceof Error ? err : new Error(String(err));
8445
- batch(() => {
8446
- setError(actionError);
8447
- setLoading(false);
8448
- });
8541
+ if (runId === activeRun) {
8542
+ batch(() => {
8543
+ setError(actionError);
8544
+ setLoading(false);
8545
+ });
8546
+ }
8449
8547
  throw actionError;
8450
8548
  }
8451
8549
  };
@@ -8459,15 +8557,14 @@ function scrollRestoration(options) {
8459
8557
  let popstateHandler = null;
8460
8558
  let currentKey = null;
8461
8559
  const save = (key) => {
8462
- positions.set(key, {
8463
- x: window.scrollX,
8464
- y: window.scrollY
8465
- });
8560
+ if (typeof window !== "undefined") {
8561
+ positions.set(key, { x: window.scrollX, y: window.scrollY });
8562
+ }
8466
8563
  currentKey = key;
8467
8564
  };
8468
8565
  const restore = (key) => {
8469
8566
  const pos = positions.get(key);
8470
- if (pos) {
8567
+ if (pos && typeof window !== "undefined") {
8471
8568
  window.scrollTo(pos.x, pos.y);
8472
8569
  }
8473
8570
  currentKey = key;
@@ -8475,7 +8572,7 @@ function scrollRestoration(options) {
8475
8572
  const getPosition = (key) => {
8476
8573
  return positions.get(key);
8477
8574
  };
8478
- if (mode === "auto") {
8575
+ if (mode === "auto" && typeof window !== "undefined") {
8479
8576
  popstateHandler = () => {
8480
8577
  if (currentKey) {
8481
8578
  save(currentKey);
@@ -8603,39 +8700,41 @@ function createPluginRegistry() {
8603
8700
  };
8604
8701
  return registry;
8605
8702
  }
8606
- var defaultRegistry = createPluginRegistry();
8607
- var defaultRegistryTouched = false;
8703
+ var _defaults = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.plugins.defaultRegistry.v1"), () => ({
8704
+ registry: createPluginRegistry(),
8705
+ touched: false
8706
+ }));
8608
8707
  function createPlugin(name, install) {
8609
8708
  return { name, install };
8610
8709
  }
8611
8710
  function plugin(plugin2, options) {
8612
- defaultRegistryTouched = true;
8613
- defaultRegistry.plugin(plugin2, options);
8711
+ _defaults.touched = true;
8712
+ _defaults.registry.plugin(plugin2, options);
8614
8713
  }
8615
8714
  function inject(key, defaultValue) {
8616
- return defaultRegistry.inject(key, defaultValue);
8715
+ return _defaults.registry.inject(key, defaultValue);
8617
8716
  }
8618
8717
  function triggerPluginMount(element) {
8619
- defaultRegistry.triggerMount(element);
8718
+ _defaults.registry.triggerMount(element);
8620
8719
  }
8621
8720
  function triggerPluginUnmount(element) {
8622
- defaultRegistry.triggerUnmount(element);
8721
+ _defaults.registry.triggerUnmount(element);
8623
8722
  }
8624
8723
  function triggerPluginError(error) {
8625
- defaultRegistry.triggerError(error);
8724
+ _defaults.registry.triggerError(error);
8626
8725
  }
8627
8726
  function resetPlugins() {
8628
- defaultRegistry.reset();
8629
- defaultRegistryTouched = false;
8727
+ _defaults.registry.reset();
8728
+ _defaults.touched = false;
8630
8729
  }
8631
8730
  function setDefaultPluginRegistry(registry) {
8632
- if (defaultRegistryTouched && defaultRegistry.installedPlugins.size > 0) {
8731
+ if (_defaults.touched && _defaults.registry.installedPlugins.size > 0) {
8633
8732
  console.warn(
8634
8733
  "[Plugin] Replacing default plugin registry while plugins are already installed on the singleton. This may indicate mixed singleton/registry usage."
8635
8734
  );
8636
8735
  }
8637
- defaultRegistry = registry;
8638
- defaultRegistryTouched = true;
8736
+ _defaults.registry = registry;
8737
+ _defaults.touched = true;
8639
8738
  }
8640
8739
 
8641
8740
  // src/plugins/modular.ts
@@ -8737,9 +8836,7 @@ function lazyModule(loader) {
8737
8836
  return loadedFlag;
8738
8837
  },
8739
8838
  async get() {
8740
- if (loadedFlag && cached !== void 0) {
8741
- return cached;
8742
- }
8839
+ if (loadedFlag) return cached;
8743
8840
  cached = await loader();
8744
8841
  loadedFlag = true;
8745
8842
  return cached;
@@ -9467,10 +9564,50 @@ function createGlobalHook() {
9467
9564
  listeners.set(event, set);
9468
9565
  }
9469
9566
  set.add(fn);
9567
+ return () => {
9568
+ set?.delete(fn);
9569
+ };
9470
9570
  },
9471
9571
  off(event, fn) {
9472
9572
  listeners.get(event)?.delete(fn);
9473
9573
  },
9574
+ getSignalNodes() {
9575
+ const out = [];
9576
+ for (const [, node] of nodes) {
9577
+ let value = "";
9578
+ try {
9579
+ const ref = node.ref;
9580
+ let raw;
9581
+ if (node.type === "effect") {
9582
+ raw = void 0;
9583
+ } else if (node.type === "computed" && ref) {
9584
+ raw = ref._v;
9585
+ } else if (ref && "value" in ref) {
9586
+ raw = ref.value;
9587
+ }
9588
+ if (raw === void 0) value = "undefined";
9589
+ else if (raw === null) value = "null";
9590
+ else if (typeof raw === "object") value = JSON.stringify(raw);
9591
+ else value = String(raw);
9592
+ } catch {
9593
+ value = "?";
9594
+ }
9595
+ if (value.length > 200) value = `${value.slice(0, 200)}...`;
9596
+ out.push({
9597
+ id: String(node.id),
9598
+ name: node.name || null,
9599
+ kind: node.type === "computed" ? "derived" : node.type,
9600
+ value,
9601
+ // Edge identities aren't tracked by this registry (only a subscriber
9602
+ // count, via node.ref.__sc) — left empty until the core exposes the
9603
+ // dependency graph. The node inventory itself is real.
9604
+ subscribers: [],
9605
+ dependencies: [],
9606
+ evalCount: 0
9607
+ });
9608
+ }
9609
+ return out;
9610
+ },
9474
9611
  emit(event, payload) {
9475
9612
  events.push({ event, payload, ts: Date.now() });
9476
9613
  if (events.length > 2e3) events.splice(0, events.length - 2e3);
@@ -9496,34 +9633,38 @@ function getOrCreateHook() {
9496
9633
  }
9497
9634
  return g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
9498
9635
  }
9499
- var activeDevTools = null;
9500
- var nextNodeId = 0;
9501
- var inferNameArmed = false;
9636
+ var _dt = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.devtools.state.v1"), () => ({
9637
+ active: null,
9638
+ nextNodeId: 0,
9639
+ // Gate for inferName(): only `true` while devtools are initialized AND in dev
9640
+ // mode — otherwise skip the Error-stack walk so prod hot paths don't allocate.
9641
+ inferNameArmed: false
9642
+ }));
9502
9643
  function getActiveDevTools() {
9503
- return activeDevTools;
9644
+ return _dt.active;
9504
9645
  }
9505
9646
  function initDevTools(config) {
9506
9647
  const maxEvents = config?.maxEvents ?? 1e3;
9507
9648
  const enabled = config?.enabled ?? isDev();
9508
9649
  const expose = config?.expose ?? isDev();
9509
9650
  if (!enabled) return createNoopApi();
9510
- inferNameArmed = true;
9651
+ _dt.inferNameArmed = true;
9511
9652
  const hook = getOrCreateHook();
9512
- nextNodeId = 0;
9653
+ _dt.nextNodeId = 0;
9513
9654
  const eventLog = [];
9514
9655
  hook.on("signal:create", (payload) => {
9515
9656
  const p2 = payload;
9516
- nextNodeId++;
9657
+ _dt.nextNodeId++;
9517
9658
  const name = inferName();
9518
9659
  const node = {
9519
- id: nextNodeId,
9660
+ id: _dt.nextNodeId,
9520
9661
  type: "signal",
9521
9662
  name,
9522
9663
  ref: p2.signal,
9523
9664
  getter: p2.getter,
9524
9665
  createdAt: Date.now()
9525
9666
  };
9526
- hook.nodes.set(nextNodeId, node);
9667
+ hook.nodes.set(_dt.nextNodeId, node);
9527
9668
  emit();
9528
9669
  });
9529
9670
  hook.on("signal:update", (payload) => {
@@ -9543,17 +9684,17 @@ function initDevTools(config) {
9543
9684
  });
9544
9685
  hook.on("computed:create", (payload) => {
9545
9686
  const p2 = payload;
9546
- nextNodeId++;
9687
+ _dt.nextNodeId++;
9547
9688
  const name = inferName();
9548
9689
  const node = {
9549
- id: nextNodeId,
9690
+ id: _dt.nextNodeId,
9550
9691
  type: "computed",
9551
9692
  name,
9552
9693
  ref: p2.signal,
9553
9694
  getter: p2.getter,
9554
9695
  createdAt: Date.now()
9555
9696
  };
9556
- hook.nodes.set(nextNodeId, node);
9697
+ hook.nodes.set(_dt.nextNodeId, node);
9557
9698
  emit();
9558
9699
  });
9559
9700
  hook.on("computed:update", (payload) => {
@@ -9570,11 +9711,11 @@ function initDevTools(config) {
9570
9711
  emit();
9571
9712
  });
9572
9713
  hook.on("effect:create", (payload) => {
9573
- nextNodeId++;
9714
+ _dt.nextNodeId++;
9574
9715
  const name = inferName();
9575
9716
  const p2 = payload;
9576
- const node = { id: nextNodeId, type: "effect", name, ref: p2.effectFn, createdAt: Date.now() };
9577
- hook.nodes.set(nextNodeId, node);
9717
+ const node = { id: _dt.nextNodeId, type: "effect", name, ref: p2.effectFn, createdAt: Date.now() };
9718
+ hook.nodes.set(_dt.nextNodeId, node);
9578
9719
  emit();
9579
9720
  });
9580
9721
  hook.on("effect:run", (payload) => {
@@ -9731,8 +9872,8 @@ function initDevTools(config) {
9731
9872
  hook.components.clear();
9732
9873
  hook.events.length = 0;
9733
9874
  isActive = false;
9734
- inferNameArmed = false;
9735
- activeDevTools = null;
9875
+ _dt.inferNameArmed = false;
9876
+ _dt.active = null;
9736
9877
  const g2 = globalThis;
9737
9878
  if (g2.__SIBU__) {
9738
9879
  delete g2.__SIBU__.devtools;
@@ -9900,7 +10041,7 @@ function initDevTools(config) {
9900
10041
  w.__SIBU_DEVTOOLS_VERSION__ = () => changeVersion;
9901
10042
  w.__SIBU_DEVTOOLS_DATA__ = buildData;
9902
10043
  }
9903
- activeDevTools = api;
10044
+ _dt.active = api;
9904
10045
  if (typeof document !== "undefined") {
9905
10046
  domObserver = new MutationObserver((mutations) => {
9906
10047
  let changed = false;
@@ -9976,7 +10117,7 @@ function initDevTools(config) {
9976
10117
  return api;
9977
10118
  }
9978
10119
  function inferName() {
9979
- if (!inferNameArmed || !isDev()) return "anonymous";
10120
+ if (!_dt.inferNameArmed || !isDev()) return "anonymous";
9980
10121
  try {
9981
10122
  const stack = new Error().stack || "";
9982
10123
  for (const line2 of stack.split("\n")) {
@@ -10057,7 +10198,7 @@ function devState(name, initial) {
10057
10198
  const oldValue = get();
10058
10199
  set(next);
10059
10200
  const newValue = get();
10060
- const dt2 = activeDevTools;
10201
+ const dt2 = _dt.active;
10061
10202
  if (dt2?.isEnabled() && !Object.is(oldValue, newValue)) {
10062
10203
  dt2.record({ type: "state-change", component, key, oldValue, newValue, timestamp: Date.now() });
10063
10204
  }
@@ -10508,6 +10649,14 @@ function createDevtoolsOverlay(options) {
10508
10649
  return { isEnabled, toggle, addPanel, removePanel, getPanels, dispose: dispose2 };
10509
10650
  }
10510
10651
 
10652
+ // src/core/rendering/createId.ts
10653
+ var COUNTER_KEY = /* @__PURE__ */ Symbol.for("sibujs.createId.v1");
10654
+ var _counter = globalThis[COUNTER_KEY] ?? (globalThis[COUNTER_KEY] = { n: 0 });
10655
+ function createId(prefix = "sibu") {
10656
+ _counter.n++;
10657
+ return `${prefix}-${_counter.n}`;
10658
+ }
10659
+
10511
10660
  // src/core/signals/watch.ts
10512
10661
  function watch(getter, callback) {
10513
10662
  devAssert(typeof getter === "function", "watch: first argument must be a getter function.");
@@ -10539,7 +10688,6 @@ function watch(getter, callback) {
10539
10688
  }
10540
10689
 
10541
10690
  // src/widgets/Combobox.ts
10542
- var comboboxIdCounter = 0;
10543
10691
  var boundComboboxes = /* @__PURE__ */ new WeakMap();
10544
10692
  function combobox(options) {
10545
10693
  const { items, filterFn, itemToString } = options;
@@ -10600,7 +10748,13 @@ function combobox(options) {
10600
10748
  function bind(els) {
10601
10749
  const existing = boundComboboxes.get(els.input);
10602
10750
  if (existing) return existing;
10603
- const listboxId = `sibu-combobox-listbox-${++comboboxIdCounter}`;
10751
+ const prevListboxId = els.listbox.id;
10752
+ const prevListboxRole = els.listbox.getAttribute("role");
10753
+ const prevListboxHidden = els.listbox.hidden;
10754
+ const prevInputRole = els.input.getAttribute("role");
10755
+ const prevInputAutocomplete = els.input.getAttribute("aria-autocomplete");
10756
+ const prevInputControls = els.input.getAttribute("aria-controls");
10757
+ const listboxId = createId("sibu-combobox-listbox");
10604
10758
  els.listbox.id = listboxId;
10605
10759
  els.listbox.setAttribute("role", "listbox");
10606
10760
  els.input.setAttribute("role", "combobox");
@@ -10664,10 +10818,14 @@ function combobox(options) {
10664
10818
  if (document.activeElement !== els.input) close();
10665
10819
  }, 100);
10666
10820
  };
10821
+ const onListboxPointerDown = (e) => {
10822
+ e.preventDefault();
10823
+ };
10667
10824
  els.input.addEventListener("input", onInput);
10668
10825
  els.input.addEventListener("keydown", onKey);
10669
10826
  els.input.addEventListener("focus", onFocus);
10670
10827
  els.input.addEventListener("blur", onBlur);
10828
+ els.listbox.addEventListener("mousedown", onListboxPointerDown);
10671
10829
  const teardown = () => {
10672
10830
  boundComboboxes.delete(els.input);
10673
10831
  fxTeardown();
@@ -10675,10 +10833,24 @@ function combobox(options) {
10675
10833
  els.input.removeEventListener("keydown", onKey);
10676
10834
  els.input.removeEventListener("focus", onFocus);
10677
10835
  els.input.removeEventListener("blur", onBlur);
10836
+ els.listbox.removeEventListener("mousedown", onListboxPointerDown);
10678
10837
  if (blurTimer !== null) {
10679
10838
  clearTimeout(blurTimer);
10680
10839
  blurTimer = null;
10681
10840
  }
10841
+ if (prevListboxId === "") els.listbox.removeAttribute("id");
10842
+ else els.listbox.id = prevListboxId;
10843
+ if (prevListboxRole === null) els.listbox.removeAttribute("role");
10844
+ else els.listbox.setAttribute("role", prevListboxRole);
10845
+ els.listbox.hidden = prevListboxHidden;
10846
+ if (prevInputRole === null) els.input.removeAttribute("role");
10847
+ else els.input.setAttribute("role", prevInputRole);
10848
+ if (prevInputAutocomplete === null) els.input.removeAttribute("aria-autocomplete");
10849
+ else els.input.setAttribute("aria-autocomplete", prevInputAutocomplete);
10850
+ if (prevInputControls === null) els.input.removeAttribute("aria-controls");
10851
+ else els.input.setAttribute("aria-controls", prevInputControls);
10852
+ els.input.removeAttribute("aria-expanded");
10853
+ els.input.removeAttribute("aria-activedescendant");
10682
10854
  };
10683
10855
  boundComboboxes.set(els.input, teardown);
10684
10856
  return teardown;
@@ -11014,7 +11186,6 @@ function accordion(options) {
11014
11186
  }
11015
11187
 
11016
11188
  // src/widgets/Popover.ts
11017
- var popoverIdCounter = 0;
11018
11189
  var boundPopovers = /* @__PURE__ */ new WeakMap();
11019
11190
  function popover() {
11020
11191
  const [isOpen, setIsOpen] = signal(false);
@@ -11030,7 +11201,7 @@ function popover() {
11030
11201
  function bind(els) {
11031
11202
  const existing = boundPopovers.get(els.trigger);
11032
11203
  if (existing) return existing;
11033
- const id = `sibu-popover-${++popoverIdCounter}`;
11204
+ const id = createId("sibu-popover");
11034
11205
  const prevPopoverRole = els.popover.getAttribute("role");
11035
11206
  const prevPopoverId = els.popover.id;
11036
11207
  const prevLabelledBy = els.popover.getAttribute("aria-labelledby");
@@ -11104,7 +11275,6 @@ function popover() {
11104
11275
  }
11105
11276
 
11106
11277
  // src/widgets/Select.ts
11107
- var selectIdCounter = 0;
11108
11278
  var boundSelects = /* @__PURE__ */ new WeakMap();
11109
11279
  function select2(options) {
11110
11280
  const { items, multiple = false, itemToString, isDisabled } = options;
@@ -11185,7 +11355,11 @@ function select2(options) {
11185
11355
  function bind(els) {
11186
11356
  const existing = boundSelects.get(els.listbox);
11187
11357
  if (existing) return existing;
11188
- const listboxId = `sibu-select-${++selectIdCounter}`;
11358
+ const prevId = els.listbox.id;
11359
+ const prevRole = els.listbox.getAttribute("role");
11360
+ const prevMultiselectable = els.listbox.getAttribute("aria-multiselectable");
11361
+ const prevTabIndex = els.listbox.getAttribute("tabindex");
11362
+ const listboxId = createId("sibu-select");
11189
11363
  els.listbox.id = listboxId;
11190
11364
  els.listbox.setAttribute("role", "listbox");
11191
11365
  els.listbox.setAttribute("aria-multiselectable", multiple ? "true" : "false");
@@ -11245,6 +11419,15 @@ function select2(options) {
11245
11419
  fxTeardown();
11246
11420
  els.listbox.removeEventListener("keydown", onKey);
11247
11421
  if (typeTimer !== null) clearTimeout(typeTimer);
11422
+ if (prevId === "") els.listbox.removeAttribute("id");
11423
+ else els.listbox.id = prevId;
11424
+ if (prevRole === null) els.listbox.removeAttribute("role");
11425
+ else els.listbox.setAttribute("role", prevRole);
11426
+ if (prevMultiselectable === null) els.listbox.removeAttribute("aria-multiselectable");
11427
+ else els.listbox.setAttribute("aria-multiselectable", prevMultiselectable);
11428
+ if (prevTabIndex === null) els.listbox.removeAttribute("tabindex");
11429
+ else els.listbox.setAttribute("tabindex", prevTabIndex);
11430
+ els.listbox.removeAttribute("aria-activedescendant");
11248
11431
  };
11249
11432
  boundSelects.set(els.listbox, teardown);
11250
11433
  return teardown;
@@ -11269,7 +11452,6 @@ function select2(options) {
11269
11452
  }
11270
11453
 
11271
11454
  // src/widgets/Tooltip.ts
11272
- var tooltipIdCounter = 0;
11273
11455
  var boundTriggers = /* @__PURE__ */ new WeakMap();
11274
11456
  function tooltip(options) {
11275
11457
  const delay = options?.delay ?? 0;
@@ -11314,7 +11496,7 @@ function tooltip(options) {
11314
11496
  function bind(els) {
11315
11497
  const existing = boundTriggers.get(els.trigger);
11316
11498
  if (existing) return existing;
11317
- const id = `sibu-tooltip-${++tooltipIdCounter}`;
11499
+ const id = createId("sibu-tooltip");
11318
11500
  els.tooltip.setAttribute("role", "tooltip");
11319
11501
  els.tooltip.id = id;
11320
11502
  const prevDescribedBy = els.trigger.getAttribute("aria-describedby");
@@ -11374,7 +11556,6 @@ function tooltip(options) {
11374
11556
  }
11375
11557
 
11376
11558
  // src/widgets/FileUpload.ts
11377
- var fileUploadIdCounter = 0;
11378
11559
  var boundFileUploads = /* @__PURE__ */ new WeakMap();
11379
11560
  function fileUpload(options) {
11380
11561
  const accept = options?.accept;
@@ -11446,7 +11627,7 @@ function fileUpload(options) {
11446
11627
  function bind(els) {
11447
11628
  const existing = boundFileUploads.get(els.input);
11448
11629
  if (existing) return existing;
11449
- const id = `sibu-fileupload-${++fileUploadIdCounter}`;
11630
+ const id = createId("sibu-fileupload");
11450
11631
  const restore = [];
11451
11632
  if (accept) els.input.accept = accept;
11452
11633
  els.input.multiple = multiple;
@@ -11557,7 +11738,7 @@ function fileUpload(options) {
11557
11738
  }
11558
11739
 
11559
11740
  // src/widgets/contentEditable.ts
11560
- function contentEditable() {
11741
+ function contentEditable(element) {
11561
11742
  const [content, setContentInternal] = signal("");
11562
11743
  const [isFocused, setFocused] = signal(false);
11563
11744
  function setContent(input2) {
@@ -11581,6 +11762,7 @@ function contentEditable() {
11581
11762
  const selection = window.getSelection();
11582
11763
  if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return;
11583
11764
  const range = selection.getRangeAt(0);
11765
+ if (element && !element.contains(range.commonAncestorContainer)) return;
11584
11766
  const ancestor = range.commonAncestorContainer;
11585
11767
  const existingWrap = findAncestorByTag(
11586
11768
  ancestor instanceof HTMLElement ? ancestor : ancestor.parentElement,
@@ -11760,12 +11942,18 @@ function datePicker(options) {
11760
11942
  function bind(els) {
11761
11943
  const existing = boundDatePickers.get(els.grid);
11762
11944
  if (existing) return existing;
11945
+ const prevGridRole = els.grid.getAttribute("role");
11946
+ const prevGridTabIndex = els.grid.getAttribute("tabindex");
11947
+ const prevGridLabel = els.grid.getAttribute("aria-label");
11763
11948
  els.grid.setAttribute("role", "grid");
11764
11949
  if (els.grid.tabIndex < 0) els.grid.tabIndex = 0;
11950
+ let pendingFocus = false;
11765
11951
  const fxTeardown = effect(() => {
11766
11952
  const sel = selectedDate();
11767
11953
  const view = viewDate();
11768
11954
  const days = daysInMonth();
11955
+ els.grid.setAttribute("aria-label", view.toLocaleDateString(void 0, { month: "long", year: "numeric" }));
11956
+ let viewCell = null;
11769
11957
  for (const d of days) {
11770
11958
  const cell = els.cell(d.date);
11771
11959
  if (!cell) continue;
@@ -11773,7 +11961,13 @@ function datePicker(options) {
11773
11961
  cell.setAttribute("aria-selected", sel && isSameCalendarDay(sel, d.date) ? "true" : "false");
11774
11962
  if (d.isDisabled) cell.setAttribute("aria-disabled", "true");
11775
11963
  else cell.removeAttribute("aria-disabled");
11776
- cell.tabIndex = isSameCalendarDay(view, d.date) ? 0 : -1;
11964
+ const isView = isSameCalendarDay(view, d.date);
11965
+ cell.tabIndex = isView ? 0 : -1;
11966
+ if (isView) viewCell = cell;
11967
+ }
11968
+ if (pendingFocus && viewCell && typeof viewCell.focus === "function") {
11969
+ pendingFocus = false;
11970
+ viewCell.focus();
11777
11971
  }
11778
11972
  });
11779
11973
  function isSameCalendarDay(a2, b2) {
@@ -11783,6 +11977,9 @@ function datePicker(options) {
11783
11977
  setViewDate((prev) => new Date(prev.getFullYear(), prev.getMonth(), prev.getDate() + delta));
11784
11978
  }
11785
11979
  const onKey = (e) => {
11980
+ if (e.key === "ArrowLeft" || e.key === "ArrowRight" || e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "Home" || e.key === "End" || e.key === "PageUp" || e.key === "PageDown") {
11981
+ pendingFocus = true;
11982
+ }
11786
11983
  switch (e.key) {
11787
11984
  case "ArrowLeft":
11788
11985
  e.preventDefault();
@@ -11831,6 +12028,12 @@ function datePicker(options) {
11831
12028
  boundDatePickers.delete(els.grid);
11832
12029
  fxTeardown();
11833
12030
  els.grid.removeEventListener("keydown", onKey);
12031
+ if (prevGridRole === null) els.grid.removeAttribute("role");
12032
+ else els.grid.setAttribute("role", prevGridRole);
12033
+ if (prevGridTabIndex === null) els.grid.removeAttribute("tabindex");
12034
+ else els.grid.setAttribute("tabindex", prevGridTabIndex);
12035
+ if (prevGridLabel === null) els.grid.removeAttribute("aria-label");
12036
+ else els.grid.setAttribute("aria-label", prevGridLabel);
11834
12037
  };
11835
12038
  boundDatePickers.set(els.grid, teardown);
11836
12039
  return teardown;
@@ -12379,6 +12582,7 @@ var materialAdapter = componentAdapter(materialConfig);
12379
12582
  pointerLock,
12380
12583
  popover,
12381
12584
  precompile,
12585
+ prefersReducedMotion,
12382
12586
  prefetch,
12383
12587
  preloadCritical,
12384
12588
  preloadImage,