@y14e/tabs 1.5.2 → 1.5.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 CHANGED
@@ -10,14 +10,14 @@ npm i @y14e/tabs
10
10
 
11
11
  ```ts
12
12
  // npm
13
- import Tabs from '@y14e/tabs';
13
+ import Tabs from '@y14e/tabs@1.5.4';
14
14
 
15
15
  // CDNs
16
- import Tabs from 'https://esm.sh/@y14e/tabs'
16
+ import Tabs from 'https://esm.sh/@y14e/tabs@1.5.4';
17
17
  // or
18
- import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs/+esm';
18
+ import Tabs from 'https://cdn.jsdelivr.net/npm/@y14e/tabs@1.5.4/+esm';
19
19
  // or
20
- import Tabs from 'https://unpkg.com/@y14e/tabs/dist/index.js';
20
+ import Tabs from 'https://esm.unpkg.com/@y14e/tabs@1.5.4';
21
21
  ```
22
22
 
23
23
  ## Usage
package/dist/index.cjs CHANGED
@@ -414,7 +414,7 @@ function createRovingTabIndex(container, options = {}) {
414
414
  console.warn("Invalid navigationOnly option. Fallback: false.");
415
415
  navigationOnly = false;
416
416
  }
417
- if (typeof selector !== "undefined" && typeof selector !== "string") {
417
+ if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
418
418
  console.warn(
419
419
  "Invalid selector. Fallback: all focusable elements (undefined)."
420
420
  );
@@ -428,13 +428,14 @@ function createRovingTabIndex(container, options = {}) {
428
428
  console.warn("Invalid wrap option. Fallback: false.");
429
429
  wrap = false;
430
430
  }
431
- const roving = new RovingTabIndex(container, {
432
- direction,
433
- navigationOnly,
434
- selector,
435
- typeahead,
436
- wrap
437
- });
431
+ const settings = { navigationOnly, typeahead, wrap };
432
+ if (direction) {
433
+ Object.assign(settings, { direction });
434
+ }
435
+ if (selector) {
436
+ Object.assign(settings, { selector });
437
+ }
438
+ const roving = new RovingTabIndex(container, settings);
438
439
  return () => roving.destroy();
439
440
  }
440
441
  var RovingTabIndex = class {
@@ -476,8 +477,8 @@ var RovingTabIndex = class {
476
477
  if (!event.composedPath().includes(this.#container)) {
477
478
  return;
478
479
  }
479
- const { key, altKey, ctrlKey, metaKey } = event;
480
- if (altKey || ctrlKey || metaKey) {
480
+ const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
481
+ if (altKey || ctrlKey || metaKey || shiftKey) {
481
482
  return;
482
483
  }
483
484
  const { direction, typeahead, wrap } = this.#options;
@@ -540,14 +541,7 @@ var RovingTabIndex = class {
540
541
  focusElement(focusable);
541
542
  };
542
543
  #update(active) {
543
- const current = /* @__PURE__ */ new Set([
544
- ...this.#getFocusables(),
545
- ...getFocusables(this.#container, {
546
- composed: true,
547
- filter: this.#selectorFilter,
548
- skipNegativeTabIndexCheck: !this.#options.navigationOnly
549
- })
550
- ]);
544
+ const current = new Set(this.#getFocusables());
551
545
  for (const focusable of this.#focusables) {
552
546
  if (current.has(focusable)) {
553
547
  continue;
@@ -915,19 +909,12 @@ var Tabs = class _Tabs {
915
909
  this.#rootElement.removeAttribute("data-tabs-initialized");
916
910
  }
917
911
  #initialize() {
918
- this.#eventController = new AbortController();
919
- const { signal } = this.#eventController;
920
912
  saveAttributes(this.#listElements, [
921
913
  "aria-hidden",
922
914
  "aria-orientation",
923
915
  "role",
924
916
  "style"
925
917
  ]);
926
- this.#listElements.forEach((list, i) => {
927
- this.#settings.avoidDuplicates && i && list.setAttribute("aria-hidden", "true");
928
- this.#settings.vertical && list.setAttribute("aria-orientation", "vertical");
929
- list.setAttribute("role", "tablist");
930
- });
931
918
  saveAttributes(this.#tabElements, [
932
919
  "aria-controls",
933
920
  "id",
@@ -935,16 +922,27 @@ var Tabs = class _Tabs {
935
922
  "style",
936
923
  "tabindex"
937
924
  ]);
925
+ saveAttributes(this.#indicatorElements, ["style"]);
926
+ saveAttributes(this.#panelElements, [
927
+ "aria-controls",
928
+ "aria-labelledby",
929
+ "id",
930
+ "role",
931
+ "tabindex"
932
+ ]);
933
+ this.#eventController = new AbortController();
934
+ const { signal } = this.#eventController;
935
+ this.#listElements.forEach((list, i) => {
936
+ this.#settings.avoidDuplicates && i && list.setAttribute("aria-hidden", "true");
937
+ this.#settings.vertical && list.setAttribute("aria-orientation", "vertical");
938
+ list.setAttribute("role", "tablist");
939
+ });
938
940
  this.#tabElements.forEach((tab, i) => {
939
941
  const id = Math.random().toString(36).slice(-8);
940
942
  const panel = this.#panelElements[i % this.#panelElements.length];
941
943
  if (!panel) {
942
944
  return;
943
945
  }
944
- i < this.#panelElements.length && saveAttributes(
945
- [panel],
946
- ["aria-controls", "aria-labelledby", "id", "role", "tabindex"]
947
- );
948
946
  panel.id ||= `tabs-panel-${id}`;
