@y14e/tabs 1.5.5 → 1.5.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 +64 -45
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +64 -45
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -10,14 +10,14 @@ npm i @y14e/tabs
|
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
12
|
// npm
|
|
13
|
-
import Tabs from '@y14e/tabs@1.5.
|
|
13
|
+
import Tabs from '@y14e/tabs@1.5.7';
|
|
14
14
|
|
|
15
15
|
// CDNs
|
|
16
|
-
import Tabs from 'https://esm.sh/@y14e/tabs@1.5.
|
|
16
|
+
import Tabs from 'https://esm.sh/@y14e/tabs@1.5.7';
|
|
17
17
|
// or
|
|
18
|
-
import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs@1.5.
|
|
18
|
+
import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs@1.5.7/+esm';
|
|
19
19
|
// or
|
|
20
|
-
import Tabs from 'https://esm.unpkg.com/@y14e/tabs@1.5.
|
|
20
|
+
import Tabs from 'https://esm.unpkg.com/@y14e/tabs@1.5.7';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
## Usage
|
package/dist/index.cjs
CHANGED
|
@@ -13,11 +13,10 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
|
13
13
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
14
14
|
if (caseInsensitive) {
|
|
15
15
|
const lower = token.toLowerCase();
|
|
16
|
-
if (tokens.
|
|
17
|
-
|
|
16
|
+
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
17
|
+
tokens.push(token);
|
|
18
|
+
element.setAttribute(attribute, serialize(tokens));
|
|
18
19
|
}
|
|
19
|
-
tokens.push(token);
|
|
20
|
-
element.setAttribute(attribute, serialize(tokens));
|
|
21
20
|
return;
|
|
22
21
|
}
|
|
23
22
|
const set = new Set(tokens);
|
|
@@ -119,11 +118,10 @@ function addTokenToAttribute2(element, attribute, token, options = {}) {
|
|
|
119
118
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
120
119
|
if (caseInsensitive) {
|
|
121
120
|
const lower = token.toLowerCase();
|
|
122
|
-
if (tokens.
|
|
123
|
-
|
|
121
|
+
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
122
|
+
tokens.push(token);
|
|
123
|
+
element.setAttribute(attribute, serialize(tokens));
|
|
124
124
|
}
|
|
125
|
-
tokens.push(token);
|
|
126
|
-
element.setAttribute(attribute, serialize(tokens));
|
|
127
125
|
return;
|
|
128
126
|
}
|
|
129
127
|
const set = new Set(tokens);
|
|
@@ -402,6 +400,8 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
402
400
|
let {
|
|
403
401
|
direction,
|
|
404
402
|
navigationOnly = false,
|
|
403
|
+
noMemory = false,
|
|
404
|
+
noStart = false,
|
|
405
405
|
selector,
|
|
406
406
|
typeahead = false,
|
|
407
407
|
wrap = false
|
|
@@ -414,6 +414,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
414
414
|
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
415
415
|
navigationOnly = false;
|
|
416
416
|
}
|
|
417
|
+
if (typeof noMemory !== "boolean") {
|
|
418
|
+
console.warn("Invalid noMemory option. Fallback: false.");
|
|
419
|
+
noMemory = false;
|
|
420
|
+
}
|
|
421
|
+
if (typeof noStart !== "boolean") {
|
|
422
|
+
console.warn("Invalid noStart option. Fallback: false.");
|
|
423
|
+
noStart = false;
|
|
424
|
+
}
|
|
417
425
|
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
418
426
|
console.warn(
|
|
419
427
|
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
@@ -428,13 +436,9 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
428
436
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
429
437
|
wrap = false;
|
|
430
438
|
}
|
|
431
|
-
const settings = { navigationOnly, typeahead, wrap };
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
}
|
|
435
|
-
if (selector) {
|
|
436
|
-
Object.assign(settings, { selector });
|
|
437
|
-
}
|
|
439
|
+
const settings = { navigationOnly, noMemory, noStart, typeahead, wrap };
|
|
440
|
+
direction && Object.assign(settings, { direction });
|
|
441
|
+
selector && Object.assign(settings, { selector });
|
|
438
442
|
const roving = new RovingTabIndex(container, settings);
|
|
439
443
|
return () => roving.destroy();
|
|
440
444
|
}
|
|
@@ -467,12 +471,29 @@ var RovingTabIndex = class {
|
|
|
467
471
|
#initialize() {
|
|
468
472
|
this.#update(document.activeElement);
|
|
469
473
|
this.#controller = new AbortController();
|
|
474
|
+
const { signal } = this.#controller;
|
|
475
|
+
document.addEventListener("focusin", this.#onFocusIn, {
|
|
476
|
+
capture: true,
|
|
477
|
+
signal
|
|
478
|
+
});
|
|
470
479
|
document.addEventListener("keydown", this.#onKeyDown, {
|
|
471
480
|
capture: true,
|
|
472
|
-
signal
|
|
481
|
+
signal
|
|
473
482
|
});
|
|
474
483
|
this.#container.setAttribute("data-roving-tabindex-initialized", "");
|
|
475
484
|
}
|
|
485
|
+
#onFocusIn = (event) => {
|
|
486
|
+
const { target } = event;
|
|
487
|
+
if (!(target instanceof Element)) {
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
const isFocusable22 = this.#focusables.has(target);
|
|
491
|
+
if (this.#options.noMemory && !isFocusable22) {
|
|
492
|
+
this.#update(null);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
isFocusable22 && this.#update(target);
|
|
496
|
+
};
|
|
476
497
|
#onKeyDown = (event) => {
|
|
477
498
|
if (!event.composedPath().includes(this.#container)) {
|
|
478
499
|
return;
|
|
@@ -534,11 +555,7 @@ var RovingTabIndex = class {
|
|
|
534
555
|
}
|
|
535
556
|
}
|
|
536
557
|
const focusable = target.at(newIndex);
|
|
537
|
-
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
this.#update(focusable);
|
|
541
|
-
focusElement(focusable);
|
|
558
|
+
focusable && focusElement(focusable);
|
|
542
559
|
};
|
|
543
560
|
#update(active) {
|
|
544
561
|
const current = new Set(this.#getFocusables());
|
|
@@ -553,7 +570,7 @@ var RovingTabIndex = class {
|
|
|
553
570
|
index >= 0 && focusables.splice(index, 1);
|
|
554
571
|
});
|
|
555
572
|
}
|
|
556
|
-
const { navigationOnly } = this.#options;
|
|
573
|
+
const { navigationOnly, noStart, typeahead } = this.#options;
|
|
557
574
|
for (const focusable of current) {
|
|
558
575
|
if (this.#focusables.has(focusable)) {
|
|
559
576
|
continue;
|
|
@@ -563,7 +580,7 @@ var RovingTabIndex = class {
|
|
|
563
580
|
saveAttributes2([focusable], ["tabindex"]);
|
|
564
581
|
focusable.setAttribute("tabindex", "-1");
|
|
565
582
|
}
|
|
566
|
-
if (!
|
|
583
|
+
if (!typeahead) {
|
|
567
584
|
continue;
|
|
568
585
|
}
|
|
569
586
|
const value = focusable.ariaKeyShortcuts?.trim();
|
|
@@ -594,7 +611,7 @@ var RovingTabIndex = class {
|
|
|
594
611
|
return;
|
|
595
612
|
}
|
|
596
613
|
[...this.#focusables].forEach((focusable, i) => {
|
|
597
|
-
focusable.setAttribute("tabindex", i ? "-1" : "0");
|
|
614
|
+
focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
|
|
598
615
|
});
|
|
599
616
|
}
|
|
600
617
|
#createSelectorFilter() {
|
|
@@ -605,7 +622,8 @@ var RovingTabIndex = class {
|
|
|
605
622
|
return getFocusables(this.#container, {
|
|
606
623
|
composed: true,
|
|
607
624
|
filter: this.#selectorFilter,
|
|
608
|
-
skipNegativeTabIndexCheck: !this.#options.navigationOnly
|
|
625
|
+
skipNegativeTabIndexCheck: !this.#options.navigationOnly,
|
|
626
|
+
skipVisibilityCheck: true
|
|
609
627
|
});
|
|
610
628
|
}
|
|
611
629
|
};
|
|
@@ -659,6 +677,7 @@ var Tabs = class _Tabs {
|
|
|
659
677
|
#animationController = null;
|
|
660
678
|
#cleanupsRovingTabIndex = [];
|
|
661
679
|
#animation = null;
|
|
680
|
+
#animationId = 0;
|
|
662
681
|
#buttons = [];
|
|
663
682
|
#indicators = [];
|
|
664
683
|
#isDestroyed = false;
|
|
@@ -761,14 +780,14 @@ var Tabs = class _Tabs {
|
|
|
761
780
|
const { style } = this.#contentElement;
|
|
762
781
|
style.setProperty("overflow", "clip");
|
|
763
782
|
style.setProperty("position", "relative");
|
|
764
|
-
const {
|
|
783
|
+
const { crossFade, fade } = this.#settings.animation.content;
|
|
765
784
|
const panel = this.#bindings.get(tab)?.panel;
|
|
766
785
|
if (!panel) {
|
|
767
786
|
return;
|
|
768
787
|
}
|
|
769
788
|
this.#panelElements.forEach((p) => {
|
|
770
789
|
const { style: style2 } = p;
|
|
771
|
-
if (
|
|
790
|
+
if (crossFade || fade) {
|
|
772
791
|
style2.setProperty("content-visibility", "visible");
|
|
773
792
|
style2.setProperty("display", "block");
|
|
774
793
|
style2.setProperty("opacity", p.hidden ? "0" : "1");
|
|
@@ -788,6 +807,7 @@ var Tabs = class _Tabs {
|
|
|
788
807
|
p.setAttribute("hidden", isFocusable2(tab2) ? "until-found" : "");
|
|
789
808
|
}
|
|
790
809
|
});
|
|
810
|
+
const animationId = ++this.#animationId;
|
|
791
811
|
this.#animation?.cancel();
|
|
792
812
|
const { duration, easing } = this.#settings.animation.content;
|
|
793
813
|
this.#animation = this.#contentElement.animate(
|
|
@@ -803,7 +823,9 @@ var Tabs = class _Tabs {
|
|
|
803
823
|
}
|
|
804
824
|
);
|
|
805
825
|
const cleanup = () => {
|
|
806
|
-
this.#
|
|
826
|
+
if (animationId === this.#animationId) {
|
|
827
|
+
this.#animation = null;
|
|
828
|
+
}
|
|
807
829
|
};
|
|
808
830
|
this.#animationController = new AbortController();
|
|
809
831
|
const { signal } = this.#animationController;
|
|
@@ -814,8 +836,10 @@ var Tabs = class _Tabs {
|
|
|
814
836
|
this.#animation.addEventListener(
|
|
815
837
|
"finish",
|
|
816
838
|
() => {
|
|
817
|
-
this.#
|
|
818
|
-
|
|
839
|
+
if (animationId === this.#animationId) {
|
|
840
|
+
this.#onAnimationFinish();
|
|
841
|
+
cleanup();
|
|
842
|
+
}
|
|
819
843
|
},
|
|
820
844
|
{
|
|
821
845
|
once: true,
|
|
@@ -835,7 +859,7 @@ var Tabs = class _Tabs {
|
|
|
835
859
|
opacity: fade ? isSelected ? [opacity, opacity, "1"] : [opacity, "0", "0"] : isSelected ? [opacity, "1"] : [opacity, "0"]
|
|
836
860
|
},
|
|
837
861
|
{
|
|
838
|
-
duration: isMatch || !(
|
|
862
|
+
duration: isMatch || !(crossFade || fade) ? 0 : this.#settings.animation.content.duration,
|
|
839
863
|
easing: "ease"
|
|
840
864
|
}
|
|
841
865
|
);
|
|
@@ -888,10 +912,7 @@ var Tabs = class _Tabs {
|
|
|
888
912
|
);
|
|
889
913
|
}
|
|
890
914
|
this.#panelElements.forEach((panel) => {
|
|
891
|
-
|
|
892
|
-
if (animation) {
|
|
893
|
-
animation.cancel();
|
|
894
|
-
}
|
|
915
|
+
this.#bindings.get(panel)?.animation?.cancel();
|
|
895
916
|
});
|
|
896
917
|
this.#onAnimationFinish();
|
|
897
918
|
this.#animationController?.abort();
|
|
@@ -973,11 +994,9 @@ var Tabs = class _Tabs {
|
|
|
973
994
|
});
|
|
974
995
|
const options = { selector: this.#settings.selector.tab, wrap: true };
|
|
975
996
|
this.#listElements.forEach((list) => {
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
});
|
|
980
|
-
}
|
|
997
|
+
list.ariaOrientation !== "undefined" && Object.assign(options, {
|
|
998
|
+
direction: this.#settings.vertical ? "vertical" : "horizontal"
|
|
999
|
+
});
|
|
981
1000
|
this.#cleanupsRovingTabIndex.push(createRovingTabIndex(list, options));
|
|
982
1001
|
list.querySelectorAll(this.#settings.selector.tab).forEach((tab) => {
|
|
983
1002
|
tab.setAttribute(
|
|
@@ -1145,7 +1164,7 @@ function isFocusable2(element) {
|
|
|
1145
1164
|
* Tabs
|
|
1146
1165
|
* WAI-ARIA compliant tabs pattern implementation in TypeScript.
|
|
1147
1166
|
*
|
|
1148
|
-
* @version 1.5.
|
|
1167
|
+
* @version 1.5.7
|
|
1149
1168
|
* @author Yusuke Kamiyamane
|
|
1150
1169
|
* @license MIT
|
|
1151
1170
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1157,7 +1176,7 @@ function isFocusable2(element) {
|
|
|
1157
1176
|
(**
|
|
1158
1177
|
* Attributes Utils
|
|
1159
1178
|
*
|
|
1160
|
-
* @version 1.1.
|
|
1179
|
+
* @version 1.1.1
|
|
1161
1180
|
* @author Yusuke Kamiyamane
|
|
1162
1181
|
* @license MIT
|
|
1163
1182
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1181,7 +1200,7 @@ function isFocusable2(element) {
|
|
|
1181
1200
|
* Lightweight roving tabindex utility with fully focus management.
|
|
1182
1201
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
1183
1202
|
*
|
|
1184
|
-
* @version 2.0
|
|
1203
|
+
* @version 2.2.0
|
|
1185
1204
|
* @author Yusuke Kamiyamane
|
|
1186
1205
|
* @license MIT
|
|
1187
1206
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1193,7 +1212,7 @@ function isFocusable2(element) {
|
|
|
1193
1212
|
(**
|
|
1194
1213
|
* Attributes Utils
|
|
1195
1214
|
*
|
|
1196
|
-
* @version 1.1.
|
|
1215
|
+
* @version 1.1.1
|
|
1197
1216
|
* @author Yusuke Kamiyamane
|
|
1198
1217
|
* @license MIT
|
|
1199
1218
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1206,7 +1225,7 @@ function isFocusable2(element) {
|
|
|
1206
1225
|
* High-precision focus management utility with full composed tree support.
|
|
1207
1226
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
1208
1227
|
*
|
|
1209
|
-
* @version 4.3.
|
|
1228
|
+
* @version 4.3.2
|
|
1210
1229
|
* @author Yusuke Kamiyamane
|
|
1211
1230
|
* @license MIT
|
|
1212
1231
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -11,11 +11,10 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
|
|
|
11
11
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
12
12
|
if (caseInsensitive) {
|
|
13
13
|
const lower = token.toLowerCase();
|
|
14
|
-
if (tokens.
|
|
15
|
-
|
|
14
|
+
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
15
|
+
tokens.push(token);
|
|
16
|
+
element.setAttribute(attribute, serialize(tokens));
|
|
16
17
|
}
|
|
17
|
-
tokens.push(token);
|
|
18
|
-
element.setAttribute(attribute, serialize(tokens));
|
|
19
18
|
return;
|
|
20
19
|
}
|
|
21
20
|
const set = new Set(tokens);
|
|
@@ -117,11 +116,10 @@ function addTokenToAttribute2(element, attribute, token, options = {}) {
|
|
|
117
116
|
const tokens = value ? parse(value).filter(Boolean) : [];
|
|
118
117
|
if (caseInsensitive) {
|
|
119
118
|
const lower = token.toLowerCase();
|
|
120
|
-
if (tokens.
|
|
121
|
-
|
|
119
|
+
if (tokens.every((token2) => token2.toLowerCase() !== lower)) {
|
|
120
|
+
tokens.push(token);
|
|
121
|
+
element.setAttribute(attribute, serialize(tokens));
|
|
122
122
|
}
|
|
123
|
-
tokens.push(token);
|
|
124
|
-
element.setAttribute(attribute, serialize(tokens));
|
|
125
123
|
return;
|
|
126
124
|
}
|
|
127
125
|
const set = new Set(tokens);
|
|
@@ -400,6 +398,8 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
400
398
|
let {
|
|
401
399
|
direction,
|
|
402
400
|
navigationOnly = false,
|
|
401
|
+
noMemory = false,
|
|
402
|
+
noStart = false,
|
|
403
403
|
selector,
|
|
404
404
|
typeahead = false,
|
|
405
405
|
wrap = false
|
|
@@ -412,6 +412,14 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
412
412
|
console.warn("Invalid navigationOnly option. Fallback: false.");
|
|
413
413
|
navigationOnly = false;
|
|
414
414
|
}
|
|
415
|
+
if (typeof noMemory !== "boolean") {
|
|
416
|
+
console.warn("Invalid noMemory option. Fallback: false.");
|
|
417
|
+
noMemory = false;
|
|
418
|
+
}
|
|
419
|
+
if (typeof noStart !== "boolean") {
|
|
420
|
+
console.warn("Invalid noStart option. Fallback: false.");
|
|
421
|
+
noStart = false;
|
|
422
|
+
}
|
|
415
423
|
if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
|
|
416
424
|
console.warn(
|
|
417
425
|
"Invalid selector. Fallback: all focusable elements (undefined)."
|
|
@@ -426,13 +434,9 @@ function createRovingTabIndex(container, options = {}) {
|
|
|
426
434
|
console.warn("Invalid wrap option. Fallback: false.");
|
|
427
435
|
wrap = false;
|
|
428
436
|
}
|
|
429
|
-
const settings = { navigationOnly, typeahead, wrap };
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
if (selector) {
|
|
434
|
-
Object.assign(settings, { selector });
|
|
435
|
-
}
|
|
437
|
+
const settings = { navigationOnly, noMemory, noStart, typeahead, wrap };
|
|
438
|
+
direction && Object.assign(settings, { direction });
|
|
439
|
+
selector && Object.assign(settings, { selector });
|
|
436
440
|
const roving = new RovingTabIndex(container, settings);
|
|
437
441
|
return () => roving.destroy();
|
|
438
442
|
}
|
|
@@ -465,12 +469,29 @@ var RovingTabIndex = class {
|
|
|
465
469
|
#initialize() {
|
|
466
470
|
this.#update(document.activeElement);
|
|
467
471
|
this.#controller = new AbortController();
|
|
472
|
+
const { signal } = this.#controller;
|
|
473
|
+
document.addEventListener("focusin", this.#onFocusIn, {
|
|
474
|
+
capture: true,
|
|
475
|
+
signal
|
|
476
|
+
});
|
|
468
477
|
document.addEventListener("keydown", this.#onKeyDown, {
|
|
469
478
|
capture: true,
|
|
470
|
-
signal
|
|
479
|
+
signal
|
|
471
480
|
});
|
|
472
481
|
this.#container.setAttribute("data-roving-tabindex-initialized", "");
|
|
473
482
|
}
|
|
483
|
+
#onFocusIn = (event) => {
|
|
484
|
+
const { target } = event;
|
|
485
|
+
if (!(target instanceof Element)) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
const isFocusable22 = this.#focusables.has(target);
|
|
489
|
+
if (this.#options.noMemory && !isFocusable22) {
|
|
490
|
+
this.#update(null);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
isFocusable22 && this.#update(target);
|
|
494
|
+
};
|
|
474
495
|
#onKeyDown = (event) => {
|
|
475
496
|
if (!event.composedPath().includes(this.#container)) {
|
|
476
497
|
return;
|
|
@@ -532,11 +553,7 @@ var RovingTabIndex = class {
|
|
|
532
553
|
}
|
|
533
554
|
}
|
|
534
555
|
const focusable = target.at(newIndex);
|
|
535
|
-
|
|
536
|
-
return;
|
|
537
|
-
}
|
|
538
|
-
this.#update(focusable);
|
|
539
|
-
focusElement(focusable);
|
|
556
|
+
focusable && focusElement(focusable);
|
|
540
557
|
};
|
|
541
558
|
#update(active) {
|
|
542
559
|
const current = new Set(this.#getFocusables());
|
|
@@ -551,7 +568,7 @@ var RovingTabIndex = class {
|
|
|
551
568
|
index >= 0 && focusables.splice(index, 1);
|
|
552
569
|
});
|
|
553
570
|
}
|
|
554
|
-
const { navigationOnly } = this.#options;
|
|
571
|
+
const { navigationOnly, noStart, typeahead } = this.#options;
|
|
555
572
|
for (const focusable of current) {
|
|
556
573
|
if (this.#focusables.has(focusable)) {
|
|
557
574
|
continue;
|
|
@@ -561,7 +578,7 @@ var RovingTabIndex = class {
|
|
|
561
578
|
saveAttributes2([focusable], ["tabindex"]);
|
|
562
579
|
focusable.setAttribute("tabindex", "-1");
|
|
563
580
|
}
|
|
564
|
-
if (!
|
|
581
|
+
if (!typeahead) {
|
|
565
582
|
continue;
|
|
566
583
|
}
|
|
567
584
|
const value = focusable.ariaKeyShortcuts?.trim();
|
|
@@ -592,7 +609,7 @@ var RovingTabIndex = class {
|
|
|
592
609
|
return;
|
|
593
610
|
}
|
|
594
611
|
[...this.#focusables].forEach((focusable, i) => {
|
|
595
|
-
focusable.setAttribute("tabindex", i ? "-1" : "0");
|
|
612
|
+
focusable.setAttribute("tabindex", i || noStart ? "-1" : "0");
|
|
596
613
|
});
|
|
597
614
|
}
|
|
598
615
|
#createSelectorFilter() {
|
|
@@ -603,7 +620,8 @@ var RovingTabIndex = class {
|
|
|
603
620
|
return getFocusables(this.#container, {
|
|
604
621
|
composed: true,
|
|
605
622
|
filter: this.#selectorFilter,
|
|
606
|
-
skipNegativeTabIndexCheck: !this.#options.navigationOnly
|
|
623
|
+
skipNegativeTabIndexCheck: !this.#options.navigationOnly,
|
|
624
|
+
skipVisibilityCheck: true
|
|
607
625
|
});
|
|
608
626
|
}
|
|
609
627
|
};
|
|
@@ -657,6 +675,7 @@ var Tabs = class _Tabs {
|
|
|
657
675
|
#animationController = null;
|
|
658
676
|
#cleanupsRovingTabIndex = [];
|
|
659
677
|
#animation = null;
|
|
678
|
+
#animationId = 0;
|
|
660
679
|
#buttons = [];
|
|
661
680
|
#indicators = [];
|
|
662
681
|
#isDestroyed = false;
|
|
@@ -759,14 +778,14 @@ var Tabs = class _Tabs {
|
|
|
759
778
|
const { style } = this.#contentElement;
|
|
760
779
|
style.setProperty("overflow", "clip");
|
|
761
780
|
style.setProperty("position", "relative");
|
|
762
|
-
const {
|
|
781
|
+
const { crossFade, fade } = this.#settings.animation.content;
|
|
763
782
|
const panel = this.#bindings.get(tab)?.panel;
|
|
764
783
|
if (!panel) {
|
|
765
784
|
return;
|
|
766
785
|
}
|
|
767
786
|
this.#panelElements.forEach((p) => {
|
|
768
787
|
const { style: style2 } = p;
|
|
769
|
-
if (
|
|
788
|
+
if (crossFade || fade) {
|
|
770
789
|
style2.setProperty("content-visibility", "visible");
|
|
771
790
|
style2.setProperty("display", "block");
|
|
772
791
|
style2.setProperty("opacity", p.hidden ? "0" : "1");
|
|
@@ -786,6 +805,7 @@ var Tabs = class _Tabs {
|
|
|
786
805
|
p.setAttribute("hidden", isFocusable2(tab2) ? "until-found" : "");
|
|
787
806
|
}
|
|
788
807
|
});
|
|
808
|
+
const animationId = ++this.#animationId;
|
|
789
809
|
this.#animation?.cancel();
|
|
790
810
|
const { duration, easing } = this.#settings.animation.content;
|
|
791
811
|
this.#animation = this.#contentElement.animate(
|
|
@@ -801,7 +821,9 @@ var Tabs = class _Tabs {
|
|
|
801
821
|
}
|
|
802
822
|
);
|
|
803
823
|
const cleanup = () => {
|
|
804
|
-
this.#
|
|
824
|
+
if (animationId === this.#animationId) {
|
|
825
|
+
this.#animation = null;
|
|
826
|
+
}
|
|
805
827
|
};
|
|
806
828
|
this.#animationController = new AbortController();
|
|
807
829
|
const { signal } = this.#animationController;
|
|
@@ -812,8 +834,10 @@ var Tabs = class _Tabs {
|
|
|
812
834
|
this.#animation.addEventListener(
|
|
813
835
|
"finish",
|
|
814
836
|
() => {
|
|
815
|
-
this.#
|
|
816
|
-
|
|
837
|
+
if (animationId === this.#animationId) {
|
|
838
|
+
this.#onAnimationFinish();
|
|
839
|
+
cleanup();
|
|
840
|
+
}
|
|
817
841
|
},
|
|
818
842
|
{
|
|
819
843
|
once: true,
|
|
@@ -833,7 +857,7 @@ var Tabs = class _Tabs {
|
|
|
833
857
|
opacity: fade ? isSelected ? [opacity, opacity, "1"] : [opacity, "0", "0"] : isSelected ? [opacity, "1"] : [opacity, "0"]
|
|
834
858
|
},
|
|
835
859
|
{
|
|
836
|
-
duration: isMatch || !(
|
|
860
|
+
duration: isMatch || !(crossFade || fade) ? 0 : this.#settings.animation.content.duration,
|
|
837
861
|
easing: "ease"
|
|
838
862
|
}
|
|
839
863
|
);
|
|
@@ -886,10 +910,7 @@ var Tabs = class _Tabs {
|
|
|
886
910
|
);
|
|
887
911
|
}
|
|
888
912
|
this.#panelElements.forEach((panel) => {
|
|
889
|
-
|
|
890
|
-
if (animation) {
|
|
891
|
-
animation.cancel();
|
|
892
|
-
}
|
|
913
|
+
this.#bindings.get(panel)?.animation?.cancel();
|
|
893
914
|
});
|
|
894
915
|
this.#onAnimationFinish();
|
|
895
916
|
this.#animationController?.abort();
|
|
@@ -971,11 +992,9 @@ var Tabs = class _Tabs {
|
|
|
971
992
|
});
|
|
972
993
|
const options = { selector: this.#settings.selector.tab, wrap: true };
|
|
973
994
|
this.#listElements.forEach((list) => {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
});
|
|
978
|
-
}
|
|
995
|
+
list.ariaOrientation !== "undefined" && Object.assign(options, {
|
|
996
|
+
direction: this.#settings.vertical ? "vertical" : "horizontal"
|
|
997
|
+
});
|
|
979
998
|
this.#cleanupsRovingTabIndex.push(createRovingTabIndex(list, options));
|
|
980
999
|
list.querySelectorAll(this.#settings.selector.tab).forEach((tab) => {
|
|
981
1000
|
tab.setAttribute(
|
|
@@ -1143,7 +1162,7 @@ function isFocusable2(element) {
|
|
|
1143
1162
|
* Tabs
|
|
1144
1163
|
* WAI-ARIA compliant tabs pattern implementation in TypeScript.
|
|
1145
1164
|
*
|
|
1146
|
-
* @version 1.5.
|
|
1165
|
+
* @version 1.5.7
|
|
1147
1166
|
* @author Yusuke Kamiyamane
|
|
1148
1167
|
* @license MIT
|
|
1149
1168
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1155,7 +1174,7 @@ function isFocusable2(element) {
|
|
|
1155
1174
|
(**
|
|
1156
1175
|
* Attributes Utils
|
|
1157
1176
|
*
|
|
1158
|
-
* @version 1.1.
|
|
1177
|
+
* @version 1.1.1
|
|
1159
1178
|
* @author Yusuke Kamiyamane
|
|
1160
1179
|
* @license MIT
|
|
1161
1180
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1179,7 +1198,7 @@ function isFocusable2(element) {
|
|
|
1179
1198
|
* Lightweight roving tabindex utility with fully focus management.
|
|
1180
1199
|
* Designed for accessible menus, tabs, toolbars, and composite widgets.
|
|
1181
1200
|
*
|
|
1182
|
-
* @version 2.0
|
|
1201
|
+
* @version 2.2.0
|
|
1183
1202
|
* @author Yusuke Kamiyamane
|
|
1184
1203
|
* @license MIT
|
|
1185
1204
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1191,7 +1210,7 @@ function isFocusable2(element) {
|
|
|
1191
1210
|
(**
|
|
1192
1211
|
* Attributes Utils
|
|
1193
1212
|
*
|
|
1194
|
-
* @version 1.1.
|
|
1213
|
+
* @version 1.1.1
|
|
1195
1214
|
* @author Yusuke Kamiyamane
|
|
1196
1215
|
* @license MIT
|
|
1197
1216
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
|
@@ -1204,7 +1223,7 @@ function isFocusable2(element) {
|
|
|
1204
1223
|
* High-precision focus management utility with full composed tree support.
|
|
1205
1224
|
* Handles complex focus rules including tabindex ordering, radio groups, inert.
|
|
1206
1225
|
*
|
|
1207
|
-
* @version 4.3.
|
|
1226
|
+
* @version 4.3.2
|
|
1208
1227
|
* @author Yusuke Kamiyamane
|
|
1209
1228
|
* @license MIT
|
|
1210
1229
|
* @copyright Copyright (c) Yusuke Kamiyamane
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y14e/tabs",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.7",
|
|
4
4
|
"description": "WAI-ARIA compliant tabs pattern implementation in TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
},
|
|
43
43
|
"homepage": "https://github.com/y14e/tabs#readme",
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@y14e/attributes-utils": "^1.1.
|
|
45
|
+
"@y14e/attributes-utils": "^1.1.1",
|
|
46
46
|
"@y14e/button": "^1.0.0",
|
|
47
|
-
"@y14e/roving-tabindex": "^2.0
|
|
47
|
+
"@y14e/roving-tabindex": "^2.2.0",
|
|
48
48
|
"bun-types": "latest",
|
|
49
49
|
"tsup": "^8.0.0",
|
|
50
50
|
"typescript": "^5.6.0",
|