@y14e/disclosure-css 1.3.5 → 1.3.7
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 +4 -4
- package/dist/index.cjs +91 -84
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +91 -84
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -10,14 +10,14 @@ npm i @y14e/disclosure-css
|
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
// npm
|
|
13
|
-
import Disclosure from '@y14e/disclosure-css@1.3.
|
|
13
|
+
import Disclosure from '@y14e/disclosure-css@1.3.7';
|
|
14
14
|
|
|
15
15
|
// CDNs
|
|
16
|
-
import Disclosure from 'https://esm.sh/@y14e/disclosure-css@1.3.
|
|
16
|
+
import Disclosure from 'https://esm.sh/@y14e/disclosure-css@1.3.7';
|
|
17
17
|
// or
|
|
18
|
-
import Disclosure from 'https://cdn.jsdelivr.net/npm/@y14e/disclosure-css@1.3.
|
|
18
|
+
import Disclosure from 'https://cdn.jsdelivr.net/npm/@y14e/disclosure-css@1.3.7/+esm';
|
|
19
19
|
// or
|
|
20
|
-
import Disclosure from 'https://esm.unpkg.com/@y14e/disclosure-css@1.3.
|
|
20
|
+
import Disclosure from 'https://esm.unpkg.com/@y14e/disclosure-css@1.3.7';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Usage
|
package/dist/index.cjs
CHANGED
|
@@ -28,28 +28,27 @@ function saveAttributes(elements, attributes) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// node_modules/@y14e/roving-tabindex/dist/index.js
|
|
31
|
-
var
|
|
32
|
-
var
|
|
31
|
+
var DEFAULT_PARSER = (value) => value.split(/\s+/);
|
|
32
|
+
var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
|
|
33
33
|
function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
34
34
|
const {
|
|
35
35
|
caseInsensitive = false,
|
|
36
|
-
parse =
|
|
37
|
-
serialize =
|
|
36
|
+
parse = DEFAULT_PARSER,
|
|
37
|
+
serialize = DEFAULT_SERIALIZER
|
|
38
38
|
} = options;
|
|
39
39
|
const value = element.getAttribute(attribute)?.trim();
|
|
40
40
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
41
41
|
if (caseInsensitive) {
|
|
42
42
|
const lower = token.toLowerCase();
|
|
43
|
-
if (tokens.
|
|
44
|
-
|
|
43
|
+
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
44
|
+
tokens.push(token);
|
|
45
|
+
element.setAttribute(attribute, serialize(tokens));
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
} else {
|
|
48
|
+
const set = new Set(tokens);
|
|
49
|
+
set.add(token);
|
|
50
|
+
element.setAttribute(attribute, serialize([...set]));
|
|
49
51
|
}
|
|
50
|
-
const set = new Set(tokens);
|
|
51
|
-
set.add(token);
|
|
52
|
-
element.setAttribute(attribute, serialize([...set]));
|
|
53
52
|
}
|
|
54
53
|
var snapshots2 = /* @__PURE__ */ new WeakMap();
|
|
55
54
|
function restoreAttributes2(elements) {
|
|
@@ -116,21 +115,16 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
116
115
|
const elements = [];
|
|
117
116
|
if (composed || include) {
|
|
118
117
|
let traverse2 = function(node) {
|
|
119
|
-
if (node instanceof Element) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
elements[elements.length] = node;
|
|
125
|
-
}
|
|
118
|
+
if (!(node instanceof Element)) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (isFocusable(node, { skipNegativeTabIndexCheck, skipVisibilityCheck }) || include?.(node)) {
|
|
122
|
+
elements[elements.length] = node;
|
|
126
123
|
}
|
|
127
124
|
const children = getComposedChildren(node);
|
|
128
125
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
129
126
|
const child = children[i];
|
|
130
|
-
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
traverse2(child);
|
|
127
|
+
child && traverse2(child);
|
|
134
128
|
}
|
|
135
129
|
};
|
|
136
130
|
traverse2(container);
|
|
@@ -138,10 +132,7 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
138
132
|
const candidates = container.querySelectorAll(FOCUSABLE_SELECTOR);
|
|
139
133
|
for (let i = 0, l = candidates.length; i < l; i++) {
|
|
140
134
|
const candidate = candidates[i];
|
|
141
|
-
if (
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
if (isFocusable(candidate, {
|
|
135
|
+
if (candidate && isFocusable(candidate, {
|
|
145
136
|
skipNegativeTabIndexCheck,
|
|
146
137
|
skipVisibilityCheck
|
|
147
138
|
})) {
|
|
@@ -244,23 +235,19 @@ function normalizeRadioGroup(elements) {
|
|
|
244
235
|
for (const group of map.values()) {
|
|
245
236
|
placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
|
|
246
237
|
}
|
|
247
|
-
return elements.filter(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
return true;
|
|
252
|
-
});
|
|
238
|
+
return elements.filter(
|
|
239
|
+
(element) => isUngroupedRadio(element) ? placeholder.has(element) : true
|
|
240
|
+
);
|
|
253
241
|
}
|
|
254
242
|
function sortByTabIndex(elements) {
|
|
255
243
|
const ordered = [];
|
|
256
244
|
const natural = [];
|
|
257
245
|
for (let i = 0, l = elements.length; i < l; i++) {
|
|
258
246
|
const element = elements[i];
|
|
259
|
-
if (
|
|
260
|
-
|
|
247
|
+
if (element) {
|
|
248
|
+
const target = getTabIndex(element) > 0 ? ordered : natural;
|
|
249
|
+
target[target.length] = element;
|
|
261
250
|
}
|
|
262
|
-
const target = getTabIndex(element) > 0 ? ordered : natural;
|
|
263
|
-
target[target.length] = element;
|
|
264
251
|
}
|
|
265
252
|
ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b));
|
|
266
253
|
let count = 0;
|
|
@@ -323,6 +310,8 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
323
310
|
let {
|
|
324
311
|
direction,
|
|
325
312
|
navigationOnly = false,
|
|
313
|
+
noMemory = false,
|
|
314
|
+
noStart = false,
|
|
326
315
|
selector,
|
|
327
316
|
typeahead = false,
|
|
328
317
|
wrap = false
|
|
@@ -335,6 +324,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
335
324
|
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
336
325
|
navigationOnly = false;
|
|
337
326
|
}
|
|
327
|
+
if (typeof noMemory !== "boolean") {
|
|
328
|
+
console.warn("Invalid noMemory option. Fallback: false.");
|
|
329
|
+
noMemory = false;
|
|
330
|
+
}
|
|
331
|
+
if (typeof noStart !== "boolean") {
|
|
332
|
+
console.warn("Invalid noStart option. Fallback: false.");
|
|
333
|
+
noStart = false;
|
|
334
|
+
}
|
|
338
335
|
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
339
336
|
console.warn(
|
|
340
337
|
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
@@ -349,13 +346,15 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
349
346
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
350
347
|
wrap = false;
|
|
351
348
|
}
|
|
352
|
-
const settings = {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
349
|
+
const settings = {
|
|
350
|
+
navigationOnly,
|
|
351
|
+
noMemory,
|
|
352
|
+
noStart,
|
|
353
|
+
typeahead,
|
|
354
|
+
wrap
|
|
355
|
+
};
|
|
356
|
+
direction && Object.assign(settings, { direction });
|
|
357
|
+
selector && Object.assign(settings, { selector });
|
|
359
358
|
const roving = new RovingTabIndex(container, settings);
|
|
360
359
|
return () => roving.destroy();
|
|
361
360
|
}
|
|
@@ -388,12 +387,25 @@ var RovingTabIndex = class {
|
|
|
388
387
|
#initialize() {
|
|
389
388
|
this.#update(document.activeElement);
|
|
390
389
|
this.#controller = new AbortController();
|
|
390
|
+
const { signal } = this.#controller;
|
|
391
|
+
document.addEventListener("focusin", this.#onFocusIn, {
|
|
392
|
+
capture: true,
|
|
393
|
+
signal
|
|
394
|
+
});
|
|
391
395
|
document.addEventListener("keydown", this.#onKeyDown, {
|
|
392
396
|
capture: true,
|
|
393
|
-
signal
|
|
397
|
+
signal
|
|
394
398
|
});
|
|
395
399
|
this.#container.setAttribute("data-roving-tabindex-initialized", "");
|
|
396
400
|
}
|
|
401
|
+
#onFocusIn = (event) => {
|
|
402
|
+
const { target } = event;
|
|
403
|
+
if (!(target instanceof Element)) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const isFocusable22 = this.#focusables.has(target);
|
|
407
|
+
this.#options.noMemory && !isFocusable22 ? this.#update(null) : isFocusable22 && this.#update(target);
|
|
408
|
+
};
|
|
397
409
|
#onKeyDown = (event) => {
|
|
398
410
|
if (!event.composedPath().includes(this.#container)) {
|
|
399
411
|
return;
|
|
@@ -424,10 +436,8 @@ var RovingTabIndex = class {
|
|
|
424
436
|
return;
|
|
425
437
|
}
|
|
426
438
|
event.preventDefault();
|
|
427
|
-
event.stopPropagation();
|
|
428
439
|
const currentIndex = current.indexOf(active);
|
|
429
|
-
let
|
|
430
|
-
let newIndex = currentIndex;
|
|
440
|
+
let newIndex;
|
|
431
441
|
let target = current;
|
|
432
442
|
switch (key) {
|
|
433
443
|
case "End":
|
|
@@ -437,15 +447,17 @@ var RovingTabIndex = class {
|
|
|
437
447
|
newIndex = 0;
|
|
438
448
|
break;
|
|
439
449
|
case "ArrowLeft":
|
|
440
|
-
case "ArrowUp":
|
|
441
|
-
rawIndex = currentIndex - 1;
|
|
450
|
+
case "ArrowUp": {
|
|
451
|
+
const rawIndex = currentIndex - 1;
|
|
442
452
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
443
453
|
break;
|
|
454
|
+
}
|
|
444
455
|
case "ArrowRight":
|
|
445
|
-
case "ArrowDown":
|
|
446
|
-
rawIndex = currentIndex + 1;
|
|
456
|
+
case "ArrowDown": {
|
|
457
|
+
const rawIndex = currentIndex + 1;
|
|
447
458
|
newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
|
|
448
459
|
break;
|
|
460
|
+
}
|
|
449
461
|
default: {
|
|
450
462
|
target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
|
|
451
463
|
const foundIndex = target.findIndex(
|
|
@@ -455,26 +467,21 @@ var RovingTabIndex = class {
|
|
|
455
467
|
}
|
|
456
468
|
}
|
|
457
469
|
const focusable = target.at(newIndex);
|
|
458
|
-
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
this.#update(focusable);
|
|
462
|
-
focusElement(focusable);
|
|
470
|
+
focusable && focusElement(focusable);
|
|
463
471
|
};
|
|
464
472
|
#update(active) {
|
|
465
473
|
const current = new Set(this.#getFocusables());
|
|
466
474
|
for (const focusable of this.#focusables) {
|
|
467
|
-
if (current.has(focusable)) {
|
|
468
|
-
|
|
475
|
+
if (!current.has(focusable)) {
|
|
476
|
+
focusable.isConnected && restoreAttributes2([focusable]);
|
|
477
|
+
this.#focusables.delete(focusable);
|
|
478
|
+
this.#focusablesByFirstChar.forEach((focusables) => {
|
|
479
|
+
const index = focusables.indexOf(focusable);
|
|
480
|
+
index >= 0 && focusables.splice(index, 1);
|
|
481
|
+
});
|
|
469
482
|
}
|
|
470
|
-
focusable.isConnected && restoreAttributes2([focusable]);
|
|
471
|
-
this.#focusables.delete(focusable);
|
|
472
|
-
this.#focusablesByFirstChar.forEach((focusables) => {
|
|
473
|
-
const index = focusables.indexOf(focusable);
|
|
474
|
-
index >= 0 && focusables.splice(index, 1);
|
|
475
|
-
});
|
|
476
483
|
}
|
|
477
|
-
const { navigationOnly } = this.#options;
|
|
484
|
+
const { navigationOnly, noStart, typeahead } = this.#options;
|
|
478
485
|
for (const focusable of current) {
|
|
479
486
|
if (this.#focusables.has(focusable)) {
|
|
480
487
|
continue;
|
|
@@ -484,7 +491,7 @@ var RovingTabIndex = class {
|
|
|
484
491
|
saveAttributes2([focusable], ["tabindex"]);
|
|
485
492
|
focusable.setAttribute("tabindex", "-1");
|
|
486
493
|
}
|
|
487
|
-
if (!
|
|
494
|
+
if (!typeahead) {
|
|
488
495
|
continue;
|
|
489
496
|
}
|
|
490
497
|
const value = focusable.ariaKeyShortcuts?.trim();
|
|
@@ -505,18 +512,17 @@ var RovingTabIndex = class {
|
|
|
505
512
|
this.#focusablesByFirstChar.set(key, focusables);
|
|
506
513
|
});
|
|
507
514
|
}
|
|
508
|
-
if (navigationOnly) {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
515
|
+
if (!navigationOnly) {
|
|
516
|
+
if (active && this.#focusables.has(active)) {
|
|
517
|
+
this.#focusables.forEach((focusable) => {
|
|
518
|
+
focusable.setAttribute("tabindex", focusable === active ? "0" : "-1");
|
|
519
|
+
});
|
|
520
|
+
} else {
|
|
521
|
+
[...this.#focusables].forEach((focusable, i) => {
|
|
522
|
+
focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
|
|
523
|
+
});
|
|
524
|
+
}
|
|
516
525
|
}
|
|
517
|
-
[...this.#focusables].forEach((focusable, i) => {
|
|
518
|
-
focusable.setAttribute("tabindex", i ? "-1" : "0");
|
|
519
|
-
});
|
|
520
526
|
}
|
|
521
527
|
#createSelectorFilter() {
|
|
522
528
|
const { selector } = this.#options;
|
|
@@ -526,7 +532,8 @@ var RovingTabIndex = class {
|
|
|
526
532
|
return getFocusables(this.#container, {
|
|
527
533
|
composed: true,
|
|
528
534
|
filter: this.#selectorFilter,
|
|
529
|
-
skipNegativeTabIndexCheck: !this.#options.navigationOnly
|
|
535
|
+
skipNegativeTabIndexCheck: !this.#options.navigationOnly,
|
|
536
|
+
skipVisibilityCheck: true
|
|
530
537
|
});
|
|
531
538
|
}
|
|
532
539
|
};
|
|
@@ -669,7 +676,7 @@ function isFocusable2(element) {
|
|
|
669
676
|
* WAI-ARIA compliant disclosure pattern implementation in TypeScript.
|
|
670
677
|
* Using the <details> and <summary> element.
|
|
671
678
|
*
|
|
672
|
-
* @version 1.3.
|
|
679
|
+
* @version 1.3.7
|
|
673
680
|
* @author Yusuke Kamiyamane
|
|
674
681
|
* @license MIT
|
|
675
682
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -681,7 +688,7 @@ function isFocusable2(element) {
|
|
|
681
688
|
(**
|
|
682
689
|
* Attributes Utils
|
|
683
690
|
*
|
|
684
|
-
* @version 1.1.
|
|
691
|
+
* @version 1.1.2
|
|
685
692
|
* @author Yusuke Kamiyamane
|
|
686
693
|
* @license MIT
|
|
687
694
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -694,7 +701,7 @@ function isFocusable2(element) {
|
|
|
694
701
|
* Lightweight roving tabindex utility with fully focus management.
|
|
695
702
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
696
703
|
*
|
|
697
|
-
* @version
|
|
704
|
+
* @version 3.0.2
|
|
698
705
|
* @author Yusuke Kamiyamane
|
|
699
706
|
* @license MIT
|
|
700
707
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -706,7 +713,7 @@ function isFocusable2(element) {
|
|
|
706
713
|
(**
|
|
707
714
|
* Attributes Utils
|
|
708
715
|
*
|
|
709
|
-
* @version 1.1.
|
|
716
|
+
* @version 1.1.2
|
|
710
717
|
* @author Yusuke Kamiyamane
|
|
711
718
|
* @license MIT
|
|
712
719
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -719,7 +726,7 @@ function isFocusable2(element) {
|
|
|
719
726
|
* High-precision focus management utility with full composed tree support.
|
|
720
727
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
721
728
|
*
|
|
722
|
-
* @version 4.3.
|
|
729
|
+
* @version 4.3.3
|
|
723
730
|
* @author Yusuke Kamiyamane
|
|
724
731
|
* @license MIT
|
|
725
732
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -26,28 +26,27 @@ function saveAttributes(elements, attributes) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// node_modules/@y14e/roving-tabindex/dist/index.js
|
|
29
|
-
var
|
|
30
|
-
var
|
|
29
|
+
var DEFAULT_PARSER = (value) => value.split(/\s+/);
|
|
30
|
+
var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
|
|
31
31
|
function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
32
32
|
const {
|
|
33
33
|
caseInsensitive = false,
|
|
34
|
-
parse =
|
|
35
|
-
serialize =
|
|
34
|
+
parse = DEFAULT_PARSER,
|
|
35
|
+
serialize = DEFAULT_SERIALIZER
|
|
36
36
|
} = options;
|
|
37
37
|
const value = element.getAttribute(attribute)?.trim();
|
|
38
38
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
39
39
|
if (caseInsensitive) {
|
|
40
40
|
const lower = token.toLowerCase();
|
|
41
|
-
if (tokens.
|
|
42
|
-
|
|
41
|
+
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
42
|
+
tokens.push(token);
|
|
43
|
+
element.setAttribute(attribute, serialize(tokens));
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
} else {
|
|
46
|
+
const set = new Set(tokens);
|
|
47
|
+
set.add(token);
|
|
48
|
+
element.setAttribute(attribute, serialize([...set]));
|
|
47
49
|
}
|
|
48
|
-
const set = new Set(tokens);
|
|
49
|
-
set.add(token);
|
|
50
|
-
element.setAttribute(attribute, serialize([...set]));
|
|
51
50
|
}
|
|
52
51
|
var snapshots2 = /* @__PURE__ */ new WeakMap();
|
|
53
52
|
function restoreAttributes2(elements) {
|
|
@@ -114,21 +113,16 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
114
113
|
const elements = [];
|
|
115
114
|
if (composed || include) {
|
|
116
115
|
let traverse2 = function(node) {
|
|
117
|
-
if (node instanceof Element) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
elements[elements.length] = node;
|
|
123
|
-
}
|
|
116
|
+
if (!(node instanceof Element)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (isFocusable(node, { skipNegativeTabIndexCheck, skipVisibilityCheck }) || include?.(node)) {
|
|
120
|
+
elements[elements.length] = node;
|
|
124
121
|
}
|
|
125
122
|
const children = getComposedChildren(node);
|
|
126
123
|
for (let i = 0, l = children.length; i < l; i++) {
|
|
127
124
|
const child = children[i];
|
|
128
|
-
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
traverse2(child);
|
|
125
|
+
child && traverse2(child);
|
|
132
126
|
}
|
|
133
127
|
};
|
|
134
128
|
traverse2(container);
|
|
@@ -136,10 +130,7 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
136
130
|
const candidates = container.querySelectorAll(FOCUSABLE_SELECTOR);
|
|
137
131
|
for (let i = 0, l = candidates.length; i < l; i++) {
|
|
138
132
|
const candidate = candidates[i];
|
|
139
|
-
if (
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (isFocusable(candidate, {
|
|
133
|
+
if (candidate && isFocusable(candidate, {
|
|
143
134
|
skipNegativeTabIndexCheck,
|
|
144
135
|
skipVisibilityCheck
|
|
145
136
|
})) {
|
|
@@ -242,23 +233,19 @@ function normalizeRadioGroup(elements) {
|
|
|
242
233
|
for (const group of map.values()) {
|
|
243
234
|
placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
|
|
244
235
|
}
|
|
245
|
-
return elements.filter(
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
return true;
|
|
250
|
-
});
|
|
236
|
+
return elements.filter(
|
|
237
|
+
(element) => isUngroupedRadio(element) ? placeholder.has(element) : true
|
|
238
|
+
);
|
|
251
239
|
}
|
|
252
240
|
function sortByTabIndex(elements) {
|
|
253
241
|
const ordered = [];
|
|
254
242
|
const natural = [];
|
|
255
243
|
for (let i = 0, l = elements.length; i < l; i++) {
|
|
256
244
|
const element = elements[i];
|
|
257
|
-
if (
|
|
258
|
-
|
|
245
|
+
if (element) {
|
|
246
|
+
const target = getTabIndex(element) > 0 ? ordered : natural;
|
|
247
|
+
target[target.length] = element;
|
|
259
248
|
}
|
|
260
|
-
const target = getTabIndex(element) > 0 ? ordered : natural;
|
|
261
|
-
target[target.length] = element;
|
|
262
249
|
}
|
|
263
250
|
ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b));
|
|
264
251
|
let count = 0;
|
|
@@ -321,6 +308,8 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
321
308
|
let {
|
|
322
309
|
direction,
|
|
323
310
|
navigationOnly = false,
|
|
311
|
+
noMemory = false,
|
|
312
|
+
noStart = false,
|
|
324
313
|
selector,
|
|
325
314
|
typeahead = false,
|
|
326
315
|
wrap = false
|
|
@@ -333,6 +322,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
333
322
|
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
334
323
|
navigationOnly = false;
|
|
335
324
|
}
|
|
325
|
+
if (typeof noMemory !== "boolean") {
|
|
326
|
+
console.warn("Invalid noMemory option. Fallback: false.");
|
|
327
|
+
noMemory = false;
|
|
328
|
+
}
|
|
329
|
+
if (typeof noStart !== "boolean") {
|
|
330
|
+
console.warn("Invalid noStart option. Fallback: false.");
|
|
331
|
+
noStart = false;
|
|
332
|
+
}
|
|
336
333
|
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
337
334
|
console.warn(
|
|
338
335
|
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
@@ -347,13 +344,15 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
347
344
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
348
345
|
wrap = false;
|
|
349
346
|
}
|
|
350
|
-
const settings = {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
347
|
+
const settings = {
|
|
348
|
+
navigationOnly,
|
|
349
|
+
noMemory,
|
|
350
|
+
noStart,
|
|
351
|
+
typeahead,
|
|
352
|
+
wrap
|
|
353
|
+
};
|
|
354
|
+
direction && Object.assign(settings, { direction });
|
|
355
|
+
selector && Object.assign(settings, { selector });
|
|
357
356
|
const roving = new RovingTabIndex(container, settings);
|
|
358
357
|
return () => roving.destroy();
|
|
359
358
|
}
|
|
@@ -386,12 +385,25 @@ var RovingTabIndex = class {
|
|
|
386
385
|
#initialize() {
|
|
387
386
|
this.#update(document.activeElement);
|
|
388
387
|
this.#controller = new AbortController();
|
|
388
|
+
const { signal } = this.#controller;
|
|
389
|
+
document.addEventListener("focusin", this.#onFocusIn, {
|
|
390
|
+
capture: true,
|
|
391
|
+
signal
|
|
392
|
+
});
|
|
389
393
|
document.addEventListener("keydown", this.#onKeyDown, {
|
|
390
394
|
capture: true,
|
|
391
|
-
signal
|
|
395
|
+
signal
|
|
392
396
|
});
|
|
393
397
|
this.#container.setAttribute("data-roving-tabindex-initialized", "");
|
|
394
398
|
}
|
|
399
|
+
#onFocusIn = (event) => {
|
|
400
|
+
const { target } = event;
|
|
401
|
+
if (!(target instanceof Element)) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const isFocusable22 = this.#focusables.has(target);
|
|
405
|
+
this.#options.noMemory && !isFocusable22 ? this.#update(null) : isFocusable22 && this.#update(target);
|
|
406
|
+
};
|
|
395
407
|
#onKeyDown = (event) => {
|
|
396
408
|
if (!event.composedPath().includes(this.#container)) {
|
|
397
409
|
return;
|
|
@@ -422,10 +434,8 @@ var RovingTabIndex = class {
|
|
|
422
434
|
return;
|
|
423
435
|
}
|
|
424
436
|
event.preventDefault();
|
|
425
|
-
event.stopPropagation();
|
|
426
437
|
const currentIndex = current.indexOf(active);
|
|
427
|
-
let
|
|
428
|
-
let newIndex = currentIndex;
|
|
438
|
+
let newIndex;
|
|
429
439
|
let target = current;
|
|
430
440
|
switch (key) {
|
|
431
441
|
case "End":
|
|
@@ -435,15 +445,17 @@ var RovingTabIndex = class {
|
|
|
435
445
|
newIndex = 0;
|
|
436
446
|
break;
|
|
437
447
|
case "ArrowLeft":
|
|
438
|
-
case "ArrowUp":
|
|
439
|
-
rawIndex = currentIndex - 1;
|
|
448
|
+
case "ArrowUp": {
|
|
449
|
+
const rawIndex = currentIndex - 1;
|
|
440
450
|
newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
|
|
441
451
|
break;
|
|
452
|
+
}
|
|
442
453
|
case "ArrowRight":
|
|
443
|
-
case "ArrowDown":
|
|
444
|
-
rawIndex = currentIndex + 1;
|
|
454
|
+
case "ArrowDown": {
|
|
455
|
+
const rawIndex = currentIndex + 1;
|
|
445
456
|
newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
|
|
446
457
|
break;
|
|
458
|
+
}
|
|
447
459
|
default: {
|
|
448
460
|
target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
|
|
449
461
|
const foundIndex = target.findIndex(
|
|
@@ -453,26 +465,21 @@ var RovingTabIndex = class {
|
|
|
453
465
|
}
|
|
454
466
|
}
|
|
455
467
|
const focusable = target.at(newIndex);
|
|
456
|
-
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
this.#update(focusable);
|
|
460
|
-
focusElement(focusable);
|
|
468
|
+
focusable && focusElement(focusable);
|
|
461
469
|
};
|
|
462
470
|
#update(active) {
|
|
463
471
|
const current = new Set(this.#getFocusables());
|
|
464
472
|
for (const focusable of this.#focusables) {
|
|
465
|
-
if (current.has(focusable)) {
|
|
466
|
-
|
|
473
|
+
if (!current.has(focusable)) {
|
|
474
|
+
focusable.isConnected && restoreAttributes2([focusable]);
|
|
475
|
+
this.#focusables.delete(focusable);
|
|
476
|
+
this.#focusablesByFirstChar.forEach((focusables) => {
|
|
477
|
+
const index = focusables.indexOf(focusable);
|
|
478
|
+
index >= 0 && focusables.splice(index, 1);
|
|
479
|
+
});
|
|
467
480
|
}
|
|
468
|
-
focusable.isConnected && restoreAttributes2([focusable]);
|
|
469
|
-
this.#focusables.delete(focusable);
|
|
470
|
-
this.#focusablesByFirstChar.forEach((focusables) => {
|
|
471
|
-
const index = focusables.indexOf(focusable);
|
|
472
|
-
index >= 0 && focusables.splice(index, 1);
|
|
473
|
-
});
|
|
474
481
|
}
|
|
475
|
-
const { navigationOnly } = this.#options;
|
|
482
|
+
const { navigationOnly, noStart, typeahead } = this.#options;
|
|
476
483
|
for (const focusable of current) {
|
|
477
484
|
if (this.#focusables.has(focusable)) {
|
|
478
485
|
continue;
|
|
@@ -482,7 +489,7 @@ var RovingTabIndex = class {
|
|
|
482
489
|
saveAttributes2([focusable], ["tabindex"]);
|
|
483
490
|
focusable.setAttribute("tabindex", "-1");
|
|
484
491
|
}
|
|
485
|
-
if (!
|
|
492
|
+
if (!typeahead) {
|
|
486
493
|
continue;
|
|
487
494
|
}
|
|
488
495
|
const value = focusable.ariaKeyShortcuts?.trim();
|
|
@@ -503,18 +510,17 @@ var RovingTabIndex = class {
|
|
|
503
510
|
this.#focusablesByFirstChar.set(key, focusables);
|
|
504
511
|
});
|
|
505
512
|
}
|
|
506
|
-
if (navigationOnly) {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
513
|
+
if (!navigationOnly) {
|
|
514
|
+
if (active && this.#focusables.has(active)) {
|
|
515
|
+
this.#focusables.forEach((focusable) => {
|
|
516
|
+
focusable.setAttribute("tabindex", focusable === active ? "0" : "-1");
|
|
517
|
+
});
|
|
518
|
+
} else {
|
|
519
|
+
[...this.#focusables].forEach((focusable, i) => {
|
|
520
|
+
focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
|
|
521
|
+
});
|
|
522
|
+
}
|
|
514
523
|
}
|
|
515
|
-
[...this.#focusables].forEach((focusable, i) => {
|
|
516
|
-
focusable.setAttribute("tabindex", i ? "-1" : "0");
|
|
517
|
-
});
|
|
518
524
|
}
|
|
519
525
|
#createSelectorFilter() {
|
|
520
526
|
const { selector } = this.#options;
|
|
@@ -524,7 +530,8 @@ var RovingTabIndex = class {
|
|
|
524
530
|
return getFocusables(this.#container, {
|
|
525
531
|
composed: true,
|
|
526
532
|
filter: this.#selectorFilter,
|
|
527
|
-
skipNegativeTabIndexCheck: !this.#options.navigationOnly
|
|
533
|
+
skipNegativeTabIndexCheck: !this.#options.navigationOnly,
|
|
534
|
+
skipVisibilityCheck: true
|
|
528
535
|
});
|
|
529
536
|
}
|
|
530
537
|
};
|
|
@@ -667,7 +674,7 @@ function isFocusable2(element) {
|
|
|
667
674
|
* WAI-ARIA compliant disclosure pattern implementation in TypeScript.
|
|
668
675
|
* Using the <details> and <summary> element.
|
|
669
676
|
*
|
|
670
|
-
* @version 1.3.
|
|
677
|
+
* @version 1.3.7
|
|
671
678
|
* @author Yusuke Kamiyamane
|
|
672
679
|
* @license MIT
|
|
673
680
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -679,7 +686,7 @@ function isFocusable2(element) {
|
|
|
679
686
|
(**
|
|
680
687
|
* Attributes Utils
|
|
681
688
|
*
|
|
682
|
-
* @version 1.1.
|
|
689
|
+
* @version 1.1.2
|
|
683
690
|
* @author Yusuke Kamiyamane
|
|
684
691
|
* @license MIT
|
|
685
692
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -692,7 +699,7 @@ function isFocusable2(element) {
|
|
|
692
699
|
* Lightweight roving tabindex utility with fully focus management.
|
|
693
700
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
694
701
|
*
|
|
695
|
-
* @version
|
|
702
|
+
* @version 3.0.2
|
|
696
703
|
* @author Yusuke Kamiyamane
|
|
697
704
|
* @license MIT
|
|
698
705
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -704,7 +711,7 @@ function isFocusable2(element) {
|
|
|
704
711
|
(**
|
|
705
712
|
* Attributes Utils
|
|
706
713
|
*
|
|
707
|
-
* @version 1.1.
|
|
714
|
+
* @version 1.1.2
|
|
708
715
|
* @author Yusuke Kamiyamane
|
|
709
716
|
* @license MIT
|
|
710
717
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -717,7 +724,7 @@ function isFocusable2(element) {
|
|
|
717
724
|
* High-precision focus management utility with full composed tree support.
|
|
718
725
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
719
726
|
*
|
|
720
|
-
* @version 4.3.
|
|
727
|
+
* @version 4.3.3
|
|
721
728
|
* @author Yusuke Kamiyamane
|
|
722
729
|
* @license MIT
|
|
723
730
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/disclosure-css",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "WAI-ARIA compliant disclosure pattern implementation in TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
},
|
|
44
44
|
"homepage": "https://github.com/y14e/disclosure-css#readme",
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@y14e/attributes-utils": "^1.1.
|
|
47
|
-
"@y14e/roving-tabindex": "^
|
|
46
|
+
"@y14e/attributes-utils": "^1.1.2",
|
|
47
|
+
"@y14e/roving-tabindex": "^3.0.2",
|
|
48
48
|
"bun-types": "latest",
|
|
49
49
|
"tsup": "^8.0.0",
|
|
50
50
|
"typescript": "^5.6.0"
|