sibujs 3.3.1 → 3.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/browser.cjs +41 -18
  2. package/dist/browser.js +5 -5
  3. package/dist/build.cjs +57 -22
  4. package/dist/build.js +14 -14
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-MHBCEJQO.js → chunk-23VT3KZB.js} +2 -2
  7. package/dist/{chunk-WL7BIR6O.js → chunk-25LY5SRH.js} +31 -24
  8. package/dist/{chunk-37BUKSLH.js → chunk-5K6RVA2S.js} +1 -1
  9. package/dist/{chunk-AMIKDMLP.js → chunk-5Y34FWED.js} +17 -6
  10. package/dist/chunk-7ZHH77QA.js +9 -0
  11. package/dist/chunk-CCSJMTRN.js +15 -0
  12. package/dist/{chunk-R3QEDXFS.js → chunk-EX77FXTT.js} +1 -1
  13. package/dist/{chunk-WW6DAGGR.js → chunk-F3HO2MP7.js} +1 -1
  14. package/dist/{chunk-ZUVLC7TM.js → chunk-F7HW2NI5.js} +2 -4
  15. package/dist/{chunk-ULLTNDRA.js → chunk-IEYFHN5V.js} +72 -25
  16. package/dist/{chunk-Z37APKBV.js → chunk-IQN5W7GE.js} +73 -16
  17. package/dist/{chunk-WZG2SZOT.js → chunk-IWFE4AHO.js} +1 -1
  18. package/dist/{chunk-IKLYI3RF.js → chunk-MYXEBADX.js} +53 -23
  19. package/dist/{chunk-6LTFHJQG.js → chunk-QCQQ2N5H.js} +41 -20
  20. package/dist/{chunk-VOVVTOEA.js → chunk-QTOOBABV.js} +22 -5
  21. package/dist/{chunk-LU2MQXQQ.js → chunk-RZKGMHH4.js} +6 -6
  22. package/dist/{chunk-GOJMFRBL.js → chunk-S3NFJO6L.js} +20 -14
  23. package/dist/{chunk-NHKQKKZU.js → chunk-SBPUXWCE.js} +1 -1
  24. package/dist/{chunk-SLMFA3ZZ.js → chunk-TBDTU7UO.js} +2 -2
  25. package/dist/{chunk-4UUMSLSL.js → chunk-TVCCXPU2.js} +5 -5
  26. package/dist/{chunk-TEFZT5PJ.js → chunk-UOMYIAG6.js} +1 -1
  27. package/dist/{chunk-XH2RTYEQ.js → chunk-WFUUT6TG.js} +15 -8
  28. package/dist/{chunk-M5KBNOSJ.js → chunk-WTFMV2RU.js} +70 -59
  29. package/dist/{chunk-3JHCYHWN.js → chunk-WWV3SJ3L.js} +19 -13
  30. package/dist/{chunk-RYMOSG5B.js → chunk-Y35NQNLG.js} +90 -60
  31. package/dist/{chunk-F7FXQ3QS.js → chunk-ZXCZWMZT.js} +1 -1
  32. package/dist/data.cjs +36 -16
  33. package/dist/data.js +8 -7
  34. package/dist/devtools.cjs +91 -35
  35. package/dist/devtools.d.cts +12 -5
  36. package/dist/devtools.d.ts +12 -5
  37. package/dist/devtools.js +7 -6
  38. package/dist/ecosystem.cjs +31 -16
  39. package/dist/ecosystem.js +11 -10
  40. package/dist/extras.cjs +485 -280
  41. package/dist/extras.d.cts +1 -1
  42. package/dist/extras.d.ts +1 -1
  43. package/dist/extras.js +28 -24
  44. package/dist/index.cjs +59 -22
  45. package/dist/index.d.cts +24 -8
  46. package/dist/index.d.ts +24 -8
  47. package/dist/index.js +25 -21
  48. package/dist/motion.cjs +223 -204
  49. package/dist/motion.d.cts +8 -1
  50. package/dist/motion.d.ts +8 -1
  51. package/dist/motion.js +6 -3
  52. package/dist/patterns.cjs +33 -20
  53. package/dist/patterns.d.cts +4 -1
  54. package/dist/patterns.d.ts +4 -1
  55. package/dist/patterns.js +6 -6
  56. package/dist/performance.cjs +90 -70
  57. package/dist/performance.js +8 -7
  58. package/dist/plugins.cjs +207 -144
  59. package/dist/plugins.d.cts +2 -1
  60. package/dist/plugins.d.ts +2 -1
  61. package/dist/plugins.js +178 -124
  62. package/dist/{ssr-6D67RAVB.js → ssr-2PPULEK2.js} +2 -2
  63. package/dist/ssr.cjs +132 -105
  64. package/dist/ssr.d.cts +8 -1
  65. package/dist/ssr.d.ts +8 -1
  66. package/dist/ssr.js +11 -10
  67. package/dist/testing.cjs +38 -18
  68. package/dist/testing.js +19 -8
  69. package/dist/ui.cjs +337 -294
  70. package/dist/ui.d.cts +0 -20
  71. package/dist/ui.d.ts +0 -20
  72. package/dist/ui.js +30 -24
  73. package/dist/widgets.cjs +95 -27
  74. package/dist/widgets.d.cts +6 -1
  75. package/dist/widgets.d.ts +6 -1
  76. package/dist/widgets.js +8 -7
  77. package/package.json +1 -1
  78. package/dist/chunk-YT6HQ6AM.js +0 -14
