@y14e/disclosure 1.3.3 → 1.3.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 +4 -4
- package/dist/index.cjs +55 -29
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +55 -29
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -10,14 +10,14 @@ npm i @y14e/disclosure
|
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
// npm
|
|
13
|
-
import Disclosure from '@y14e/disclosure';
|
|
13
|
+
import Disclosure from '@y14e/disclosure@1.3.3';
|
|
14
14
|
|
|
15
15
|
// CDNs
|
|
16
|
-
import Disclosure from 'https://esm.sh/@y14e/disclosure'
|
|
16
|
+
import Disclosure from 'https://esm.sh/@y14e/disclosure@1.3.3';
|
|
17
17
|
// or
|
|
18
|
-
import Disclosure from 'https://cdn.jsdelivr.net/npm/@y14e/disclosure/+esm';
|
|
18
|
+
import Disclosure from 'https://cdn.jsdelivr.net/npm/@y14e/disclosure@1.3.3/+esm';
|
|
19
19
|
// or
|
|
20
|
-
import Disclosure from 'https://unpkg.com/@y14e/disclosure
|
|
20
|
+
import Disclosure from 'https://esm.unpkg.com/@y14e/disclosure@1.3.3';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Usage
|
package/dist/index.cjs
CHANGED
|
@@ -82,7 +82,13 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
82
82
|
console.warn("Invalid container element. Fallback: <body> element.");
|
|
83
83
|
container = document.body;
|
|
84
84
|
}
|
|
85
|
-
let {
|
|
85
|
+
let {
|
|
86
|
+
composed = false,
|
|
87
|
+
filter,
|
|
88
|
+
include,
|
|
89
|
+
skipNegativeTabIndexCheck = false,
|
|
90
|
+
skipVisibilityCheck = false
|
|
91
|
+
} = options;
|
|
86
92
|
if (typeof composed !== "boolean") {
|
|
87
93
|
console.warn("Invalid composed option. Fallback: false.");
|
|
88
94
|
composed = false;
|
|
@@ -99,11 +105,22 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
99
105
|
);
|
|
100
106
|
include = void 0;
|
|
101
107
|
}
|
|
108
|
+
if (typeof skipNegativeTabIndexCheck !== "boolean") {
|
|
109
|
+
console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
|
|
110
|
+
skipNegativeTabIndexCheck = false;
|
|
111
|
+
}
|
|
112
|
+
if (typeof skipVisibilityCheck !== "boolean") {
|
|
113
|
+
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
114
|
+
skipVisibilityCheck = false;
|
|
115
|
+
}
|
|
102
116
|
const elements = [];
|
|
103
117
|
if (composed || include) {
|
|
104
118
|
let traverse2 = function(node) {
|
|
105
119
|
if (node instanceof Element) {
|
|
106
|
-
if (isFocusable(node
|
|
120
|
+
if (isFocusable(node, {
|
|
121
|
+
skipNegativeTabIndexCheck,
|
|
122
|
+
skipVisibilityCheck
|
|
123
|
+
}) || include?.(node)) {
|
|
107
124
|
elements[elements.length] = node;
|
|
108
125
|
}
|
|
109
126
|
}
|
|
@@ -124,7 +141,10 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
124
141
|
if (!(candidate instanceof Element)) {
|
|
125
142
|
continue;
|
|
126
143
|
}
|
|
127
|
-
if (isFocusable(candidate
|
|
144
|
+
if (isFocusable(candidate, {
|
|
145
|
+
skipNegativeTabIndexCheck,
|
|
146
|
+
skipVisibilityCheck
|
|
147
|
+
})) {
|
|
128
148
|
elements[elements.length] = candidate;
|
|
129
149
|
}
|
|
130
150
|
}
|
|
@@ -132,24 +152,35 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
132
152
|
const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
|
|
133
153
|
return filter ? unfiltered.filter(filter) : unfiltered;
|
|
134
154
|
}
|
|
135
|
-
function isFocusable(element) {
|
|
155
|
+
function isFocusable(element, options = {}) {
|
|
136
156
|
if (!(element instanceof Element)) {
|
|
137
157
|
console.warn("Invalid element");
|
|
138
158
|
return false;
|
|
139
159
|
}
|
|
160
|
+
let { skipNegativeTabIndexCheck = false, skipVisibilityCheck = false } = options;
|
|
161
|
+
if (typeof skipNegativeTabIndexCheck !== "boolean") {
|
|
162
|
+
console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
|
|
163
|
+
skipNegativeTabIndexCheck = false;
|
|
164
|
+
}
|
|
165
|
+
if (typeof skipVisibilityCheck !== "boolean") {
|
|
166
|
+
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
167
|
+
skipVisibilityCheck = false;
|
|
168
|
+
}
|
|
140
169
|
if (element.hasAttribute("hidden") || isInert(element)) {
|
|
141
170
|
return false;
|
|
142
171
|
}
|
|
143
|
-
if (getTabIndex(element) < 0) {
|
|
172
|
+
if (!skipNegativeTabIndexCheck && getTabIndex(element) < 0) {
|
|
144
173
|
return false;
|
|
145
174
|
}
|
|
146
|
-
if (!element.matches(
|
|
175
|
+
if (!element.matches(
|
|
176
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
|
|
177
|
+
)) {
|
|
147
178
|
return false;
|
|
148
179
|
}
|
|
149
180
|
if (isDisabledDeep(element)) {
|
|
150
181
|
return false;
|
|
151
182
|
}
|
|
152
|
-
if (!element.checkVisibility({
|
|
183
|
+
if (!skipVisibilityCheck && !element.checkVisibility({
|
|
153
184
|
contentVisibilityAuto: true,
|
|
154
185
|
opacityProperty: true,
|
|
155
186
|
visibilityProperty: true
|
|
@@ -318,13 +349,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
318
349
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
319
350
|
wrap = false;
|
|
320
351
|
}
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
352
|
+
const settings = { navigationOnly, typeahead, wrap };
|
|
353
|
+
if (direction !== void 0) {
|
|
354
|
+
Object.assign(settings, { direction });
|
|
355
|
+
}
|
|
356
|
+
if (selector !== void 0) {
|
|
357
|
+
Object.assign(settings, { selector });
|
|
358
|
+
}
|
|
359
|
+
const roving = new RovingTabIndex(container, settings);
|
|
328
360
|
return () => roving.destroy();
|
|
329
361
|
}
|
|
330
362
|
var RovingTabIndex = class {
|
|
@@ -366,8 +398,8 @@ var RovingTabIndex = class {
|
|
|
366
398
|
if (!event.composedPath().includes(this.#container)) {
|
|
367
399
|
return;
|
|
368
400
|
}
|
|
369
|
-
const { key, altKey, ctrlKey, metaKey } = event;
|
|
370
|
-
if (altKey || ctrlKey || metaKey) {
|
|
401
|
+
const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
|
|
402
|
+
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
371
403
|
return;
|
|
372
404
|
}
|
|
373
405
|
const { direction, typeahead, wrap } = this.#options;
|
|
@@ -430,13 +462,7 @@ var RovingTabIndex = class {
|
|
|
430
462
|
focusElement(focusable);
|
|
431
463
|
};
|
|
432
464
|
#update(active) {
|
|
433
|
-
const current =
|
|
434
|
-
...this.#getFocusables(),
|
|
435
|
-
...getFocusables(this.#container, {
|
|
436
|
-
composed: true,
|
|
437
|
-
filter: this.#selectorFilter
|
|
438
|
-
})
|
|
439
|
-
]);
|
|
465
|
+
const current = new Set(this.#getFocusables());
|
|
440
466
|
for (const focusable of this.#focusables) {
|
|
441
467
|
if (current.has(focusable)) {
|
|
442
468
|
continue;
|
|
@@ -500,7 +526,7 @@ var RovingTabIndex = class {
|
|
|
500
526
|
return getFocusables(this.#container, {
|
|
501
527
|
composed: true,
|
|
502
528
|
filter: this.#selectorFilter,
|
|
503
|
-
|
|
529
|
+
skipNegativeTabIndexCheck: !this.#options.navigationOnly
|
|
504
530
|
});
|
|
505
531
|
}
|
|
506
532
|
};
|
|
@@ -788,7 +814,7 @@ function waitAnimationFinish(animation) {
|
|
|
788
814
|
* WAI-ARIA compliant disclosure pattern implementation in TypeScript.
|
|
789
815
|
* Using the <details> and <summary> element.
|
|
790
816
|
*
|
|
791
|
-
* @version 1.3.
|
|
817
|
+
* @version 1.3.4
|
|
792
818
|
* @author Yusuke Kamiyamane
|
|
793
819
|
* @license MIT
|
|
794
820
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -800,7 +826,7 @@ function waitAnimationFinish(animation) {
|
|
|
800
826
|
(**
|
|
801
827
|
* Attributes Utils
|
|
802
828
|
*
|
|
803
|
-
* @version 1.0
|
|
829
|
+
* @version 1.1.0
|
|
804
830
|
* @author Yusuke Kamiyamane
|
|
805
831
|
* @license MIT
|
|
806
832
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -813,7 +839,7 @@ function waitAnimationFinish(animation) {
|
|
|
813
839
|
* Lightweight roving tabindex utility with fully focus management.
|
|
814
840
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
815
841
|
*
|
|
816
|
-
* @version
|
|
842
|
+
* @version 2.0.3
|
|
817
843
|
* @author Yusuke Kamiyamane
|
|
818
844
|
* @license MIT
|
|
819
845
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -825,7 +851,7 @@ function waitAnimationFinish(animation) {
|
|
|
825
851
|
(**
|
|
826
852
|
* Attributes Utils
|
|
827
853
|
*
|
|
828
|
-
* @version 1.0
|
|
854
|
+
* @version 1.1.0
|
|
829
855
|
* @author Yusuke Kamiyamane
|
|
830
856
|
* @license MIT
|
|
831
857
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -838,7 +864,7 @@ function waitAnimationFinish(animation) {
|
|
|
838
864
|
* High-precision focus management utility with full composed tree support.
|
|
839
865
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
840
866
|
*
|
|
841
|
-
* @version 4.1
|
|
867
|
+
* @version 4.3.1
|
|
842
868
|
* @author Yusuke Kamiyamane
|
|
843
869
|
* @license MIT
|
|
844
870
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -80,7 +80,13 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
80
80
|
console.warn("Invalid container element. Fallback: <body> element.");
|
|
81
81
|
container = document.body;
|
|
82
82
|
}
|
|
83
|
-
let {
|
|
83
|
+
let {
|
|
84
|
+
composed = false,
|
|
85
|
+
filter,
|
|
86
|
+
include,
|
|
87
|
+
skipNegativeTabIndexCheck = false,
|
|
88
|
+
skipVisibilityCheck = false
|
|
89
|
+
} = options;
|
|
84
90
|
if (typeof composed !== "boolean") {
|
|
85
91
|
console.warn("Invalid composed option. Fallback: false.");
|
|
86
92
|
composed = false;
|
|
@@ -97,11 +103,22 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
97
103
|
);
|
|
98
104
|
include = void 0;
|
|
99
105
|
}
|
|
106
|
+
if (typeof skipNegativeTabIndexCheck !== "boolean") {
|
|
107
|
+
console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
|
|
108
|
+
skipNegativeTabIndexCheck = false;
|
|
109
|
+
}
|
|
110
|
+
if (typeof skipVisibilityCheck !== "boolean") {
|
|
111
|
+
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
112
|
+
skipVisibilityCheck = false;
|
|
113
|
+
}
|
|
100
114
|
const elements = [];
|
|
101
115
|
if (composed || include) {
|
|
102
116
|
let traverse2 = function(node) {
|
|
103
117
|
if (node instanceof Element) {
|
|
104
|
-
if (isFocusable(node
|
|
118
|
+
if (isFocusable(node, {
|
|
119
|
+
skipNegativeTabIndexCheck,
|
|
120
|
+
skipVisibilityCheck
|
|
121
|
+
}) || include?.(node)) {
|
|
105
122
|
elements[elements.length] = node;
|
|
106
123
|
}
|
|
107
124
|
}
|
|
@@ -122,7 +139,10 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
122
139
|
if (!(candidate instanceof Element)) {
|
|
123
140
|
continue;
|
|
124
141
|
}
|
|
125
|
-
if (isFocusable(candidate
|
|
142
|
+
if (isFocusable(candidate, {
|
|
143
|
+
skipNegativeTabIndexCheck,
|
|
144
|
+
skipVisibilityCheck
|
|
145
|
+
})) {
|
|
126
146
|
elements[elements.length] = candidate;
|
|
127
147
|
}
|
|
128
148
|
}
|
|
@@ -130,24 +150,35 @@ function getFocusables(container = document.body, options = {}) {
|
|
|
130
150
|
const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
|
|
131
151
|
return filter ? unfiltered.filter(filter) : unfiltered;
|
|
132
152
|
}
|
|
133
|
-
function isFocusable(element) {
|
|
153
|
+
function isFocusable(element, options = {}) {
|
|
134
154
|
if (!(element instanceof Element)) {
|
|
135
155
|
console.warn("Invalid element");
|
|
136
156
|
return false;
|
|
137
157
|
}
|
|
158
|
+
let { skipNegativeTabIndexCheck = false, skipVisibilityCheck = false } = options;
|
|
159
|
+
if (typeof skipNegativeTabIndexCheck !== "boolean") {
|
|
160
|
+
console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
|
|
161
|
+
skipNegativeTabIndexCheck = false;
|
|
162
|
+
}
|
|
163
|
+
if (typeof skipVisibilityCheck !== "boolean") {
|
|
164
|
+
console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
|
|
165
|
+
skipVisibilityCheck = false;
|
|
166
|
+
}
|
|
138
167
|
if (element.hasAttribute("hidden") || isInert(element)) {
|
|
139
168
|
return false;
|
|
140
169
|
}
|
|
141
|
-
if (getTabIndex(element) < 0) {
|
|
170
|
+
if (!skipNegativeTabIndexCheck && getTabIndex(element) < 0) {
|
|
142
171
|
return false;
|
|
143
172
|
}
|
|
144
|
-
if (!element.matches(
|
|
173
|
+
if (!element.matches(
|
|
174
|
+
skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
|
|
175
|
+
)) {
|
|
145
176
|
return false;
|
|
146
177
|
}
|
|
147
178
|
if (isDisabledDeep(element)) {
|
|
148
179
|
return false;
|
|
149
180
|
}
|
|
150
|
-
if (!element.checkVisibility({
|
|
181
|
+
if (!skipVisibilityCheck && !element.checkVisibility({
|
|
151
182
|
contentVisibilityAuto: true,
|
|
152
183
|
opacityProperty: true,
|
|
153
184
|
visibilityProperty: true
|
|
@@ -316,13 +347,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
316
347
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
317
348
|
wrap = false;
|
|
318
349
|
}
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
350
|
+
const settings = { navigationOnly, typeahead, wrap };
|
|
351
|
+
if (direction !== void 0) {
|
|
352
|
+
Object.assign(settings, { direction });
|
|
353
|
+
}
|
|
354
|
+
if (selector !== void 0) {
|
|
355
|
+
Object.assign(settings, { selector });
|
|
356
|
+
}
|
|
357
|
+
const roving = new RovingTabIndex(container, settings);
|
|
326
358
|
return () => roving.destroy();
|
|
327
359
|
}
|
|
328
360
|
var RovingTabIndex = class {
|
|
@@ -364,8 +396,8 @@ var RovingTabIndex = class {
|
|
|
364
396
|
if (!event.composedPath().includes(this.#container)) {
|
|
365
397
|
return;
|
|
366
398
|
}
|
|
367
|
-
const { key, altKey, ctrlKey, metaKey } = event;
|
|
368
|
-
if (altKey || ctrlKey || metaKey) {
|
|
399
|
+
const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
|
|
400
|
+
if (altKey || ctrlKey || metaKey || shiftKey) {
|
|
369
401
|
return;
|
|
370
402
|
}
|
|
371
403
|
const { direction, typeahead, wrap } = this.#options;
|
|
@@ -428,13 +460,7 @@ var RovingTabIndex = class {
|
|
|
428
460
|
focusElement(focusable);
|
|
429
461
|
};
|
|
430
462
|
#update(active) {
|
|
431
|
-
const current =
|
|
432
|
-
...this.#getFocusables(),
|
|
433
|
-
...getFocusables(this.#container, {
|
|
434
|
-
composed: true,
|
|
435
|
-
filter: this.#selectorFilter
|
|
436
|
-
})
|
|
437
|
-
]);
|
|
463
|
+
const current = new Set(this.#getFocusables());
|
|
438
464
|
for (const focusable of this.#focusables) {
|
|
439
465
|
if (current.has(focusable)) {
|
|
440
466
|
continue;
|
|
@@ -498,7 +524,7 @@ var RovingTabIndex = class {
|
|
|
498
524
|
return getFocusables(this.#container, {
|
|
499
525
|
composed: true,
|
|
500
526
|
filter: this.#selectorFilter,
|
|
501
|
-
|
|
527
|
+
skipNegativeTabIndexCheck: !this.#options.navigationOnly
|
|
502
528
|
});
|
|
503
529
|
}
|
|
504
530
|
};
|
|
@@ -786,7 +812,7 @@ function waitAnimationFinish(animation) {
|
|
|
786
812
|
* WAI-ARIA compliant disclosure pattern implementation in TypeScript.
|
|
787
813
|
* Using the <details> and <summary> element.
|
|
788
814
|
*
|
|
789
|
-
* @version 1.3.
|
|
815
|
+
* @version 1.3.4
|
|
790
816
|
* @author Yusuke Kamiyamane
|
|
791
817
|
* @license MIT
|
|
792
818
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -798,7 +824,7 @@ function waitAnimationFinish(animation) {
|
|
|
798
824
|
(**
|
|
799
825
|
* Attributes Utils
|
|
800
826
|
*
|
|
801
|
-
* @version 1.0
|
|
827
|
+
* @version 1.1.0
|
|
802
828
|
* @author Yusuke Kamiyamane
|
|
803
829
|
* @license MIT
|
|
804
830
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -811,7 +837,7 @@ function waitAnimationFinish(animation) {
|
|
|
811
837
|
* Lightweight roving tabindex utility with fully focus management.
|
|
812
838
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
813
839
|
*
|
|
814
|
-
* @version
|
|
840
|
+
* @version 2.0.3
|
|
815
841
|
* @author Yusuke Kamiyamane
|
|
816
842
|
* @license MIT
|
|
817
843
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -823,7 +849,7 @@ function waitAnimationFinish(animation) {
|
|
|
823
849
|
(**
|
|
824
850
|
* Attributes Utils
|
|
825
851
|
*
|
|
826
|
-
* @version 1.0
|
|
852
|
+
* @version 1.1.0
|
|
827
853
|
* @author Yusuke Kamiyamane
|
|
828
854
|
* @license MIT
|
|
829
855
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -836,7 +862,7 @@ function waitAnimationFinish(animation) {
|
|
|
836
862
|
* High-precision focus management utility with full composed tree support.
|
|
837
863
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
838
864
|
*
|
|
839
|
-
* @version 4.1
|
|
865
|
+
* @version 4.3.1
|
|
840
866
|
* @author Yusuke Kamiyamane
|
|
841
867
|
* @license MIT
|
|
842
868
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/disclosure",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
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#readme",
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@y14e/attributes-utils": "^1.0
|
|
47
|
-
"@y14e/roving-tabindex": "^
|
|
46
|
+
"@y14e/attributes-utils": "^1.1.0",
|
|
47
|
+
"@y14e/roving-tabindex": "^2.0.3",
|
|
48
48
|
"bun-types": "latest",
|
|
49
49
|
"tsup": "^8.0.0",
|
|
50
50
|
"typescript": "^5.6.0",
|