949
947
  addTokenToAttribute(tab, "aria-controls", panel.id);
950
948
  !tab.hasAttribute("aria-selected") && tab.setAttribute("aria-selected", "false");
@@ -959,7 +957,6 @@ var Tabs = class _Tabs {
959
957
  tab.addEventListener("focus", this.#onTabFocus, { signal });
960
958
  this.#buttons.push(new Button(tab));
961
959
  });
962
- saveAttributes(this.#indicatorElements, ["style"]);
963
960
  this.#indicatorElements.forEach((indicator) => {
964
961
  indicator.closest(this.#settings.selector.list)?.style.setProperty("position", "relative");
965
962
  const { style } = indicator;
@@ -974,14 +971,14 @@ var Tabs = class _Tabs {
974
971
  signal
975
972
  });
976
973
  });
974
+ const options = { selector: this.#settings.selector.tab, wrap: true };
977
975
  this.#listElements.forEach((list) => {
978
- this.#cleanupsRovingTabIndex.push(
979
- createRovingTabIndex(list, {
980
- direction: list.ariaOrientation === "undefined" ? void 0 : this.#settings.vertical ? "vertical" : "horizontal",
981
- selector: this.#settings.selector.tab,
982
- wrap: true
983
- })
984
- );
976
+ if (list.ariaOrientation !== "undefined") {
977
+ Object.assign(options, {
978
+ direction: this.#settings.vertical ? "vertical" : "horizontal"
979
+ });
980
+ }
981
+ this.#cleanupsRovingTabIndex.push(createRovingTabIndex(list, options));
985
982
  list.querySelectorAll(this.#settings.selector.tab).forEach((tab) => {
986
983
  tab.setAttribute(
987
984
  "tabindex",
@@ -1149,7 +1146,7 @@ function isFocusable2(element) {
1149
1146
  * Tabs
1150
1147
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
1151
1148
  *
1152
- * @version 1.5.1
1149
+ * @version 1.5.4
1153
1150
  * @author Yusuke Kamiyamane
1154
1151
  * @license MIT
1155
1152
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1161,7 +1158,7 @@ function isFocusable2(element) {
1161
1158
  (**
1162
1159
  * Attributes Utils
1163
1160
  *
1164
- * @version 1.0.5
1161
+ * @version 1.1.0
1165
1162
  * @author Yusuke Kamiyamane
1166
1163
  * @license MIT
1167
1164
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1185,7 +1182,7 @@ function isFocusable2(element) {
1185
1182
  * Lightweight roving tabindex utility with fully focus management.
1186
1183
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1187
1184
  *
1188
- * @version 2.0.0
1185
+ * @version 2.0.4
1189
1186
  * @author Yusuke Kamiyamane
1190
1187
  * @license MIT
1191
1188
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1197,7 +1194,7 @@ function isFocusable2(element) {
1197
1194
  (**
1198
1195
  * Attributes Utils
1199
1196
  *
1200
- * @version 1.0.5
1197
+ * @version 1.1.0
1201
1198
  * @author Yusuke Kamiyamane
1202
1199
  * @license MIT
1203
1200
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1210,7 +1207,7 @@ function isFocusable2(element) {
1210
1207
  * High-precision focus management utility with full composed tree support.
1211
1208
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1212
1209
  *
1213
- * @version 4.3.0
1210
+ * @version 4.3.1
1214
1211
  * @author Yusuke Kamiyamane
1215
1212
  * @license MIT
1216
1213
  * @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 1.5.1
5
+ * @version 1.5.4
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 1.5.1
5
+ * @version 1.5.4
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -412,7 +412,7 @@ function createRovingTabIndex(container, options = {}) {
412
412
  console.warn("Invalid navigationOnly option. Fallback: false.");
413
413
  navigationOnly = false;
414
414
  }
415
- if (typeof selector !== "undefined" && typeof selector !== "string") {
415
+ if (typeof selector !== "undefined" && (typeof selector !== "string" || !selector.trim())) {
416
416
  console.warn(
417
417
  "Invalid selector. Fallback: all focusable elements (undefined)."
418
418
  );
@@ -426,13 +426,14 @@ function createRovingTabIndex(container, options = {}) {
426
426
  console.warn("Invalid wrap option. Fallback: false.");
427
427
  wrap = false;
428
428
  }
429
- const roving = new RovingTabIndex(container, {
430
- direction,
431
- navigationOnly,
432
- selector,
433
- typeahead,
434
- wrap
435
- });
429
+ const settings = { navigationOnly, typeahead, wrap };
430
+ if (direction) {
431
+ Object.assign(settings, { direction });
432
+ }
433
+ if (selector) {
434
+ Object.assign(settings, { selector });
435
+ }
436
+ const roving = new RovingTabIndex(container, settings);
436
437
  return () => roving.destroy();
437
438
  }
438
439
  var RovingTabIndex = class {
@@ -474,8 +475,8 @@ var RovingTabIndex = class {
474
475
  if (!event.composedPath().includes(this.#container)) {
475
476
  return;
476
477
  }
477
- const { key, altKey, ctrlKey, metaKey } = event;
478
- if (altKey || ctrlKey || metaKey) {
478
+ const { key, altKey, ctrlKey, metaKey, shiftKey } = event;
479
+ if (altKey || ctrlKey || metaKey || shiftKey) {
479
480
  return;
480
481
  }
481
482
  const { direction, typeahead, wrap } = this.#options;
@@ -538,14 +539,7 @@ var RovingTabIndex = class {
538
539
  focusElement(focusable);
539
540
  };
540
541
  #update(active) {
541
- const current = /* @__PURE__ */ new Set([
542
- ...this.#getFocusables(),
543
- ...getFocusables(this.#container, {
544
- composed: true,
545
- filter: this.#selectorFilter,
546
- skipNegativeTabIndexCheck: !this.#options.navigationOnly
547
- })
548
- ]);
542
+ const current = new Set(this.#getFocusables());
549
543
  for (const focusable of this.#focusables) {
550
544
  if (current.has(focusable)) {
551
545
  continue;
@@ -913,19 +907,12 @@ var Tabs = class _Tabs {
913
907
  this.#rootElement.removeAttribute("data-tabs-initialized");
914
908
  }
915
909
  #initialize() {
916
- this.#eventController = new AbortController();
917
- const { signal } = this.#eventController;
918
910
  saveAttributes(this.#listElements, [
919
911
  "aria-hidden",
920
912
  "aria-orientation",
921
913
  "role",
922
914
  "style"
923
915
  ]);
924
- this.#listElements.forEach((list, i) => {
925
- this.#settings.avoidDuplicates && i && list.setAttribute("aria-hidden", "true");
926
- this.#settings.vertical && list.setAttribute("aria-orientation", "vertical");
927
- list.setAttribute("role", "tablist");
928
- });
929
916
  saveAttributes(this.#tabElements, [
930
917
  "aria-controls",
931
918
  "id",
@@ -933,16 +920,27 @@ var Tabs = class _Tabs {
933
920
  "style",
934
921
  "tabindex"
935
922
  ]);
923
+ saveAttributes(this.#indicatorElements, ["style"]);
924
+ saveAttributes(this.#panelElements, [
925
+ "aria-controls",
926
+ "aria-labelledby",
927
+ "id",
928
+ "role",
929
+ "tabindex"
930
+ ]);
931
+ this.#eventController = new AbortController();
932
+ const { signal } = this.#eventController;
933
+ this.#listElements.forEach((list, i) => {
934
+ this.#settings.avoidDuplicates && i && list.setAttribute("aria-hidden", "true");
935
+ this.#settings.vertical && list.setAttribute("aria-orientation", "vertical");
936
+ list.setAttribute("role", "tablist");
937
+ });
936
938
  this.#tabElements.forEach((tab, i) => {
937
939
  const id = Math.random().toString(36).slice(-8);
938
940
  const panel = this.#panelElements[i % this.#panelElements.length];
939
941
  if (!panel) {
940
942
  return;
941
943
  }
942
- i < this.#panelElements.length && saveAttributes(
943
- [panel],
944
- ["aria-controls", "aria-labelledby", "id", "role", "tabindex"]
945
- );
946
944
  panel.id ||= `tabs-panel-${id}`;
947
945
  addTokenToAttribute(tab, "aria-controls", panel.id);
948
946
  !tab.hasAttribute("aria-selected") && tab.setAttribute("aria-selected", "false");
@@ -957,7 +955,6 @@ var Tabs = class _Tabs {
957
955
  tab.addEventListener("focus", this.#onTabFocus, { signal });
958
956
  this.#buttons.push(new Button(tab));
959
957
  });
960
- saveAttributes(this.#indicatorElements, ["style"]);
961
958
  this.#indicatorElements.forEach((indicator) => {
962
959
  indicator.closest(this.#settings.selector.list)?.style.setProperty("position", "relative");
963
960
  const { style } = indicator;
@@ -972,14 +969,14 @@ var Tabs = class _Tabs {
972
969
  signal
973
970
  });
974
971
  });
972
+ const options = { selector: this.#settings.selector.tab, wrap: true };
975
973
  this.#listElements.forEach((list) => {
976
- this.#cleanupsRovingTabIndex.push(
977
- createRovingTabIndex(list, {
978
- direction: list.ariaOrientation === "undefined" ? void 0 : this.#settings.vertical ? "vertical" : "horizontal",
979
- selector: this.#settings.selector.tab,
980
- wrap: true
981
- })
982
- );
974
+ if (list.ariaOrientation !== "undefined") {
975
+ Object.assign(options, {
976
+ direction: this.#settings.vertical ? "vertical" : "horizontal"
977
+ });
978
+ }
979
+ this.#cleanupsRovingTabIndex.push(createRovingTabIndex(list, options));
983
980
  list.querySelectorAll(this.#settings.selector.tab).forEach((tab) => {
984
981
  tab.setAttribute(
985
982
  "tabindex",
@@ -1147,7 +1144,7 @@ function isFocusable2(element) {
1147
1144
  * Tabs
1148
1145
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
1149
1146
  *
1150
- * @version 1.5.1
1147
+ * @version 1.5.4
1151
1148
  * @author Yusuke Kamiyamane
1152
1149
  * @license MIT
1153
1150
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1159,7 +1156,7 @@ function isFocusable2(element) {
1159
1156
  (**
1160
1157
  * Attributes Utils
1161
1158
  *
1162
- * @version 1.0.5
1159
+ * @version 1.1.0
1163
1160
  * @author Yusuke Kamiyamane
1164
1161
  * @license MIT
1165
1162
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1183,7 +1180,7 @@ function isFocusable2(element) {
1183
1180
  * Lightweight roving tabindex utility with fully focus management.
1184
1181
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1185
1182
  *
1186
- * @version 2.0.0
1183
+ * @version 2.0.4
1187
1184
  * @author Yusuke Kamiyamane
1188
1185
  * @license MIT
1189
1186
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1195,7 +1192,7 @@ function isFocusable2(element) {
1195
1192
  (**
1196
1193
  * Attributes Utils
1197
1194
  *
1198
- * @version 1.0.5
1195
+ * @version 1.1.0
1199
1196
  * @author Yusuke Kamiyamane
1200
1197
  * @license MIT
1201
1198
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1208,7 +1205,7 @@ function isFocusable2(element) {
1208
1205
  * High-precision focus management utility with full composed tree support.
1209
1206
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1210
1207
  *
1211
- * @version 4.3.0
1208
+ * @version 4.3.1
1212
1209
  * @author Yusuke Kamiyamane
1213
1210
  * @license MIT
1214
1211
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/tabs",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
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.0.5",
45
+ "@y14e/attributes-utils": "^1.1.0",
46
46
  "@y14e/button": "^1.0.0",
47
- "@y14e/roving-tabindex": "^2.0.0",
47
+ "@y14e/roving-tabindex": "^2.0.4",
48
48
  "bun-types": "latest",
49
49
  "tsup": "^8.0.0",
50
50
  "typescript": "^5.6.0",