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.
- package/dist/browser.cjs +21 -4
- package/dist/browser.js +4 -4
- package/dist/build.cjs +3343 -3009
- package/dist/build.js +12 -11
- package/dist/cdn.global.js +7 -7
- package/dist/{chunk-AEOLHSSQ.js → chunk-3DVGCW7O.js} +72 -25
- package/dist/{chunk-6TCOWMGY.js → chunk-3Z2NGWQI.js} +1 -1
- package/dist/chunk-7ZHH77QA.js +9 -0
- package/dist/{chunk-2ARSB7NG.js → chunk-APFRCIRI.js} +2906 -2569
- package/dist/{chunk-62V653X2.js → chunk-AXFWGY32.js} +79 -44
- package/dist/{chunk-N5TQVEKE.js → chunk-BUKYCWHX.js} +1 -1
- package/dist/{chunk-655B7MMR.js → chunk-CEBWDD63.js} +15 -8
- package/dist/{chunk-YUBEOWII.js → chunk-ELXMRSVN.js} +16 -5
- package/dist/{chunk-FJIRS3FM.js → chunk-F7HW2NI5.js} +1 -3
- package/dist/{chunk-P7C7SEJV.js → chunk-FKQG7FTY.js} +5 -5
- package/dist/{chunk-RLTFJYDN.js → chunk-H5FI5WDP.js} +1 -1
- package/dist/{chunk-G6N3LMO2.js → chunk-ITWCTZYH.js} +1 -1
- package/dist/{chunk-YUR5SX7F.js → chunk-JCO7AHNU.js} +70 -59
- package/dist/{chunk-ZEUP4TUD.js → chunk-JNGGM2XE.js} +6 -6
- package/dist/{chunk-QCFBIVIQ.js → chunk-K35BAR4P.js} +1 -1
- package/dist/{chunk-JCQG2I2G.js → chunk-KZBEVFXZ.js} +1 -1
- package/dist/{chunk-FJO2ZL4Q.js → chunk-OAVXAFAY.js} +73 -16
- package/dist/{chunk-A7CZH3GN.js → chunk-ODXVQ3CS.js} +41 -20
- package/dist/{chunk-4NJEAPLI.js → chunk-OOUQUCNN.js} +1 -1
- package/dist/{chunk-5VH3GIDX.js → chunk-RT3IYFN2.js} +1 -1
- package/dist/{chunk-Q46YIQYW.js → chunk-S3V6ZXPI.js} +22 -5
- package/dist/{chunk-IQJ36UTJ.js → chunk-WSGLJYFI.js} +31 -24
- package/dist/{chunk-3JHCYHWN.js → chunk-WWV3SJ3L.js} +19 -13
- package/dist/data.cjs +16 -2
- package/dist/data.js +7 -6
- package/dist/devtools.cjs +71 -21
- package/dist/devtools.d.cts +12 -5
- package/dist/devtools.d.ts +12 -5
- package/dist/devtools.js +6 -5
- package/dist/ecosystem.cjs +11 -2
- package/dist/ecosystem.d.cts +1 -1
- package/dist/ecosystem.d.ts +1 -1
- package/dist/ecosystem.js +10 -9
- package/dist/extras.cjs +454 -250
- package/dist/extras.d.cts +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/extras.js +26 -22
- package/dist/index.cjs +3385 -3045
- package/dist/index.d.cts +1179 -1057
- package/dist/index.d.ts +1179 -1057
- package/dist/index.js +32 -19
- package/dist/motion.cjs +223 -204
- package/dist/motion.d.cts +8 -1
- package/dist/motion.d.ts +8 -1
- package/dist/motion.js +6 -3
- package/dist/patterns.cjs +13 -6
- package/dist/patterns.d.cts +4 -1
- package/dist/patterns.d.ts +4 -1
- package/dist/patterns.js +5 -5
- package/dist/performance.cjs +70 -56
- package/dist/performance.js +6 -5
- package/dist/plugins.cjs +98 -42
- package/dist/plugins.d.cts +2 -1
- package/dist/plugins.d.ts +2 -1
- package/dist/plugins.js +89 -36
- package/dist/ssr.cjs +112 -91
- package/dist/ssr.d.cts +8 -1
- package/dist/ssr.d.ts +8 -1
- package/dist/ssr.js +9 -8
- package/dist/{tagFactory-S17H2qxu.d.ts → tagFactory-Bzupt4Pj.d.cts} +1 -1
- package/dist/{tagFactory-S17H2qxu.d.cts → tagFactory-Bzupt4Pj.d.ts} +1 -1
- package/dist/testing.cjs +18 -4
- package/dist/testing.js +18 -7
- package/dist/ui.cjs +322 -281
- package/dist/ui.d.cts +0 -20
- package/dist/ui.d.ts +0 -20
- package/dist/ui.js +27 -21
- package/dist/widgets.cjs +75 -13
- package/dist/widgets.d.cts +6 -1
- package/dist/widgets.d.ts +6 -1
- package/dist/widgets.js +7 -6
- package/package.json +4 -1
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-
|
|
41
|
+
} from "./chunk-AXFWGY32.js";
|
|
42
42
|
import {
|
|
43
43
|
RenderProp,
|
|
44
44
|
assertType,
|
|
@@ -58,20 +58,23 @@ import {
|
|
|
58
58
|
import {
|
|
59
59
|
createId
|
|
60
60
|
} from "./chunk-CCSJMTRN.js";
|
|
61
|
-
import "./chunk-
|
|
62
|
-
import "./chunk-
|
|
61
|
+
import "./chunk-K35BAR4P.js";
|
|
62
|
+
import "./chunk-ITWCTZYH.js";
|
|
63
63
|
import {
|
|
64
|
-
|
|
65
|
-
} from "./chunk-
|
|
64
|
+
globalSingleton
|
|
65
|
+
} from "./chunk-7ZHH77QA.js";
|
|
66
66
|
import "./chunk-L3GAGWCC.js";
|
|
67
67
|
import {
|
|
68
68
|
effect
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-BUKYCWHX.js";
|
|
70
70
|
import "./chunk-S3NFJO6L.js";
|
|
71
|
+
import {
|
|
72
|
+
registerDisposer
|
|
73
|
+
} from "./chunk-5VGSK6D2.js";
|
|
71
74
|
import {
|
|
72
75
|
signal
|
|
73
|
-
} from "./chunk-
|
|
74
|
-
import "./chunk-
|
|
76
|
+
} from "./chunk-KZBEVFXZ.js";
|
|
77
|
+
import "./chunk-OOUQUCNN.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
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
391
|
-
if (
|
|
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
|
-
|
|
405
|
-
if (
|
|
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 = true ? "3.
|
|
481
|
+
var _runtimeVersion = true ? "3.4.0" : "dev";
|
|
474
482
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
475
483
|
function resolveReactiveApi() {
|
|
476
484
|
const g = globalThis;
|
|
@@ -912,7 +920,6 @@ function watch(getter, callback) {
|
|
|
912
920
|
}
|
|
913
921
|
|
|
914
922
|
// src/widgets/Combobox.ts
|
|
915
|
-
var comboboxIdCounter = 0;
|
|
916
923
|
var boundComboboxes = /* @__PURE__ */ new WeakMap();
|
|
917
924
|
function combobox(options) {
|
|
918
925
|
const { items, filterFn, itemToString } = options;
|
|
@@ -973,7 +980,13 @@ function combobox(options) {
|
|
|
973
980
|
function bind(els) {
|
|
974
981
|
const existing = boundComboboxes.get(els.input);
|
|
975
982
|
if (existing) return existing;
|
|
976
|
-
const
|
|
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");
|
|
977
990
|
els.listbox.id = listboxId;
|
|
978
991
|
els.listbox.setAttribute("role", "listbox");
|
|
979
992
|
els.input.setAttribute("role", "combobox");
|
|
@@ -1037,10 +1050,14 @@ function combobox(options) {
|
|
|
1037
1050
|
if (document.activeElement !== els.input) close();
|
|
1038
1051
|
}, 100);
|
|
1039
1052
|
};
|
|
1053
|
+
const onListboxPointerDown = (e) => {
|
|
1054
|
+
e.preventDefault();
|
|
1055
|
+
};
|
|
1040
1056
|
els.input.addEventListener("input", onInput);
|
|
1041
1057
|
els.input.addEventListener("keydown", onKey);
|
|
1042
1058
|
els.input.addEventListener("focus", onFocus);
|
|
1043
1059
|
els.input.addEventListener("blur", onBlur);
|
|
1060
|
+
els.listbox.addEventListener("mousedown", onListboxPointerDown);
|
|
1044
1061
|
const teardown = () => {
|
|
1045
1062
|
boundComboboxes.delete(els.input);
|
|
1046
1063
|
fxTeardown();
|
|
@@ -1048,10 +1065,24 @@ function combobox(options) {
|
|
|
1048
1065
|
els.input.removeEventListener("keydown", onKey);
|
|
1049
1066
|
els.input.removeEventListener("focus", onFocus);
|
|
1050
1067
|
els.input.removeEventListener("blur", onBlur);
|
|
1068
|
+
els.listbox.removeEventListener("mousedown", onListboxPointerDown);
|
|
1051
1069
|
if (blurTimer !== null) {
|
|
1052
1070
|
clearTimeout(blurTimer);
|
|
1053
1071
|
blurTimer = null;
|
|
1054
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");
|
|
1055
1086
|
};
|
|
1056
1087
|
boundComboboxes.set(els.input, teardown);
|
|
1057
1088
|
return teardown;
|
|
@@ -1387,7 +1418,6 @@ function accordion(options) {
|
|
|
1387
1418
|
}
|
|
1388
1419
|
|
|
1389
1420
|
// src/widgets/Popover.ts
|
|
1390
|
-
var popoverIdCounter = 0;
|
|
1391
1421
|
var boundPopovers = /* @__PURE__ */ new WeakMap();
|
|
1392
1422
|
function popover() {
|
|
1393
1423
|
const [isOpen, setIsOpen] = signal(false);
|
|
@@ -1403,7 +1433,7 @@ function popover() {
|
|
|
1403
1433
|
function bind(els) {
|
|
1404
1434
|
const existing = boundPopovers.get(els.trigger);
|
|
1405
1435
|
if (existing) return existing;
|
|
1406
|
-
const id =
|
|
1436
|
+
const id = createId("sibu-popover");
|
|
1407
1437
|
const prevPopoverRole = els.popover.getAttribute("role");
|
|
1408
1438
|
const prevPopoverId = els.popover.id;
|
|
1409
1439
|
const prevLabelledBy = els.popover.getAttribute("aria-labelledby");
|
|
@@ -1477,7 +1507,6 @@ function popover() {
|
|
|
1477
1507
|
}
|
|
1478
1508
|
|
|
1479
1509
|
// src/widgets/Select.ts
|
|
1480
|
-
var selectIdCounter = 0;
|
|
1481
1510
|
var boundSelects = /* @__PURE__ */ new WeakMap();
|
|
1482
1511
|
function select(options) {
|
|
1483
1512
|
const { items, multiple = false, itemToString, isDisabled } = options;
|
|
@@ -1558,7 +1587,11 @@ function select(options) {
|
|
|
1558
1587
|
function bind(els) {
|
|
1559
1588
|
const existing = boundSelects.get(els.listbox);
|
|
1560
1589
|
if (existing) return existing;
|
|
1561
|
-
const
|
|
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");
|
|
1562
1595
|
els.listbox.id = listboxId;
|
|
1563
1596
|
els.listbox.setAttribute("role", "listbox");
|
|
1564
1597
|
els.listbox.setAttribute("aria-multiselectable", multiple ? "true" : "false");
|
|
@@ -1618,6 +1651,15 @@ function select(options) {
|
|
|
1618
1651
|
fxTeardown();
|
|
1619
1652
|
els.listbox.removeEventListener("keydown", onKey);
|
|
1620
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");
|
|
1621
1663
|
};
|
|
1622
1664
|
boundSelects.set(els.listbox, teardown);
|
|
1623
1665
|
return teardown;
|
|
@@ -1642,7 +1684,6 @@ function select(options) {
|
|
|
1642
1684
|
}
|
|
1643
1685
|
|
|
1644
1686
|
// src/widgets/Tooltip.ts
|
|
1645
|
-
var tooltipIdCounter = 0;
|
|
1646
1687
|
var boundTriggers = /* @__PURE__ */ new WeakMap();
|
|
1647
1688
|
function tooltip(options) {
|
|
1648
1689
|
const delay = options?.delay ?? 0;
|
|
@@ -1687,7 +1728,7 @@ function tooltip(options) {
|
|
|
1687
1728
|
function bind(els) {
|
|
1688
1729
|
const existing = boundTriggers.get(els.trigger);
|
|
1689
1730
|
if (existing) return existing;
|
|
1690
|
-
const id =
|
|
1731
|
+
const id = createId("sibu-tooltip");
|
|
1691
1732
|
els.tooltip.setAttribute("role", "tooltip");
|
|
1692
1733
|
els.tooltip.id = id;
|
|
1693
1734
|
const prevDescribedBy = els.trigger.getAttribute("aria-describedby");
|
|
@@ -1747,7 +1788,6 @@ function tooltip(options) {
|
|
|
1747
1788
|
}
|
|
1748
1789
|
|
|
1749
1790
|
// src/widgets/FileUpload.ts
|
|
1750
|
-
var fileUploadIdCounter = 0;
|
|
1751
1791
|
var boundFileUploads = /* @__PURE__ */ new WeakMap();
|
|
1752
1792
|
function fileUpload(options) {
|
|
1753
1793
|
const accept = options?.accept;
|
|
@@ -1819,7 +1859,7 @@ function fileUpload(options) {
|
|
|
1819
1859
|
function bind(els) {
|
|
1820
1860
|
const existing = boundFileUploads.get(els.input);
|
|
1821
1861
|
if (existing) return existing;
|
|
1822
|
-
const id =
|
|
1862
|
+
const id = createId("sibu-fileupload");
|
|
1823
1863
|
const restore = [];
|
|
1824
1864
|
if (accept) els.input.accept = accept;
|
|
1825
1865
|
els.input.multiple = multiple;
|
|
@@ -1948,7 +1988,7 @@ function stripHtml(html) {
|
|
|
1948
1988
|
}
|
|
1949
1989
|
|
|
1950
1990
|
// src/widgets/contentEditable.ts
|
|
1951
|
-
function contentEditable() {
|
|
1991
|
+
function contentEditable(element) {
|
|
1952
1992
|
const [content, setContentInternal] = signal("");
|
|
1953
1993
|
const [isFocused, setFocused] = signal(false);
|
|
1954
1994
|
function setContent(input) {
|
|
@@ -1972,6 +2012,7 @@ function contentEditable() {
|
|
|
1972
2012
|
const selection = window.getSelection();
|
|
1973
2013
|
if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return;
|
|
1974
2014
|
const range = selection.getRangeAt(0);
|
|
2015
|
+
if (element && !element.contains(range.commonAncestorContainer)) return;
|
|
1975
2016
|
const ancestor = range.commonAncestorContainer;
|
|
1976
2017
|
const existingWrap = findAncestorByTag(
|
|
1977
2018
|
ancestor instanceof HTMLElement ? ancestor : ancestor.parentElement,
|
|
@@ -2151,12 +2192,18 @@ function datePicker(options) {
|
|
|
2151
2192
|
function bind(els) {
|
|
2152
2193
|
const existing = boundDatePickers.get(els.grid);
|
|
2153
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");
|
|
2154
2198
|
els.grid.setAttribute("role", "grid");
|
|
2155
2199
|
if (els.grid.tabIndex < 0) els.grid.tabIndex = 0;
|
|
2200
|
+
let pendingFocus = false;
|
|
2156
2201
|
const fxTeardown = effect(() => {
|
|
2157
2202
|
const sel = selectedDate();
|
|
2158
2203
|
const view = viewDate();
|
|
2159
2204
|
const days = daysInMonth();
|
|
2205
|
+
els.grid.setAttribute("aria-label", view.toLocaleDateString(void 0, { month: "long", year: "numeric" }));
|
|
2206
|
+
let viewCell = null;
|
|
2160
2207
|
for (const d of days) {
|
|
2161
2208
|
const cell = els.cell(d.date);
|
|
2162
2209
|
if (!cell) continue;
|
|
@@ -2164,7 +2211,13 @@ function datePicker(options) {
|
|
|
2164
2211
|
cell.setAttribute("aria-selected", sel && isSameCalendarDay(sel, d.date) ? "true" : "false");
|
|
2165
2212
|
if (d.isDisabled) cell.setAttribute("aria-disabled", "true");
|
|
2166
2213
|
else cell.removeAttribute("aria-disabled");
|
|
2167
|
-
|
|
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();
|
|
2168
2221
|
}
|
|
2169
2222
|
});
|
|
2170
2223
|
function isSameCalendarDay(a, b) {
|
|
@@ -2174,6 +2227,9 @@ function datePicker(options) {
|
|
|
2174
2227
|
setViewDate((prev) => new Date(prev.getFullYear(), prev.getMonth(), prev.getDate() + delta));
|
|
2175
2228
|
}
|
|
2176
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
|
+
}
|
|
2177
2233
|
switch (e.key) {
|
|
2178
2234
|
case "ArrowLeft":
|
|
2179
2235
|
e.preventDefault();
|
|
@@ -2222,6 +2278,12 @@ function datePicker(options) {
|
|
|
2222
2278
|
boundDatePickers.delete(els.grid);
|
|
2223
2279
|
fxTeardown();
|
|
2224
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);
|
|
2225
2287
|
};
|
|
2226
2288
|
boundDatePickers.set(els.grid, teardown);
|
|
2227
2289
|
return teardown;
|
package/dist/widgets.d.cts
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.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-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-OAVXAFAY.js";
|
|
12
|
+
import "./chunk-H5FI5WDP.js";
|
|
13
|
+
import "./chunk-CCSJMTRN.js";
|
|
14
|
+
import "./chunk-ITWCTZYH.js";
|
|
14
15
|
import "./chunk-L3GAGWCC.js";
|
|
15
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-BUKYCWHX.js";
|
|
16
17
|
import "./chunk-S3NFJO6L.js";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-KZBEVFXZ.js";
|
|
19
|
+
import "./chunk-OOUQUCNN.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
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "A lightweight, function-based frontend framework that combines the best of React, Svelte, and Vue — with zero VDOM and maximum simplicity. Designed for developers who want fine-grained reactivity and full control without compilation or magic.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"frontend",
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
"format": "biome format --write src/ tests/",
|
|
34
34
|
"test": "vitest",
|
|
35
35
|
"test:ui": "vitest --ui",
|
|
36
|
+
"test:browser": "npm run build && playwright test",
|
|
37
|
+
"test:browser:install": "playwright install chromium firefox webkit",
|
|
36
38
|
"build": "tsup index.ts data.ts browser.ts patterns.ts motion.ts ui.ts widgets.ts ssr.ts devtools.ts performance.ts ecosystem.ts plugins.ts build.ts testing.ts extras.ts --dts --format esm,cjs --out-dir dist --clean && tsup cdn.ts --format iife --globalName Sibu --out-dir dist --no-dts --minify",
|
|
37
39
|
"bench": "node bench.mjs",
|
|
38
40
|
"bench:save": "node bench.mjs --save",
|
|
@@ -135,6 +137,7 @@
|
|
|
135
137
|
},
|
|
136
138
|
"devDependencies": {
|
|
137
139
|
"@biomejs/biome": "2.4.7",
|
|
140
|
+
"@playwright/test": "^1.61.1",
|
|
138
141
|
"@types/node": "^25.5.0",
|
|
139
142
|
"@vitest/coverage-v8": "^3.1.3",
|
|
140
143
|
"@vitest/ui": "^3.1.3",
|