package/dist/ui.d.cts CHANGED
@@ -244,26 +244,6 @@ declare function hover(target: HTMLElement): {
244
244
  dispose: () => void;
245
245
  };
246
246
 
247
- /**
248
- * scrollLock stacks body scroll locks — useful when a modal / drawer / sheet
249
- * stack is open and background scroll must be suppressed.
250
- *
251
- * Each `lock()` call increments an internal counter and applies
252
- * `overflow: hidden` + preserves the scrollbar-width padding to prevent
253
- * layout shift. Calling `unlock()` decrements; when the counter hits zero
254
- * the previous body style is restored.
255
- *
256
- * Safe to call from multiple concurrent overlays — the last one to unlock
257
- * releases the lock.
258
- *
259
- * @example
260
- * ```ts
261
- * const lock = scrollLock();
262
- * lock.lock();
263
- * // ... modal open
264
- * lock.unlock();
265
- * ```
266
- */
267
247
  interface ScrollLockHandle {
268
248
  /** Activate a lock. Idempotent per-handle if called twice. */
269
249
  lock: () => void;
package/dist/ui.d.ts CHANGED
@@ -244,26 +244,6 @@ declare function hover(target: HTMLElement): {
244
244
  dispose: () => void;
245
245
  };
246
246
 
247
- /**
248
- * scrollLock stacks body scroll locks — useful when a modal / drawer / sheet
249
- * stack is open and background scroll must be suppressed.
250
- *
251
- * Each `lock()` call increments an internal counter and applies
252
- * `overflow: hidden` + preserves the scrollbar-width padding to prevent
253
- * layout shift. Calling `unlock()` decrements; when the counter hits zero
254
- * the previous body style is restored.
255
- *
256
- * Safe to call from multiple concurrent overlays — the last one to unlock
257
- * releases the lock.
258
- *
259
- * @example
260
- * ```ts
261
- * const lock = scrollLock();
262
- * lock.lock();
263
- * // ... modal open
264
- * lock.unlock();
265
- * ```
266
- */
267
247
  interface ScrollLockHandle {
268
248
  /** Activate a lock. Idempotent per-handle if called twice. */
269
249
  lock: () => void;
package/dist/ui.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  toast,
39
39
  withScopedStyle,
40
40
  zipMask
41
- } from "./chunk-RYMOSG5B.js";
41
+ } from "./chunk-Y35NQNLG.js";
42
42
  import {
43
43
  RenderProp,
44
44
  assertType,
@@ -56,22 +56,25 @@ import {
56
56
  withWrapper
57
57
  } from "./chunk-VJE6DDYM.js";
58
58
  import {
59
- createId
60
- } from "./chunk-YT6HQ6AM.js";
61
- import "./chunk-NHKQKKZU.js";
62
- import "./chunk-WW6DAGGR.js";
59
+ globalSingleton
60
+ } from "./chunk-7ZHH77QA.js";
63
61
  import {
64
- registerDisposer
65
- } from "./chunk-5VGSK6D2.js";
62
+ createId
63
+ } from "./chunk-CCSJMTRN.js";
64
+ import "./chunk-SBPUXWCE.js";
65
+ import "./chunk-F3HO2MP7.js";
66
66
  import "./chunk-L3GAGWCC.js";
