sibujs 1.4.0 → 2.0.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/README.md +105 -119
- package/dist/browser.cjs +288 -80
- package/dist/browser.d.cts +19 -9
- package/dist/browser.d.ts +19 -9
- package/dist/browser.js +6 -6
- package/dist/build.cjs +1019 -313
- package/dist/build.d.cts +1 -1
- package/dist/build.d.ts +1 -1
- package/dist/build.js +15 -13
- package/dist/cdn.global.js +17 -16
- package/dist/chunk-2RA7SHDA.js +65 -0
- package/dist/chunk-2UPRY23K.js +80 -0
- package/dist/chunk-3JHCYHWN.js +125 -0
- package/dist/{chunk-ZWKZCBO6.js → chunk-3LR7GLWQ.js} +154 -33
- package/dist/{chunk-3AIRKM3B.js → chunk-3NSGB5JN.js} +115 -34
- package/dist/{chunk-3ARAQO7B.js → chunk-52YJLLRO.js} +29 -6
- package/dist/chunk-54EDRCEF.js +93 -0
- package/dist/chunk-7JDB7I65.js +1327 -0
- package/dist/{chunk-WZSPOOER.js → chunk-CC65Y57T.js} +8 -5
- package/dist/{chunk-23VV7YD3.js → chunk-DFPFITST.js} +25 -30
- package/dist/{chunk-WR5D4EGH.js → chunk-GTBNNBJ6.js} +14 -2
- package/dist/chunk-HB24TBAF.js +121 -0
- package/dist/{chunk-CZUGLNJS.js → chunk-ITX6OO3F.js} +3 -3
- package/dist/{chunk-JAKHTMQU.js → chunk-JA6667UN.js} +206 -46
- package/dist/{chunk-77L6NL3X.js → chunk-JXMMDLBY.js} +306 -183
- package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
- package/dist/{chunk-F3FA4F32.js → chunk-KLRMB5ZS.js} +135 -79
- package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
- package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
- package/dist/{chunk-TSOKIX5Z.js → chunk-MIUAXB7K.js} +126 -74
- package/dist/{chunk-QWZG56ET.js → chunk-ND2664SF.js} +558 -190
- package/dist/{chunk-JCI5M6U6.js → chunk-O2MNQFLP.js} +261 -79
- package/dist/{chunk-EWFVA3TJ.js → chunk-R73P76YZ.js} +1 -1
- package/dist/{chunk-2BYQDGN3.js → chunk-SAHNHTFC.js} +234 -63
- package/dist/chunk-UCS6AMJ7.js +79 -0
- package/dist/{chunk-ZD6OAMTH.js → chunk-VLPPXTYG.js} +90 -35
- package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
- package/dist/{contracts-xo5ckdRP.d.cts → contracts-ey_Qh8ef.d.cts} +7 -8
- package/dist/{contracts-xo5ckdRP.d.ts → contracts-ey_Qh8ef.d.ts} +7 -8
- package/dist/{customElement-D2DJp_xn.d.cts → customElement-CPfIrbvg.d.cts} +18 -9
- package/dist/{customElement-D2DJp_xn.d.ts → customElement-CPfIrbvg.d.ts} +18 -9
- package/dist/data.cjs +452 -100
- package/dist/data.d.cts +20 -2
- package/dist/data.d.ts +20 -2
- package/dist/data.js +11 -9
- package/dist/devtools.cjs +535 -247
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +34 -30
- package/dist/ecosystem.cjs +499 -143
- package/dist/ecosystem.d.cts +13 -11
- package/dist/ecosystem.d.ts +13 -11
- package/dist/ecosystem.js +12 -11
- package/dist/extras.cjs +3639 -1629
- package/dist/extras.d.cts +11 -11
- package/dist/extras.d.ts +11 -11
- package/dist/extras.js +58 -45
- package/dist/index.cjs +1023 -313
- package/dist/index.d.cts +128 -55
- package/dist/index.d.ts +128 -55
- package/dist/index.js +28 -16
- package/dist/{introspect-BumjnBKr.d.cts → introspect-BWNjNw64.d.cts} +22 -2
- package/dist/{introspect-CZrlcaYy.d.ts → introspect-cY2pg9pW.d.ts} +22 -2
- package/dist/motion.cjs +90 -36
- package/dist/motion.d.cts +1 -1
- package/dist/motion.d.ts +1 -1
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +414 -81
- package/dist/patterns.d.cts +53 -20
- package/dist/patterns.d.ts +53 -20
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +364 -108
- package/dist/performance.d.cts +29 -17
- package/dist/performance.d.ts +29 -17
- package/dist/performance.js +13 -6
- package/dist/plugin-D30wlGW5.d.cts +71 -0
- package/dist/plugin-D30wlGW5.d.ts +71 -0
- package/dist/plugins.cjs +652 -271
- package/dist/plugins.d.cts +13 -6
- package/dist/plugins.d.ts +13 -6
- package/dist/plugins.js +116 -50
- package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
- package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
- package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
- package/dist/ssr.cjs +648 -219
- package/dist/ssr.d.cts +27 -7
- package/dist/ssr.d.ts +27 -7
- package/dist/ssr.js +12 -11
- package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.cts} +9 -1
- package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.ts} +9 -1
- package/dist/testing.cjs +252 -63
- package/dist/testing.d.cts +17 -4
- package/dist/testing.d.ts +17 -4
- package/dist/testing.js +100 -44
- package/dist/ui.cjs +576 -168
- package/dist/ui.d.cts +13 -16
- package/dist/ui.d.ts +13 -16
- package/dist/ui.js +20 -17
- package/dist/widgets.cjs +1001 -93
- package/dist/widgets.d.cts +104 -2
- package/dist/widgets.d.ts +104 -2
- package/dist/widgets.js +9 -7
- package/package.json +8 -2
- package/dist/chunk-32DY64NT.js +0 -282
- package/dist/chunk-3CRQALYP.js +0 -877
- package/dist/chunk-4EI4AG32.js +0 -482
- package/dist/chunk-4MYMUBRS.js +0 -21
- package/dist/chunk-6HLLIF3K.js +0 -398
- package/dist/chunk-6LSNVCS2.js +0 -937
- package/dist/chunk-6SA3QQES.js +0 -61
- package/dist/chunk-7BF6TK55.js +0 -1097
- package/dist/chunk-7TQKR4PP.js +0 -294
- package/dist/chunk-7V26P53V.js +0 -712
- package/dist/chunk-AZ3ISID5.js +0 -298
- package/dist/chunk-B7SWRFUT.js +0 -332
- package/dist/chunk-BGN5ZMP4.js +0 -26
- package/dist/chunk-BTU3TJDS.js +0 -365
- package/dist/chunk-BW3WT46K.js +0 -937
- package/dist/chunk-C6KFWOFV.js +0 -616
- package/dist/chunk-CHF5OHIA.js +0 -61
- package/dist/chunk-CHJ27IGK.js +0 -26
- package/dist/chunk-CMBFNA7L.js +0 -27
- package/dist/chunk-DAHRH4ON.js +0 -331
- package/dist/chunk-DKOHBI74.js +0 -924
- package/dist/chunk-DTCOOBMX.js +0 -725
- package/dist/chunk-EBGIRKQY.js +0 -616
- package/dist/chunk-EUZND3CB.js +0 -27
- package/dist/chunk-EVCZO745.js +0 -365
- package/dist/chunk-FGOEVHY3.js +0 -60
- package/dist/chunk-G3BOQPVO.js +0 -365
- package/dist/chunk-GCOK2LC3.js +0 -282
- package/dist/chunk-HGMJFBC7.js +0 -654
- package/dist/chunk-K5ZUMYVS.js +0 -89
- package/dist/chunk-KQPDEVVS.js +0 -398
- package/dist/chunk-L6JRBDNS.js +0 -60
- package/dist/chunk-LA6KQEDU.js +0 -712
- package/dist/chunk-MDVXJWFN.js +0 -304
- package/dist/chunk-MEZVEBPN.js +0 -2008
- package/dist/chunk-MK4ERFYL.js +0 -2249
- package/dist/chunk-MLKGABMK.js +0 -9
- package/dist/chunk-MQ5GOYPH.js +0 -2249
- package/dist/chunk-N6IZB6KJ.js +0 -567
- package/dist/chunk-NEKUBFPT.js +0 -60
- package/dist/chunk-NHUC2QWH.js +0 -282
- package/dist/chunk-NMRUZALC.js +0 -1097
- package/dist/chunk-NYVAC6P5.js +0 -37
- package/dist/chunk-OF7UZIVB.js +0 -725
- package/dist/chunk-P6W3STU4.js +0 -2249
- package/dist/chunk-PBHF5WKN.js +0 -616
- package/dist/chunk-PTQJDMRT.js +0 -146
- package/dist/chunk-PZEGYCF5.js +0 -61
- package/dist/chunk-QBMDLBU2.js +0 -975
- package/dist/chunk-RQGQSLQK.js +0 -725
- package/dist/chunk-SDLZDHKP.js +0 -107
- package/dist/chunk-TNQWPPE6.js +0 -37
- package/dist/chunk-UHNL42EF.js +0 -2730
- package/dist/chunk-UNXCEF6S.js +0 -21
- package/dist/chunk-V2XTI523.js +0 -347
- package/dist/chunk-VAU366PN.js +0 -2241
- package/dist/chunk-VMVDTCXB.js +0 -712
- package/dist/chunk-VRW3FULF.js +0 -725
- package/dist/chunk-WADYRCO2.js +0 -304
- package/dist/chunk-WILQZRO4.js +0 -282
- package/dist/chunk-WUHJISPP.js +0 -298
- package/dist/chunk-XYU6TZOW.js +0 -182
- package/dist/chunk-Y6GP4QGG.js +0 -276
- package/dist/chunk-YECR7UIA.js +0 -347
- package/dist/chunk-YUTWTI4B.js +0 -654
- package/dist/chunk-Z65KYU7I.js +0 -26
- package/dist/chunk-Z6POF5YC.js +0 -975
- package/dist/chunk-ZBJP6WFL.js +0 -482
- package/dist/contracts-DDrwxvJ-.d.cts +0 -245
- package/dist/contracts-DDrwxvJ-.d.ts +0 -245
- package/dist/contracts-DOrhwbke.d.cts +0 -245
- package/dist/contracts-DOrhwbke.d.ts +0 -245
- package/dist/customElement-BKQfbSZQ.d.cts +0 -262
- package/dist/customElement-BKQfbSZQ.d.ts +0 -262
- package/dist/customElement-yz8uyk-0.d.cts +0 -308
- package/dist/customElement-yz8uyk-0.d.ts +0 -308
- package/dist/introspect-Cb0zgpi2.d.cts +0 -477
- package/dist/introspect-Y2xNXGSf.d.ts +0 -477
- package/dist/plugin-Bek4RhJY.d.cts +0 -43
- package/dist/plugin-Bek4RhJY.d.ts +0 -43
- package/dist/ssr-3RXHP5ES.js +0 -38
- package/dist/ssr-6GIMY5MX.js +0 -38
- package/dist/ssr-BA6sxxUd.d.cts +0 -135
- package/dist/ssr-BA6sxxUd.d.ts +0 -135
- package/dist/ssr-WKUPVSSK.js +0 -36
- package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
- package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
bindAttribute
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DFPFITST.js";
|
|
4
4
|
import {
|
|
5
5
|
derived
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-54EDRCEF.js";
|
|
7
|
+
import {
|
|
8
|
+
dispose,
|
|
9
|
+
registerDisposer
|
|
10
|
+
} from "./chunk-2UPRY23K.js";
|
|
7
11
|
import {
|
|
8
12
|
effect
|
|
9
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-HB24TBAF.js";
|
|
10
14
|
import {
|
|
11
15
|
signal
|
|
12
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-CC65Y57T.js";
|
|
13
17
|
import {
|
|
14
18
|
track
|
|
15
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-VLPPXTYG.js";
|
|
16
20
|
|
|
17
21
|
// src/ui/form.ts
|
|
18
22
|
function required(message = "This field is required") {
|
|
@@ -90,7 +94,7 @@ function bindField(field, extras) {
|
|
|
90
94
|
blur: () => field.touch()
|
|
91
95
|
};
|
|
92
96
|
const { on: extraOn, value: _ignoreValue, ...restExtras } = extras ?? {};
|
|
93
|
-
const mergedOn = extraOn && typeof extraOn === "object" ? { ...
|
|
97
|
+
const mergedOn = extraOn && typeof extraOn === "object" ? { ...extraOn, ...fieldOn } : fieldOn;
|
|
94
98
|
return {
|
|
95
99
|
value: field.value,
|
|
96
100
|
on: mergedOn,
|
|
@@ -115,9 +119,18 @@ function form(config) {
|
|
|
115
119
|
}
|
|
116
120
|
return null;
|
|
117
121
|
});
|
|
122
|
+
const wrappedSet = (next) => {
|
|
123
|
+
setValue(next);
|
|
124
|
+
setManualErrors((prev) => {
|
|
125
|
+
if (!(name in prev) || prev[name] == null) return prev;
|
|
126
|
+
const copy = { ...prev };
|
|
127
|
+
copy[name] = null;
|
|
128
|
+
return copy;
|
|
129
|
+
});
|
|
130
|
+
};
|
|
118
131
|
fieldMap[name] = {
|
|
119
132
|
value,
|
|
120
|
-
set:
|
|
133
|
+
set: wrappedSet,
|
|
121
134
|
error,
|
|
122
135
|
touched: isTouched,
|
|
123
136
|
touch: () => setTouched(true),
|
|
@@ -161,14 +174,23 @@ function form(config) {
|
|
|
161
174
|
}
|
|
162
175
|
return result;
|
|
163
176
|
});
|
|
177
|
+
const [submitting, setSubmitting] = signal(false);
|
|
164
178
|
function handleSubmit(onSubmit) {
|
|
165
179
|
return (e) => {
|
|
166
180
|
if (e) e.preventDefault();
|
|
181
|
+
if (submitting()) return;
|
|
167
182
|
for (const field of Object.values(fieldMap)) {
|
|
168
183
|
field.touch();
|
|
169
184
|
}
|
|
170
185
|
if (isValid()) {
|
|
171
|
-
onSubmit(values());
|
|
186
|
+
const result = onSubmit(values());
|
|
187
|
+
if (result && typeof result.then === "function") {
|
|
188
|
+
setSubmitting(true);
|
|
189
|
+
result.then(
|
|
190
|
+
() => setSubmitting(false),
|
|
191
|
+
() => setSubmitting(false)
|
|
192
|
+
);
|
|
193
|
+
}
|
|
172
194
|
}
|
|
173
195
|
};
|
|
174
196
|
}
|
|
@@ -185,6 +207,7 @@ function form(config) {
|
|
|
185
207
|
errors,
|
|
186
208
|
isValid,
|
|
187
209
|
isDirty,
|
|
210
|
+
submitting,
|
|
188
211
|
touched: touchedState,
|
|
189
212
|
values,
|
|
190
213
|
handleSubmit,
|
|
@@ -210,9 +233,9 @@ function VirtualList(props) {
|
|
|
210
233
|
content.style.right = "0";
|
|
211
234
|
spacer.appendChild(content);
|
|
212
235
|
container.appendChild(spacer);
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
236
|
+
const onScroll = () => setScrollTop(container.scrollTop);
|
|
237
|
+
container.addEventListener("scroll", onScroll);
|
|
238
|
+
registerDisposer(container, () => container.removeEventListener("scroll", onScroll));
|
|
216
239
|
const update = () => {
|
|
217
240
|
const items = props.items();
|
|
218
241
|
const totalHeight = items.length * props.itemHeight;
|
|
@@ -241,6 +264,7 @@ function intersection(options) {
|
|
|
241
264
|
let observer = null;
|
|
242
265
|
let currentElement = null;
|
|
243
266
|
function observe(element) {
|
|
267
|
+
if (typeof IntersectionObserver === "undefined") return;
|
|
244
268
|
unobserve();
|
|
245
269
|
currentElement = element;
|
|
246
270
|
observer = new IntersectionObserver((entries) => {
|
|
@@ -268,6 +292,11 @@ function intersection(options) {
|
|
|
268
292
|
};
|
|
269
293
|
}
|
|
270
294
|
function lazyLoad(element, loader, options) {
|
|
295
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
296
|
+
loader();
|
|
297
|
+
return () => {
|
|
298
|
+
};
|
|
299
|
+
}
|
|
271
300
|
const observer = new IntersectionObserver((entries) => {
|
|
272
301
|
for (const entry of entries) {
|
|
273
302
|
if (entry.isIntersecting) {
|
|
@@ -320,20 +349,65 @@ function inputMask(options) {
|
|
|
320
349
|
}
|
|
321
350
|
return raw;
|
|
322
351
|
}
|
|
352
|
+
function isSlot(c) {
|
|
353
|
+
return c === "9" || c === "A" || c === "*";
|
|
354
|
+
}
|
|
355
|
+
function buildStripRegex() {
|
|
356
|
+
const hasDigit = options.pattern.includes("9");
|
|
357
|
+
const hasLetter = options.pattern.includes("A");
|
|
358
|
+
const hasAny = options.pattern.includes("*");
|
|
359
|
+
if (hasAny) {
|
|
360
|
+
const literals = /* @__PURE__ */ new Set();
|
|
361
|
+
for (const c of options.pattern) {
|
|
362
|
+
if (!isSlot(c)) literals.add(c.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
363
|
+
}
|
|
364
|
+
return literals.size > 0 ? new RegExp(`[${Array.from(literals).join("")}]`, "g") : /(?!)/g;
|
|
365
|
+
}
|
|
366
|
+
if (hasDigit && hasLetter) return /[^a-zA-Z0-9]/g;
|
|
367
|
+
if (hasDigit) return /[^0-9]/g;
|
|
368
|
+
if (hasLetter) return /[^a-zA-Z]/g;
|
|
369
|
+
return /[^a-zA-Z0-9]/g;
|
|
370
|
+
}
|
|
371
|
+
const stripRegex = buildStripRegex();
|
|
372
|
+
const rawCharTest = options.pattern.includes("*") ? () => true : (c) => /[a-zA-Z0-9]/.test(c);
|
|
323
373
|
function bind(input) {
|
|
324
|
-
|
|
325
|
-
const
|
|
374
|
+
const onInput = () => {
|
|
375
|
+
const cursorBefore = input.selectionStart ?? input.value.length;
|
|
376
|
+
const oldValue = input.value;
|
|
377
|
+
const raw = oldValue.replace(stripRegex, "");
|
|
326
378
|
const masked = applyMask(raw);
|
|
327
379
|
setValue(masked);
|
|
328
380
|
setRawValue(extractRaw(masked));
|
|
329
381
|
input.value = masked;
|
|
330
|
-
|
|
331
|
-
|
|
382
|
+
let rawBefore = 0;
|
|
383
|
+
for (let i = 0; i < cursorBefore && i < oldValue.length; i++) {
|
|
384
|
+
if (rawCharTest(oldValue[i])) rawBefore++;
|
|
385
|
+
}
|
|
386
|
+
let newCursor = 0;
|
|
387
|
+
let counted = 0;
|
|
388
|
+
for (; newCursor < masked.length; newCursor++) {
|
|
389
|
+
if (newCursor < options.pattern.length && isSlot(options.pattern[newCursor])) {
|
|
390
|
+
counted++;
|
|
391
|
+
if (counted >= rawBefore) {
|
|
392
|
+
newCursor++;
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
input.setSelectionRange(newCursor, newCursor);
|
|
398
|
+
};
|
|
399
|
+
const onFocus = () => {
|
|
332
400
|
if (!input.value) {
|
|
333
401
|
const display = options.pattern.replace(/9/g, placeholder).replace(/A/g, placeholder).replace(/\*/g, placeholder);
|
|
334
402
|
input.placeholder = display;
|
|
335
403
|
}
|
|
336
|
-
}
|
|
404
|
+
};
|
|
405
|
+
input.addEventListener("input", onInput);
|
|
406
|
+
input.addEventListener("focus", onFocus);
|
|
407
|
+
return () => {
|
|
408
|
+
input.removeEventListener("input", onInput);
|
|
409
|
+
input.removeEventListener("focus", onFocus);
|
|
410
|
+
};
|
|
337
411
|
}
|
|
338
412
|
return { value, rawValue, bind };
|
|
339
413
|
}
|
|
@@ -375,8 +449,20 @@ function focus() {
|
|
|
375
449
|
let currentElement = null;
|
|
376
450
|
function bind(element) {
|
|
377
451
|
currentElement = element;
|
|
378
|
-
|
|
379
|
-
|
|
452
|
+
const onFocus = () => setIsFocused(true);
|
|
453
|
+
const onBlur = () => setIsFocused(false);
|
|
454
|
+
element.addEventListener("focus", onFocus);
|
|
455
|
+
element.addEventListener("blur", onBlur);
|
|
456
|
+
let disposed = false;
|
|
457
|
+
const dispose2 = () => {
|
|
458
|
+
if (disposed) return;
|
|
459
|
+
disposed = true;
|
|
460
|
+
element.removeEventListener("focus", onFocus);
|
|
461
|
+
element.removeEventListener("blur", onBlur);
|
|
462
|
+
if (currentElement === element) currentElement = null;
|
|
463
|
+
};
|
|
464
|
+
registerDisposer(element, dispose2);
|
|
465
|
+
return dispose2;
|
|
380
466
|
}
|
|
381
467
|
function focus2() {
|
|
382
468
|
currentElement?.focus();
|
|
@@ -391,12 +477,39 @@ function FocusTrap(nodes, options = {}) {
|
|
|
391
477
|
container.setAttribute("data-sibu-focus-trap", "true");
|
|
392
478
|
container.appendChild(nodes);
|
|
393
479
|
const previouslyFocused = document.activeElement;
|
|
394
|
-
|
|
480
|
+
const FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [contenteditable]';
|
|
481
|
+
function isEffectivelyVisible(el) {
|
|
482
|
+
let node = el;
|
|
483
|
+
while (node) {
|
|
484
|
+
if (node.hasAttribute("inert")) return false;
|
|
485
|
+
if (node.getAttribute("aria-hidden") === "true") return false;
|
|
486
|
+
if (node.hidden) return false;
|
|
487
|
+
node = node.parentElement;
|
|
488
|
+
}
|
|
489
|
+
if (el.offsetParent === null && el.getClientRects().length === 0) return false;
|
|
490
|
+
return true;
|
|
491
|
+
}
|
|
492
|
+
function getFocusable() {
|
|
493
|
+
const raw = Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
494
|
+
const out = [];
|
|
495
|
+
for (const el of raw) {
|
|
496
|
+
if (el.hasAttribute("disabled")) continue;
|
|
497
|
+
if (el.getAttribute("aria-hidden") === "true") continue;
|
|
498
|
+
if (el.hasAttribute("inert")) continue;
|
|
499
|
+
const ce = el.getAttribute("contenteditable");
|
|
500
|
+
if (ce !== null && ce === "false") continue;
|
|
501
|
+
if (!isEffectivelyVisible(el)) continue;
|
|
502
|
+
out.push(el);
|
|
503
|
+
}
|
|
504
|
+
return out;
|
|
505
|
+
}
|
|
506
|
+
const onTrapKeydown = (e) => {
|
|
395
507
|
if (e.key !== "Tab") return;
|
|
396
|
-
const focusable =
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
508
|
+
const focusable = getFocusable();
|
|
509
|
+
if (focusable.length === 0) {
|
|
510
|
+
e.preventDefault();
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
400
513
|
const first = focusable[0];
|
|
401
514
|
const last = focusable[focusable.length - 1];
|
|
402
515
|
if (e.shiftKey) {
|
|
@@ -410,33 +523,36 @@ function FocusTrap(nodes, options = {}) {
|
|
|
410
523
|
first.focus();
|
|
411
524
|
}
|
|
412
525
|
}
|
|
413
|
-
}
|
|
526
|
+
};
|
|
527
|
+
container.addEventListener("keydown", onTrapKeydown);
|
|
414
528
|
if (options.autoFocus !== false) {
|
|
415
529
|
queueMicrotask(() => {
|
|
416
|
-
const first =
|
|
417
|
-
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
418
|
-
);
|
|
530
|
+
const first = getFocusable()[0];
|
|
419
531
|
first?.focus();
|
|
420
532
|
});
|
|
421
533
|
}
|
|
534
|
+
let trapObserver = null;
|
|
535
|
+
function restoreFocusAndCleanup() {
|
|
536
|
+
if (options.restoreFocus !== false) previouslyFocused?.focus();
|
|
537
|
+
container.removeEventListener("keydown", onTrapKeydown);
|
|
538
|
+
if (trapObserver) {
|
|
539
|
+
trapObserver.disconnect();
|
|
540
|
+
trapObserver = null;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
422
543
|
if (options.restoreFocus !== false) {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (removed === container || removed.contains(container)) {
|
|
427
|
-
previouslyFocused?.focus();
|
|
428
|
-
observer.disconnect();
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
544
|
+
trapObserver = new MutationObserver(() => {
|
|
545
|
+
if (!container.isConnected) {
|
|
546
|
+
restoreFocusAndCleanup();
|
|
432
547
|
}
|
|
433
548
|
});
|
|
434
549
|
queueMicrotask(() => {
|
|
435
|
-
if (container.
|
|
436
|
-
|
|
550
|
+
if (container.isConnected) {
|
|
551
|
+
trapObserver.observe(container, { childList: true, subtree: true });
|
|
437
552
|
}
|
|
438
553
|
});
|
|
439
554
|
}
|
|
555
|
+
registerDisposer(container, restoreFocusAndCleanup);
|
|
440
556
|
return container;
|
|
441
557
|
}
|
|
442
558
|
function hotkey(combo, handler, options = {}) {
|
|
@@ -469,7 +585,16 @@ function hotkey(combo, handler, options = {}) {
|
|
|
469
585
|
document.addEventListener("keydown", listener);
|
|
470
586
|
return () => document.removeEventListener("keydown", listener);
|
|
471
587
|
}
|
|
472
|
-
|
|
588
|
+
var announceQueues = {
|
|
589
|
+
polite: [],
|
|
590
|
+
assertive: []
|
|
591
|
+
};
|
|
592
|
+
var announceDraining = {
|
|
593
|
+
polite: false,
|
|
594
|
+
assertive: false
|
|
595
|
+
};
|
|
596
|
+
var ANNOUNCE_INTERVAL_MS = 150;
|
|
597
|
+
function ensureLiveRegion(priority) {
|
|
473
598
|
let region = document.getElementById(`sibu-announce-${priority}`);
|
|
474
599
|
if (!region) {
|
|
475
600
|
region = document.createElement("div");
|
|
@@ -480,11 +605,33 @@ function announce(message, priority = "polite") {
|
|
|
480
605
|
region.style.cssText = "position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;";
|
|
481
606
|
document.body.appendChild(region);
|
|
482
607
|
}
|
|
608
|
+
return region;
|
|
609
|
+
}
|
|
610
|
+
function drainAnnounceQueue(priority) {
|
|
611
|
+
if (announceDraining[priority]) return;
|
|
612
|
+
const queue = announceQueues[priority];
|
|
613
|
+
if (queue.length === 0) return;
|
|
614
|
+
announceDraining[priority] = true;
|
|
615
|
+
const region = ensureLiveRegion(priority);
|
|
616
|
+
const next = queue.shift();
|
|
483
617
|
region.textContent = "";
|
|
484
618
|
requestAnimationFrame(() => {
|
|
485
|
-
if (region)
|
|
619
|
+
if (!region.isConnected) {
|
|
620
|
+
announceDraining[priority] = false;
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
region.textContent = next;
|
|
624
|
+
setTimeout(() => {
|
|
625
|
+
announceDraining[priority] = false;
|
|
626
|
+
drainAnnounceQueue(priority);
|
|
627
|
+
}, ANNOUNCE_INTERVAL_MS);
|
|
486
628
|
});
|
|
487
629
|
}
|
|
630
|
+
function announce(message, priority = "polite") {
|
|
631
|
+
if (typeof document === "undefined") return;
|
|
632
|
+
announceQueues[priority].push(message);
|
|
633
|
+
drainAnnounceQueue(priority);
|
|
634
|
+
}
|
|
488
635
|
|
|
489
636
|
// src/ui/scopedStyle.ts
|
|
490
637
|
var scopeCounter = 0;
|
|
@@ -522,6 +669,10 @@ function scopedStyle(css) {
|
|
|
522
669
|
if (trimmed.startsWith("@") || trimmed.startsWith("from") || trimmed.startsWith("to") || /^\d+%$/.test(trimmed)) {
|
|
523
670
|
return match;
|
|
524
671
|
}
|
|
672
|
+
const pseudoIdx = trimmed.indexOf("::");
|
|
673
|
+
if (pseudoIdx >= 0) {
|
|
674
|
+
return `${trimmed.slice(0, pseudoIdx)}[${attr}]${trimmed.slice(pseudoIdx)}${delimiter}`;
|
|
675
|
+
}
|
|
525
676
|
return `${trimmed}[${attr}]${delimiter}`;
|
|
526
677
|
});
|
|
527
678
|
if (typeof document !== "undefined") {
|
|
@@ -617,59 +768,91 @@ function bindData(el, key, getter) {
|
|
|
617
768
|
}
|
|
618
769
|
|
|
619
770
|
// src/ui/dialog.ts
|
|
771
|
+
var dialogStack = [];
|
|
772
|
+
var globalListenerAttached = false;
|
|
773
|
+
function __resetDialogStack() {
|
|
774
|
+
while (dialogStack.length > 0) dialogStack.pop();
|
|
775
|
+
if (typeof window !== "undefined" && globalListenerAttached) {
|
|
776
|
+
window.removeEventListener("keydown", handleGlobalKeydown);
|
|
777
|
+
globalListenerAttached = false;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
function handleGlobalKeydown(event) {
|
|
781
|
+
if (event.key !== "Escape") return;
|
|
782
|
+
const top = dialogStack[dialogStack.length - 1];
|
|
783
|
+
if (top) top.close();
|
|
784
|
+
}
|
|
785
|
+
function ensureGlobalListener() {
|
|
786
|
+
if (typeof window === "undefined" || globalListenerAttached) return;
|
|
787
|
+
window.addEventListener("keydown", handleGlobalKeydown);
|
|
788
|
+
globalListenerAttached = true;
|
|
789
|
+
}
|
|
790
|
+
function removeGlobalListenerIfIdle() {
|
|
791
|
+
if (typeof window === "undefined") return;
|
|
792
|
+
if (!globalListenerAttached) return;
|
|
793
|
+
if (dialogStack.length > 0) return;
|
|
794
|
+
window.removeEventListener("keydown", handleGlobalKeydown);
|
|
795
|
+
globalListenerAttached = false;
|
|
796
|
+
}
|
|
620
797
|
function dialog() {
|
|
621
798
|
const [isOpen, setIsOpen] = signal(false);
|
|
622
|
-
|
|
623
|
-
function
|
|
624
|
-
if (
|
|
625
|
-
|
|
626
|
-
|
|
799
|
+
const entry = { close: () => close() };
|
|
800
|
+
function pushOnStack() {
|
|
801
|
+
if (dialogStack.indexOf(entry) !== -1) return;
|
|
802
|
+
dialogStack.push(entry);
|
|
803
|
+
ensureGlobalListener();
|
|
804
|
+
}
|
|
805
|
+
function removeFromStack() {
|
|
806
|
+
const idx = dialogStack.indexOf(entry);
|
|
807
|
+
if (idx !== -1) dialogStack.splice(idx, 1);
|
|
808
|
+
removeGlobalListenerIfIdle();
|
|
627
809
|
}
|
|
628
810
|
function open() {
|
|
811
|
+
if (isOpen()) return;
|
|
629
812
|
setIsOpen(true);
|
|
630
|
-
|
|
631
|
-
window.addEventListener("keydown", handleKeydown);
|
|
632
|
-
listenerAttached = true;
|
|
633
|
-
}
|
|
813
|
+
pushOnStack();
|
|
634
814
|
}
|
|
635
815
|
function close() {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
listenerAttached = false;
|
|
816
|
+
if (!isOpen()) {
|
|
817
|
+
removeFromStack();
|
|
818
|
+
return;
|
|
640
819
|
}
|
|
820
|
+
setIsOpen(false);
|
|
821
|
+
removeFromStack();
|
|
641
822
|
}
|
|
642
823
|
function toggle() {
|
|
643
|
-
if (isOpen())
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
824
|
+
if (isOpen()) close();
|
|
825
|
+
else open();
|
|
826
|
+
}
|
|
827
|
+
function dispose2() {
|
|
828
|
+
removeFromStack();
|
|
829
|
+
setIsOpen(false);
|
|
648
830
|
}
|
|
649
|
-
return { open, close, isOpen, toggle };
|
|
831
|
+
return { open, close, isOpen, toggle, dispose: dispose2 };
|
|
650
832
|
}
|
|
651
833
|
|
|
652
834
|
// src/ui/toast.ts
|
|
653
|
-
var toastCounter = 0;
|
|
654
835
|
function toast(options) {
|
|
655
836
|
const duration = options?.duration ?? 3e3;
|
|
656
837
|
const maxToasts = options?.maxToasts ?? Infinity;
|
|
657
838
|
const [toasts, setToasts] = signal([]);
|
|
658
839
|
const timers = /* @__PURE__ */ new Map();
|
|
840
|
+
let toastCounter = 0;
|
|
659
841
|
function show(message, type) {
|
|
660
842
|
const id = `toast-${++toastCounter}`;
|
|
661
843
|
const toast2 = { id, message, type };
|
|
844
|
+
const trimmedIds = [];
|
|
662
845
|
setToasts((prev) => {
|
|
663
846
|
const next = [...prev, toast2];
|
|
664
847
|
if (next.length > maxToasts) {
|
|
665
848
|
const removed = next.splice(0, next.length - maxToasts);
|
|
666
|
-
for (const r of removed)
|
|
667
|
-
clearTimerForToast(r.id);
|
|
668
|
-
}
|
|
849
|
+
for (const r of removed) trimmedIds.push(r.id);
|
|
669
850
|
}
|
|
670
851
|
return next;
|
|
671
852
|
});
|
|
672
|
-
|
|
853
|
+
for (const tid of trimmedIds) clearTimerForToast(tid);
|
|
854
|
+
const wasTrimmed = trimmedIds.indexOf(id) !== -1;
|
|
855
|
+
if (duration > 0 && !wasTrimmed) {
|
|
673
856
|
const timer = setTimeout(() => {
|
|
674
857
|
dismiss(id);
|
|
675
858
|
}, duration);
|
|
@@ -755,14 +938,14 @@ function infiniteScroll(options) {
|
|
|
755
938
|
},
|
|
756
939
|
configurable: true
|
|
757
940
|
});
|
|
758
|
-
function
|
|
941
|
+
function dispose2() {
|
|
759
942
|
disposed = true;
|
|
760
943
|
if (observer) {
|
|
761
944
|
observer.disconnect();
|
|
762
945
|
observer = null;
|
|
763
946
|
}
|
|
764
947
|
}
|
|
765
|
-
return { sentinelRef: originalRef, loading, dispose };
|
|
948
|
+
return { sentinelRef: originalRef, loading, dispose: dispose2 };
|
|
766
949
|
}
|
|
767
950
|
|
|
768
951
|
// src/ui/pagination.ts
|
|
@@ -841,7 +1024,7 @@ function defineElement(name, component, options = {}) {
|
|
|
841
1024
|
class SibuElement extends HTMLElement {
|
|
842
1025
|
constructor() {
|
|
843
1026
|
super();
|
|
844
|
-
this._rendered =
|
|
1027
|
+
this._rendered = null;
|
|
845
1028
|
if (options.shadow !== false) {
|
|
846
1029
|
this._root = this.attachShadow({ mode: options.mode || "open" });
|
|
847
1030
|
} else {
|
|
@@ -855,25 +1038,23 @@ function defineElement(name, component, options = {}) {
|
|
|
855
1038
|
this._render();
|
|
856
1039
|
}
|
|
857
1040
|
disconnectedCallback() {
|
|
858
|
-
|
|
859
|
-
this._root.innerHTML = "";
|
|
860
|
-
}
|
|
861
|
-
this._rendered = false;
|
|
1041
|
+
this._teardown();
|
|
862
1042
|
}
|
|
863
1043
|
attributeChangedCallback() {
|
|
864
1044
|
if (this._rendered) {
|
|
865
1045
|
this._render();
|
|
866
1046
|
}
|
|
867
1047
|
}
|
|
1048
|
+
_teardown() {
|
|
1049
|
+
if (this._rendered) {
|
|
1050
|
+
dispose(this._rendered);
|
|
1051
|
+
this._rendered = null;
|
|
1052
|
+
}
|
|
1053
|
+
this._root.replaceChildren();
|
|
1054
|
+
}
|
|
868
1055
|
_render() {
|
|
1056
|
+
this._teardown();
|
|
869
1057
|
const props = this._getProps();
|
|
870
|
-
if (this._root instanceof ShadowRoot) {
|
|
871
|
-
this._root.innerHTML = "";
|
|
872
|
-
} else {
|
|
873
|
-
while (this._root.firstChild) {
|
|
874
|
-
this._root.removeChild(this._root.firstChild);
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
1058
|
if (options.styles && this._root instanceof ShadowRoot) {
|
|
878
1059
|
const styleEl = document.createElement("style");
|
|
879
1060
|
styleEl.textContent = options.styles;
|
|
@@ -881,7 +1062,7 @@ function defineElement(name, component, options = {}) {
|
|
|
881
1062
|
}
|
|
882
1063
|
const el = component(props, this);
|
|
883
1064
|
this._root.appendChild(el);
|
|
884
|
-
this._rendered =
|
|
1065
|
+
this._rendered = el;
|
|
885
1066
|
}
|
|
886
1067
|
_getProps() {
|
|
887
1068
|
const props = {};
|
|
@@ -946,6 +1127,7 @@ export {
|
|
|
946
1127
|
bindAttrs,
|
|
947
1128
|
bindBoolAttr,
|
|
948
1129
|
bindData,
|
|
1130
|
+
__resetDialogStack,
|
|
949
1131
|
dialog,
|
|
950
1132
|
toast,
|
|
951
1133
|
infiniteScroll,
|