@y14e/accordion 2.0.3 → 2.0.4
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 +11 -12
- package/dist/index.bundle.cjs +207 -88
- package/dist/index.bundle.js +207 -88
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -10,14 +10,14 @@ npm i @y14e/accordion
|
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
// npm
|
|
13
|
-
import Accordion from
|
|
13
|
+
import Accordion from "@y14e/accordion";
|
|
14
14
|
|
|
15
15
|
// CDNs
|
|
16
|
-
import Accordion from
|
|
16
|
+
import Accordion from "https://esm.sh/@y14e/accordion@2.0.4";
|
|
17
17
|
// or
|
|
18
|
-
import Accordion from
|
|
18
|
+
import Accordion from "https://cdn.jsdelivr.net/npm/@y14e/accordion@2.0.4/+esm";
|
|
19
19
|
// or
|
|
20
|
-
import Accordion from
|
|
20
|
+
import Accordion from "https://esm.unpkg.com/@y14e/accordion@2.0.4";
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
@@ -28,7 +28,6 @@ new Accordion(root, options);
|
|
|
28
28
|
//
|
|
29
29
|
// root: HTMLElement
|
|
30
30
|
// options (optional): AccordionOptions
|
|
31
|
-
|
|
32
31
|
```
|
|
33
32
|
|
|
34
33
|
## 🪄 Options
|
|
@@ -36,13 +35,13 @@ new Accordion(root, options);
|
|
|
36
35
|
```ts
|
|
37
36
|
interface AccordionOptions {
|
|
38
37
|
animation: {
|
|
39
|
-
duration: number;
|
|
40
|
-
easing: string;
|
|
38
|
+
duration: number; // ms (default: 300)
|
|
39
|
+
easing: string; // <easing-function> (default: 'ease')
|
|
41
40
|
};
|
|
42
41
|
collapsible: boolean; // default: true
|
|
43
42
|
selector: {
|
|
44
|
-
content: string;
|
|
45
|
-
trigger: string;
|
|
43
|
+
content: string; // default: '[data-accordion-content]'
|
|
44
|
+
trigger: string; // default: '[data-accordion-trigger]'
|
|
46
45
|
};
|
|
47
46
|
}
|
|
48
47
|
```
|
|
@@ -52,15 +51,15 @@ interface AccordionOptions {
|
|
|
52
51
|
Override the global default settings applied to all accordion instances.
|
|
53
52
|
|
|
54
53
|
```ts
|
|
55
|
-
import Accordion from
|
|
54
|
+
import Accordion from "@y14e/accordion";
|
|
56
55
|
|
|
57
56
|
Accordion.defaults = {
|
|
58
57
|
animation: {
|
|
59
58
|
duration: 1000,
|
|
60
59
|
},
|
|
61
60
|
selector: {
|
|
62
|
-
content:
|
|
63
|
-
trigger:
|
|
61
|
+
content: ".content",
|
|
62
|
+
trigger: ".trigger",
|
|
64
63
|
},
|
|
65
64
|
};
|
|
66
65
|
|
package/dist/index.bundle.cjs
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// node_modules/@y14e/attributes-utils/dist/index.js
|
|
4
4
|
var DEFAULT_PARSER = (value) => value.split(/\s+/);
|
|
5
5
|
var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
|
|
6
|
-
function
|
|
7
|
-
const value = element.getAttribute(
|
|
6
|
+
function addAttributeToken(element, name, token, options = {}) {
|
|
7
|
+
const value = element.getAttribute(name)?.trim();
|
|
8
8
|
const {
|
|
9
9
|
caseInsensitive = false,
|
|
10
10
|
parse = DEFAULT_PARSER,
|
|
@@ -15,42 +15,48 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
|
15
15
|
const lower = token.toLowerCase();
|
|
16
16
|
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
17
17
|
tokens.push(token);
|
|
18
|
-
element.setAttribute(
|
|
18
|
+
element.setAttribute(name, serialize(tokens));
|
|
19
19
|
}
|
|
20
20
|
} else {
|
|
21
21
|
const set = new Set(tokens);
|
|
22
22
|
set.add(token);
|
|
23
|
-
element.setAttribute(
|
|
23
|
+
element.setAttribute(name, serialize([...set]));
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
27
|
-
function restoreAttributes(
|
|
28
|
-
for (const element of
|
|
27
|
+
function restoreAttributes(element_or_elements) {
|
|
28
|
+
for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
|
|
29
29
|
const snapshot = snapshots.get(element);
|
|
30
30
|
if (!snapshot) {
|
|
31
31
|
continue;
|
|
32
32
|
}
|
|
33
|
-
for (const [
|
|
34
|
-
value === null ? element.removeAttribute(
|
|
33
|
+
for (const [name, value] of snapshot.entries()) {
|
|
34
|
+
value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
|
|
35
35
|
}
|
|
36
36
|
snapshots.delete(element);
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
function saveAttributes(
|
|
40
|
-
|
|
39
|
+
function saveAttributes(element_or_elements, name_or_names) {
|
|
40
|
+
const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
|
|
41
|
+
(Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
|
|
41
42
|
let snapshot = snapshots.get(element);
|
|
42
43
|
if (!snapshot) {
|
|
43
44
|
snapshot = /* @__PURE__ */ new Map();
|
|
44
45
|
snapshots.set(element, snapshot);
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
-
snapshot.set(
|
|
47
|
+
names.forEach((name) => {
|
|
48
|
+
snapshot.set(name, element.getAttribute(name));
|
|
48
49
|
});
|
|
49
50
|
});
|
|
50
51
|
}
|
|
52
|
+
var addTokenToAttribute = addAttributeToken;
|
|
51
53
|
|
|
52
54
|
// node_modules/power-focusable/dist/index.js
|
|
53
55
|
var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
|
|
56
|
+
var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
|
|
57
|
+
/(,\s*)?\[tabindex="-1"\]/g,
|
|
58
|
+
""
|
|
59
|
+
);
|
|
54
60
|
function getFocusables(container = document.body, options = {}) {
|
|
55
61
|
if (!(container instanceof Element)) {
|
|
56
62
|
console.warn("Invalid container element. Fallback: <body> element.");
|
|
@@ -87,36 +93,43 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
87
93
|
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
88
94
|
skipVisibilityCheck = false;
|
|
89
95
|
}
|
|
90
|
-
const
|
|
96
|
+
const candidates = [];
|
|
91
97
|
if (composed || include) {
|
|
92
98
|
let traverse2 = function(node) {
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
if (isFocusable(node, {
|
|
100
|
+
skipNegativeTabIndexCheck,
|
|
101
|
+
skipVisibilityCheck
|
|
102
|
+
}) || include?.(node)) {
|
|
103
|
+
candidates[candidates.length] = node;
|
|
98
104
|
}
|
|
99
|
-
const
|
|
100
|
-
for (let i = 0, l =
|
|
101
|
-
const child =
|
|
105
|
+
const children2 = composed ? getComposedChildren(node) : getChildren(node);
|
|
106
|
+
for (let i = 0, l = children2.length; i < l; i++) {
|
|
107
|
+
const child = children2[i];
|
|
102
108
|
child && traverse2(child);
|
|
103
109
|
}
|
|
104
110
|
};
|
|
105
|
-
|
|
111
|
+
const children = composed ? getComposedChildren(container) : getChildren(container);
|
|
112
|
+
for (let i = 0, l = children.length; i < l; i++) {
|
|
113
|
+
const child = children[i];
|
|
114
|
+
child && traverse2(child);
|
|
115
|
+
}
|
|
106
116
|
} else {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
117
|
+
const matches = container.querySelectorAll(
|
|
118
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
119
|
+
);
|
|
120
|
+
for (let i = 0, l = matches.length; i < l; i++) {
|
|
121
|
+
const matched = matches[i];
|
|
122
|
+
if (matched && isFocusable(matched, {
|
|
111
123
|
skipNegativeTabIndexCheck,
|
|
112
124
|
skipVisibilityCheck
|
|
113
125
|
})) {
|
|
114
|
-
|
|
126
|
+
candidates[candidates.length] = matched;
|
|
115
127
|
}
|
|
116
128
|
}
|
|
117
129
|
}
|
|
118
|
-
|
|
119
|
-
|
|
130
|
+
return normalizeRadioGroup(
|
|
131
|
+
sortByTabIndex(filter ? candidates.filter(filter) : candidates)
|
|
132
|
+
);
|
|
120
133
|
}
|
|
121
134
|
function isFocusable(element, options = {}) {
|
|
122
135
|
if (!(element instanceof Element)) {
|
|
@@ -139,7 +152,7 @@ function isFocusable(element, options = {}) {
|
|
|
139
152
|
return false;
|
|
140
153
|
}
|
|
141
154
|
if (!element.matches(
|
|
142
|
-
skipNegativeTabIndexCheck ?
|
|
155
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
143
156
|
)) {
|
|
144
157
|
return false;
|
|
145
158
|
}
|
|
@@ -197,22 +210,42 @@ function normalizeRadioGroup(elements) {
|
|
|
197
210
|
if (!map) {
|
|
198
211
|
map = /* @__PURE__ */ new Map();
|
|
199
212
|
}
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
if (
|
|
203
|
-
|
|
213
|
+
const root = element.getRootNode();
|
|
214
|
+
let value = map.get(root);
|
|
215
|
+
if (!value) {
|
|
216
|
+
value = /* @__PURE__ */ new Map();
|
|
217
|
+
map.set(root, value);
|
|
218
|
+
}
|
|
219
|
+
let v = value.get(element.form);
|
|
220
|
+
if (!v) {
|
|
221
|
+
v = /* @__PURE__ */ new Map();
|
|
222
|
+
value.set(element.form, v);
|
|
223
|
+
}
|
|
224
|
+
let vv = v.get(element.name);
|
|
225
|
+
if (!vv) {
|
|
226
|
+
vv = [];
|
|
227
|
+
v.set(element.name, vv);
|
|
204
228
|
}
|
|
229
|
+
vv[vv.length] = element;
|
|
205
230
|
}
|
|
206
231
|
if (!map) {
|
|
207
232
|
return elements;
|
|
208
233
|
}
|
|
209
234
|
const placeholder = /* @__PURE__ */ new Set();
|
|
210
|
-
for (const
|
|
211
|
-
|
|
235
|
+
for (const value of map.values()) {
|
|
236
|
+
for (const v of value.values()) {
|
|
237
|
+
for (const vv of v.values()) {
|
|
238
|
+
const radio = vv.find((element) => element.checked) ?? vv[0];
|
|
239
|
+
radio && placeholder.add(radio);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
212
242
|
}
|
|
213
|
-
return elements.filter(
|
|
214
|
-
|
|
215
|
-
|
|
243
|
+
return elements.filter((element) => {
|
|
244
|
+
if (!(element instanceof HTMLInputElement)) {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
return !isUngroupedRadio(element) || placeholder.has(element);
|
|
248
|
+
});
|
|
216
249
|
}
|
|
217
250
|
function sortByTabIndex(elements) {
|
|
218
251
|
const ordered = [];
|
|
@@ -284,7 +317,7 @@ function isInert(element) {
|
|
|
284
317
|
return "inert" in element && !!element.inert;
|
|
285
318
|
}
|
|
286
319
|
function isUngroupedRadio(element) {
|
|
287
|
-
return element
|
|
320
|
+
return element.type === "radio" && !!element.name;
|
|
288
321
|
}
|
|
289
322
|
|
|
290
323
|
// node_modules/@y14e/button/dist/index.js
|
|
@@ -336,6 +369,56 @@ var Button = class {
|
|
|
336
369
|
};
|
|
337
370
|
};
|
|
338
371
|
|
|
372
|
+
// node_modules/@y14e/roving-tabindex/node_modules/@y14e/attributes-utils/dist/index.js
|
|
373
|
+
var DEFAULT_PARSER2 = (value) => value.split(/\s+/);
|
|
374
|
+
var DEFAULT_SERIALIZER2 = (tokens) => tokens.join(" ");
|
|
375
|
+
function addTokenToAttribute2(element, name, token, options = {}) {
|
|
376
|
+
const value = element.getAttribute(name)?.trim();
|
|
377
|
+
const {
|
|
378
|
+
caseInsensitive = false,
|
|
379
|
+
parse = DEFAULT_PARSER2,
|
|
380
|
+
serialize = DEFAULT_SERIALIZER2
|
|
381
|
+
} = options;
|
|
382
|
+
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
383
|
+
if (caseInsensitive) {
|
|
384
|
+
const lower = token.toLowerCase();
|
|
385
|
+
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
386
|
+
tokens.push(token);
|
|
387
|
+
element.setAttribute(name, serialize(tokens));
|
|
388
|
+
}
|
|
389
|
+
} else {
|
|
390
|
+
const set = new Set(tokens);
|
|
391
|
+
set.add(token);
|
|
392
|
+
element.setAttribute(name, serialize([...set]));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
var snapshots2 = /* @__PURE__ */ new WeakMap();
|
|
396
|
+
function restoreAttributes2(element_or_elements) {
|
|
397
|
+
for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
|
|
398
|
+
const snapshot = snapshots2.get(element);
|
|
399
|
+
if (!snapshot) {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
for (const [name, value] of snapshot.entries()) {
|
|
403
|
+
value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
|
|
404
|
+
}
|
|
405
|
+
snapshots2.delete(element);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
function saveAttributes2(element_or_elements, name_or_names) {
|
|
409
|
+
const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
|
|
410
|
+
(Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
|
|
411
|
+
let snapshot = snapshots2.get(element);
|
|
412
|
+
if (!snapshot) {
|
|
413
|
+
snapshot = /* @__PURE__ */ new Map();
|
|
414
|
+
snapshots2.set(element, snapshot);
|
|
415
|
+
}
|
|
416
|
+
names.forEach((name) => {
|
|
417
|
+
snapshot.set(name, element.getAttribute(name));
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
339
422
|
// node_modules/@y14e/roving-tabindex/dist/index.js
|
|
340
423
|
function createRovingTabIndex(container, options = {}) {
|
|
341
424
|
if (!(container instanceof Element)) {
|
|
@@ -343,14 +426,8 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
343
426
|
return () => {
|
|
344
427
|
};
|
|
345
428
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return () => roving.destroy();
|
|
349
|
-
} catch (error) {
|
|
350
|
-
error instanceof Error && console.warn(error.message || error);
|
|
351
|
-
return () => {
|
|
352
|
-
};
|
|
353
|
-
}
|
|
429
|
+
const roving = new RovingTabIndex(container, options);
|
|
430
|
+
return () => roving.destroy();
|
|
354
431
|
}
|
|
355
432
|
var RovingTabIndex = class _RovingTabIndex {
|
|
356
433
|
static #initialized = /* @__PURE__ */ new Set();
|
|
@@ -364,17 +441,17 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
364
441
|
constructor(container, options = {}) {
|
|
365
442
|
this.#container = container;
|
|
366
443
|
let {
|
|
367
|
-
direction,
|
|
444
|
+
direction = "both",
|
|
368
445
|
navigationOnly = false,
|
|
369
446
|
noMemory = false,
|
|
370
447
|
noStart = false,
|
|
371
|
-
selector,
|
|
448
|
+
selector = "",
|
|
372
449
|
typeahead = false,
|
|
373
450
|
wrap = false
|
|
374
451
|
} = options;
|
|
375
|
-
if (
|
|
376
|
-
console.warn("Invalid direction option. Fallback: both
|
|
377
|
-
direction =
|
|
452
|
+
if (!["both", "horizontal", "vertical"].includes(direction)) {
|
|
453
|
+
console.warn("Invalid direction option. Fallback: 'both'.");
|
|
454
|
+
direction = "both";
|
|
378
455
|
}
|
|
379
456
|
if (typeof navigationOnly !== "boolean") {
|
|
380
457
|
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
@@ -388,11 +465,21 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
388
465
|
console.warn("Invalid noStart option. Fallback: false.");
|
|
389
466
|
noStart = false;
|
|
390
467
|
}
|
|
391
|
-
if (
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
468
|
+
if (selector !== "") {
|
|
469
|
+
let hasError = false;
|
|
470
|
+
if (typeof selector !== "string" || !selector.trim()) {
|
|
471
|
+
hasError = true;
|
|
472
|
+
} else {
|
|
473
|
+
try {
|
|
474
|
+
this.#container.querySelector(selector);
|
|
475
|
+
} catch {
|
|
476
|
+
hasError = true;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
if (hasError) {
|
|
480
|
+
console.warn("Invalid selector. Fallback: no selector string.");
|
|
481
|
+
selector = "";
|
|
482
|
+
}
|
|
396
483
|
}
|
|
397
484
|
if (typeof typeahead !== "boolean") {
|
|
398
485
|
console.warn("Invalid typeahead option. Fallback: false.");
|
|
@@ -402,9 +489,15 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
402
489
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
403
490
|
wrap = false;
|
|
404
491
|
}
|
|
405
|
-
this.#settings = {
|
|
406
|
-
|
|
407
|
-
|
|
492
|
+
this.#settings = {
|
|
493
|
+
direction,
|
|
494
|
+
navigationOnly,
|
|
495
|
+
noMemory,
|
|
496
|
+
noStart,
|
|
497
|
+
selector,
|
|
498
|
+
typeahead,
|
|
499
|
+
wrap
|
|
500
|
+
};
|
|
408
501
|
this.#selectorFilter = this.#createSelectorFilter();
|
|
409
502
|
this.#initialize();
|
|
410
503
|
}
|
|
@@ -415,7 +508,10 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
415
508
|
this.#isDestroyed = true;
|
|
416
509
|
this.#controller?.abort();
|
|
417
510
|
this.#controller = null;
|
|
418
|
-
|
|
511
|
+
this.#focusables.forEach((focusable) => {
|
|
512
|
+
_RovingTabIndex.#initialized.delete(focusable);
|
|
513
|
+
restoreAttributes2(focusable);
|
|
514
|
+
});
|
|
419
515
|
this.#focusables.clear();
|
|
420
516
|
this.#focusablesByFirstChar.clear();
|
|
421
517
|
}
|
|
@@ -452,7 +548,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
452
548
|
return;
|
|
453
549
|
}
|
|
454
550
|
const { direction, typeahead, wrap } = this.#settings;
|
|
455
|
-
const isBoth =
|
|
551
|
+
const isBoth = direction === "both";
|
|
456
552
|
const isHorizontal = direction === "horizontal";
|
|
457
553
|
if (![
|
|
458
554
|
"End",
|
|
@@ -464,18 +560,20 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
464
560
|
return;
|
|
465
561
|
}
|
|
466
562
|
}
|
|
563
|
+
const candidates = this.#getFocusables().filter(
|
|
564
|
+
(focusable2) => this.#focusables.has(focusable2)
|
|
565
|
+
);
|
|
467
566
|
const active = getActiveElement();
|
|
468
567
|
if (!(active instanceof Element)) {
|
|
469
568
|
return;
|
|
470
569
|
}
|
|
471
|
-
|
|
472
|
-
if (!current.includes(active)) {
|
|
570
|
+
if (!candidates.includes(active)) {
|
|
473
571
|
return;
|
|
474
572
|
}
|
|
475
573
|
event.preventDefault();
|
|
476
|
-
const currentIndex = current.indexOf(active);
|
|
477
574
|
let newIndex;
|
|
478
|
-
|
|
575
|
+
const activeIndex = candidates.indexOf(active);
|
|
576
|
+
let focusables = candidates;
|
|
479
577
|
switch (key) {
|
|
480
578
|
case "End":
|
|
481
579
|
newIndex = -1;
|
|
@@ -485,37 +583,47 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
485
583
|
break;
|
|
486
584
|
case "ArrowLeft":
|
|
487
585
|
case "ArrowUp": {
|
|
488
|
-
const rawIndex =
|
|
586
|
+
const rawIndex = activeIndex - 1;
|
|
489
587
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
490
588
|
break;
|
|
491
589
|
}
|
|
492
590
|
case "ArrowRight":
|
|
493
591
|
case "ArrowDown": {
|
|
494
|
-
const rawIndex =
|
|
495
|
-
|
|
592
|
+
const rawIndex = activeIndex + 1;
|
|
593
|
+
const length = focusables.length;
|
|
594
|
+
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
496
595
|
break;
|
|
497
596
|
}
|
|
498
597
|
default: {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
598
|
+
const focusablesByFirstChar = new Set(
|
|
599
|
+
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
600
|
+
);
|
|
601
|
+
focusables = candidates.filter(
|
|
602
|
+
(candidate) => focusablesByFirstChar.has(candidate)
|
|
603
|
+
);
|
|
604
|
+
const afterIndex = focusables.findIndex(
|
|
605
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
502
606
|
);
|
|
503
|
-
newIndex =
|
|
607
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
504
608
|
}
|
|
505
609
|
}
|
|
506
|
-
const focusable =
|
|
610
|
+
const focusable = focusables.at(newIndex);
|
|
507
611
|
focusable && focusElement(focusable);
|
|
508
612
|
};
|
|
509
613
|
#update(active) {
|
|
510
614
|
const current = new Set(this.#getFocusables());
|
|
511
615
|
for (const focusable of this.#focusables) {
|
|
512
616
|
if (!current.has(focusable)) {
|
|
513
|
-
|
|
617
|
+
_RovingTabIndex.#initialized.delete(focusable);
|
|
618
|
+
restoreAttributes2(focusable);
|
|
514
619
|
this.#focusables.delete(focusable);
|
|
515
|
-
this.#focusablesByFirstChar
|
|
620
|
+
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
516
621
|
const index = focusables.indexOf(focusable);
|
|
517
|
-
index >= 0
|
|
518
|
-
|
|
622
|
+
if (index >= 0) {
|
|
623
|
+
focusables.splice(index, 1);
|
|
624
|
+
!focusables.length && this.#focusablesByFirstChar.delete(key);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
519
627
|
}
|
|
520
628
|
}
|
|
521
629
|
const { navigationOnly, noStart, typeahead } = this.#settings;
|
|
@@ -524,12 +632,12 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
524
632
|
continue;
|
|
525
633
|
}
|
|
526
634
|
if (_RovingTabIndex.#initialized.has(focusable)) {
|
|
527
|
-
|
|
635
|
+
continue;
|
|
528
636
|
}
|
|
529
637
|
this.#focusables.add(focusable);
|
|
530
638
|
_RovingTabIndex.#initialized.add(focusable);
|
|
531
639
|
if (!navigationOnly) {
|
|
532
|
-
|
|
640
|
+
saveAttributes2(focusable, "tabindex");
|
|
533
641
|
focusable.setAttribute("tabindex", "-1");
|
|
534
642
|
}
|
|
535
643
|
if (!typeahead) {
|
|
@@ -542,8 +650,8 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
542
650
|
);
|
|
543
651
|
if (char) {
|
|
544
652
|
keys.add(char);
|
|
545
|
-
|
|
546
|
-
|
|
653
|
+
saveAttributes2(focusable, "aria-keyshortcuts");
|
|
654
|
+
addTokenToAttribute2(focusable, "aria-keyshortcuts", char, {
|
|
547
655
|
caseInsensitive: true
|
|
548
656
|
});
|
|
549
657
|
}
|
|
@@ -822,7 +930,7 @@ var Accordion = class _Accordion {
|
|
|
822
930
|
);
|
|
823
931
|
}
|
|
824
932
|
#createBinding(trigger, content) {
|
|
825
|
-
return {
|
|
933
|
+
return { animation: null, content, trigger };
|
|
826
934
|
}
|
|
827
935
|
#isFocusable(element) {
|
|
828
936
|
return !element.hasAttribute("disabled") && element.tabIndex >= 0;
|
|
@@ -853,7 +961,7 @@ function waitAnimationFinish(animation) {
|
|
|
853
961
|
* Accordion
|
|
854
962
|
* WAI-ARIA compliant accordion pattern implementation in TypeScript.
|
|
855
963
|
*
|
|
856
|
-
* @version 2.0.
|
|
964
|
+
* @version 2.0.4
|
|
857
965
|
* @author Yusuke Kamiyamane
|
|
858
966
|
* @license MIT
|
|
859
967
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -865,7 +973,7 @@ function waitAnimationFinish(animation) {
|
|
|
865
973
|
(**
|
|
866
974
|
* Attributes Utils
|
|
867
975
|
*
|
|
868
|
-
* @version
|
|
976
|
+
* @version 2.0.0
|
|
869
977
|
* @author Yusuke Kamiyamane
|
|
870
978
|
* @license MIT
|
|
871
979
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -878,7 +986,7 @@ power-focusable/dist/index.js:
|
|
|
878
986
|
* High-precision focus management utility with full composed tree support.
|
|
879
987
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
880
988
|
*
|
|
881
|
-
* @version 4.3.
|
|
989
|
+
* @version 4.3.23
|
|
882
990
|
* @author Yusuke Kamiyamane
|
|
883
991
|
* @license MIT
|
|
884
992
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -896,13 +1004,24 @@ power-focusable/dist/index.js:
|
|
|
896
1004
|
* @see {@link https://github.com/y14e/button}
|
|
897
1005
|
*)
|
|
898
1006
|
|
|
1007
|
+
@y14e/attributes-utils/dist/index.js:
|
|
1008
|
+
(**
|
|
1009
|
+
* Attributes Utils
|
|
1010
|
+
*
|
|
1011
|
+
* @version 1.1.7
|
|
1012
|
+
* @author Yusuke Kamiyamane
|
|
1013
|
+
* @license MIT
|
|
1014
|
+
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
1015
|
+
* @see {@link https://github.com/y14e/attributes-utils}
|
|
1016
|
+
*)
|
|
1017
|
+
|
|
899
1018
|
@y14e/roving-tabindex/dist/index.js:
|
|
900
1019
|
(**
|
|
901
1020
|
* Roving Tabindex
|
|
902
1021
|
* Lightweight roving tabindex utility with fully focus management.
|
|
903
1022
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
904
1023
|
*
|
|
905
|
-
* @version 3.1.
|
|
1024
|
+
* @version 3.1.20
|
|
906
1025
|
* @author Yusuke Kamiyamane
|
|
907
1026
|
* @license MIT
|
|
908
1027
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.bundle.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// node_modules/@y14e/attributes-utils/dist/index.js
|
|
2
2
|
var DEFAULT_PARSER = (value) => value.split(/\s+/);
|
|
3
3
|
var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
|
|
4
|
-
function
|
|
5
|
-
const value = element.getAttribute(
|
|
4
|
+
function addAttributeToken(element, name, token, options = {}) {
|
|
5
|
+
const value = element.getAttribute(name)?.trim();
|
|
6
6
|
const {
|
|
7
7
|
caseInsensitive = false,
|
|
8
8
|
parse = DEFAULT_PARSER,
|
|
@@ -13,42 +13,48 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
|
13
13
|
const lower = token.toLowerCase();
|
|
14
14
|
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
15
15
|
tokens.push(token);
|
|
16
|
-
element.setAttribute(
|
|
16
|
+
element.setAttribute(name, serialize(tokens));
|
|
17
17
|
}
|
|
18
18
|
} else {
|
|
19
19
|
const set = new Set(tokens);
|
|
20
20
|
set.add(token);
|
|
21
|
-
element.setAttribute(
|
|
21
|
+
element.setAttribute(name, serialize([...set]));
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
var snapshots = /* @__PURE__ */ new WeakMap();
|
|
25
|
-
function restoreAttributes(
|
|
26
|
-
for (const element of
|
|
25
|
+
function restoreAttributes(element_or_elements) {
|
|
26
|
+
for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
|
|
27
27
|
const snapshot = snapshots.get(element);
|
|
28
28
|
if (!snapshot) {
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
|
-
for (const [
|
|
32
|
-
value === null ? element.removeAttribute(
|
|
31
|
+
for (const [name, value] of snapshot.entries()) {
|
|
32
|
+
value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
|
|
33
33
|
}
|
|
34
34
|
snapshots.delete(element);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
function saveAttributes(
|
|
38
|
-
|
|
37
|
+
function saveAttributes(element_or_elements, name_or_names) {
|
|
38
|
+
const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
|
|
39
|
+
(Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
|
|
39
40
|
let snapshot = snapshots.get(element);
|
|
40
41
|
if (!snapshot) {
|
|
41
42
|
snapshot = /* @__PURE__ */ new Map();
|
|
42
43
|
snapshots.set(element, snapshot);
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
-
snapshot.set(
|
|
45
|
+
names.forEach((name) => {
|
|
46
|
+
snapshot.set(name, element.getAttribute(name));
|
|
46
47
|
});
|
|
47
48
|
});
|
|
48
49
|
}
|
|
50
|
+
var addTokenToAttribute = addAttributeToken;
|
|
49
51
|
|
|
50
52
|
// node_modules/power-focusable/dist/index.js
|
|
51
53
|
var FOCUSABLE_SELECTOR = `:is(a[href], area[href], button, embed, iframe, input:not([type="hidden" i]), object, select, details > summary:first-of-type, textarea, [contenteditable]:not([contenteditable="false" i]), [controls], [tabindex]):not(:disabled, [hidden], [inert], [tabindex="-1"])`;
|
|
54
|
+
var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
|
|
55
|
+
/(,\s*)?\[tabindex="-1"\]/g,
|
|
56
|
+
""
|
|
57
|
+
);
|
|
52
58
|
function getFocusables(container = document.body, options = {}) {
|
|
53
59
|
if (!(container instanceof Element)) {
|
|
54
60
|
console.warn("Invalid container element. Fallback: <body> element.");
|
|
@@ -85,36 +91,43 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
85
91
|
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
86
92
|
skipVisibilityCheck = false;
|
|
87
93
|
}
|
|
88
|
-
const
|
|
94
|
+
const candidates = [];
|
|
89
95
|
if (composed || include) {
|
|
90
96
|
let traverse2 = function(node) {
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
if (isFocusable(node, {
|
|
98
|
+
skipNegativeTabIndexCheck,
|
|
99
|
+
skipVisibilityCheck
|
|
100
|
+
}) || include?.(node)) {
|
|
101
|
+
candidates[candidates.length] = node;
|
|
96
102
|
}
|
|
97
|
-
const
|
|
98
|
-
for (let i = 0, l =
|
|
99
|
-
const child =
|
|
103
|
+
const children2 = composed ? getComposedChildren(node) : getChildren(node);
|
|
104
|
+
for (let i = 0, l = children2.length; i < l; i++) {
|
|
105
|
+
const child = children2[i];
|
|
100
106
|
child && traverse2(child);
|
|
101
107
|
}
|
|
102
108
|
};
|
|
103
|
-
|
|
109
|
+
const children = composed ? getComposedChildren(container) : getChildren(container);
|
|
110
|
+
for (let i = 0, l = children.length; i < l; i++) {
|
|
111
|
+
const child = children[i];
|
|
112
|
+
child && traverse2(child);
|
|
113
|
+
}
|
|
104
114
|
} else {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
115
|
+
const matches = container.querySelectorAll(
|
|
116
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
117
|
+
);
|
|
118
|
+
for (let i = 0, l = matches.length; i < l; i++) {
|
|
119
|
+
const matched = matches[i];
|
|
120
|
+
if (matched && isFocusable(matched, {
|
|
109
121
|
skipNegativeTabIndexCheck,
|
|
110
122
|
skipVisibilityCheck
|
|
111
123
|
})) {
|
|
112
|
-
|
|
124
|
+
candidates[candidates.length] = matched;
|
|
113
125
|
}
|
|
114
126
|
}
|
|
115
127
|
}
|
|
116
|
-
|
|
117
|
-
|
|
128
|
+
return normalizeRadioGroup(
|
|
129
|
+
sortByTabIndex(filter ? candidates.filter(filter) : candidates)
|
|
130
|
+
);
|
|
118
131
|
}
|
|
119
132
|
function isFocusable(element, options = {}) {
|
|
120
133
|
if (!(element instanceof Element)) {
|
|
@@ -137,7 +150,7 @@ function isFocusable(element, options = {}) {
|
|
|
137
150
|
return false;
|
|
138
151
|
}
|
|
139
152
|
if (!element.matches(
|
|
140
|
-
skipNegativeTabIndexCheck ?
|
|
153
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
141
154
|
)) {
|
|
142
155
|
return false;
|
|
143
156
|
}
|
|
@@ -195,22 +208,42 @@ function normalizeRadioGroup(elements) {
|
|
|
195
208
|
if (!map) {
|
|
196
209
|
map = /* @__PURE__ */ new Map();
|
|
197
210
|
}
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
if (
|
|
201
|
-
|
|
211
|
+
const root = element.getRootNode();
|
|
212
|
+
let value = map.get(root);
|
|
213
|
+
if (!value) {
|
|
214
|
+
value = /* @__PURE__ */ new Map();
|
|
215
|
+
map.set(root, value);
|
|
216
|
+
}
|
|
217
|
+
let v = value.get(element.form);
|
|
218
|
+
if (!v) {
|
|
219
|
+
v = /* @__PURE__ */ new Map();
|
|
220
|
+
value.set(element.form, v);
|
|
221
|
+
}
|
|
222
|
+
let vv = v.get(element.name);
|
|
223
|
+
if (!vv) {
|
|
224
|
+
vv = [];
|
|
225
|
+
v.set(element.name, vv);
|
|
202
226
|
}
|
|
227
|
+
vv[vv.length] = element;
|
|
203
228
|
}
|
|
204
229
|
if (!map) {
|
|
205
230
|
return elements;
|
|
206
231
|
}
|
|
207
232
|
const placeholder = /* @__PURE__ */ new Set();
|
|
208
|
-
for (const
|
|
209
|
-
|
|
233
|
+
for (const value of map.values()) {
|
|
234
|
+
for (const v of value.values()) {
|
|
235
|
+
for (const vv of v.values()) {
|
|
236
|
+
const radio = vv.find((element) => element.checked) ?? vv[0];
|
|
237
|
+
radio && placeholder.add(radio);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
210
240
|
}
|
|
211
|
-
return elements.filter(
|
|
212
|
-
|
|
213
|
-
|
|
241
|
+
return elements.filter((element) => {
|
|
242
|
+
if (!(element instanceof HTMLInputElement)) {
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
return !isUngroupedRadio(element) || placeholder.has(element);
|
|
246
|
+
});
|
|
214
247
|
}
|
|
215
248
|
function sortByTabIndex(elements) {
|
|
216
249
|
const ordered = [];
|
|
@@ -282,7 +315,7 @@ function isInert(element) {
|
|
|
282
315
|
return "inert" in element && !!element.inert;
|
|
283
316
|
}
|
|
284
317
|
function isUngroupedRadio(element) {
|
|
285
|
-
return element
|
|
318
|
+
return element.type === "radio" && !!element.name;
|
|
286
319
|
}
|
|
287
320
|
|
|
288
321
|
// node_modules/@y14e/button/dist/index.js
|
|
@@ -334,6 +367,56 @@ var Button = class {
|
|
|
334
367
|
};
|
|
335
368
|
};
|
|
336
369
|
|
|
370
|
+
// node_modules/@y14e/roving-tabindex/node_modules/@y14e/attributes-utils/dist/index.js
|
|
371
|
+
var DEFAULT_PARSER2 = (value) => value.split(/\s+/);
|
|
372
|
+
var DEFAULT_SERIALIZER2 = (tokens) => tokens.join(" ");
|
|
373
|
+
function addTokenToAttribute2(element, name, token, options = {}) {
|
|
374
|
+
const value = element.getAttribute(name)?.trim();
|
|
375
|
+
const {
|
|
376
|
+
caseInsensitive = false,
|
|
377
|
+
parse = DEFAULT_PARSER2,
|
|
378
|
+
serialize = DEFAULT_SERIALIZER2
|
|
379
|
+
} = options;
|
|
380
|
+
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
381
|
+
if (caseInsensitive) {
|
|
382
|
+
const lower = token.toLowerCase();
|
|
383
|
+
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
384
|
+
tokens.push(token);
|
|
385
|
+
element.setAttribute(name, serialize(tokens));
|
|
386
|
+
}
|
|
387
|
+
} else {
|
|
388
|
+
const set = new Set(tokens);
|
|
389
|
+
set.add(token);
|
|
390
|
+
element.setAttribute(name, serialize([...set]));
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
var snapshots2 = /* @__PURE__ */ new WeakMap();
|
|
394
|
+
function restoreAttributes2(element_or_elements) {
|
|
395
|
+
for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
|
|
396
|
+
const snapshot = snapshots2.get(element);
|
|
397
|
+
if (!snapshot) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
for (const [name, value] of snapshot.entries()) {
|
|
401
|
+
value === null ? element.removeAttribute(name) : element.setAttribute(name, value);
|
|
402
|
+
}
|
|
403
|
+
snapshots2.delete(element);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
function saveAttributes2(element_or_elements, name_or_names) {
|
|
407
|
+
const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
|
|
408
|
+
(Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
|
|
409
|
+
let snapshot = snapshots2.get(element);
|
|
410
|
+
if (!snapshot) {
|
|
411
|
+
snapshot = /* @__PURE__ */ new Map();
|
|
412
|
+
snapshots2.set(element, snapshot);
|
|
413
|
+
}
|
|
414
|
+
names.forEach((name) => {
|
|
415
|
+
snapshot.set(name, element.getAttribute(name));
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
337
420
|
// node_modules/@y14e/roving-tabindex/dist/index.js
|
|
338
421
|
function createRovingTabIndex(container, options = {}) {
|
|
339
422
|
if (!(container instanceof Element)) {
|
|
@@ -341,14 +424,8 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
341
424
|
return () => {
|
|
342
425
|
};
|
|
343
426
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
return () => roving.destroy();
|
|
347
|
-
} catch (error) {
|
|
348
|
-
error instanceof Error && console.warn(error.message || error);
|
|
349
|
-
return () => {
|
|
350
|
-
};
|
|
351
|
-
}
|
|
427
|
+
const roving = new RovingTabIndex(container, options);
|
|
428
|
+
return () => roving.destroy();
|
|
352
429
|
}
|
|
353
430
|
var RovingTabIndex = class _RovingTabIndex {
|
|
354
431
|
static #initialized = /* @__PURE__ */ new Set();
|
|
@@ -362,17 +439,17 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
362
439
|
constructor(container, options = {}) {
|
|
363
440
|
this.#container = container;
|
|
364
441
|
let {
|
|
365
|
-
direction,
|
|
442
|
+
direction = "both",
|
|
366
443
|
navigationOnly = false,
|
|
367
444
|
noMemory = false,
|
|
368
445
|
noStart = false,
|
|
369
|
-
selector,
|
|
446
|
+
selector = "",
|
|
370
447
|
typeahead = false,
|
|
371
448
|
wrap = false
|
|
372
449
|
} = options;
|
|
373
|
-
if (
|
|
374
|
-
console.warn("Invalid direction option. Fallback: both
|
|
375
|
-
direction =
|
|
450
|
+
if (!["both", "horizontal", "vertical"].includes(direction)) {
|
|
451
|
+
console.warn("Invalid direction option. Fallback: 'both'.");
|
|
452
|
+
direction = "both";
|
|
376
453
|
}
|
|
377
454
|
if (typeof navigationOnly !== "boolean") {
|
|
378
455
|
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
@@ -386,11 +463,21 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
386
463
|
console.warn("Invalid noStart option. Fallback: false.");
|
|
387
464
|
noStart = false;
|
|
388
465
|
}
|
|
389
|
-
if (
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
466
|
+
if (selector !== "") {
|
|
467
|
+
let hasError = false;
|
|
468
|
+
if (typeof selector !== "string" || !selector.trim()) {
|
|
469
|
+
hasError = true;
|
|
470
|
+
} else {
|
|
471
|
+
try {
|
|
472
|
+
this.#container.querySelector(selector);
|
|
473
|
+
} catch {
|
|
474
|
+
hasError = true;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
if (hasError) {
|
|
478
|
+
console.warn("Invalid selector. Fallback: no selector string.");
|
|
479
|
+
selector = "";
|
|
480
|
+
}
|
|
394
481
|
}
|
|
395
482
|
if (typeof typeahead !== "boolean") {
|
|
396
483
|
console.warn("Invalid typeahead option. Fallback: false.");
|
|
@@ -400,9 +487,15 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
400
487
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
401
488
|
wrap = false;
|
|
402
489
|
}
|
|
403
|
-
this.#settings = {
|
|
404
|
-
|
|
405
|
-
|
|
490
|
+
this.#settings = {
|
|
491
|
+
direction,
|
|
492
|
+
navigationOnly,
|
|
493
|
+
noMemory,
|
|
494
|
+
noStart,
|
|
495
|
+
selector,
|
|
496
|
+
typeahead,
|
|
497
|
+
wrap
|
|
498
|
+
};
|
|
406
499
|
this.#selectorFilter = this.#createSelectorFilter();
|
|
407
500
|
this.#initialize();
|
|
408
501
|
}
|
|
@@ -413,7 +506,10 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
413
506
|
this.#isDestroyed = true;
|
|
414
507
|
this.#controller?.abort();
|
|
415
508
|
this.#controller = null;
|
|
416
|
-
|
|
509
|
+
this.#focusables.forEach((focusable) => {
|
|
510
|
+
_RovingTabIndex.#initialized.delete(focusable);
|
|
511
|
+
restoreAttributes2(focusable);
|
|
512
|
+
});
|
|
417
513
|
this.#focusables.clear();
|
|
418
514
|
this.#focusablesByFirstChar.clear();
|
|
419
515
|
}
|
|
@@ -450,7 +546,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
450
546
|
return;
|
|
451
547
|
}
|
|
452
548
|
const { direction, typeahead, wrap } = this.#settings;
|
|
453
|
-
const isBoth =
|
|
549
|
+
const isBoth = direction === "both";
|
|
454
550
|
const isHorizontal = direction === "horizontal";
|
|
455
551
|
if (![
|
|
456
552
|
"End",
|
|
@@ -462,18 +558,20 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
462
558
|
return;
|
|
463
559
|
}
|
|
464
560
|
}
|
|
561
|
+
const candidates = this.#getFocusables().filter(
|
|
562
|
+
(focusable2) => this.#focusables.has(focusable2)
|
|
563
|
+
);
|
|
465
564
|
const active = getActiveElement();
|
|
466
565
|
if (!(active instanceof Element)) {
|
|
467
566
|
return;
|
|
468
567
|
}
|
|
469
|
-
|
|
470
|
-
if (!current.includes(active)) {
|
|
568
|
+
if (!candidates.includes(active)) {
|
|
471
569
|
return;
|
|
472
570
|
}
|
|
473
571
|
event.preventDefault();
|
|
474
|
-
const currentIndex = current.indexOf(active);
|
|
475
572
|
let newIndex;
|
|
476
|
-
|
|
573
|
+
const activeIndex = candidates.indexOf(active);
|
|
574
|
+
let focusables = candidates;
|
|
477
575
|
switch (key) {
|
|
478
576
|
case "End":
|
|
479
577
|
newIndex = -1;
|
|
@@ -483,37 +581,47 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
483
581
|
break;
|
|
484
582
|
case "ArrowLeft":
|
|
485
583
|
case "ArrowUp": {
|
|
486
|
-
const rawIndex =
|
|
584
|
+
const rawIndex = activeIndex - 1;
|
|
487
585
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
488
586
|
break;
|
|
489
587
|
}
|
|
490
588
|
case "ArrowRight":
|
|
491
589
|
case "ArrowDown": {
|
|
492
|
-
const rawIndex =
|
|
493
|
-
|
|
590
|
+
const rawIndex = activeIndex + 1;
|
|
591
|
+
const length = focusables.length;
|
|
592
|
+
newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
|
|
494
593
|
break;
|
|
495
594
|
}
|
|
496
595
|
default: {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
596
|
+
const focusablesByFirstChar = new Set(
|
|
597
|
+
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
598
|
+
);
|
|
599
|
+
focusables = candidates.filter(
|
|
600
|
+
(candidate) => focusablesByFirstChar.has(candidate)
|
|
601
|
+
);
|
|
602
|
+
const afterIndex = focusables.findIndex(
|
|
603
|
+
(focusable2) => candidates.indexOf(focusable2) > activeIndex
|
|
500
604
|
);
|
|
501
|
-
newIndex =
|
|
605
|
+
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
502
606
|
}
|
|
503
607
|
}
|
|
504
|
-
const focusable =
|
|
608
|
+
const focusable = focusables.at(newIndex);
|
|
505
609
|
focusable && focusElement(focusable);
|
|
506
610
|
};
|
|
507
611
|
#update(active) {
|
|
508
612
|
const current = new Set(this.#getFocusables());
|
|
509
613
|
for (const focusable of this.#focusables) {
|
|
510
614
|
if (!current.has(focusable)) {
|
|
511
|
-
|
|
615
|
+
_RovingTabIndex.#initialized.delete(focusable);
|
|
616
|
+
restoreAttributes2(focusable);
|
|
512
617
|
this.#focusables.delete(focusable);
|
|
513
|
-
this.#focusablesByFirstChar
|
|
618
|
+
for (const [key, focusables] of this.#focusablesByFirstChar) {
|
|
514
619
|
const index = focusables.indexOf(focusable);
|
|
515
|
-
index >= 0
|
|
516
|
-
|
|
620
|
+
if (index >= 0) {
|
|
621
|
+
focusables.splice(index, 1);
|
|
622
|
+
!focusables.length && this.#focusablesByFirstChar.delete(key);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
517
625
|
}
|
|
518
626
|
}
|
|
519
627
|
const { navigationOnly, noStart, typeahead } = this.#settings;
|
|
@@ -522,12 +630,12 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
522
630
|
continue;
|
|
523
631
|
}
|
|
524
632
|
if (_RovingTabIndex.#initialized.has(focusable)) {
|
|
525
|
-
|
|
633
|
+
continue;
|
|
526
634
|
}
|
|
527
635
|
this.#focusables.add(focusable);
|
|
528
636
|
_RovingTabIndex.#initialized.add(focusable);
|
|
529
637
|
if (!navigationOnly) {
|
|
530
|
-
|
|
638
|
+
saveAttributes2(focusable, "tabindex");
|
|
531
639
|
focusable.setAttribute("tabindex", "-1");
|
|
532
640
|
}
|
|
533
641
|
if (!typeahead) {
|
|
@@ -540,8 +648,8 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
540
648
|
);
|
|
541
649
|
if (char) {
|
|
542
650
|
keys.add(char);
|
|
543
|
-
|
|
544
|
-
|
|
651
|
+
saveAttributes2(focusable, "aria-keyshortcuts");
|
|
652
|
+
addTokenToAttribute2(focusable, "aria-keyshortcuts", char, {
|
|
545
653
|
caseInsensitive: true
|
|
546
654
|
});
|
|
547
655
|
}
|
|
@@ -820,7 +928,7 @@ var Accordion = class _Accordion {
|
|
|
820
928
|
);
|
|
821
929
|
}
|
|
822
930
|
#createBinding(trigger, content) {
|
|
823
|
-
return {
|
|
931
|
+
return { animation: null, content, trigger };
|
|
824
932
|
}
|
|
825
933
|
#isFocusable(element) {
|
|
826
934
|
return !element.hasAttribute("disabled") && element.tabIndex >= 0;
|
|
@@ -851,7 +959,7 @@ function waitAnimationFinish(animation) {
|
|
|
851
959
|
* Accordion
|
|
852
960
|
* WAI-ARIA compliant accordion pattern implementation in TypeScript.
|
|
853
961
|
*
|
|
854
|
-
* @version 2.0.
|
|
962
|
+
* @version 2.0.4
|
|
855
963
|
* @author Yusuke Kamiyamane
|
|
856
964
|
* @license MIT
|
|
857
965
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -863,7 +971,7 @@ function waitAnimationFinish(animation) {
|
|
|
863
971
|
(**
|
|
864
972
|
* Attributes Utils
|
|
865
973
|
*
|
|
866
|
-
* @version
|
|
974
|
+
* @version 2.0.0
|
|
867
975
|
* @author Yusuke Kamiyamane
|
|
868
976
|
* @license MIT
|
|
869
977
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -876,7 +984,7 @@ power-focusable/dist/index.js:
|
|
|
876
984
|
* High-precision focus management utility with full composed tree support.
|
|
877
985
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
878
986
|
*
|
|
879
|
-
* @version 4.3.
|
|
987
|
+
* @version 4.3.23
|
|
880
988
|
* @author Yusuke Kamiyamane
|
|
881
989
|
* @license MIT
|
|
882
990
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -894,13 +1002,24 @@ power-focusable/dist/index.js:
|
|
|
894
1002
|
* @see {@link https://github.com/y14e/button}
|
|
895
1003
|
*)
|
|
896
1004
|
|
|
1005
|
+
@y14e/attributes-utils/dist/index.js:
|
|
1006
|
+
(**
|
|
1007
|
+
* Attributes Utils
|
|
1008
|
+
*
|
|
1009
|
+
* @version 1.1.7
|
|
1010
|
+
* @author Yusuke Kamiyamane
|
|
1011
|
+
* @license MIT
|
|
1012
|
+
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
1013
|
+
* @see {@link https://github.com/y14e/attributes-utils}
|
|
1014
|
+
*)
|
|
1015
|
+
|
|
897
1016
|
@y14e/roving-tabindex/dist/index.js:
|
|
898
1017
|
(**
|
|
899
1018
|
* Roving Tabindex
|
|
900
1019
|
* Lightweight roving tabindex utility with fully focus management.
|
|
901
1020
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
902
1021
|
*
|
|
903
|
-
* @version 3.1.
|
|
1022
|
+
* @version 3.1.20
|
|
904
1023
|
* @author Yusuke Kamiyamane
|
|
905
1024
|
* @license MIT
|
|
906
1025
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.cjs
CHANGED
|
@@ -251,7 +251,7 @@ var Accordion = class _Accordion {
|
|
|
251
251
|
);
|
|
252
252
|
}
|
|
253
253
|
#createBinding(trigger, content) {
|
|
254
|
-
return {
|
|
254
|
+
return { animation: null, content, trigger };
|
|
255
255
|
}
|
|
256
256
|
#isFocusable(element) {
|
|
257
257
|
return !element.hasAttribute("disabled") && element.tabIndex >= 0;
|
|
@@ -282,7 +282,7 @@ function waitAnimationFinish(animation) {
|
|
|
282
282
|
* Accordion
|
|
283
283
|
* WAI-ARIA compliant accordion pattern implementation in TypeScript.
|
|
284
284
|
*
|
|
285
|
-
* @version 2.0.
|
|
285
|
+
* @version 2.0.4
|
|
286
286
|
* @author Yusuke Kamiyamane
|
|
287
287
|
* @license MIT
|
|
288
288
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -245,7 +245,7 @@ var Accordion = class _Accordion {
|
|
|
245
245
|
);
|
|
246
246
|
}
|
|
247
247
|
#createBinding(trigger, content) {
|
|
248
|
-
return {
|
|
248
|
+
return { animation: null, content, trigger };
|
|
249
249
|
}
|
|
250
250
|
#isFocusable(element) {
|
|
251
251
|
return !element.hasAttribute("disabled") && element.tabIndex >= 0;
|
|
@@ -276,7 +276,7 @@ function waitAnimationFinish(animation) {
|
|
|
276
276
|
* Accordion
|
|
277
277
|
* WAI-ARIA compliant accordion pattern implementation in TypeScript.
|
|
278
278
|
*
|
|
279
|
-
* @version 2.0.
|
|
279
|
+
* @version 2.0.4
|
|
280
280
|
* @author Yusuke Kamiyamane
|
|
281
281
|
* @license MIT
|
|
282
282
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/accordion",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "WAI-ARIA compliant accordion pattern implementation in TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"node": ">=18"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@y14e/attributes-utils": "^
|
|
54
|
+
"@y14e/attributes-utils": "^2.0.0",
|
|
55
55
|
"@y14e/button": "^1.0.6",
|
|
56
|
-
"@y14e/roving-tabindex": "^3.1.
|
|
56
|
+
"@y14e/roving-tabindex": "^3.1.20"
|
|
57
57
|
}
|
|
58
58
|
}
|