@y14e/disclosure-css 2.0.10 → 2.0.12
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 +5 -5
- package/dist/index.bundle.cjs +59 -91
- package/dist/index.bundle.js +59 -91
- package/dist/index.cjs +4 -4
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/package.json +27 -27
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
|
|
13
|
+
import { Disclosure } from '@y14e/disclosure-css';
|
|
14
14
|
|
|
15
15
|
// CDNs
|
|
16
|
-
import { Disclosure } from
|
|
16
|
+
import { Disclosure } from 'https://esm.sh/@y14e/disclosure-css@2.0.12';
|
|
17
17
|
// or
|
|
18
|
-
import { Disclosure } from
|
|
18
|
+
import { Disclosure } from 'https://cdn.jsdelivr.net/npm/@y14e/disclosure-css@2.0.12/+esm';
|
|
19
19
|
// or
|
|
20
|
-
import { Disclosure } from
|
|
20
|
+
import { Disclosure } from 'https://esm.unpkg.com/@y14e/disclosure-css@2.0.12';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
@@ -43,7 +43,7 @@ interface DisclosureOptions {
|
|
|
43
43
|
Override the global default settings applied to all disclosure instances.
|
|
44
44
|
|
|
45
45
|
```ts
|
|
46
|
-
import { Disclosure } from
|
|
46
|
+
import { Disclosure } from '@y14e/disclosure-css';
|
|
47
47
|
|
|
48
48
|
Disclosure.defaults = {
|
|
49
49
|
collapsible: false,
|
package/dist/index.bundle.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// node_modules/@y14e/attribute-utils/dist/index.js
|
|
4
|
-
var DEFAULT_PARSER = (
|
|
5
|
-
var DEFAULT_SERIALIZER = (
|
|
4
|
+
var DEFAULT_PARSER = (v) => v.split(/\s+/);
|
|
5
|
+
var DEFAULT_SERIALIZER = (t) => t.join(" ");
|
|
6
6
|
function addAttributeToken(element, name, token, options = {}) {
|
|
7
7
|
if (!isValid(element, name, token)) {
|
|
8
8
|
return;
|
|
@@ -12,7 +12,7 @@ function addAttributeToken(element, name, token, options = {}) {
|
|
|
12
12
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
13
13
|
if (caseInsensitive) {
|
|
14
14
|
const lower = token.toLowerCase();
|
|
15
|
-
if (tokens.every((
|
|
15
|
+
if (tokens.every((t) => t.toLowerCase() !== lower)) {
|
|
16
16
|
tokens.push(token);
|
|
17
17
|
element.setAttribute(name, serialize(tokens));
|
|
18
18
|
}
|
|
@@ -37,16 +37,16 @@ function restoreAttributes(element_or_elements) {
|
|
|
37
37
|
}
|
|
38
38
|
function saveAttributes(element_or_elements, name_or_names) {
|
|
39
39
|
const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
|
|
40
|
-
(Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements])
|
|
40
|
+
for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
|
|
41
41
|
let snapshot = snapshots.get(element);
|
|
42
42
|
if (!snapshot) {
|
|
43
43
|
snapshot = /* @__PURE__ */ new Map();
|
|
44
44
|
snapshots.set(element, snapshot);
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
for (const name of names) {
|
|
47
47
|
snapshot.set(name, element.getAttribute(name));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
50
|
}
|
|
51
51
|
function isValid(element, name, token) {
|
|
52
52
|
if (!(element instanceof Element)) {
|
|
@@ -91,7 +91,7 @@ function resolveOptions(options) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// node_modules/power-focusable/dist/index.js
|
|
94
|
-
var FOCUSABLE_SELECTOR =
|
|
94
|
+
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"])';
|
|
95
95
|
var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
|
|
96
96
|
/(,\s*)?\[tabindex="-1"\]/g,
|
|
97
97
|
""
|
|
@@ -115,31 +115,21 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
115
115
|
skipNegativeTabIndexCheck,
|
|
116
116
|
skipVisibilityCheck
|
|
117
117
|
}) || include?.(node)) {
|
|
118
|
-
candidates
|
|
119
|
-
}
|
|
120
|
-
const children2 = composed ? getComposedChildren(node) : getChildren(node);
|
|
121
|
-
for (let i = 0, l = children2.length; i < l; i++) {
|
|
122
|
-
const child = children2[i];
|
|
123
|
-
child && traverse2(child);
|
|
118
|
+
candidates.push(node);
|
|
124
119
|
}
|
|
120
|
+
(composed ? getComposedChildren(node) : [...node.children]).map(traverse2);
|
|
125
121
|
};
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
child && traverse2(child);
|
|
130
|
-
}
|
|
122
|
+
(composed ? getComposedChildren(container) : [...container.children]).map(
|
|
123
|
+
traverse2
|
|
124
|
+
);
|
|
131
125
|
} else {
|
|
132
|
-
const
|
|
126
|
+
for (const match of container.querySelectorAll(
|
|
133
127
|
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
const matched = matches[i];
|
|
137
|
-
if (matched && isFocusable(matched, {
|
|
128
|
+
)) {
|
|
129
|
+
match && isFocusable(match, {
|
|
138
130
|
skipNegativeTabIndexCheck,
|
|
139
131
|
skipVisibilityCheck
|
|
140
|
-
}))
|
|
141
|
-
candidates[candidates.length] = matched;
|
|
142
|
-
}
|
|
132
|
+
}) && candidates.push(match);
|
|
143
133
|
}
|
|
144
134
|
}
|
|
145
135
|
return normalizeRadioGroup(
|
|
@@ -206,8 +196,7 @@ function isDisabledDeep(element) {
|
|
|
206
196
|
}
|
|
207
197
|
function normalizeRadioGroup(elements) {
|
|
208
198
|
let map = null;
|
|
209
|
-
for (
|
|
210
|
-
const element = elements[i];
|
|
199
|
+
for (const element of elements) {
|
|
211
200
|
if (!(element instanceof HTMLInputElement)) {
|
|
212
201
|
continue;
|
|
213
202
|
}
|
|
@@ -218,31 +207,31 @@ function normalizeRadioGroup(elements) {
|
|
|
218
207
|
map = /* @__PURE__ */ new Map();
|
|
219
208
|
}
|
|
220
209
|
const root = element.getRootNode();
|
|
221
|
-
let
|
|
222
|
-
if (!
|
|
223
|
-
|
|
224
|
-
map.set(root,
|
|
210
|
+
let groups = map.get(root);
|
|
211
|
+
if (!groups) {
|
|
212
|
+
groups = /* @__PURE__ */ new Map();
|
|
213
|
+
map.set(root, groups);
|
|
225
214
|
}
|
|
226
|
-
let
|
|
227
|
-
if (!
|
|
228
|
-
|
|
229
|
-
|
|
215
|
+
let group = groups.get(element.form);
|
|
216
|
+
if (!group) {
|
|
217
|
+
group = /* @__PURE__ */ new Map();
|
|
218
|
+
groups.set(element.form, group);
|
|
230
219
|
}
|
|
231
|
-
let
|
|
232
|
-
if (!
|
|
233
|
-
|
|
234
|
-
|
|
220
|
+
let radios = group.get(element.name);
|
|
221
|
+
if (!radios) {
|
|
222
|
+
radios = [];
|
|
223
|
+
group.set(element.name, radios);
|
|
235
224
|
}
|
|
236
|
-
|
|
225
|
+
radios.push(element);
|
|
237
226
|
}
|
|
238
227
|
if (!map) {
|
|
239
228
|
return elements;
|
|
240
229
|
}
|
|
241
230
|
const placeholder = /* @__PURE__ */ new Set();
|
|
242
|
-
for (const
|
|
243
|
-
for (const
|
|
244
|
-
for (const
|
|
245
|
-
const radio =
|
|
231
|
+
for (const groups of map.values()) {
|
|
232
|
+
for (const group of groups.values()) {
|
|
233
|
+
for (const radios of group.values()) {
|
|
234
|
+
const radio = radios.find((r) => r.checked) ?? radios[0];
|
|
246
235
|
radio && placeholder.add(radio);
|
|
247
236
|
}
|
|
248
237
|
}
|
|
@@ -257,27 +246,14 @@ function normalizeRadioGroup(elements) {
|
|
|
257
246
|
function sortByTabIndex(elements) {
|
|
258
247
|
const ordered = [];
|
|
259
248
|
const natural = [];
|
|
260
|
-
for (
|
|
261
|
-
|
|
262
|
-
if (element) {
|
|
263
|
-
const target = getTabIndex(element) > 0 ? ordered : natural;
|
|
264
|
-
target[target.length] = element;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b));
|
|
268
|
-
let count = 0;
|
|
269
|
-
const sorted = new Array(ordered.length + natural.length);
|
|
270
|
-
for (let i = 0, l = ordered.length; i < l; i++) {
|
|
271
|
-
sorted[count++] = ordered[i];
|
|
249
|
+
for (const element of elements) {
|
|
250
|
+
(getTabIndex(element) > 0 ? ordered : natural).push(element);
|
|
272
251
|
}
|
|
273
|
-
|
|
274
|
-
sorted[count++] = natural[i];
|
|
275
|
-
}
|
|
276
|
-
return sorted;
|
|
252
|
+
return ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b)).concat(natural);
|
|
277
253
|
}
|
|
278
254
|
function getComposedChildren(node) {
|
|
279
255
|
if (node instanceof ShadowRoot) {
|
|
280
|
-
return
|
|
256
|
+
return [...node.children];
|
|
281
257
|
}
|
|
282
258
|
if (!(node instanceof Element)) {
|
|
283
259
|
return [];
|
|
@@ -289,9 +265,9 @@ function getComposedChildren(node) {
|
|
|
289
265
|
}
|
|
290
266
|
}
|
|
291
267
|
if (node instanceof HTMLElement && node.shadowRoot?.mode === "open") {
|
|
292
|
-
return
|
|
268
|
+
return [...node.shadowRoot.children];
|
|
293
269
|
}
|
|
294
|
-
return
|
|
270
|
+
return [...node.children];
|
|
295
271
|
}
|
|
296
272
|
function focusElement(element) {
|
|
297
273
|
"focus" in element && typeof element.focus === "function" && element.focus();
|
|
@@ -303,13 +279,6 @@ function getActiveElement() {
|
|
|
303
279
|
}
|
|
304
280
|
return current;
|
|
305
281
|
}
|
|
306
|
-
function getChildren(node) {
|
|
307
|
-
const elements = [];
|
|
308
|
-
for (let child = node.firstElementChild; child; child = child.nextElementSibling) {
|
|
309
|
-
elements[elements.length] = child;
|
|
310
|
-
}
|
|
311
|
-
return elements;
|
|
312
|
-
}
|
|
313
282
|
function getTabIndex(element) {
|
|
314
283
|
return "tabIndex" in element ? Number(element.tabIndex) : 0;
|
|
315
284
|
}
|
|
@@ -414,10 +383,10 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
414
383
|
this.#isDestroyed = true;
|
|
415
384
|
this.#controller?.abort();
|
|
416
385
|
this.#controller = null;
|
|
417
|
-
this.#focusables
|
|
386
|
+
for (const focusable of this.#focusables) {
|
|
418
387
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
419
388
|
restoreAttributes(focusable);
|
|
420
|
-
}
|
|
389
|
+
}
|
|
421
390
|
this.#focusables.clear();
|
|
422
391
|
this.#focusablesByFirstChar.clear();
|
|
423
392
|
}
|
|
@@ -467,7 +436,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
467
436
|
}
|
|
468
437
|
}
|
|
469
438
|
const candidates = this.#getFocusables().filter(
|
|
470
|
-
(
|
|
439
|
+
(f) => this.#focusables.has(f)
|
|
471
440
|
);
|
|
472
441
|
const active = getActiveElement();
|
|
473
442
|
if (!(active instanceof Element)) {
|
|
@@ -504,11 +473,9 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
504
473
|
const focusablesByFirstChar = new Set(
|
|
505
474
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
506
475
|
);
|
|
507
|
-
focusables = candidates.filter(
|
|
508
|
-
(candidate) => focusablesByFirstChar.has(candidate)
|
|
509
|
-
);
|
|
476
|
+
focusables = candidates.filter((c) => focusablesByFirstChar.has(c));
|
|
510
477
|
const afterIndex = focusables.findIndex(
|
|
511
|
-
(
|
|
478
|
+
(f) => candidates.indexOf(f) > activeIndex
|
|
512
479
|
);
|
|
513
480
|
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
514
481
|
}
|
|
@@ -552,7 +519,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
552
519
|
const char = focusable.textContent?.trim()?.at(0)?.toUpperCase();
|
|
553
520
|
const value = focusable.ariaKeyShortcuts?.trim();
|
|
554
521
|
const keys = new Set(
|
|
555
|
-
value ? value.split(/\s+/).filter((
|
|
522
|
+
value ? value.split(/\s+/).filter((k) => /^\S$/i.test(k)).map((k) => k.toUpperCase()) : []
|
|
556
523
|
);
|
|
557
524
|
if (char) {
|
|
558
525
|
keys.add(char);
|
|
@@ -561,17 +528,17 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
561
528
|
caseInsensitive: true
|
|
562
529
|
});
|
|
563
530
|
}
|
|
564
|
-
|
|
531
|
+
for (const key of keys) {
|
|
565
532
|
const focusables = this.#focusablesByFirstChar.get(key) ?? [];
|
|
566
533
|
focusables.push(focusable);
|
|
567
534
|
this.#focusablesByFirstChar.set(key, focusables);
|
|
568
|
-
}
|
|
535
|
+
}
|
|
569
536
|
}
|
|
570
537
|
if (!navigationOnly) {
|
|
571
538
|
if (active && this.#focusables.has(active)) {
|
|
572
|
-
this.#focusables
|
|
539
|
+
for (const focusable of this.#focusables) {
|
|
573
540
|
focusable.setAttribute("tabindex", focusable === active ? "0" : "-1");
|
|
574
|
-
}
|
|
541
|
+
}
|
|
575
542
|
} else {
|
|
576
543
|
[...this.#focusables].forEach((focusable, i) => {
|
|
577
544
|
focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
|
|
@@ -601,6 +568,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
601
568
|
typeahead = false,
|
|
602
569
|
wrap = false
|
|
603
570
|
} = options;
|
|
571
|
+
direction = direction.toLowerCase();
|
|
604
572
|
if (!["both", "horizontal", "vertical"].includes(direction)) {
|
|
605
573
|
console.warn("Invalid direction option. Fallback: 'both'.");
|
|
606
574
|
direction = "both";
|
|
@@ -753,14 +721,14 @@ var Disclosure = class _Disclosure {
|
|
|
753
721
|
]);
|
|
754
722
|
this.#controller = new AbortController();
|
|
755
723
|
const { signal } = this.#controller;
|
|
756
|
-
this.#summaryElements
|
|
724
|
+
for (const summary of this.#summaryElements) {
|
|
757
725
|
if (!this.#isFocusable(summary)) {
|
|
758
726
|
summary.setAttribute("aria-disabled", "true");
|
|
759
727
|
summary.setAttribute("tabindex", "-1");
|
|
760
728
|
summary.style.setProperty("pointer-events", "none");
|
|
761
729
|
}
|
|
762
730
|
summary.addEventListener("click", this.#onSummaryClick, { signal });
|
|
763
|
-
}
|
|
731
|
+
}
|
|
764
732
|
this.#cleanupRovingTabIndex = createRovingTabIndex(this.#rootElement, {
|
|
765
733
|
direction: "vertical",
|
|
766
734
|
navigationOnly: true,
|
|
@@ -786,7 +754,7 @@ var Disclosure = class _Disclosure {
|
|
|
786
754
|
if (details.open === isExpand) {
|
|
787
755
|
return;
|
|
788
756
|
}
|
|
789
|
-
if (!isExpand && !this.#settings.collapsible && this.#detailsElements.filter((
|
|
757
|
+
if (!isExpand && !this.#settings.collapsible && this.#detailsElements.filter((d) => d.open).length <= 1) {
|
|
790
758
|
return;
|
|
791
759
|
}
|
|
792
760
|
details.open = isExpand;
|
|
@@ -812,7 +780,7 @@ var Disclosure = class _Disclosure {
|
|
|
812
780
|
* WAI-ARIA compliant disclosure pattern implementation in TypeScript.
|
|
813
781
|
* Using the <details> and <summary> element.
|
|
814
782
|
*
|
|
815
|
-
* @version 2.0.
|
|
783
|
+
* @version 2.0.11
|
|
816
784
|
* @author Yusuke Kamiyamane
|
|
817
785
|
* @license MIT
|
|
818
786
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -824,7 +792,7 @@ var Disclosure = class _Disclosure {
|
|
|
824
792
|
(**
|
|
825
793
|
* Attribute Utils
|
|
826
794
|
*
|
|
827
|
-
* @version 2.0.
|
|
795
|
+
* @version 2.0.12
|
|
828
796
|
* @author Yusuke Kamiyamane
|
|
829
797
|
* @license MIT
|
|
830
798
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -837,7 +805,7 @@ power-focusable/dist/index.js:
|
|
|
837
805
|
* High-precision focus management utility with full composed tree support.
|
|
838
806
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
839
807
|
*
|
|
840
|
-
* @version 4.3.
|
|
808
|
+
* @version 4.3.33
|
|
841
809
|
* @author Yusuke Kamiyamane
|
|
842
810
|
* @license MIT
|
|
843
811
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -850,7 +818,7 @@ power-focusable/dist/index.js:
|
|
|
850
818
|
* Lightweight roving tabindex utility with fully focus management.
|
|
851
819
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
852
820
|
*
|
|
853
|
-
* @version 3.1.
|
|
821
|
+
* @version 3.1.31
|
|
854
822
|
* @author Yusuke Kamiyamane
|
|
855
823
|
* @license MIT
|
|
856
824
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.bundle.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// node_modules/@y14e/attribute-utils/dist/index.js
|
|
2
|
-
var DEFAULT_PARSER = (
|
|
3
|
-
var DEFAULT_SERIALIZER = (
|
|
2
|
+
var DEFAULT_PARSER = (v) => v.split(/\s+/);
|
|
3
|
+
var DEFAULT_SERIALIZER = (t) => t.join(" ");
|
|
4
4
|
function addAttributeToken(element, name, token, options = {}) {
|
|
5
5
|
if (!isValid(element, name, token)) {
|
|
6
6
|
return;
|
|
@@ -10,7 +10,7 @@ function addAttributeToken(element, name, token, options = {}) {
|
|
|
10
10
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
11
11
|
if (caseInsensitive) {
|
|
12
12
|
const lower = token.toLowerCase();
|
|
13
|
-
if (tokens.every((
|
|
13
|
+
if (tokens.every((t) => t.toLowerCase() !== lower)) {
|
|
14
14
|
tokens.push(token);
|
|
15
15
|
element.setAttribute(name, serialize(tokens));
|
|
16
16
|
}
|
|
@@ -35,16 +35,16 @@ function restoreAttributes(element_or_elements) {
|
|
|
35
35
|
}
|
|
36
36
|
function saveAttributes(element_or_elements, name_or_names) {
|
|
37
37
|
const names = Array.isArray(name_or_names) ? name_or_names : [name_or_names];
|
|
38
|
-
(Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements])
|
|
38
|
+
for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
|
|
39
39
|
let snapshot = snapshots.get(element);
|
|
40
40
|
if (!snapshot) {
|
|
41
41
|
snapshot = /* @__PURE__ */ new Map();
|
|
42
42
|
snapshots.set(element, snapshot);
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
for (const name of names) {
|
|
45
45
|
snapshot.set(name, element.getAttribute(name));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
48
|
}
|
|
49
49
|
function isValid(element, name, token) {
|
|
50
50
|
if (!(element instanceof Element)) {
|
|
@@ -89,7 +89,7 @@ function resolveOptions(options) {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
// node_modules/power-focusable/dist/index.js
|
|
92
|
-
var FOCUSABLE_SELECTOR =
|
|
92
|
+
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"])';
|
|
93
93
|
var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
|
|
94
94
|
/(,\s*)?\[tabindex="-1"\]/g,
|
|
95
95
|
""
|
|
@@ -113,31 +113,21 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
113
113
|
skipNegativeTabIndexCheck,
|
|
114
114
|
skipVisibilityCheck
|
|
115
115
|
}) || include?.(node)) {
|
|
116
|
-
candidates
|
|
117
|
-
}
|
|
118
|
-
const children2 = composed ? getComposedChildren(node) : getChildren(node);
|
|
119
|
-
for (let i = 0, l = children2.length; i < l; i++) {
|
|
120
|
-
const child = children2[i];
|
|
121
|
-
child && traverse2(child);
|
|
116
|
+
candidates.push(node);
|
|
122
117
|
}
|
|
118
|
+
(composed ? getComposedChildren(node) : [...node.children]).map(traverse2);
|
|
123
119
|
};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
child && traverse2(child);
|
|
128
|
-
}
|
|
120
|
+
(composed ? getComposedChildren(container) : [...container.children]).map(
|
|
121
|
+
traverse2
|
|
122
|
+
);
|
|
129
123
|
} else {
|
|
130
|
-
const
|
|
124
|
+
for (const match of container.querySelectorAll(
|
|
131
125
|
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
const matched = matches[i];
|
|
135
|
-
if (matched && isFocusable(matched, {
|
|
126
|
+
)) {
|
|
127
|
+
match && isFocusable(match, {
|
|
136
128
|
skipNegativeTabIndexCheck,
|
|
137
129
|
skipVisibilityCheck
|
|
138
|
-
}))
|
|
139
|
-
candidates[candidates.length] = matched;
|
|
140
|
-
}
|
|
130
|
+
}) && candidates.push(match);
|
|
141
131
|
}
|
|
142
132
|
}
|
|
143
133
|
return normalizeRadioGroup(
|
|
@@ -204,8 +194,7 @@ function isDisabledDeep(element) {
|
|
|
204
194
|
}
|
|
205
195
|
function normalizeRadioGroup(elements) {
|
|
206
196
|
let map = null;
|
|
207
|
-
for (
|
|
208
|
-
const element = elements[i];
|
|
197
|
+
for (const element of elements) {
|
|
209
198
|
if (!(element instanceof HTMLInputElement)) {
|
|
210
199
|
continue;
|
|
211
200
|
}
|
|
@@ -216,31 +205,31 @@ function normalizeRadioGroup(elements) {
|
|
|
216
205
|
map = /* @__PURE__ */ new Map();
|
|
217
206
|
}
|
|
218
207
|
const root = element.getRootNode();
|
|
219
|
-
let
|
|
220
|
-
if (!
|
|
221
|
-
|
|
222
|
-
map.set(root,
|
|
208
|
+
let groups = map.get(root);
|
|
209
|
+
if (!groups) {
|
|
210
|
+
groups = /* @__PURE__ */ new Map();
|
|
211
|
+
map.set(root, groups);
|
|
223
212
|
}
|
|
224
|
-
let
|
|
225
|
-
if (!
|
|
226
|
-
|
|
227
|
-
|
|
213
|
+
let group = groups.get(element.form);
|
|
214
|
+
if (!group) {
|
|
215
|
+
group = /* @__PURE__ */ new Map();
|
|
216
|
+
groups.set(element.form, group);
|
|
228
217
|
}
|
|
229
|
-
let
|
|
230
|
-
if (!
|
|
231
|
-
|
|
232
|
-
|
|
218
|
+
let radios = group.get(element.name);
|
|
219
|
+
if (!radios) {
|
|
220
|
+
radios = [];
|
|
221
|
+
group.set(element.name, radios);
|
|
233
222
|
}
|
|
234
|
-
|
|
223
|
+
radios.push(element);
|
|
235
224
|
}
|
|
236
225
|
if (!map) {
|
|
237
226
|
return elements;
|
|
238
227
|
}
|
|
239
228
|
const placeholder = /* @__PURE__ */ new Set();
|
|
240
|
-
for (const
|
|
241
|
-
for (const
|
|
242
|
-
for (const
|
|
243
|
-
const radio =
|
|
229
|
+
for (const groups of map.values()) {
|
|
230
|
+
for (const group of groups.values()) {
|
|
231
|
+
for (const radios of group.values()) {
|
|
232
|
+
const radio = radios.find((r) => r.checked) ?? radios[0];
|
|
244
233
|
radio && placeholder.add(radio);
|
|
245
234
|
}
|
|
246
235
|
}
|
|
@@ -255,27 +244,14 @@ function normalizeRadioGroup(elements) {
|
|
|
255
244
|
function sortByTabIndex(elements) {
|
|
256
245
|
const ordered = [];
|
|
257
246
|
const natural = [];
|
|
258
|
-
for (
|
|
259
|
-
|
|
260
|
-
if (element) {
|
|
261
|
-
const target = getTabIndex(element) > 0 ? ordered : natural;
|
|
262
|
-
target[target.length] = element;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b));
|
|
266
|
-
let count = 0;
|
|
267
|
-
const sorted = new Array(ordered.length + natural.length);
|
|
268
|
-
for (let i = 0, l = ordered.length; i < l; i++) {
|
|
269
|
-
sorted[count++] = ordered[i];
|
|
247
|
+
for (const element of elements) {
|
|
248
|
+
(getTabIndex(element) > 0 ? ordered : natural).push(element);
|
|
270
249
|
}
|
|
271
|
-
|
|
272
|
-
sorted[count++] = natural[i];
|
|
273
|
-
}
|
|
274
|
-
return sorted;
|
|
250
|
+
return ordered.sort((a, b) => getTabIndex(a) - getTabIndex(b)).concat(natural);
|
|
275
251
|
}
|
|
276
252
|
function getComposedChildren(node) {
|
|
277
253
|
if (node instanceof ShadowRoot) {
|
|
278
|
-
return
|
|
254
|
+
return [...node.children];
|
|
279
255
|
}
|
|
280
256
|
if (!(node instanceof Element)) {
|
|
281
257
|
return [];
|
|
@@ -287,9 +263,9 @@ function getComposedChildren(node) {
|
|
|
287
263
|
}
|
|
288
264
|
}
|
|
289
265
|
if (node instanceof HTMLElement && node.shadowRoot?.mode === "open") {
|
|
290
|
-
return
|
|
266
|
+
return [...node.shadowRoot.children];
|
|
291
267
|
}
|
|
292
|
-
return
|
|
268
|
+
return [...node.children];
|
|
293
269
|
}
|
|
294
270
|
function focusElement(element) {
|
|
295
271
|
"focus" in element && typeof element.focus === "function" && element.focus();
|
|
@@ -301,13 +277,6 @@ function getActiveElement() {
|
|
|
301
277
|
}
|
|
302
278
|
return current;
|
|
303
279
|
}
|
|
304
|
-
function getChildren(node) {
|
|
305
|
-
const elements = [];
|
|
306
|
-
for (let child = node.firstElementChild; child; child = child.nextElementSibling) {
|
|
307
|
-
elements[elements.length] = child;
|
|
308
|
-
}
|
|
309
|
-
return elements;
|
|
310
|
-
}
|
|
311
280
|
function getTabIndex(element) {
|
|
312
281
|
return "tabIndex" in element ? Number(element.tabIndex) : 0;
|
|
313
282
|
}
|
|
@@ -412,10 +381,10 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
412
381
|
this.#isDestroyed = true;
|
|
413
382
|
this.#controller?.abort();
|
|
414
383
|
this.#controller = null;
|
|
415
|
-
this.#focusables
|
|
384
|
+
for (const focusable of this.#focusables) {
|
|
416
385
|
_RovingTabIndex.#initialized.delete(focusable);
|
|
417
386
|
restoreAttributes(focusable);
|
|
418
|
-
}
|
|
387
|
+
}
|
|
419
388
|
this.#focusables.clear();
|
|
420
389
|
this.#focusablesByFirstChar.clear();
|
|
421
390
|
}
|
|
@@ -465,7 +434,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
465
434
|
}
|
|
466
435
|
}
|
|
467
436
|
const candidates = this.#getFocusables().filter(
|
|
468
|
-
(
|
|
437
|
+
(f) => this.#focusables.has(f)
|
|
469
438
|
);
|
|
470
439
|
const active = getActiveElement();
|
|
471
440
|
if (!(active instanceof Element)) {
|
|
@@ -502,11 +471,9 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
502
471
|
const focusablesByFirstChar = new Set(
|
|
503
472
|
this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
|
|
504
473
|
);
|
|
505
|
-
focusables = candidates.filter(
|
|
506
|
-
(candidate) => focusablesByFirstChar.has(candidate)
|
|
507
|
-
);
|
|
474
|
+
focusables = candidates.filter((c) => focusablesByFirstChar.has(c));
|
|
508
475
|
const afterIndex = focusables.findIndex(
|
|
509
|
-
(
|
|
476
|
+
(f) => candidates.indexOf(f) > activeIndex
|
|
510
477
|
);
|
|
511
478
|
newIndex = afterIndex >= 0 ? afterIndex : 0;
|
|
512
479
|
}
|
|
@@ -550,7 +517,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
550
517
|
const char = focusable.textContent?.trim()?.at(0)?.toUpperCase();
|
|
551
518
|
const value = focusable.ariaKeyShortcuts?.trim();
|
|
552
519
|
const keys = new Set(
|
|
553
|
-
value ? value.split(/\s+/).filter((
|
|
520
|
+
value ? value.split(/\s+/).filter((k) => /^\S$/i.test(k)).map((k) => k.toUpperCase()) : []
|
|
554
521
|
);
|
|
555
522
|
if (char) {
|
|
556
523
|
keys.add(char);
|
|
@@ -559,17 +526,17 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
559
526
|
caseInsensitive: true
|
|
560
527
|
});
|
|
561
528
|
}
|
|
562
|
-
|
|
529
|
+
for (const key of keys) {
|
|
563
530
|
const focusables = this.#focusablesByFirstChar.get(key) ?? [];
|
|
564
531
|
focusables.push(focusable);
|
|
565
532
|
this.#focusablesByFirstChar.set(key, focusables);
|
|
566
|
-
}
|
|
533
|
+
}
|
|
567
534
|
}
|
|
568
535
|
if (!navigationOnly) {
|
|
569
536
|
if (active && this.#focusables.has(active)) {
|
|
570
|
-
this.#focusables
|
|
537
|
+
for (const focusable of this.#focusables) {
|
|
571
538
|
focusable.setAttribute("tabindex", focusable === active ? "0" : "-1");
|
|
572
|
-
}
|
|
539
|
+
}
|
|
573
540
|
} else {
|
|
574
541
|
[...this.#focusables].forEach((focusable, i) => {
|
|
575
542
|
focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
|
|
@@ -599,6 +566,7 @@ var RovingTabIndex = class _RovingTabIndex {
|
|
|
599
566
|
typeahead = false,
|
|
600
567
|
wrap = false
|
|
601
568
|
} = options;
|
|
569
|
+
direction = direction.toLowerCase();
|
|
602
570
|
if (!["both", "horizontal", "vertical"].includes(direction)) {
|
|
603
571
|
console.warn("Invalid direction option. Fallback: 'both'.");
|
|
604
572
|
direction = "both";
|
|
@@ -751,14 +719,14 @@ var Disclosure = class _Disclosure {
|
|
|
751
719
|
]);
|
|
752
720
|
this.#controller = new AbortController();
|
|
753
721
|
const { signal } = this.#controller;
|
|
754
|
-
this.#summaryElements
|
|
722
|
+
for (const summary of this.#summaryElements) {
|
|
755
723
|
if (!this.#isFocusable(summary)) {
|
|
756
724
|
summary.setAttribute("aria-disabled", "true");
|
|
757
725
|
summary.setAttribute("tabindex", "-1");
|
|
758
726
|
summary.style.setProperty("pointer-events", "none");
|
|
759
727
|
}
|
|
760
728
|
summary.addEventListener("click", this.#onSummaryClick, { signal });
|
|
761
|
-
}
|
|
729
|
+
}
|
|
762
730
|
this.#cleanupRovingTabIndex = createRovingTabIndex(this.#rootElement, {
|
|
763
731
|
direction: "vertical",
|
|
764
732
|
navigationOnly: true,
|
|
@@ -784,7 +752,7 @@ var Disclosure = class _Disclosure {
|
|
|
784
752
|
if (details.open === isExpand) {
|
|
785
753
|
return;
|
|
786
754
|
}
|
|
787
|
-
if (!isExpand && !this.#settings.collapsible && this.#detailsElements.filter((
|
|
755
|
+
if (!isExpand && !this.#settings.collapsible && this.#detailsElements.filter((d) => d.open).length <= 1) {
|
|
788
756
|
return;
|
|
789
757
|
}
|
|
790
758
|
details.open = isExpand;
|
|
@@ -810,7 +778,7 @@ var Disclosure = class _Disclosure {
|
|
|
810
778
|
* WAI-ARIA compliant disclosure pattern implementation in TypeScript.
|
|
811
779
|
* Using the <details> and <summary> element.
|
|
812
780
|
*
|
|
813
|
-
* @version 2.0.
|
|
781
|
+
* @version 2.0.11
|
|
814
782
|
* @author Yusuke Kamiyamane
|
|
815
783
|
* @license MIT
|
|
816
784
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -822,7 +790,7 @@ var Disclosure = class _Disclosure {
|
|
|
822
790
|
(**
|
|
823
791
|
* Attribute Utils
|
|
824
792
|
*
|
|
825
|
-
* @version 2.0.
|
|
793
|
+
* @version 2.0.12
|
|
826
794
|
* @author Yusuke Kamiyamane
|
|
827
795
|
* @license MIT
|
|
828
796
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -835,7 +803,7 @@ power-focusable/dist/index.js:
|
|
|
835
803
|
* High-precision focus management utility with full composed tree support.
|
|
836
804
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
837
805
|
*
|
|
838
|
-
* @version 4.3.
|
|
806
|
+
* @version 4.3.33
|
|
839
807
|
* @author Yusuke Kamiyamane
|
|
840
808
|
* @license MIT
|
|
841
809
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -848,7 +816,7 @@ power-focusable/dist/index.js:
|
|
|
848
816
|
* Lightweight roving tabindex utility with fully focus management.
|
|
849
817
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
850
818
|
*
|
|
851
|
-
* @version 3.1.
|
|
819
|
+
* @version 3.1.31
|
|
852
820
|
* @author Yusuke Kamiyamane
|
|
853
821
|
* @license MIT
|
|
854
822
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.cjs
CHANGED
|
@@ -131,14 +131,14 @@ var Disclosure = class _Disclosure {
|
|
|
131
131
|
]);
|
|
132
132
|
this.#controller = new AbortController();
|
|
133
133
|
const { signal } = this.#controller;
|
|
134
|
-
this.#summaryElements
|
|
134
|
+
for (const summary of this.#summaryElements) {
|
|
135
135
|
if (!this.#isFocusable(summary)) {
|
|
136
136
|
summary.setAttribute("aria-disabled", "true");
|
|
137
137
|
summary.setAttribute("tabindex", "-1");
|
|
138
138
|
summary.style.setProperty("pointer-events", "none");
|
|
139
139
|
}
|
|
140
140
|
summary.addEventListener("click", this.#onSummaryClick, { signal });
|
|
141
|
-
}
|
|
141
|
+
}
|
|
142
142
|
this.#cleanupRovingTabIndex = rovingTabindex.createRovingTabIndex(this.#rootElement, {
|
|
143
143
|
direction: "vertical",
|
|
144
144
|
navigationOnly: true,
|
|
@@ -164,7 +164,7 @@ var Disclosure = class _Disclosure {
|
|
|
164
164
|
if (details.open === isExpand) {
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
|
-
if (!isExpand && !this.#settings.collapsible && this.#detailsElements.filter((
|
|
167
|
+
if (!isExpand && !this.#settings.collapsible && this.#detailsElements.filter((d) => d.open).length <= 1) {
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
170
|
details.open = isExpand;
|
|
@@ -190,7 +190,7 @@ var Disclosure = class _Disclosure {
|
|
|
190
190
|
* WAI-ARIA compliant disclosure pattern implementation in TypeScript.
|
|
191
191
|
* Using the <details> and <summary> element.
|
|
192
192
|
*
|
|
193
|
-
* @version 2.0.
|
|
193
|
+
* @version 2.0.11
|
|
194
194
|
* @author Yusuke Kamiyamane
|
|
195
195
|
* @license MIT
|
|
196
196
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -109,14 +109,14 @@ var Disclosure = class _Disclosure {
|
|
|
109
109
|
]);
|
|
110
110
|
this.#controller = new AbortController();
|
|
111
111
|
const { signal } = this.#controller;
|
|
112
|
-
this.#summaryElements
|
|
112
|
+
for (const summary of this.#summaryElements) {
|
|
113
113
|
if (!this.#isFocusable(summary)) {
|
|
114
114
|
summary.setAttribute("aria-disabled", "true");
|
|
115
115
|
summary.setAttribute("tabindex", "-1");
|
|
116
116
|
summary.style.setProperty("pointer-events", "none");
|
|
117
117
|
}
|
|
118
118
|
summary.addEventListener("click", this.#onSummaryClick, { signal });
|
|
119
|
-
}
|
|
119
|
+
}
|
|
120
120
|
this.#cleanupRovingTabIndex = createRovingTabIndex(this.#rootElement, {
|
|
121
121
|
direction: "vertical",
|
|
122
122
|
navigationOnly: true,
|
|
@@ -142,7 +142,7 @@ var Disclosure = class _Disclosure {
|
|
|
142
142
|
if (details.open === isExpand) {
|
|
143
143
|
return;
|
|
144
144
|
}
|
|
145
|
-
if (!isExpand && !this.#settings.collapsible && this.#detailsElements.filter((
|
|
145
|
+
if (!isExpand && !this.#settings.collapsible && this.#detailsElements.filter((d) => d.open).length <= 1) {
|
|
146
146
|
return;
|
|
147
147
|
}
|
|
148
148
|
details.open = isExpand;
|
|
@@ -168,7 +168,7 @@ var Disclosure = class _Disclosure {
|
|
|
168
168
|
* WAI-ARIA compliant disclosure pattern implementation in TypeScript.
|
|
169
169
|
* Using the <details> and <summary> element.
|
|
170
170
|
*
|
|
171
|
-
* @version 2.0.
|
|
171
|
+
* @version 2.0.11
|
|
172
172
|
* @author Yusuke Kamiyamane
|
|
173
173
|
* @license MIT
|
|
174
174
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/disclosure-css",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.12",
|
|
4
4
|
"description": "WAI-ARIA compliant disclosure pattern implementation in TypeScript",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"a11y",
|
|
7
|
+
"accessibility",
|
|
8
|
+
"disclosure",
|
|
9
|
+
"collapsible",
|
|
10
|
+
"component",
|
|
11
|
+
"typescript",
|
|
12
|
+
"utility"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/y14e/disclosure-css#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/y14e/disclosure-css/issues"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/y14e/disclosure-css.git"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "Yusuke Kamiyamane",
|
|
5
24
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.cjs",
|
|
7
|
-
"module": "./dist/index.js",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
25
|
"exports": {
|
|
10
26
|
".": {
|
|
11
27
|
"types": "./dist/index.d.ts",
|
|
@@ -13,6 +29,9 @@
|
|
|
13
29
|
"require": "./dist/index.cjs"
|
|
14
30
|
}
|
|
15
31
|
},
|
|
32
|
+
"main": "./dist/index.cjs",
|
|
33
|
+
"module": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
16
35
|
"files": [
|
|
17
36
|
"dist",
|
|
18
37
|
"LICENSE",
|
|
@@ -20,28 +39,9 @@
|
|
|
20
39
|
],
|
|
21
40
|
"scripts": {
|
|
22
41
|
"build": "tsup",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
},
|
|
26
|
-
"keywords": [
|
|
27
|
-
"a11y",
|
|
28
|
-
"accessibility",
|
|
29
|
-
"disclosure",
|
|
30
|
-
"collapsible",
|
|
31
|
-
"component",
|
|
32
|
-
"typescript",
|
|
33
|
-
"utility"
|
|
34
|
-
],
|
|
35
|
-
"author": "Yusuke Kamiyamane",
|
|
36
|
-
"license": "MIT",
|
|
37
|
-
"repository": {
|
|
38
|
-
"type": "git",
|
|
39
|
-
"url": "git+https://github.com/y14e/disclosure-css.git"
|
|
42
|
+
"lint": "tsc --noEmit",
|
|
43
|
+
"prepublishOnly": "npm run build"
|
|
40
44
|
},
|
|
41
|
-
"bugs": {
|
|
42
|
-
"url": "https://github.com/y14e/disclosure-css/issues"
|
|
43
|
-
},
|
|
44
|
-
"homepage": "https://github.com/y14e/disclosure-css#readme",
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"bun-types": "latest",
|
|
47
47
|
"tsup": "^8.0.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"esbuild": true
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@y14e/attribute-utils": "^2.0.
|
|
58
|
-
"@y14e/roving-tabindex": "^3.1.
|
|
57
|
+
"@y14e/attribute-utils": "^2.0.12",
|
|
58
|
+
"@y14e/roving-tabindex": "^3.1.31"
|
|
59
59
|
}
|
|
60
60
|
}
|