@y14e/tabs 2.0.6 → 2.0.8

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 CHANGED
@@ -13,11 +13,11 @@ npm i @y14e/tabs
13
13
  import Tabs from '@y14e/tabs';
14
14
 
15
15
  // CDNs
16
- import Tabs from 'https://esm.sh/@y14e/tabs@2.0.6';
16
+ import Tabs from 'https://esm.sh/@y14e/tabs@2.0.8';
17
17
  // or
18
- import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs@2.0.6/+esm';
18
+ import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs@2.0.8/+esm';
19
19
  // or
20
- import Tabs from 'https://esm.unpkg.com/@y14e/tabs@2.0.6';
20
+ import Tabs from 'https://esm.unpkg.com/@y14e/tabs@2.0.8';
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -24,8 +24,8 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
24
24
  }
25
25
  }
26
26
  var snapshots = /* @__PURE__ */ new WeakMap();
27
- function restoreAttributes(elements) {
28
- for (const element of elements) {
27
+ function restoreAttributes(element_or_elements) {
28
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
29
29
  const snapshot = snapshots.get(element);
30
30
  if (!snapshot) {
31
31
  continue;
@@ -36,8 +36,9 @@ function restoreAttributes(elements) {
36
36
  snapshots.delete(element);
37
37
  }
38
38
  }
39
- function saveAttributes(elements, attributes) {
40
- elements.forEach((element) => {
39
+ function saveAttributes(element_or_elements, attribute_or_attributes) {
40
+ const attributes = Array.isArray(attribute_or_attributes) ? attribute_or_attributes : [attribute_or_attributes];
41
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
41
42
  let snapshot = snapshots.get(element);
42
43
  if (!snapshot) {
43
44
  snapshot = /* @__PURE__ */ new Map();
@@ -51,6 +52,10 @@ function saveAttributes(elements, attributes) {
51
52
 
52
53
  // node_modules/power-focusable/dist/index.js
53
54
  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"])`;
55
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
56
+ /(,\s*)?\[tabindex="-1"\]/g,
57
+ ""
58
+ );
54
59
  function getFocusables(container = document.body, options = {}) {
55
60
  if (!(container instanceof Element)) {
56
61
  console.warn("Invalid container element. Fallback: <body> element.");
@@ -87,36 +92,43 @@ function getFocusables(container = document.body, options = {}) {
87
92
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
88
93
  skipVisibilityCheck = false;
89
94
  }
90
- const elements = [];
95
+ const candidates = [];
91
96
  if (composed || include) {
92
97
  let traverse2 = function(node) {
93
- if (!(node instanceof Element)) {
94
- return;
95
- }
96
- if (isFocusable(node, { skipNegativeTabIndexCheck, skipVisibilityCheck }) || include?.(node)) {
97
- elements[elements.length] = node;
98
+ if (isFocusable(node, {
99
+ skipNegativeTabIndexCheck,
100
+ skipVisibilityCheck
101
+ }) || include?.(node)) {
102
+ candidates[candidates.length] = node;
98
103
  }
99
- const children = getComposedChildren(node);
100
- for (let i = 0, l = children.length; i < l; i++) {
101
- const child = children[i];
104
+ const children2 = composed ? getComposedChildren(node) : getChildren(node);
105
+ for (let i = 0, l = children2.length; i < l; i++) {
106
+ const child = children2[i];
102
107
  child && traverse2(child);
103
108
  }
104
109
  };
105
- traverse2(container);
110
+ const children = composed ? getComposedChildren(container) : getChildren(container);
111
+ for (let i = 0, l = children.length; i < l; i++) {
112
+ const child = children[i];
113
+ child && traverse2(child);
114
+ }
106
115
  } else {
107
- const candidates = container.querySelectorAll(FOCUSABLE_SELECTOR);
108
- for (let i = 0, l = candidates.length; i < l; i++) {
109
- const candidate = candidates[i];
110
- if (candidate && isFocusable(candidate, {
116
+ const matches = container.querySelectorAll(
117
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
118
+ );
119
+ for (let i = 0, l = matches.length; i < l; i++) {
120
+ const matched = matches[i];
121
+ if (matched && isFocusable(matched, {
111
122
  skipNegativeTabIndexCheck,
112
123
  skipVisibilityCheck
113
124
  })) {
114
- elements[elements.length] = candidate;
125
+ candidates[candidates.length] = matched;
115
126
  }
116
127
  }
117
128
  }
118
- const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
119
- return filter ? unfiltered.filter(filter) : unfiltered;
129
+ return normalizeRadioGroup(
130
+ sortByTabIndex(filter ? candidates.filter(filter) : candidates)
131
+ );
120
132
  }
121
133
  function isFocusable(element, options = {}) {
122
134
  if (!(element instanceof Element)) {
@@ -139,7 +151,7 @@ function isFocusable(element, options = {}) {
139
151
  return false;
140
152
  }
141
153
  if (!element.matches(
142
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
154
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
143
155
  )) {
144
156
  return false;
145
157
  }
@@ -197,22 +209,42 @@ function normalizeRadioGroup(elements) {
197
209
  if (!map) {
198
210
  map = /* @__PURE__ */ new Map();
199
211
  }
200
- const key = `${element.form?.id ?? "no-form"}::${element.name}`;
201
- const group = map.get(key) ?? map.set(key, []).get(key);
202
- if (group) {
203
- group[group.length] = element;
212
+ const root = element.getRootNode();
213
+ let value = map.get(root);
214
+ if (!value) {
215
+ value = /* @__PURE__ */ new Map();
216
+ map.set(root, value);
217
+ }
218
+ let v = value.get(element.form);
219
+ if (!v) {
220
+ v = /* @__PURE__ */ new Map();
221
+ value.set(element.form, v);
204
222
  }
223
+ let vv = v.get(element.name);
224
+ if (!vv) {
225
+ vv = [];
226
+ v.set(element.name, vv);
227
+ }
228
+ vv[vv.length] = element;
205
229
  }
206
230
  if (!map) {
207
231
  return elements;
208
232
  }
209
233
  const placeholder = /* @__PURE__ */ new Set();
210
- for (const group of map.values()) {
211
- placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
234
+ for (const value of map.values()) {
235
+ for (const v of value.values()) {
236
+ for (const vv of v.values()) {
237
+ const radio = vv.find((element) => element.checked) ?? vv[0];
238
+ radio && placeholder.add(radio);
239
+ }
240
+ }
212
241
  }
213
- return elements.filter(
214
- (element) => isUngroupedRadio(element) ? placeholder.has(element) : true
215
- );
242
+ return elements.filter((element) => {
243
+ if (!(element instanceof HTMLInputElement)) {
244
+ return true;
245
+ }
246
+ return !isUngroupedRadio(element) || placeholder.has(element);
247
+ });
216
248
  }
217
249
  function sortByTabIndex(elements) {
218
250
  const ordered = [];
@@ -284,7 +316,7 @@ function isInert(element) {
284
316
  return "inert" in element && !!element.inert;
285
317
  }
286
318
  function isUngroupedRadio(element) {
287
- return element instanceof HTMLInputElement && element.type === "radio" && !!element.name;
319
+ return element.type === "radio" && !!element.name;
288
320
  }
289
321
 
290
322
  // node_modules/@y14e/button/dist/index.js
@@ -343,14 +375,8 @@ function createRovingTabIndex(container, options = {}) {
343
375
  return () => {
344
376
  };
345
377
  }
346
- try {
347
- const roving = new RovingTabIndex(container, options);
348
- return () => roving.destroy();
349
- } catch (error) {
350
- error instanceof Error && console.warn(error.message || error);
351
- return () => {
352
- };
353
- }
378
+ const roving = new RovingTabIndex(container, options);
379
+ return () => roving.destroy();
354
380
  }
355
381
  var RovingTabIndex = class _RovingTabIndex {
356
382
  static #initialized = /* @__PURE__ */ new Set();
@@ -364,17 +390,17 @@ var RovingTabIndex = class _RovingTabIndex {
364
390
  constructor(container, options = {}) {
365
391
  this.#container = container;
366
392
  let {
367
- direction,
393
+ direction = "both",
368
394
  navigationOnly = false,
369
395
  noMemory = false,
370
396
  noStart = false,
371
- selector,
397
+ selector = "",
372
398
  typeahead = false,
373
399
  wrap = false
374
400
  } = options;
375
- if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
376
- console.warn("Invalid direction option. Fallback: both (undefined).");
377
- direction = void 0;
401
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
402
+ console.warn("Invalid direction option. Fallback: 'both'.");
403
+ direction = "both";
378
404
  }
379
405
  if (typeof navigationOnly !== "boolean") {
380
406
  console.warn("Invalid navigationOnly option. Fallback: false.");
@@ -388,11 +414,18 @@ var RovingTabIndex = class _RovingTabIndex {
388
414
  console.warn("Invalid noStart option. Fallback: false.");
389
415
  noStart = false;
390
416
  }
391
- if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
392
- console.warn(
393
- "Invalid selector. Fallback: all focusable elements (undefined)."
394
- );
395
- selector = void 0;
417
+ if (selector !== "") {
418
+ if (typeof selector !== "string" || !selector.trim()) {
419
+ console.warn("Invalid selector. Fallback: no selector string.");
420
+ selector = "";
421
+ } else {
422
+ try {
423
+ container.querySelector(selector);
424
+ } catch {
425
+ console.warn("Invalid selector. Fallback: no selector string.");
426
+ selector = "";
427
+ }
428
+ }
396
429
  }
397
430
  if (typeof typeahead !== "boolean") {
398
431
  console.warn("Invalid typeahead option. Fallback: false.");
@@ -402,9 +435,15 @@ var RovingTabIndex = class _RovingTabIndex {
402
435
  console.warn("Invalid wrap option. Fallback: false.");
403
436
  wrap = false;
404
437
  }
405
- this.#settings = { navigationOnly, noMemory, noStart, typeahead, wrap };
406
- direction && Object.assign(this.#settings, { direction });
407
- selector && Object.assign(this.#settings, { selector });
438
+ this.#settings = {
439
+ direction,
440
+ navigationOnly,
441
+ noMemory,
442
+ noStart,
443
+ selector,
444
+ typeahead,
445
+ wrap
446
+ };
408
447
  this.#selectorFilter = this.#createSelectorFilter();
409
448
  this.#initialize();
410
449
  }
@@ -415,7 +454,10 @@ var RovingTabIndex = class _RovingTabIndex {
415
454
  this.#isDestroyed = true;
416
455
  this.#controller?.abort();
417
456
  this.#controller = null;
418
- restoreAttributes([...this.#focusables]);
457
+ this.#focusables.forEach((focusable) => {
458
+ _RovingTabIndex.#initialized.delete(focusable);
459
+ restoreAttributes(focusable);
460
+ });
419
461
  this.#focusables.clear();
420
462
  this.#focusablesByFirstChar.clear();
421
463
  }
@@ -452,7 +494,7 @@ var RovingTabIndex = class _RovingTabIndex {
452
494
  return;
453
495
  }
454
496
  const { direction, typeahead, wrap } = this.#settings;
455
- const isBoth = !direction;
497
+ const isBoth = direction === "both";
456
498
  const isHorizontal = direction === "horizontal";
457
499
  if (![
458
500
  "End",
@@ -468,14 +510,16 @@ var RovingTabIndex = class _RovingTabIndex {
468
510
  if (!(active instanceof Element)) {
469
511
  return;
470
512
  }
471
- const current = this.#getFocusables();
472
- if (!current.includes(active)) {
513
+ const candidates = this.#getFocusables().filter(
514
+ (focusable2) => this.#focusables.has(focusable2)
515
+ );
516
+ if (!candidates.includes(active)) {
473
517
  return;
474
518
  }
475
519
  event.preventDefault();
476
- const currentIndex = current.indexOf(active);
520
+ const activeIndex = candidates.indexOf(active);
477
521
  let newIndex;
478
- let target = current;
522
+ let target = candidates;
479
523
  switch (key) {
480
524
  case "End":
481
525
  newIndex = -1;
@@ -485,22 +529,26 @@ var RovingTabIndex = class _RovingTabIndex {
485
529
  break;
486
530
  case "ArrowLeft":
487
531
  case "ArrowUp": {
488
- const rawIndex = currentIndex - 1;
532
+ const rawIndex = activeIndex - 1;
489
533
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
490
534
  break;
491
535
  }
492
536
  case "ArrowRight":
493
537
  case "ArrowDown": {
494
- const rawIndex = currentIndex + 1;
495
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
538
+ const rawIndex = activeIndex + 1;
539
+ const length = target.length;
540
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
496
541
  break;
497
542
  }
498
543
  default: {
499
- target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
500
- const foundIndex = target.findIndex(
501
- (focusable2) => current.indexOf(focusable2) > currentIndex
544
+ const focusables = new Set(
545
+ this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
502
546
  );
503
- newIndex = foundIndex >= 0 ? foundIndex : 0;
547
+ target = candidates.filter((focusable2) => focusables.has(focusable2));
548
+ const afterIndex = target.findIndex(
549
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
550
+ );
551
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
504
552
  }
505
553
  }
506
554
  const focusable = target.at(newIndex);
@@ -510,12 +558,16 @@ var RovingTabIndex = class _RovingTabIndex {
510
558
  const current = new Set(this.#getFocusables());
511
559
  for (const focusable of this.#focusables) {
512
560
  if (!current.has(focusable)) {
513
- focusable.isConnected && restoreAttributes([focusable]);
561
+ _RovingTabIndex.#initialized.delete(focusable);
562
+ restoreAttributes(focusable);
514
563
  this.#focusables.delete(focusable);
515
- this.#focusablesByFirstChar.forEach((focusables) => {
564
+ for (const [key, focusables] of this.#focusablesByFirstChar) {
516
565
  const index = focusables.indexOf(focusable);
517
- index >= 0 && focusables.splice(index, 1);
518
- });
566
+ if (index >= 0) {
567
+ focusables.splice(index, 1);
568
+ !focusables.length && this.#focusablesByFirstChar.delete(key);
569
+ }
570
+ }
519
571
  }
520
572
  }
521
573
  const { navigationOnly, noStart, typeahead } = this.#settings;
@@ -524,12 +576,12 @@ var RovingTabIndex = class _RovingTabIndex {
524
576
  continue;
525
577
  }
526
578
  if (_RovingTabIndex.#initialized.has(focusable)) {
527
- throw new TypeError("Already initialized");
579
+ continue;
528
580
  }
529
581
  this.#focusables.add(focusable);
530
582
  _RovingTabIndex.#initialized.add(focusable);
531
583
  if (!navigationOnly) {
532
- saveAttributes([focusable], ["tabindex"]);
584
+ saveAttributes(focusable, "tabindex");
533
585
  focusable.setAttribute("tabindex", "-1");
534
586
  }
535
587
  if (!typeahead) {
@@ -542,7 +594,7 @@ var RovingTabIndex = class _RovingTabIndex {
542
594
  );
543
595
  if (char) {
544
596
  keys.add(char);
545
- saveAttributes([focusable], ["aria-keyshortcuts"]);
597
+ saveAttributes(focusable, "aria-keyshortcuts");
546
598
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
547
599
  caseInsensitive: true
548
600
  });
@@ -719,7 +771,6 @@ var Tabs = class _Tabs {
719
771
  this.#rootElement.setAttribute("data-tabs-animating", "");
720
772
  const { style } = this.#contentElement;
721
773
  style.setProperty("overflow", "clip");
722
- style.setProperty("position", "relative");
723
774
  const { crossFade, fade } = this.#settings.animation.content;
724
775
  const panel = this.#bindings.get(tab)?.panel;
725
776
  if (!panel) {
@@ -729,11 +780,8 @@ var Tabs = class _Tabs {
729
780
  const { style: style2 } = p;
730
781
  if (fade) {
731
782
  style2.setProperty("content-visibility", "visible");
732
- style2.setProperty("display", "block");
733
783
  style2.setProperty("opacity", p.hidden ? "0" : "1");
734
784
  }
735
- style2.setProperty("inline-size", "100%");
736
- style2.setProperty("position", "absolute");
737
785
  p === panel && !this.#hasFocusable(p) ? p.setAttribute("tabindex", "0") : p.removeAttribute("tabindex");
738
786
  });
739
787
  this.#panelElements.forEach((p, i) => {
@@ -860,6 +908,7 @@ var Tabs = class _Tabs {
860
908
  ...this.#indicatorElements,
861
909
  ...this.#panelElements
862
910
  ]);
911
+ this.#contentElement && restoreAttributes(this.#contentElement);
863
912
  this.#listElements.length = 0;
864
913
  this.#tabElements.length = 0;
865
914
  this.#contentElement = null;
@@ -880,12 +929,14 @@ var Tabs = class _Tabs {
880
929
  "style",
881
930
  "tabindex"
882
931
  ]);
883
- saveAttributes(this.#indicatorElements, ["style"]);
932
+ saveAttributes(this.#indicatorElements, "style");
933
+ this.#contentElement && saveAttributes(this.#contentElement, "style");
884
934
  saveAttributes(this.#panelElements, [
885
935
  "aria-controls",
886
936
  "aria-labelledby",
887
937
  "id",
888
938
  "role",
939
+ "style",
889
940
  "tabindex"
890
941
  ]);
891
942
  this.#eventController = new AbortController();
@@ -917,13 +968,20 @@ var Tabs = class _Tabs {
917
968
  });
918
969
  this.#indicatorElements.forEach((indicator) => {
919
970
  indicator.closest(this.#settings.selector.list)?.style.setProperty("position", "relative");
920
- const { style } = indicator;
921
- style.setProperty("display", "block");
922
- style.setProperty("position", "absolute");
971
+ const { style: style2 } = indicator;
972
+ style2.setProperty("display", "block");
973
+ style2.setProperty("position", "absolute");
923
974
  this.#indicators.push(new TabsIndicator(indicator, this.#settings));
924
975
  });
976
+ if (!this.#contentElement) {
977
+ return;
978
+ }
979
+ const { style } = this.#contentElement;
980
+ style.setProperty("align-items", "start");
981
+ style.setProperty("display", "grid");
925
982
  this.#panelElements.forEach((panel) => {
926
983
  panel.setAttribute("role", "tabpanel");
984
+ panel.style.setProperty("grid-area", "1 / 1");
927
985
  !panel.hasAttribute("hidden") && !this.#hasFocusable(panel) && panel.setAttribute("tabindex", "0");
928
986
  panel.addEventListener("beforematch", this.#onPanelBeforeMatch, {
929
987
  signal
@@ -961,17 +1019,11 @@ var Tabs = class _Tabs {
961
1019
  this.#isAvoidedTab(tab) && tab.blur();
962
1020
  };
963
1021
  #onContentAnimationFinish() {
964
- ["block-size", "overflow", "position"].forEach((name) => {
1022
+ ["block-size", "overflow"].forEach((name) => {
965
1023
  this.#contentElement?.style.removeProperty(name);
966
1024
  });
967
1025
  this.#panelElements.forEach((panel) => {
968
- [
969
- "content-visibility",
970
- "display",
971
- "inline-size",
972
- "opacity",
973
- "position"
974
- ].forEach((name) => {
1026
+ ["content-visibility", "opacity"].forEach((name) => {
975
1027
  panel.style.removeProperty(name);
976
1028
  });
977
1029
  });
@@ -1098,7 +1150,7 @@ var TabsIndicator = class {
1098
1150
  * Tabs
1099
1151
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
1100
1152
  *
1101
- * @version 2.0.6
1153
+ * @version 2.0.8
1102
1154
  * @author Yusuke Kamiyamane
1103
1155
  * @license MIT
1104
1156
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1110,7 +1162,7 @@ var TabsIndicator = class {
1110
1162
  (**
1111
1163
  * Attributes Utils
1112
1164
  *
1113
- * @version 1.1.3
1165
+ * @version 1.1.4
1114
1166
  * @author Yusuke Kamiyamane
1115
1167
  * @license MIT
1116
1168
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1123,7 +1175,7 @@ power-focusable/dist/index.js:
1123
1175
  * High-precision focus management utility with full composed tree support.
1124
1176
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1125
1177
  *
1126
- * @version 4.3.10
1178
+ * @version 4.3.21
1127
1179
  * @author Yusuke Kamiyamane
1128
1180
  * @license MIT
1129
1181
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1147,7 +1199,7 @@ power-focusable/dist/index.js:
1147
1199
  * Lightweight roving tabindex utility with fully focus management.
1148
1200
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1149
1201
  *
1150
- * @version 3.1.9
1202
+ * @version 3.1.18
1151
1203
  * @author Yusuke Kamiyamane
1152
1204
  * @license MIT
1153
1205
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -22,8 +22,8 @@ function addTokenToAttribute(element, attribute, token, options = {}) {
22
22
  }
23
23
  }
24
24
  var snapshots = /* @__PURE__ */ new WeakMap();
25
- function restoreAttributes(elements) {
26
- for (const element of elements) {
25
+ function restoreAttributes(element_or_elements) {
26
+ for (const element of Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]) {
27
27
  const snapshot = snapshots.get(element);
28
28
  if (!snapshot) {
29
29
  continue;
@@ -34,8 +34,9 @@ function restoreAttributes(elements) {
34
34
  snapshots.delete(element);
35
35
  }
36
36
  }
37
- function saveAttributes(elements, attributes) {
38
- elements.forEach((element) => {
37
+ function saveAttributes(element_or_elements, attribute_or_attributes) {
38
+ const attributes = Array.isArray(attribute_or_attributes) ? attribute_or_attributes : [attribute_or_attributes];
39
+ (Array.isArray(element_or_elements) ? element_or_elements : [element_or_elements]).forEach((element) => {
39
40
  let snapshot = snapshots.get(element);
40
41
  if (!snapshot) {
41
42
  snapshot = /* @__PURE__ */ new Map();
@@ -49,6 +50,10 @@ function saveAttributes(elements, attributes) {
49
50
 
50
51
  // node_modules/power-focusable/dist/index.js
51
52
  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"])`;
53
+ var FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX = FOCUSABLE_SELECTOR.replace(
54
+ /(,\s*)?\[tabindex="-1"\]/g,
55
+ ""
56
+ );
52
57
  function getFocusables(container = document.body, options = {}) {
53
58
  if (!(container instanceof Element)) {
54
59
  console.warn("Invalid container element. Fallback: <body> element.");
@@ -85,36 +90,43 @@ function getFocusables(container = document.body, options = {}) {
85
90
  console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
86
91
  skipVisibilityCheck = false;
87
92
  }
88
- const elements = [];
93
+ const candidates = [];
89
94
  if (composed || include) {
90
95
  let traverse2 = function(node) {
91
- if (!(node instanceof Element)) {
92
- return;
93
- }
94
- if (isFocusable(node, { skipNegativeTabIndexCheck, skipVisibilityCheck }) || include?.(node)) {
95
- elements[elements.length] = node;
96
+ if (isFocusable(node, {
97
+ skipNegativeTabIndexCheck,
98
+ skipVisibilityCheck
99
+ }) || include?.(node)) {
100
+ candidates[candidates.length] = node;
96
101
  }
97
- const children = getComposedChildren(node);
98
- for (let i = 0, l = children.length; i < l; i++) {
99
- const child = children[i];
102
+ const children2 = composed ? getComposedChildren(node) : getChildren(node);
103
+ for (let i = 0, l = children2.length; i < l; i++) {
104
+ const child = children2[i];
100
105
  child && traverse2(child);
101
106
  }
102
107
  };
103
- traverse2(container);
108
+ const children = composed ? getComposedChildren(container) : getChildren(container);
109
+ for (let i = 0, l = children.length; i < l; i++) {
110
+ const child = children[i];
111
+ child && traverse2(child);
112
+ }
104
113
  } else {
105
- const candidates = container.querySelectorAll(FOCUSABLE_SELECTOR);
106
- for (let i = 0, l = candidates.length; i < l; i++) {
107
- const candidate = candidates[i];
108
- if (candidate && isFocusable(candidate, {
114
+ const matches = container.querySelectorAll(
115
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
116
+ );
117
+ for (let i = 0, l = matches.length; i < l; i++) {
118
+ const matched = matches[i];
119
+ if (matched && isFocusable(matched, {
109
120
  skipNegativeTabIndexCheck,
110
121
  skipVisibilityCheck
111
122
  })) {
112
- elements[elements.length] = candidate;
123
+ candidates[candidates.length] = matched;
113
124
  }
114
125
  }
115
126
  }
116
- const unfiltered = normalizeRadioGroup(sortByTabIndex(elements));
117
- return filter ? unfiltered.filter(filter) : unfiltered;
127
+ return normalizeRadioGroup(
128
+ sortByTabIndex(filter ? candidates.filter(filter) : candidates)
129
+ );
118
130
  }
119
131
  function isFocusable(element, options = {}) {
120
132
  if (!(element instanceof Element)) {
@@ -137,7 +149,7 @@ function isFocusable(element, options = {}) {
137
149
  return false;
138
150
  }
139
151
  if (!element.matches(
140
- skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR.replace(/(,\s*)?\[tabindex="-1"\]/g, "") : FOCUSABLE_SELECTOR
152
+ skipNegativeTabIndexCheck ? FOCUSABLE_SELECTOR_WITH_NEGATIVE_TABINDEX : FOCUSABLE_SELECTOR
141
153
  )) {
142
154
  return false;
143
155
  }
@@ -195,22 +207,42 @@ function normalizeRadioGroup(elements) {
195
207
  if (!map) {
196
208
  map = /* @__PURE__ */ new Map();
197
209
  }
198
- const key = `${element.form?.id ?? "no-form"}::${element.name}`;
199
- const group = map.get(key) ?? map.set(key, []).get(key);
200
- if (group) {
201
- group[group.length] = element;
210
+ const root = element.getRootNode();
211
+ let value = map.get(root);
212
+ if (!value) {
213
+ value = /* @__PURE__ */ new Map();
214
+ map.set(root, value);
215
+ }
216
+ let v = value.get(element.form);
217
+ if (!v) {
218
+ v = /* @__PURE__ */ new Map();
219
+ value.set(element.form, v);
202
220
  }
221
+ let vv = v.get(element.name);
222
+ if (!vv) {
223
+ vv = [];
224
+ v.set(element.name, vv);
225
+ }
226
+ vv[vv.length] = element;
203
227
  }
204
228
  if (!map) {
205
229
  return elements;
206
230
  }
207
231
  const placeholder = /* @__PURE__ */ new Set();
208
- for (const group of map.values()) {
209
- placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
232
+ for (const value of map.values()) {
233
+ for (const v of value.values()) {
234
+ for (const vv of v.values()) {
235
+ const radio = vv.find((element) => element.checked) ?? vv[0];
236
+ radio && placeholder.add(radio);
237
+ }
238
+ }
210
239
  }
211
- return elements.filter(
212
- (element) => isUngroupedRadio(element) ? placeholder.has(element) : true
213
- );
240
+ return elements.filter((element) => {
241
+ if (!(element instanceof HTMLInputElement)) {
242
+ return true;
243
+ }
244
+ return !isUngroupedRadio(element) || placeholder.has(element);
245
+ });
214
246
  }
215
247
  function sortByTabIndex(elements) {
216
248
  const ordered = [];
@@ -282,7 +314,7 @@ function isInert(element) {
282
314
  return "inert" in element && !!element.inert;
283
315
  }
284
316
  function isUngroupedRadio(element) {
285
- return element instanceof HTMLInputElement && element.type === "radio" && !!element.name;
317
+ return element.type === "radio" && !!element.name;
286
318
  }
287
319
 
288
320
  // node_modules/@y14e/button/dist/index.js
@@ -341,14 +373,8 @@ function createRovingTabIndex(container, options = {}) {
341
373
  return () => {
342
374
  };
343
375
  }
344
- try {
345
- const roving = new RovingTabIndex(container, options);
346
- return () => roving.destroy();
347
- } catch (error) {
348
- error instanceof Error && console.warn(error.message || error);
349
- return () => {
350
- };
351
- }
376
+ const roving = new RovingTabIndex(container, options);
377
+ return () => roving.destroy();
352
378
  }
353
379
  var RovingTabIndex = class _RovingTabIndex {
354
380
  static #initialized = /* @__PURE__ */ new Set();
@@ -362,17 +388,17 @@ var RovingTabIndex = class _RovingTabIndex {
362
388
  constructor(container, options = {}) {
363
389
  this.#container = container;
364
390
  let {
365
- direction,
391
+ direction = "both",
366
392
  navigationOnly = false,
367
393
  noMemory = false,
368
394
  noStart = false,
369
- selector,
395
+ selector = "",
370
396
  typeahead = false,
371
397
  wrap = false
372
398
  } = options;
373
- if (typeof direction !== "undefined" && !["horizontal", "vertical"].includes(direction)) {
374
- console.warn("Invalid direction option. Fallback: both (undefined).");
375
- direction = void 0;
399
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
400
+ console.warn("Invalid direction option. Fallback: 'both'.");
401
+ direction = "both";
376
402
  }
377
403
  if (typeof navigationOnly !== "boolean") {
378
404
  console.warn("Invalid navigationOnly option. Fallback: false.");
@@ -386,11 +412,18 @@ var RovingTabIndex = class _RovingTabIndex {
386
412
  console.warn("Invalid noStart option. Fallback: false.");
387
413
  noStart = false;
388
414
  }
389
- if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
390
- console.warn(
391
- "Invalid selector. Fallback: all focusable elements (undefined)."
392
- );
393
- selector = void 0;
415
+ if (selector !== "") {
416
+ if (typeof selector !== "string" || !selector.trim()) {
417
+ console.warn("Invalid selector. Fallback: no selector string.");
418
+ selector = "";
419
+ } else {
420
+ try {
421
+ container.querySelector(selector);
422
+ } catch {
423
+ console.warn("Invalid selector. Fallback: no selector string.");
424
+ selector = "";
425
+ }
426
+ }
394
427
  }
395
428
  if (typeof typeahead !== "boolean") {
396
429
  console.warn("Invalid typeahead option. Fallback: false.");
@@ -400,9 +433,15 @@ var RovingTabIndex = class _RovingTabIndex {
400
433
  console.warn("Invalid wrap option. Fallback: false.");
401
434
  wrap = false;
402
435
  }
403
- this.#settings = { navigationOnly, noMemory, noStart, typeahead, wrap };
404
- direction && Object.assign(this.#settings, { direction });
405
- selector && Object.assign(this.#settings, { selector });
436
+ this.#settings = {
437
+ direction,
438
+ navigationOnly,
439
+ noMemory,
440
+ noStart,
441
+ selector,
442
+ typeahead,
443
+ wrap
444
+ };
406
445
  this.#selectorFilter = this.#createSelectorFilter();
407
446
  this.#initialize();
408
447
  }
@@ -413,7 +452,10 @@ var RovingTabIndex = class _RovingTabIndex {
413
452
  this.#isDestroyed = true;
414
453
  this.#controller?.abort();
415
454
  this.#controller = null;
416
- restoreAttributes([...this.#focusables]);
455
+ this.#focusables.forEach((focusable) => {
456
+ _RovingTabIndex.#initialized.delete(focusable);
457
+ restoreAttributes(focusable);
458
+ });
417
459
  this.#focusables.clear();
418
460
  this.#focusablesByFirstChar.clear();
419
461
  }
@@ -450,7 +492,7 @@ var RovingTabIndex = class _RovingTabIndex {
450
492
  return;
451
493
  }
452
494
  const { direction, typeahead, wrap } = this.#settings;
453
- const isBoth = !direction;
495
+ const isBoth = direction === "both";
454
496
  const isHorizontal = direction === "horizontal";
455
497
  if (![
456
498
  "End",
@@ -466,14 +508,16 @@ var RovingTabIndex = class _RovingTabIndex {
466
508
  if (!(active instanceof Element)) {
467
509
  return;
468
510
  }
469
- const current = this.#getFocusables();
470
- if (!current.includes(active)) {
511
+ const candidates = this.#getFocusables().filter(
512
+ (focusable2) => this.#focusables.has(focusable2)
513
+ );
514
+ if (!candidates.includes(active)) {
471
515
  return;
472
516
  }
473
517
  event.preventDefault();
474
- const currentIndex = current.indexOf(active);
518
+ const activeIndex = candidates.indexOf(active);
475
519
  let newIndex;
476
- let target = current;
520
+ let target = candidates;
477
521
  switch (key) {
478
522
  case "End":
479
523
  newIndex = -1;
@@ -483,22 +527,26 @@ var RovingTabIndex = class _RovingTabIndex {
483
527
  break;
484
528
  case "ArrowLeft":
485
529
  case "ArrowUp": {
486
- const rawIndex = currentIndex - 1;
530
+ const rawIndex = activeIndex - 1;
487
531
  newIndex = wrap ? rawIndex : Math.max(rawIndex, 0);
488
532
  break;
489
533
  }
490
534
  case "ArrowRight":
491
535
  case "ArrowDown": {
492
- const rawIndex = currentIndex + 1;
493
- newIndex = wrap ? rawIndex % current.length : Math.min(rawIndex, current.length - 1);
536
+ const rawIndex = activeIndex + 1;
537
+ const length = target.length;
538
+ newIndex = wrap ? rawIndex % length : Math.min(rawIndex, length - 1);
494
539
  break;
495
540
  }
496
541
  default: {
497
- target = this.#focusablesByFirstChar.get(key.toUpperCase()) ?? [];
498
- const foundIndex = target.findIndex(
499
- (focusable2) => current.indexOf(focusable2) > currentIndex
542
+ const focusables = new Set(
543
+ this.#focusablesByFirstChar.get(key.toUpperCase()) ?? []
500
544
  );
501
- newIndex = foundIndex >= 0 ? foundIndex : 0;
545
+ target = candidates.filter((focusable2) => focusables.has(focusable2));
546
+ const afterIndex = target.findIndex(
547
+ (focusable2) => candidates.indexOf(focusable2) > activeIndex
548
+ );
549
+ newIndex = afterIndex >= 0 ? afterIndex : 0;
502
550
  }
503
551
  }
504
552
  const focusable = target.at(newIndex);
@@ -508,12 +556,16 @@ var RovingTabIndex = class _RovingTabIndex {
508
556
  const current = new Set(this.#getFocusables());
509
557
  for (const focusable of this.#focusables) {
510
558
  if (!current.has(focusable)) {
511
- focusable.isConnected && restoreAttributes([focusable]);
559
+ _RovingTabIndex.#initialized.delete(focusable);
560
+ restoreAttributes(focusable);
512
561
  this.#focusables.delete(focusable);
513
- this.#focusablesByFirstChar.forEach((focusables) => {
562
+ for (const [key, focusables] of this.#focusablesByFirstChar) {
514
563
  const index = focusables.indexOf(focusable);
515
- index >= 0 && focusables.splice(index, 1);
516
- });
564
+ if (index >= 0) {
565
+ focusables.splice(index, 1);
566
+ !focusables.length && this.#focusablesByFirstChar.delete(key);
567
+ }
568
+ }
517
569
  }
518
570
  }
519
571
  const { navigationOnly, noStart, typeahead } = this.#settings;
@@ -522,12 +574,12 @@ var RovingTabIndex = class _RovingTabIndex {
522
574
  continue;
523
575
  }
524
576
  if (_RovingTabIndex.#initialized.has(focusable)) {
525
- throw new TypeError("Already initialized");
577
+ continue;
526
578
  }
527
579
  this.#focusables.add(focusable);
528
580
  _RovingTabIndex.#initialized.add(focusable);
529
581
  if (!navigationOnly) {
530
- saveAttributes([focusable], ["tabindex"]);
582
+ saveAttributes(focusable, "tabindex");
531
583
  focusable.setAttribute("tabindex", "-1");
532
584
  }
533
585
  if (!typeahead) {
@@ -540,7 +592,7 @@ var RovingTabIndex = class _RovingTabIndex {
540
592
  );
541
593
  if (char) {
542
594
  keys.add(char);
543
- saveAttributes([focusable], ["aria-keyshortcuts"]);
595
+ saveAttributes(focusable, "aria-keyshortcuts");
544
596
  addTokenToAttribute(focusable, "aria-keyshortcuts", char, {
545
597
  caseInsensitive: true
546
598
  });
@@ -717,7 +769,6 @@ var Tabs = class _Tabs {
717
769
  this.#rootElement.setAttribute("data-tabs-animating", "");
718
770
  const { style } = this.#contentElement;
719
771
  style.setProperty("overflow", "clip");
720
- style.setProperty("position", "relative");
721
772
  const { crossFade, fade } = this.#settings.animation.content;
722
773
  const panel = this.#bindings.get(tab)?.panel;
723
774
  if (!panel) {
@@ -727,11 +778,8 @@ var Tabs = class _Tabs {
727
778
  const { style: style2 } = p;
728
779
  if (fade) {
729
780
  style2.setProperty("content-visibility", "visible");
730
- style2.setProperty("display", "block");
731
781
  style2.setProperty("opacity", p.hidden ? "0" : "1");
732
782
  }
733
- style2.setProperty("inline-size", "100%");
734
- style2.setProperty("position", "absolute");
735
783
  p === panel && !this.#hasFocusable(p) ? p.setAttribute("tabindex", "0") : p.removeAttribute("tabindex");
736
784
  });
737
785
  this.#panelElements.forEach((p, i) => {
@@ -858,6 +906,7 @@ var Tabs = class _Tabs {
858
906
  ...this.#indicatorElements,
859
907
  ...this.#panelElements
860
908
  ]);
909
+ this.#contentElement && restoreAttributes(this.#contentElement);
861
910
  this.#listElements.length = 0;
862
911
  this.#tabElements.length = 0;
863
912
  this.#contentElement = null;
@@ -878,12 +927,14 @@ var Tabs = class _Tabs {
878
927
  "style",
879
928
  "tabindex"
880
929
  ]);
881
- saveAttributes(this.#indicatorElements, ["style"]);
930
+ saveAttributes(this.#indicatorElements, "style");
931
+ this.#contentElement && saveAttributes(this.#contentElement, "style");
882
932
  saveAttributes(this.#panelElements, [
883
933
  "aria-controls",
884
934
  "aria-labelledby",
885
935
  "id",
886
936
  "role",
937
+ "style",
887
938
  "tabindex"
888
939
  ]);
889
940
  this.#eventController = new AbortController();
@@ -915,13 +966,20 @@ var Tabs = class _Tabs {
915
966
  });
916
967
  this.#indicatorElements.forEach((indicator) => {
917
968
  indicator.closest(this.#settings.selector.list)?.style.setProperty("position", "relative");
918
- const { style } = indicator;
919
- style.setProperty("display", "block");
920
- style.setProperty("position", "absolute");
969
+ const { style: style2 } = indicator;
970
+ style2.setProperty("display", "block");
971
+ style2.setProperty("position", "absolute");
921
972
  this.#indicators.push(new TabsIndicator(indicator, this.#settings));
922
973
  });
974
+ if (!this.#contentElement) {
975
+ return;
976
+ }
977
+ const { style } = this.#contentElement;
978
+ style.setProperty("align-items", "start");
979
+ style.setProperty("display", "grid");
923
980
  this.#panelElements.forEach((panel) => {
924
981
  panel.setAttribute("role", "tabpanel");
982
+ panel.style.setProperty("grid-area", "1 / 1");
925
983
  !panel.hasAttribute("hidden") && !this.#hasFocusable(panel) && panel.setAttribute("tabindex", "0");
926
984
  panel.addEventListener("beforematch", this.#onPanelBeforeMatch, {
927
985
  signal
@@ -959,17 +1017,11 @@ var Tabs = class _Tabs {
959
1017
  this.#isAvoidedTab(tab) && tab.blur();
960
1018
  };
961
1019
  #onContentAnimationFinish() {
962
- ["block-size", "overflow", "position"].forEach((name) => {
1020
+ ["block-size", "overflow"].forEach((name) => {
963
1021
  this.#contentElement?.style.removeProperty(name);
964
1022
  });
965
1023
  this.#panelElements.forEach((panel) => {
966
- [
967
- "content-visibility",
968
- "display",
969
- "inline-size",
970
- "opacity",
971
- "position"
972
- ].forEach((name) => {
1024
+ ["content-visibility", "opacity"].forEach((name) => {
973
1025
  panel.style.removeProperty(name);
974
1026
  });
975
1027
  });
@@ -1096,7 +1148,7 @@ var TabsIndicator = class {
1096
1148
  * Tabs
1097
1149
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
1098
1150
  *
1099
- * @version 2.0.6
1151
+ * @version 2.0.8
1100
1152
  * @author Yusuke Kamiyamane
1101
1153
  * @license MIT
1102
1154
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1108,7 +1160,7 @@ var TabsIndicator = class {
1108
1160
  (**
1109
1161
  * Attributes Utils
1110
1162
  *
1111
- * @version 1.1.3
1163
+ * @version 1.1.4
1112
1164
  * @author Yusuke Kamiyamane
1113
1165
  * @license MIT
1114
1166
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1121,7 +1173,7 @@ power-focusable/dist/index.js:
1121
1173
  * High-precision focus management utility with full composed tree support.
1122
1174
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1123
1175
  *
1124
- * @version 4.3.10
1176
+ * @version 4.3.21
1125
1177
  * @author Yusuke Kamiyamane
1126
1178
  * @license MIT
1127
1179
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1145,7 +1197,7 @@ power-focusable/dist/index.js:
1145
1197
  * Lightweight roving tabindex utility with fully focus management.
1146
1198
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1147
1199
  *
1148
- * @version 3.1.9
1200
+ * @version 3.1.18
1149
1201
  * @author Yusuke Kamiyamane
1150
1202
  * @license MIT
1151
1203
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -148,7 +148,6 @@ var Tabs = class _Tabs {
148
148
  this.#rootElement.setAttribute("data-tabs-animating", "");
149
149
  const { style } = this.#contentElement;
150
150
  style.setProperty("overflow", "clip");
151
- style.setProperty("position", "relative");
152
151
  const { crossFade, fade } = this.#settings.animation.content;
153
152
  const panel = this.#bindings.get(tab)?.panel;
154
153
  if (!panel) {
@@ -158,11 +157,8 @@ var Tabs = class _Tabs {
158
157
  const { style: style2 } = p;
159
158
  if (fade) {
160
159
  style2.setProperty("content-visibility", "visible");
161
- style2.setProperty("display", "block");
162
160
  style2.setProperty("opacity", p.hidden ? "0" : "1");
163
161
  }
164
- style2.setProperty("inline-size", "100%");
165
- style2.setProperty("position", "absolute");
166
162
  p === panel && !this.#hasFocusable(p) ? p.setAttribute("tabindex", "0") : p.removeAttribute("tabindex");
167
163
  });
168
164
  this.#panelElements.forEach((p, i) => {
@@ -289,6 +285,7 @@ var Tabs = class _Tabs {
289
285
  ...this.#indicatorElements,
290
286
  ...this.#panelElements
291
287
  ]);
288
+ this.#contentElement && attributesUtils.restoreAttributes(this.#contentElement);
292
289
  this.#listElements.length = 0;
293
290
  this.#tabElements.length = 0;
294
291
  this.#contentElement = null;
@@ -309,12 +306,14 @@ var Tabs = class _Tabs {
309
306
  "style",
310
307
  "tabindex"
311
308
  ]);
312
- attributesUtils.saveAttributes(this.#indicatorElements, ["style"]);
309
+ attributesUtils.saveAttributes(this.#indicatorElements, "style");
310
+ this.#contentElement && attributesUtils.saveAttributes(this.#contentElement, "style");
313
311
  attributesUtils.saveAttributes(this.#panelElements, [
314
312
  "aria-controls",
315
313
  "aria-labelledby",
316
314
  "id",
317
315
  "role",
316
+ "style",
318
317
  "tabindex"
319
318
  ]);
320
319
  this.#eventController = new AbortController();
@@ -346,13 +345,20 @@ var Tabs = class _Tabs {
346
345
  });
347
346
  this.#indicatorElements.forEach((indicator) => {
348
347
  indicator.closest(this.#settings.selector.list)?.style.setProperty("position", "relative");
349
- const { style } = indicator;
350
- style.setProperty("display", "block");
351
- style.setProperty("position", "absolute");
348
+ const { style: style2 } = indicator;
349
+ style2.setProperty("display", "block");
350
+ style2.setProperty("position", "absolute");
352
351
  this.#indicators.push(new TabsIndicator(indicator, this.#settings));
353
352
  });
353
+ if (!this.#contentElement) {
354
+ return;
355
+ }
356
+ const { style } = this.#contentElement;
357
+ style.setProperty("align-items", "start");
358
+ style.setProperty("display", "grid");
354
359
  this.#panelElements.forEach((panel) => {
355
360
  panel.setAttribute("role", "tabpanel");
361
+ panel.style.setProperty("grid-area", "1 / 1");
356
362
  !panel.hasAttribute("hidden") && !this.#hasFocusable(panel) && panel.setAttribute("tabindex", "0");
357
363
  panel.addEventListener("beforematch", this.#onPanelBeforeMatch, {
358
364
  signal
@@ -390,17 +396,11 @@ var Tabs = class _Tabs {
390
396
  this.#isAvoidedTab(tab) && tab.blur();
391
397
  };
392
398
  #onContentAnimationFinish() {
393
- ["block-size", "overflow", "position"].forEach((name) => {
399
+ ["block-size", "overflow"].forEach((name) => {
394
400
  this.#contentElement?.style.removeProperty(name);
395
401
  });
396
402
  this.#panelElements.forEach((panel) => {
397
- [
398
- "content-visibility",
399
- "display",
400
- "inline-size",
401
- "opacity",
402
- "position"
403
- ].forEach((name) => {
403
+ ["content-visibility", "opacity"].forEach((name) => {
404
404
  panel.style.removeProperty(name);
405
405
  });
406
406
  });
@@ -527,7 +527,7 @@ var TabsIndicator = class {
527
527
  * Tabs
528
528
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
529
529
  *
530
- * @version 2.0.6
530
+ * @version 2.0.8
531
531
  * @author Yusuke Kamiyamane
532
532
  * @license MIT
533
533
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Tabs
3
3
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.6
5
+ * @version 2.0.8
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Tabs
3
3
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.6
5
+ * @version 2.0.8
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -142,7 +142,6 @@ var Tabs = class _Tabs {
142
142
  this.#rootElement.setAttribute("data-tabs-animating", "");
143
143
  const { style } = this.#contentElement;
144
144
  style.setProperty("overflow", "clip");
145
- style.setProperty("position", "relative");
146
145
  const { crossFade, fade } = this.#settings.animation.content;
147
146
  const panel = this.#bindings.get(tab)?.panel;
148
147
  if (!panel) {
@@ -152,11 +151,8 @@ var Tabs = class _Tabs {
152
151
  const { style: style2 } = p;
153
152
  if (fade) {
154
153
  style2.setProperty("content-visibility", "visible");
155
- style2.setProperty("display", "block");
156
154
  style2.setProperty("opacity", p.hidden ? "0" : "1");
157
155
  }
158
- style2.setProperty("inline-size", "100%");
159
- style2.setProperty("position", "absolute");
160
156
  p === panel && !this.#hasFocusable(p) ? p.setAttribute("tabindex", "0") : p.removeAttribute("tabindex");
161
157
  });
162
158
  this.#panelElements.forEach((p, i) => {
@@ -283,6 +279,7 @@ var Tabs = class _Tabs {
283
279
  ...this.#indicatorElements,
284
280
  ...this.#panelElements
285
281
  ]);
282
+ this.#contentElement && restoreAttributes(this.#contentElement);
286
283
  this.#listElements.length = 0;
287
284
  this.#tabElements.length = 0;
288
285
  this.#contentElement = null;
@@ -303,12 +300,14 @@ var Tabs = class _Tabs {
303
300
  "style",
304
301
  "tabindex"
305
302
  ]);
306
- saveAttributes(this.#indicatorElements, ["style"]);
303
+ saveAttributes(this.#indicatorElements, "style");
304
+ this.#contentElement && saveAttributes(this.#contentElement, "style");
307
305
  saveAttributes(this.#panelElements, [
308
306
  "aria-controls",
309
307
  "aria-labelledby",
310
308
  "id",
311
309
  "role",
310
+ "style",
312
311
  "tabindex"
313
312
  ]);
314
313
  this.#eventController = new AbortController();
@@ -340,13 +339,20 @@ var Tabs = class _Tabs {
340
339
  });
341
340
  this.#indicatorElements.forEach((indicator) => {
342
341
  indicator.closest(this.#settings.selector.list)?.style.setProperty("position", "relative");
343
- const { style } = indicator;
344
- style.setProperty("display", "block");
345
- style.setProperty("position", "absolute");
342
+ const { style: style2 } = indicator;
343
+ style2.setProperty("display", "block");
344
+ style2.setProperty("position", "absolute");
346
345
  this.#indicators.push(new TabsIndicator(indicator, this.#settings));
347
346
  });
347
+ if (!this.#contentElement) {
348
+ return;
349
+ }
350
+ const { style } = this.#contentElement;
351
+ style.setProperty("align-items", "start");
352
+ style.setProperty("display", "grid");
348
353
  this.#panelElements.forEach((panel) => {
349
354
  panel.setAttribute("role", "tabpanel");
355
+ panel.style.setProperty("grid-area", "1 / 1");
350
356
  !panel.hasAttribute("hidden") && !this.#hasFocusable(panel) && panel.setAttribute("tabindex", "0");
351
357
  panel.addEventListener("beforematch", this.#onPanelBeforeMatch, {
352
358
  signal
@@ -384,17 +390,11 @@ var Tabs = class _Tabs {
384
390
  this.#isAvoidedTab(tab) && tab.blur();
385
391
  };
386
392
  #onContentAnimationFinish() {
387
- ["block-size", "overflow", "position"].forEach((name) => {
393
+ ["block-size", "overflow"].forEach((name) => {
388
394
  this.#contentElement?.style.removeProperty(name);
389
395
  });
390
396
  this.#panelElements.forEach((panel) => {
391
- [
392
- "content-visibility",
393
- "display",
394
- "inline-size",
395
- "opacity",
396
- "position"
397
- ].forEach((name) => {
397
+ ["content-visibility", "opacity"].forEach((name) => {
398
398
  panel.style.removeProperty(name);
399
399
  });
400
400
  });
@@ -521,7 +521,7 @@ var TabsIndicator = class {
521
521
  * Tabs
522
522
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
523
523
  *
524
- * @version 2.0.6
524
+ * @version 2.0.8
525
525
  * @author Yusuke Kamiyamane
526
526
  * @license MIT
527
527
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/tabs",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "description": "WAI-ARIA compliant tabs pattern implementation in TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -50,8 +50,8 @@
50
50
  "node": ">=18"
51
51
  },
52
52
  "dependencies": {
53
- "@y14e/attributes-utils": "^1.1.3",
53
+ "@y14e/attributes-utils": "^1.1.4",
54
54
  "@y14e/button": "^1.0.6",
55
- "@y14e/roving-tabindex": "^3.1.9"
55
+ "@y14e/roving-tabindex": "^3.1.18"
56
56
  }
57
57
  }