67
67
  import {
68
68
  effect
69
- } from "./chunk-MHBCEJQO.js";
70
- import "./chunk-GOJMFRBL.js";
69
+ } from "./chunk-23VT3KZB.js";
70
+ import "./chunk-S3NFJO6L.js";
71
+ import {
72
+ registerDisposer
73
+ } from "./chunk-5VGSK6D2.js";
71
74
  import {
72
75
  signal
73
- } from "./chunk-WZG2SZOT.js";
74
- import "./chunk-TEFZT5PJ.js";
76
+ } from "./chunk-IWFE4AHO.js";
77
+ import "./chunk-UOMYIAG6.js";
75
78
  import "./chunk-COY6PUD2.js";
76
79
 
77
80
  // src/ui/formAction.ts
@@ -375,24 +378,27 @@ function hover(target) {
375
378
  target.removeEventListener("pointerenter", onEnter);
376
379
  target.removeEventListener("pointerleave", onLeave);
377
380
  }
381
+ registerDisposer(target, dispose);
378
382
  return { hovered, dispose };
379
383
  }
380
384
 
381
385
  // src/ui/scrollLock.ts
382
- var lockCount = 0;
383
- var savedOverflow = null;
384
- var savedPaddingRight = null;
386
+ var _lock = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.scrollLock.v1"), () => ({
387
+ count: 0,
388
+ savedOverflow: null,
389
+ savedPaddingRight: null
390
+ }));
385
391
  function scrollLock() {
386
392
  let owned = false;
387
393
  function lock() {
388
394
  if (owned) return;
389
395
  owned = true;
390
- lockCount++;
391
- if (lockCount !== 1 || typeof document === "undefined") return;
396
+ _lock.count++;
397
+ if (_lock.count !== 1 || typeof document === "undefined") return;
392
398
  const body = document.body;
393
399
  const scrollBarWidth = window.innerWidth - document.documentElement.clientWidth;
394
- savedOverflow = body.style.overflow;
395
- savedPaddingRight = body.style.paddingRight;
400
+ _lock.savedOverflow = body.style.overflow;
401
+ _lock.savedPaddingRight = body.style.paddingRight;
396
402
  body.style.overflow = "hidden";
397
403
  if (scrollBarWidth > 0) {
398
404
  body.style.paddingRight = `${scrollBarWidth}px`;
@@ -401,13 +407,13 @@ function scrollLock() {
401
407
  function unlock() {
402
408
  if (!owned) return;
403
409
  owned = false;
404
- lockCount = Math.max(0, lockCount - 1);
405
- if (lockCount !== 0 || typeof document === "undefined") return;
410
+ _lock.count = Math.max(0, _lock.count - 1);
411
+ if (_lock.count !== 0 || typeof document === "undefined") return;
406
412
  const body = document.body;
407
- body.style.overflow = savedOverflow ?? "";
408
- body.style.paddingRight = savedPaddingRight ?? "";
409
- savedOverflow = null;
410
- savedPaddingRight = null;
413
+ body.style.overflow = _lock.savedOverflow ?? "";
414
+ body.style.paddingRight = _lock.savedPaddingRight ?? "";
415
+ _lock.savedOverflow = null;
416
+ _lock.savedPaddingRight = null;
411
417
  }
412
418
  return { lock, unlock };
413
419
  }
package/dist/widgets.cjs CHANGED
@@ -32,6 +32,14 @@ __export(widgets_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(widgets_exports);
34
34
 
35
+ // src/core/rendering/createId.ts
36
+ var COUNTER_KEY = /* @__PURE__ */ Symbol.for("sibujs.createId.v1");
37
+ var _counter = globalThis[COUNTER_KEY] ?? (globalThis[COUNTER_KEY] = { n: 0 });
38
+ function createId(prefix = "sibu") {
39
+ _counter.n++;
40
+ return `${prefix}-${_counter.n}`;
41
+ }
42
+
35
43
  // src/core/dev.ts
36
44
  function isDev() {
37
45
  return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
@@ -470,7 +478,7 @@ function forEachSubscriber(signal2, visit) {
470
478
 
471
479
  // src/reactivity/track.ts
472
480
  var _isDev3 = isDev();
473
- var _runtimeVersion = typeof __SIBU_VERSION__ !== "undefined" ? __SIBU_VERSION__ : "dev";
481
+ var _runtimeVersion = true ? "3.3.3" : "dev";
474
482
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
475
483
  function resolveReactiveApi() {
476
484
  const g = globalThis;
@@ -606,23 +614,29 @@ function derived(getter, options) {
606
614
  }
607
615
 
608
616
  // src/core/ssr-context.ts
609
- var als = null;
610
- try {
611
- if (typeof process !== "undefined" && process.versions && process.versions.node) {
612
- let mod = null;
613
- const getBuiltin = process.getBuiltinModule;
614
- if (typeof getBuiltin === "function") {
615
- mod = getBuiltin("node:async_hooks");
616
- } else {
617
- const req = Function("return typeof require==='function'?require:null")();
618
- if (req) mod = req("node:async_hooks");
617
+ var SSR_KEY = /* @__PURE__ */ Symbol.for("sibujs.ssr.v1");
618
+ function detectSSRShared() {
619
+ let detected = null;
620
+ try {
621
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
622
+ let mod = null;
623
+ const getBuiltin = process.getBuiltinModule;
624
+ if (typeof getBuiltin === "function") {
625
+ mod = getBuiltin("node:async_hooks");
626
+ } else {
627
+ const req = Function("return typeof require==='function'?require:null")();
628
+ if (req) mod = req("node:async_hooks");
629
+ }
630
+ if (mod) detected = new mod.AsyncLocalStorage();
619
631
  }
620
- if (mod) als = new mod.AsyncLocalStorage();
632
+ } catch {
633
+ detected = null;
621
634
  }
622
- } catch {
623
- als = null;
635
+ return { als: detected, fallbackStore: { ssr: false, suspenseIdCounter: 0 } };
624
636
  }
625
- var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
637
+ var _shared = globalThis[SSR_KEY] ?? (globalThis[SSR_KEY] = detectSSRShared());
638
+ var als = _shared.als;
639
+ var fallbackStore = _shared.fallbackStore;
626
640
  function getSSRStore() {
627
641
  if (als) {
628
642
  const s = als.getStore();
@@ -906,7 +920,6 @@ function watch(getter, callback) {
906
920
  }
907
921
 
908
922
  // src/widgets/Combobox.ts
909
- var comboboxIdCounter = 0;
910
923
  var boundComboboxes = /* @__PURE__ */ new WeakMap();
911
924
  function combobox(options) {
912
925
  const { items, filterFn, itemToString } = options;
@@ -967,7 +980,13 @@ function combobox(options) {
967
980
  function bind(els) {
968
981
  const existing = boundComboboxes.get(els.input);
969
982
  if (existing) return existing;
970
- const listboxId = `sibu-combobox-listbox-${++comboboxIdCounter}`;
983
+ const prevListboxId = els.listbox.id;
984
+ const prevListboxRole = els.listbox.getAttribute("role");
985
+ const prevListboxHidden = els.listbox.hidden;
986
+ const prevInputRole = els.input.getAttribute("role");
987
+ const prevInputAutocomplete = els.input.getAttribute("aria-autocomplete");
988
+ const prevInputControls = els.input.getAttribute("aria-controls");
989
+ const listboxId = createId("sibu-combobox-listbox");
971
990
  els.listbox.id = listboxId;
972
991
  els.listbox.setAttribute("role", "listbox");
973
992
  els.input.setAttribute("role", "combobox");
@@ -1031,10 +1050,14 @@ function combobox(options) {
1031
1050
  if (document.activeElement !== els.input) close();
1032
1051
  }, 100);
1033
1052
  };
1053
+ const onListboxPointerDown = (e) => {
1054
+ e.preventDefault();
1055
+ };
1034
1056
  els.input.addEventListener("input", onInput);
1035
1057
  els.input.addEventListener("keydown", onKey);
1036
1058
  els.input.addEventListener("focus", onFocus);
1037
1059
  els.input.addEventListener("blur", onBlur);
1060
+ els.listbox.addEventListener("mousedown", onListboxPointerDown);
1038
1061
  const teardown = () => {
1039
1062
  boundComboboxes.delete(els.input);
1040
1063
  fxTeardown();
@@ -1042,10 +1065,24 @@ function combobox(options) {
1042
1065
  els.input.removeEventListener("keydown", onKey);
1043
1066
  els.input.removeEventListener("focus", onFocus);
1044
1067
  els.input.removeEventListener("blur", onBlur);
1068
+ els.listbox.removeEventListener("mousedown", onListboxPointerDown);
1045
1069
  if (blurTimer !== null) {
1046
1070
  clearTimeout(blurTimer);
1047
1071
  blurTimer = null;
1048
1072
  }
1073
+ if (prevListboxId === "") els.listbox.removeAttribute("id");
1074
+ else els.listbox.id = prevListboxId;
1075
+ if (prevListboxRole === null) els.listbox.removeAttribute("role");
1076
+ else els.listbox.setAttribute("role", prevListboxRole);
1077
+ els.listbox.hidden = prevListboxHidden;
1078
+ if (prevInputRole === null) els.input.removeAttribute("role");
1079
+ else els.input.setAttribute("role", prevInputRole);
1080
+ if (prevInputAutocomplete === null) els.input.removeAttribute("aria-autocomplete");
1081
+ else els.input.setAttribute("aria-autocomplete", prevInputAutocomplete);
1082
+ if (prevInputControls === null) els.input.removeAttribute("aria-controls");
1083
+ else els.input.setAttribute("aria-controls", prevInputControls);
1084
+ els.input.removeAttribute("aria-expanded");
1085
+ els.input.removeAttribute("aria-activedescendant");
1049
1086
  };
1050
1087
  boundComboboxes.set(els.input, teardown);
1051
1088
  return teardown;
@@ -1381,7 +1418,6 @@ function accordion(options) {
1381
1418
  }
1382
1419
 
1383
1420
  // src/widgets/Popover.ts
1384
- var popoverIdCounter = 0;
1385
1421
  var boundPopovers = /* @__PURE__ */ new WeakMap();
1386
1422
  function popover() {
1387
1423
  const [isOpen, setIsOpen] = signal(false);
@@ -1397,7 +1433,7 @@ function popover() {
1397
1433
  function bind(els) {
1398
1434
  const existing = boundPopovers.get(els.trigger);
1399
1435
  if (existing) return existing;
1400
- const id = `sibu-popover-${++popoverIdCounter}`;
1436
+ const id = createId("sibu-popover");
1401
1437
  const prevPopoverRole = els.popover.getAttribute("role");
1402
1438
  const prevPopoverId = els.popover.id;
1403
1439
  const prevLabelledBy = els.popover.getAttribute("aria-labelledby");
@@ -1471,7 +1507,6 @@ function popover() {
1471
1507
  }
1472
1508
 
1473
1509
  // src/widgets/Select.ts
1474
- var selectIdCounter = 0;
1475
1510
  var boundSelects = /* @__PURE__ */ new WeakMap();
1476
1511
  function select(options) {
1477
1512
  const { items, multiple = false, itemToString, isDisabled } = options;
@@ -1552,7 +1587,11 @@ function select(options) {
1552
1587
  function bind(els) {
1553
1588
  const existing = boundSelects.get(els.listbox);
1554
1589
  if (existing) return existing;
1555
- const listboxId = `sibu-select-${++selectIdCounter}`;
1590
+ const prevId = els.listbox.id;
1591
+ const prevRole = els.listbox.getAttribute("role");
1592
+ const prevMultiselectable = els.listbox.getAttribute("aria-multiselectable");
1593
+ const prevTabIndex = els.listbox.getAttribute("tabindex");
1594
+ const listboxId = createId("sibu-select");
1556
1595
  els.listbox.id = listboxId;
1557
1596
  els.listbox.setAttribute("role", "listbox");
1558
1597
  els.listbox.setAttribute("aria-multiselectable", multiple ? "true" : "false");
@@ -1612,6 +1651,15 @@ function select(options) {
1612
1651
  fxTeardown();
1613
1652
  els.listbox.removeEventListener("keydown", onKey);
1614
1653
  if (typeTimer !== null) clearTimeout(typeTimer);
1654
+ if (prevId === "") els.listbox.removeAttribute("id");
1655
+ else els.listbox.id = prevId;
1656
+ if (prevRole === null) els.listbox.removeAttribute("role");
1657
+ else els.listbox.setAttribute("role", prevRole);
1658
+ if (prevMultiselectable === null) els.listbox.removeAttribute("aria-multiselectable");
1659
+ else els.listbox.setAttribute("aria-multiselectable", prevMultiselectable);
1660
+ if (prevTabIndex === null) els.listbox.removeAttribute("tabindex");
1661
+ else els.listbox.setAttribute("tabindex", prevTabIndex);
1662
+ els.listbox.removeAttribute("aria-activedescendant");
1615
1663
  };
1616
1664
  boundSelects.set(els.listbox, teardown);
1617
1665
  return teardown;
@@ -1636,7 +1684,6 @@ function select(options) {
1636
1684
  }
1637
1685
 
1638
1686
  // src/widgets/Tooltip.ts
1639
- var tooltipIdCounter = 0;
1640
1687
  var boundTriggers = /* @__PURE__ */ new WeakMap();
1641
1688
  function tooltip(options) {
1642
1689
  const delay = options?.delay ?? 0;
@@ -1681,7 +1728,7 @@ function tooltip(options) {
1681
1728
  function bind(els) {
1682
1729
  const existing = boundTriggers.get(els.trigger);
1683
1730
  if (existing) return existing;
1684
- const id = `sibu-tooltip-${++tooltipIdCounter}`;
1731
+ const id = createId("sibu-tooltip");
1685
1732
  els.tooltip.setAttribute("role", "tooltip");
1686
1733
  els.tooltip.id = id;
1687
1734
  const prevDescribedBy = els.trigger.getAttribute("aria-describedby");
@@ -1741,7 +1788,6 @@ function tooltip(options) {
1741
1788
  }
1742
1789
 
1743
1790
  // src/widgets/FileUpload.ts
1744
- var fileUploadIdCounter = 0;
1745
1791
  var boundFileUploads = /* @__PURE__ */ new WeakMap();
1746
1792
  function fileUpload(options) {
1747
1793
  const accept = options?.accept;
@@ -1813,7 +1859,7 @@ function fileUpload(options) {
1813
1859
  function bind(els) {
1814
1860
  const existing = boundFileUploads.get(els.input);
1815
1861
  if (existing) return existing;
1816
- const id = `sibu-fileupload-${++fileUploadIdCounter}`;
1862
+ const id = createId("sibu-fileupload");
1817
1863
  const restore = [];
1818
1864
  if (accept) els.input.accept = accept;
1819
1865
  els.input.multiple = multiple;
@@ -1942,7 +1988,7 @@ function stripHtml(html) {
1942
1988
  }
1943
1989
 
1944
1990
  // src/widgets/contentEditable.ts
1945
- function contentEditable() {
1991
+ function contentEditable(element) {
1946
1992
  const [content, setContentInternal] = signal("");
1947
1993
  const [isFocused, setFocused] = signal(false);
1948
1994
  function setContent(input) {
@@ -1966,6 +2012,7 @@ function contentEditable() {
1966
2012
  const selection = window.getSelection();
1967
2013
  if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return;
1968
2014
  const range = selection.getRangeAt(0);
2015
+ if (element && !element.contains(range.commonAncestorContainer)) return;
1969
2016
  const ancestor = range.commonAncestorContainer;
1970
2017
  const existingWrap = findAncestorByTag(
1971
2018
  ancestor instanceof HTMLElement ? ancestor : ancestor.parentElement,
@@ -2145,12 +2192,18 @@ function datePicker(options) {
2145
2192
  function bind(els) {
2146
2193
  const existing = boundDatePickers.get(els.grid);
2147
2194
  if (existing) return existing;
2195
+ const prevGridRole = els.grid.getAttribute("role");
2196
+ const prevGridTabIndex = els.grid.getAttribute("tabindex");
2197
+ const prevGridLabel = els.grid.getAttribute("aria-label");
2148
2198
  els.grid.setAttribute("role", "grid");
2149
2199
  if (els.grid.tabIndex < 0) els.grid.tabIndex = 0;
2200
+ let pendingFocus = false;
2150
2201
  const fxTeardown = effect(() => {
2151
2202
  const sel = selectedDate();
2152
2203
  const view = viewDate();
2153
2204
  const days = daysInMonth();
2205
+ els.grid.setAttribute("aria-label", view.toLocaleDateString(void 0, { month: "long", year: "numeric" }));
2206
+ let viewCell = null;
2154
2207
  for (const d of days) {
2155
2208
  const cell = els.cell(d.date);
2156
2209
  if (!cell) continue;
@@ -2158,7 +2211,13 @@ function datePicker(options) {
2158
2211
  cell.setAttribute("aria-selected", sel && isSameCalendarDay(sel, d.date) ? "true" : "false");
2159
2212
  if (d.isDisabled) cell.setAttribute("aria-disabled", "true");
2160
2213
  else cell.removeAttribute("aria-disabled");
2161
- cell.tabIndex = isSameCalendarDay(view, d.date) ? 0 : -1;
2214
+ const isView = isSameCalendarDay(view, d.date);
2215
+ cell.tabIndex = isView ? 0 : -1;
2216
+ if (isView) viewCell = cell;
2217
+ }
2218
+ if (pendingFocus && viewCell && typeof viewCell.focus === "function") {
2219
+ pendingFocus = false;
2220
+ viewCell.focus();
2162
2221
  }
2163
2222
  });
2164
2223
  function isSameCalendarDay(a, b) {
@@ -2168,6 +2227,9 @@ function datePicker(options) {
2168
2227
  setViewDate((prev) => new Date(prev.getFullYear(), prev.getMonth(), prev.getDate() + delta));
2169
2228
  }
2170
2229
  const onKey = (e) => {
2230
+ 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") {
2231
+ pendingFocus = true;
2232
+ }
2171
2233
  switch (e.key) {
2172
2234
  case "ArrowLeft":
2173
2235
  e.preventDefault();
@@ -2216,6 +2278,12 @@ function datePicker(options) {
2216
2278
  boundDatePickers.delete(els.grid);
2217
2279
  fxTeardown();
2218
2280
  els.grid.removeEventListener("keydown", onKey);
2281
+ if (prevGridRole === null) els.grid.removeAttribute("role");
2282
+ else els.grid.setAttribute("role", prevGridRole);
2283
+ if (prevGridTabIndex === null) els.grid.removeAttribute("tabindex");
2284
+ else els.grid.setAttribute("tabindex", prevGridTabIndex);
2285
+ if (prevGridLabel === null) els.grid.removeAttribute("aria-label");
2286
+ else els.grid.setAttribute("aria-label", prevGridLabel);
2219
2287
  };
2220
2288
  boundDatePickers.set(els.grid, teardown);
2221
2289
  return teardown;
@@ -216,8 +216,13 @@ interface SetContentOptions {
216
216
  * Uses the modern Selection/Range API instead of the deprecated
217
217
  * document.execCommand. Formatting is applied by wrapping the current
218
218
  * selection in the appropriate inline element.
219
+ *
220
+ * @param element Optional editor element to scope formatting to. When provided,
221
+ * `bold()`/`italic()`/`underline()` ignore any selection that lives outside it
222
+ * — otherwise a selection elsewhere on the page could be mutated, since the
223
+ * Selection API is global.
219
224
  */
220
- declare function contentEditable(): {
225
+ declare function contentEditable(element?: HTMLElement): {
221
226
  content: () => string;
222
227
  /**
223
228
  * Update the reactive content value.
package/dist/widgets.d.ts CHANGED
@@ -216,8 +216,13 @@ interface SetContentOptions {
216
216
  * Uses the modern Selection/Range API instead of the deprecated
217
217
  * document.execCommand. Formatting is applied by wrapping the current
218
218
  * selection in the appropriate inline element.
219
+ *
220
+ * @param element Optional editor element to scope formatting to. When provided,
221
+ * `bold()`/`italic()`/`underline()` ignore any selection that lives outside it
222
+ * — otherwise a selection elsewhere on the page could be mutated, since the
223
+ * Selection API is global.
219
224
  */
220
- declare function contentEditable(): {
225
+ declare function contentEditable(element?: HTMLElement): {
221
226
  content: () => string;
222
227
  /**
223
228
  * Update the reactive content value.
package/dist/widgets.js CHANGED
@@ -8,14 +8,15 @@ import {
8
8
  select,
9
9
  tabs,
10
10
  tooltip
11
- } from "./chunk-Z37APKBV.js";
12
- import "./chunk-SLMFA3ZZ.js";
13
- import "./chunk-WW6DAGGR.js";
11
+ } from "./chunk-IQN5W7GE.js";
12
+ import "./chunk-TBDTU7UO.js";
13
+ import "./chunk-CCSJMTRN.js";
14
+ import "./chunk-F3HO2MP7.js";
14
15
  import "./chunk-L3GAGWCC.js";
15
- import "./chunk-MHBCEJQO.js";
16
- import "./chunk-GOJMFRBL.js";
17
- import "./chunk-WZG2SZOT.js";
18
- import "./chunk-TEFZT5PJ.js";
16
+ import "./chunk-23VT3KZB.js";
17
+ import "./chunk-S3NFJO6L.js";
18
+ import "./chunk-IWFE4AHO.js";
19
+ import "./chunk-UOMYIAG6.js";
19
20
  import "./chunk-COY6PUD2.js";
20
21
  export {
21
22
  accordion,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sibujs",
3
- "version": "3.3.1",
3
+ "version": "3.3.3",
4
4
  "description": "A lightweight, function-based frontend framework that combines the best of React, Svelte, and Vue — with zero VDOM and maximum simplicity. Designed for developers who want fine-grained reactivity and full control without compilation or magic.",
5
5
  "keywords": [
6
6
  "frontend",
@@ -1,14 +0,0 @@
1
- // src/core/rendering/createId.ts
2
- var idCounter = 0;
3
- function createId(prefix = "sibu") {
4
- idCounter++;
5
- return `${prefix}-${idCounter}`;
6
- }
7
- function __resetIdCounter() {
8
- idCounter = 0;
9
- }
10
-
11
- export {
12
- createId,
13
- __resetIdCounter
14
- };