@y14e/tabs 2.0.13 → 2.0.15

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.13";
16
+ import { Tabs } from "https://esm.sh/@y14e/tabs@2.0.15";
17
17
  // or
18
- import { Tabs } from "https://cdn.jsdelivr.net/npm/@y14e/tabs@2.0.13/+esm";
18
+ import { Tabs } from "https://cdn.jsdelivr.net/npm/@y14e/tabs@2.0.15/+esm";
19
19
  // or
20
- import { Tabs } from "https://esm.unpkg.com/@y14e/tabs@2.0.13";
20
+ import { Tabs } from "https://esm.unpkg.com/@y14e/tabs@2.0.15";
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // node_modules/@y14e/attribute-util/dist/index.js
3
+ // node_modules/@y14e/attribute-utils/dist/index.js
4
4
  var DEFAULT_PARSER = (value) => value.split(/\s+/);
5
5
  var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
6
6
  function addAttributeToken(element, name, token, options = {}) {
@@ -415,17 +415,9 @@ var RovingTabIndex = class _RovingTabIndex {
415
415
  noStart = false;
416
416
  }
417
417
  if (selector !== "") {
418
- let hasError = false;
419
- if (typeof selector !== "string" || !selector.trim()) {
420
- hasError = true;
421
- } else {
422
- try {
423
- this.#container.querySelector(selector);
424
- } catch {
425
- hasError = true;
426
- }
427
- }
428
- if (hasError) {
418
+ try {
419
+ document.querySelector(selector);
420
+ } catch {
429
421
  console.warn("Invalid selector. Fallback: no selector string.");
430
422
  selector = "";
431
423
  }
@@ -1063,7 +1055,7 @@ var Tabs = class _Tabs {
1063
1055
  return !element.hasAttribute("disabled");
1064
1056
  }
1065
1057
  #mergeOptions(target, source) {
1066
- return {
1058
+ const merged = {
1067
1059
  ...target,
1068
1060
  ...source,
1069
1061
  animation: {
@@ -1081,6 +1073,117 @@ var Tabs = class _Tabs {
1081
1073
  ...source.selector ?? {}
1082
1074
  }
1083
1075
  };
1076
+ const animation = merged.animation;
1077
+ const mergedContentAnimation = animation.content;
1078
+ const defaultContentAnimation = this.#defaults.animation.content;
1079
+ if (typeof mergedContentAnimation.crossFade !== "boolean") {
1080
+ const crossFade = defaultContentAnimation.crossFade;
1081
+ console.warn(
1082
+ `Invalid content animation crossFade option. Fallback: ${crossFade}.`
1083
+ );
1084
+ mergedContentAnimation.crossFade = crossFade;
1085
+ }
1086
+ const contentDuration = mergedContentAnimation.duration;
1087
+ if (typeof contentDuration !== "number" || Number.isNaN(contentDuration)) {
1088
+ const duration = defaultContentAnimation.duration;
1089
+ console.warn(
1090
+ `Invalid content animation duration. Fallback: ${duration} (ms).`
1091
+ );
1092
+ mergedContentAnimation.duration = duration;
1093
+ }
1094
+ if (contentDuration < 0) {
1095
+ console.warn("Invalid content animation duration. Fallback: 0 (ms).");
1096
+ mergedContentAnimation.duration = 0;
1097
+ }
1098
+ if (!CSS.supports("animation-timing-function", mergedContentAnimation.easing)) {
1099
+ const easing = defaultContentAnimation.easing;
1100
+ console.warn(`Invalid content animation easing. Fallback: '${easing}'.`);
1101
+ mergedContentAnimation.easing = easing;
1102
+ }
1103
+ if (typeof mergedContentAnimation.fade !== "boolean") {
1104
+ const fade = defaultContentAnimation.fade;
1105
+ console.warn(`Invalid content animation fade option. Fallback: ${fade}.`);
1106
+ mergedContentAnimation.fade = fade;
1107
+ }
1108
+ const mergedIndicatorAnimation = animation.indicator;
1109
+ const indicatorDuration = mergedIndicatorAnimation.duration;
1110
+ const defaultIndicatorAnimation = this.#defaults.animation.indicator;
1111
+ if (typeof indicatorDuration !== "number" || Number.isNaN(indicatorDuration)) {
1112
+ const duration = defaultIndicatorAnimation.duration;
1113
+ console.warn(
1114
+ `Invalid indicator animation duration. Fallback: ${duration} (ms).`
1115
+ );
1116
+ mergedIndicatorAnimation.duration = duration;
1117
+ }
1118
+ if (indicatorDuration < 0) {
1119
+ console.warn("Invalid indicator animation duration. Fallback: 0 (ms).");
1120
+ mergedIndicatorAnimation.duration = 0;
1121
+ }
1122
+ if (!CSS.supports(
1123
+ "animation-timing-function",
1124
+ mergedIndicatorAnimation.easing
1125
+ )) {
1126
+ const easing = defaultIndicatorAnimation.easing;
1127
+ console.warn(
1128
+ `Invalid indicator animation easing. Fallback: '${easing}'.`
1129
+ );
1130
+ mergedIndicatorAnimation.easing = easing;
1131
+ }
1132
+ if (typeof merged.avoidDuplicates !== "boolean") {
1133
+ const avoidDuplicates = this.#defaults.avoidDuplicates;
1134
+ console.warn(
1135
+ `Invalid avoidDuplicates option. Fallback: ${avoidDuplicates}.`
1136
+ );
1137
+ merged.avoidDuplicates = avoidDuplicates;
1138
+ }
1139
+ if (typeof merged.manual !== "boolean") {
1140
+ const manual = this.#defaults.manual;
1141
+ console.warn(`Invalid manual option. Fallback: ${manual}.`);
1142
+ merged.manual = manual;
1143
+ }
1144
+ const mergedSelector = merged.selector;
1145
+ const defaultSelector = this.#defaults.selector;
1146
+ try {
1147
+ document.querySelector(mergedSelector.content);
1148
+ } catch {
1149
+ const content = defaultSelector.content;
1150
+ console.warn(`Invalid content selector. Fallback: '${content}'.`);
1151
+ mergedSelector.content = content;
1152
+ }
1153
+ try {
1154
+ document.querySelector(mergedSelector.indicator);
1155
+ } catch {
1156
+ const indicator = defaultSelector.indicator;
1157
+ console.warn(`Invalid indicator selector. Fallback: '${indicator}'.`);
1158
+ mergedSelector.indicator = indicator;
1159
+ }
1160
+ try {
1161
+ document.querySelector(mergedSelector.list);
1162
+ } catch {
1163
+ const list = defaultSelector.list;
1164
+ console.warn(`Invalid list selector. Fallback: '${list}'.`);
1165
+ mergedSelector.list = list;
1166
+ }
1167
+ try {
1168
+ document.querySelector(mergedSelector.panel);
1169
+ } catch {
1170
+ const panel = defaultSelector.panel;
1171
+ console.warn(`Invalid panel selector. Fallback: '${panel}'.`);
1172
+ mergedSelector.panel = panel;
1173
+ }
1174
+ try {
1175
+ document.querySelector(mergedSelector.tab);
1176
+ } catch {
1177
+ const tab = defaultSelector.tab;
1178
+ console.warn(`Invalid tab selector. Fallback: '${tab}'.`);
1179
+ mergedSelector.tab = tab;
1180
+ }
1181
+ if (typeof merged.vertical !== "boolean") {
1182
+ const vertical = this.#defaults.vertical;
1183
+ console.warn(`Invalid vertical option. Fallback: ${vertical}.`);
1184
+ merged.vertical = vertical;
1185
+ }
1186
+ return merged;
1084
1187
  }
1085
1188
  };
1086
1189
  var TabsIndicator = class {
@@ -1155,7 +1258,7 @@ var TabsIndicator = class {
1155
1258
  * Tabs
1156
1259
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
1157
1260
  *
1158
- * @version 2.0.13
1261
+ * @version 2.0.15
1159
1262
  * @author Yusuke Kamiyamane
1160
1263
  * @license MIT
1161
1264
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1163,15 +1266,15 @@ var TabsIndicator = class {
1163
1266
  */
1164
1267
  /*! Bundled license information:
1165
1268
 
1166
- @y14e/attribute-util/dist/index.js:
1269
+ @y14e/attribute-utils/dist/index.js:
1167
1270
  (**
1168
- * Attribute Util
1271
+ * Attribute Utils
1169
1272
  *
1170
- * @version 2.0.2
1273
+ * @version 2.0.5
1171
1274
  * @author Yusuke Kamiyamane
1172
1275
  * @license MIT
1173
1276
  * @copyright Copyright (c) Yusuke Kamiyamane
1174
- * @see {@link https://github.com/y14e/attribute-util}
1277
+ * @see {@link https://github.com/y14e/attribute-utils}
1175
1278
  *)
1176
1279
 
1177
1280
  power-focusable/dist/index.js:
@@ -1180,7 +1283,7 @@ power-focusable/dist/index.js:
1180
1283
  * High-precision focus management utility with full composed tree support.
1181
1284
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1182
1285
  *
1183
- * @version 4.3.25
1286
+ * @version 4.3.28
1184
1287
  * @author Yusuke Kamiyamane
1185
1288
  * @license MIT
1186
1289
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1204,7 +1307,7 @@ power-focusable/dist/index.js:
1204
1307
  * Lightweight roving tabindex utility with fully focus management.
1205
1308
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1206
1309
  *
1207
- * @version 3.1.22
1310
+ * @version 3.1.25
1208
1311
  * @author Yusuke Kamiyamane
1209
1312
  * @license MIT
1210
1313
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1,4 +1,4 @@
1
- // node_modules/@y14e/attribute-util/dist/index.js
1
+ // node_modules/@y14e/attribute-utils/dist/index.js
2
2
  var DEFAULT_PARSER = (value) => value.split(/\s+/);
3
3
  var DEFAULT_SERIALIZER = (tokens) => tokens.join(" ");
4
4
  function addAttributeToken(element, name, token, options = {}) {
@@ -413,17 +413,9 @@ var RovingTabIndex = class _RovingTabIndex {
413
413
  noStart = false;
414
414
  }
415
415
  if (selector !== "") {
416
- let hasError = false;
417
- if (typeof selector !== "string" || !selector.trim()) {
418
- hasError = true;
419
- } else {
420
- try {
421
- this.#container.querySelector(selector);
422
- } catch {
423
- hasError = true;
424
- }
425
- }
426
- if (hasError) {
416
+ try {
417
+ document.querySelector(selector);
418
+ } catch {
427
419
  console.warn("Invalid selector. Fallback: no selector string.");
428
420
  selector = "";
429
421
  }
@@ -1061,7 +1053,7 @@ var Tabs = class _Tabs {
1061
1053
  return !element.hasAttribute("disabled");
1062
1054
  }
1063
1055
  #mergeOptions(target, source) {
1064
- return {
1056
+ const merged = {
1065
1057
  ...target,
1066
1058
  ...source,
1067
1059
  animation: {
@@ -1079,6 +1071,117 @@ var Tabs = class _Tabs {
1079
1071
  ...source.selector ?? {}
1080
1072
  }
1081
1073
  };
1074
+ const animation = merged.animation;
1075
+ const mergedContentAnimation = animation.content;
1076
+ const defaultContentAnimation = this.#defaults.animation.content;
1077
+ if (typeof mergedContentAnimation.crossFade !== "boolean") {
1078
+ const crossFade = defaultContentAnimation.crossFade;
1079
+ console.warn(
1080
+ `Invalid content animation crossFade option. Fallback: ${crossFade}.`
1081
+ );
1082
+ mergedContentAnimation.crossFade = crossFade;
1083
+ }
1084
+ const contentDuration = mergedContentAnimation.duration;
1085
+ if (typeof contentDuration !== "number" || Number.isNaN(contentDuration)) {
1086
+ const duration = defaultContentAnimation.duration;
1087
+ console.warn(
1088
+ `Invalid content animation duration. Fallback: ${duration} (ms).`
1089
+ );
1090
+ mergedContentAnimation.duration = duration;
1091
+ }
1092
+ if (contentDuration < 0) {
1093
+ console.warn("Invalid content animation duration. Fallback: 0 (ms).");
1094
+ mergedContentAnimation.duration = 0;
1095
+ }
1096
+ if (!CSS.supports("animation-timing-function", mergedContentAnimation.easing)) {
1097
+ const easing = defaultContentAnimation.easing;
1098
+ console.warn(`Invalid content animation easing. Fallback: '${easing}'.`);
1099
+ mergedContentAnimation.easing = easing;
1100
+ }
1101
+ if (typeof mergedContentAnimation.fade !== "boolean") {
1102
+ const fade = defaultContentAnimation.fade;
1103
+ console.warn(`Invalid content animation fade option. Fallback: ${fade}.`);
1104
+ mergedContentAnimation.fade = fade;
1105
+ }
1106
+ const mergedIndicatorAnimation = animation.indicator;
1107
+ const indicatorDuration = mergedIndicatorAnimation.duration;
1108
+ const defaultIndicatorAnimation = this.#defaults.animation.indicator;
1109
+ if (typeof indicatorDuration !== "number" || Number.isNaN(indicatorDuration)) {
1110
+ const duration = defaultIndicatorAnimation.duration;
1111
+ console.warn(
1112
+ `Invalid indicator animation duration. Fallback: ${duration} (ms).`
1113
+ );
1114
+ mergedIndicatorAnimation.duration = duration;
1115
+ }
1116
+ if (indicatorDuration < 0) {
1117
+ console.warn("Invalid indicator animation duration. Fallback: 0 (ms).");
1118
+ mergedIndicatorAnimation.duration = 0;
1119
+ }
1120
+ if (!CSS.supports(
1121
+ "animation-timing-function",
1122
+ mergedIndicatorAnimation.easing
1123
+ )) {
1124
+ const easing = defaultIndicatorAnimation.easing;
1125
+ console.warn(
1126
+ `Invalid indicator animation easing. Fallback: '${easing}'.`
1127
+ );
1128
+ mergedIndicatorAnimation.easing = easing;
1129
+ }
1130
+ if (typeof merged.avoidDuplicates !== "boolean") {
1131
+ const avoidDuplicates = this.#defaults.avoidDuplicates;
1132
+ console.warn(
1133
+ `Invalid avoidDuplicates option. Fallback: ${avoidDuplicates}.`
1134
+ );
1135
+ merged.avoidDuplicates = avoidDuplicates;
1136
+ }
1137
+ if (typeof merged.manual !== "boolean") {
1138
+ const manual = this.#defaults.manual;
1139
+ console.warn(`Invalid manual option. Fallback: ${manual}.`);
1140
+ merged.manual = manual;
1141
+ }
1142
+ const mergedSelector = merged.selector;
1143
+ const defaultSelector = this.#defaults.selector;
1144
+ try {
1145
+ document.querySelector(mergedSelector.content);
1146
+ } catch {
1147
+ const content = defaultSelector.content;
1148
+ console.warn(`Invalid content selector. Fallback: '${content}'.`);
1149
+ mergedSelector.content = content;
1150
+ }
1151
+ try {
1152
+ document.querySelector(mergedSelector.indicator);
1153
+ } catch {
1154
+ const indicator = defaultSelector.indicator;
1155
+ console.warn(`Invalid indicator selector. Fallback: '${indicator}'.`);
1156
+ mergedSelector.indicator = indicator;
1157
+ }
1158
+ try {
1159
+ document.querySelector(mergedSelector.list);
1160
+ } catch {
1161
+ const list = defaultSelector.list;
1162
+ console.warn(`Invalid list selector. Fallback: '${list}'.`);
1163
+ mergedSelector.list = list;
1164
+ }
1165
+ try {
1166
+ document.querySelector(mergedSelector.panel);
1167
+ } catch {
1168
+ const panel = defaultSelector.panel;
1169
+ console.warn(`Invalid panel selector. Fallback: '${panel}'.`);
1170
+ mergedSelector.panel = panel;
1171
+ }
1172
+ try {
1173
+ document.querySelector(mergedSelector.tab);
1174
+ } catch {
1175
+ const tab = defaultSelector.tab;
1176
+ console.warn(`Invalid tab selector. Fallback: '${tab}'.`);
1177
+ mergedSelector.tab = tab;
1178
+ }
1179
+ if (typeof merged.vertical !== "boolean") {
1180
+ const vertical = this.#defaults.vertical;
1181
+ console.warn(`Invalid vertical option. Fallback: ${vertical}.`);
1182
+ merged.vertical = vertical;
1183
+ }
1184
+ return merged;
1082
1185
  }
1083
1186
  };
1084
1187
  var TabsIndicator = class {
@@ -1153,7 +1256,7 @@ var TabsIndicator = class {
1153
1256
  * Tabs
1154
1257
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
1155
1258
  *
1156
- * @version 2.0.13
1259
+ * @version 2.0.15
1157
1260
  * @author Yusuke Kamiyamane
1158
1261
  * @license MIT
1159
1262
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1161,15 +1264,15 @@ var TabsIndicator = class {
1161
1264
  */
1162
1265
  /*! Bundled license information:
1163
1266
 
1164
- @y14e/attribute-util/dist/index.js:
1267
+ @y14e/attribute-utils/dist/index.js:
1165
1268
  (**
1166
- * Attribute Util
1269
+ * Attribute Utils
1167
1270
  *
1168
- * @version 2.0.2
1271
+ * @version 2.0.5
1169
1272
  * @author Yusuke Kamiyamane
1170
1273
  * @license MIT
1171
1274
  * @copyright Copyright (c) Yusuke Kamiyamane
1172
- * @see {@link https://github.com/y14e/attribute-util}
1275
+ * @see {@link https://github.com/y14e/attribute-utils}
1173
1276
  *)
1174
1277
 
1175
1278
  power-focusable/dist/index.js:
@@ -1178,7 +1281,7 @@ power-focusable/dist/index.js:
1178
1281
  * High-precision focus management utility with full composed tree support.
1179
1282
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
1180
1283
  *
1181
- * @version 4.3.25
1284
+ * @version 4.3.28
1182
1285
  * @author Yusuke Kamiyamane
1183
1286
  * @license MIT
1184
1287
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1202,7 +1305,7 @@ power-focusable/dist/index.js:
1202
1305
  * Lightweight roving tabindex utility with fully focus management.
1203
1306
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1204
1307
  *
1205
- * @version 3.1.22
1308
+ * @version 3.1.25
1206
1309
  * @author Yusuke Kamiyamane
1207
1310
  * @license MIT
1208
1311
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var util = require('@y14e/attribute-util');
3
+ var utils = require('@y14e/attribute-utils');
4
4
  var button = require('@y14e/button');
5
5
  var rovingTabindex = require('@y14e/roving-tabindex');
6
6
 
@@ -22,7 +22,7 @@ function _interopNamespace(e) {
22
22
  return Object.freeze(n);
23
23
  }
24
24
 
25
- var util__namespace = /*#__PURE__*/_interopNamespace(util);
25
+ var utils__namespace = /*#__PURE__*/_interopNamespace(utils);
26
26
 
27
27
  // src/index.ts
28
28
  var Tabs = class _Tabs {
@@ -295,13 +295,13 @@ var Tabs = class _Tabs {
295
295
  this.#onContentAnimationFinish();
296
296
  this.#animationController?.abort();
297
297
  this.#animationController = null;
298
- util__namespace.restoreAttributes([
298
+ utils__namespace.restoreAttributes([
299
299
  ...this.#listElements,
300
300
  ...this.#tabElements,
301
301
  ...this.#indicatorElements,
302
302
  ...this.#panelElements
303
303
  ]);
304
- this.#contentElement && util__namespace.restoreAttributes(this.#contentElement);
304
+ this.#contentElement && utils__namespace.restoreAttributes(this.#contentElement);
305
305
  this.#listElements.length = 0;
306
306
  this.#tabElements.length = 0;
307
307
  this.#contentElement = null;
@@ -309,22 +309,22 @@ var Tabs = class _Tabs {
309
309
  this.#rootElement.removeAttribute("data-tabs-initialized");
310
310
  }
311
311
  #initialize() {
312
- util__namespace.saveAttributes(this.#listElements, [
312
+ utils__namespace.saveAttributes(this.#listElements, [
313
313
  "aria-hidden",
314
314
  "aria-orientation",
315
315
  "role",
316
316
  "style"
317
317
  ]);
318
- util__namespace.saveAttributes(this.#tabElements, [
318
+ utils__namespace.saveAttributes(this.#tabElements, [
319
319
  "aria-controls",
320
320
  "id",
321
321
  "role",
322
322
  "style",
323
323
  "tabindex"
324
324
  ]);
325
- util__namespace.saveAttributes(this.#indicatorElements, "style");
326
- this.#contentElement && util__namespace.saveAttributes(this.#contentElement, "style");
327
- util__namespace.saveAttributes(this.#panelElements, [
325
+ utils__namespace.saveAttributes(this.#indicatorElements, "style");
326
+ this.#contentElement && utils__namespace.saveAttributes(this.#contentElement, "style");
327
+ utils__namespace.saveAttributes(this.#panelElements, [
328
328
  "aria-controls",
329
329
  "aria-labelledby",
330
330
  "id",
@@ -346,7 +346,7 @@ var Tabs = class _Tabs {
346
346
  return;
347
347
  }
348
348
  panel.id ||= `tabs-panel-${id}`;
349
- util__namespace.addAttributeToken(tab, "aria-controls", panel.id);
349
+ utils__namespace.addAttributeToken(tab, "aria-controls", panel.id);
350
350
  !tab.hasAttribute("aria-selected") && tab.setAttribute("aria-selected", "false");
351
351
  const isAvoided = this.#isAvoidedTab(tab);
352
352
  if (!isAvoided) {
@@ -354,7 +354,7 @@ var Tabs = class _Tabs {
354
354
  }
355
355
  tab.setAttribute("role", "tab");
356
356
  !this.#isFocusable(tab) && tab.style.setProperty("pointer-events", "none");
357
- util__namespace.addAttributeToken(panel, "aria-labelledby", tab.id);
357
+ utils__namespace.addAttributeToken(panel, "aria-labelledby", tab.id);
358
358
  tab.addEventListener("click", this.#onTabClick, { signal });
359
359
  tab.addEventListener("focus", this.#onTabFocus, { signal });
360
360
  this.#buttons.push(new button.Button(tab));
@@ -451,7 +451,7 @@ var Tabs = class _Tabs {
451
451
  return !element.hasAttribute("disabled");
452
452
  }
453
453
  #mergeOptions(target, source) {
454
- return {
454
+ const merged = {
455
455
  ...target,
456
456
  ...source,
457
457
  animation: {
@@ -469,6 +469,117 @@ var Tabs = class _Tabs {
469
469
  ...source.selector ?? {}
470
470
  }
471
471
  };
472
+ const animation = merged.animation;
473
+ const mergedContentAnimation = animation.content;
474
+ const defaultContentAnimation = this.#defaults.animation.content;
475
+ if (typeof mergedContentAnimation.crossFade !== "boolean") {
476
+ const crossFade = defaultContentAnimation.crossFade;
477
+ console.warn(
478
+ `Invalid content animation crossFade option. Fallback: ${crossFade}.`
479
+ );
480
+ mergedContentAnimation.crossFade = crossFade;
481
+ }
482
+ const contentDuration = mergedContentAnimation.duration;
483
+ if (typeof contentDuration !== "number" || Number.isNaN(contentDuration)) {
484
+ const duration = defaultContentAnimation.duration;
485
+ console.warn(
486
+ `Invalid content animation duration. Fallback: ${duration} (ms).`
487
+ );
488
+ mergedContentAnimation.duration = duration;
489
+ }
490
+ if (contentDuration < 0) {
491
+ console.warn("Invalid content animation duration. Fallback: 0 (ms).");
492
+ mergedContentAnimation.duration = 0;
493
+ }
494
+ if (!CSS.supports("animation-timing-function", mergedContentAnimation.easing)) {
495
+ const easing = defaultContentAnimation.easing;
496
+ console.warn(`Invalid content animation easing. Fallback: '${easing}'.`);
497
+ mergedContentAnimation.easing = easing;
498
+ }
499
+ if (typeof mergedContentAnimation.fade !== "boolean") {
500
+ const fade = defaultContentAnimation.fade;
501
+ console.warn(`Invalid content animation fade option. Fallback: ${fade}.`);
502
+ mergedContentAnimation.fade = fade;
503
+ }
504
+ const mergedIndicatorAnimation = animation.indicator;
505
+ const indicatorDuration = mergedIndicatorAnimation.duration;
506
+ const defaultIndicatorAnimation = this.#defaults.animation.indicator;
507
+ if (typeof indicatorDuration !== "number" || Number.isNaN(indicatorDuration)) {
508
+ const duration = defaultIndicatorAnimation.duration;
509
+ console.warn(
510
+ `Invalid indicator animation duration. Fallback: ${duration} (ms).`
511
+ );
512
+ mergedIndicatorAnimation.duration = duration;
513
+ }
514
+ if (indicatorDuration < 0) {
515
+ console.warn("Invalid indicator animation duration. Fallback: 0 (ms).");
516
+ mergedIndicatorAnimation.duration = 0;
517
+ }
518
+ if (!CSS.supports(
519
+ "animation-timing-function",
520
+ mergedIndicatorAnimation.easing
521
+ )) {
522
+ const easing = defaultIndicatorAnimation.easing;
523
+ console.warn(
524
+ `Invalid indicator animation easing. Fallback: '${easing}'.`
525
+ );
526
+ mergedIndicatorAnimation.easing = easing;
527
+ }
528
+ if (typeof merged.avoidDuplicates !== "boolean") {
529
+ const avoidDuplicates = this.#defaults.avoidDuplicates;
530
+ console.warn(
531
+ `Invalid avoidDuplicates option. Fallback: ${avoidDuplicates}.`
532
+ );
533
+ merged.avoidDuplicates = avoidDuplicates;
534
+ }
535
+ if (typeof merged.manual !== "boolean") {
536
+ const manual = this.#defaults.manual;
537
+ console.warn(`Invalid manual option. Fallback: ${manual}.`);
538
+ merged.manual = manual;
539
+ }
540
+ const mergedSelector = merged.selector;
541
+ const defaultSelector = this.#defaults.selector;
542
+ try {
543
+ document.querySelector(mergedSelector.content);
544
+ } catch {
545
+ const content = defaultSelector.content;
546
+ console.warn(`Invalid content selector. Fallback: '${content}'.`);
547
+ mergedSelector.content = content;
548
+ }
549
+ try {
550
+ document.querySelector(mergedSelector.indicator);
551
+ } catch {
552
+ const indicator = defaultSelector.indicator;
553
+ console.warn(`Invalid indicator selector. Fallback: '${indicator}'.`);
554
+ mergedSelector.indicator = indicator;
555
+ }
556
+ try {
557
+ document.querySelector(mergedSelector.list);
558
+ } catch {
559
+ const list = defaultSelector.list;
560
+ console.warn(`Invalid list selector. Fallback: '${list}'.`);
561
+ mergedSelector.list = list;
562
+ }
563
+ try {
564
+ document.querySelector(mergedSelector.panel);
565
+ } catch {
566
+ const panel = defaultSelector.panel;
567
+ console.warn(`Invalid panel selector. Fallback: '${panel}'.`);
568
+ mergedSelector.panel = panel;
569
+ }
570
+ try {
571
+ document.querySelector(mergedSelector.tab);
572
+ } catch {
573
+ const tab = defaultSelector.tab;
574
+ console.warn(`Invalid tab selector. Fallback: '${tab}'.`);
575
+ mergedSelector.tab = tab;
576
+ }
577
+ if (typeof merged.vertical !== "boolean") {
578
+ const vertical = this.#defaults.vertical;
579
+ console.warn(`Invalid vertical option. Fallback: ${vertical}.`);
580
+ merged.vertical = vertical;
581
+ }
582
+ return merged;
472
583
  }
473
584
  };
474
585
  var TabsIndicator = class {
@@ -543,7 +654,7 @@ var TabsIndicator = class {
543
654
  * Tabs
544
655
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
545
656
  *
546
- * @version 2.0.13
657
+ * @version 2.0.15
547
658
  * @author Yusuke Kamiyamane
548
659
  * @license MIT
549
660
  * @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.13
5
+ * @version 2.0.15
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.13
5
+ * @version 2.0.15
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as util from '@y14e/attribute-util';
1
+ import * as utils from '@y14e/attribute-utils';
2
2
  import { Button } from '@y14e/button';
3
3
  import { createRovingTabIndex } from '@y14e/roving-tabindex';
4
4
 
@@ -273,13 +273,13 @@ var Tabs = class _Tabs {
273
273
  this.#onContentAnimationFinish();
274
274
  this.#animationController?.abort();
275
275
  this.#animationController = null;
276
- util.restoreAttributes([
276
+ utils.restoreAttributes([
277
277
  ...this.#listElements,
278
278
  ...this.#tabElements,
279
279
  ...this.#indicatorElements,
280
280
  ...this.#panelElements
281
281
  ]);
282
- this.#contentElement && util.restoreAttributes(this.#contentElement);
282
+ this.#contentElement && utils.restoreAttributes(this.#contentElement);
283
283
  this.#listElements.length = 0;
284
284
  this.#tabElements.length = 0;
285
285
  this.#contentElement = null;
@@ -287,22 +287,22 @@ var Tabs = class _Tabs {
287
287
  this.#rootElement.removeAttribute("data-tabs-initialized");
288
288
  }
289
289
  #initialize() {
290
- util.saveAttributes(this.#listElements, [
290
+ utils.saveAttributes(this.#listElements, [
291
291
  "aria-hidden",
292
292
  "aria-orientation",
293
293
  "role",
294
294
  "style"
295
295
  ]);
296
- util.saveAttributes(this.#tabElements, [
296
+ utils.saveAttributes(this.#tabElements, [
297
297
  "aria-controls",
298
298
  "id",
299
299
  "role",
300
300
  "style",
301
301
  "tabindex"
302
302
  ]);
303
- util.saveAttributes(this.#indicatorElements, "style");
304
- this.#contentElement && util.saveAttributes(this.#contentElement, "style");
305
- util.saveAttributes(this.#panelElements, [
303
+ utils.saveAttributes(this.#indicatorElements, "style");
304
+ this.#contentElement && utils.saveAttributes(this.#contentElement, "style");
305
+ utils.saveAttributes(this.#panelElements, [
306
306
  "aria-controls",
307
307
  "aria-labelledby",
308
308
  "id",
@@ -324,7 +324,7 @@ var Tabs = class _Tabs {
324
324
  return;
325
325
  }
326
326
  panel.id ||= `tabs-panel-${id}`;
327
- util.addAttributeToken(tab, "aria-controls", panel.id);
327
+ utils.addAttributeToken(tab, "aria-controls", panel.id);
328
328
  !tab.hasAttribute("aria-selected") && tab.setAttribute("aria-selected", "false");
329
329
  const isAvoided = this.#isAvoidedTab(tab);
330
330
  if (!isAvoided) {
@@ -332,7 +332,7 @@ var Tabs = class _Tabs {
332
332
  }
333
333
  tab.setAttribute("role", "tab");
334
334
  !this.#isFocusable(tab) && tab.style.setProperty("pointer-events", "none");
335
- util.addAttributeToken(panel, "aria-labelledby", tab.id);
335
+ utils.addAttributeToken(panel, "aria-labelledby", tab.id);
336
336
  tab.addEventListener("click", this.#onTabClick, { signal });
337
337
  tab.addEventListener("focus", this.#onTabFocus, { signal });
338
338
  this.#buttons.push(new Button(tab));
@@ -429,7 +429,7 @@ var Tabs = class _Tabs {
429
429
  return !element.hasAttribute("disabled");
430
430
  }
431
431
  #mergeOptions(target, source) {
432
- return {
432
+ const merged = {
433
433
  ...target,
434
434
  ...source,
435
435
  animation: {
@@ -447,6 +447,117 @@ var Tabs = class _Tabs {
447
447
  ...source.selector ?? {}
448
448
  }
449
449
  };
450
+ const animation = merged.animation;
451
+ const mergedContentAnimation = animation.content;
452
+ const defaultContentAnimation = this.#defaults.animation.content;
453
+ if (typeof mergedContentAnimation.crossFade !== "boolean") {
454
+ const crossFade = defaultContentAnimation.crossFade;
455
+ console.warn(
456
+ `Invalid content animation crossFade option. Fallback: ${crossFade}.`
457
+ );
458
+ mergedContentAnimation.crossFade = crossFade;
459
+ }
460
+ const contentDuration = mergedContentAnimation.duration;
461
+ if (typeof contentDuration !== "number" || Number.isNaN(contentDuration)) {
462
+ const duration = defaultContentAnimation.duration;
463
+ console.warn(
464
+ `Invalid content animation duration. Fallback: ${duration} (ms).`
465
+ );
466
+ mergedContentAnimation.duration = duration;
467
+ }
468
+ if (contentDuration < 0) {
469
+ console.warn("Invalid content animation duration. Fallback: 0 (ms).");
470
+ mergedContentAnimation.duration = 0;
471
+ }
472
+ if (!CSS.supports("animation-timing-function", mergedContentAnimation.easing)) {
473
+ const easing = defaultContentAnimation.easing;
474
+ console.warn(`Invalid content animation easing. Fallback: '${easing}'.`);
475
+ mergedContentAnimation.easing = easing;
476
+ }
477
+ if (typeof mergedContentAnimation.fade !== "boolean") {
478
+ const fade = defaultContentAnimation.fade;
479
+ console.warn(`Invalid content animation fade option. Fallback: ${fade}.`);
480
+ mergedContentAnimation.fade = fade;
481
+ }
482
+ const mergedIndicatorAnimation = animation.indicator;
483
+ const indicatorDuration = mergedIndicatorAnimation.duration;
484
+ const defaultIndicatorAnimation = this.#defaults.animation.indicator;
485
+ if (typeof indicatorDuration !== "number" || Number.isNaN(indicatorDuration)) {
486
+ const duration = defaultIndicatorAnimation.duration;
487
+ console.warn(
488
+ `Invalid indicator animation duration. Fallback: ${duration} (ms).`
489
+ );
490
+ mergedIndicatorAnimation.duration = duration;
491
+ }
492
+ if (indicatorDuration < 0) {
493
+ console.warn("Invalid indicator animation duration. Fallback: 0 (ms).");
494
+ mergedIndicatorAnimation.duration = 0;
495
+ }
496
+ if (!CSS.supports(
497
+ "animation-timing-function",
498
+ mergedIndicatorAnimation.easing
499
+ )) {
500
+ const easing = defaultIndicatorAnimation.easing;
501
+ console.warn(
502
+ `Invalid indicator animation easing. Fallback: '${easing}'.`
503
+ );
504
+ mergedIndicatorAnimation.easing = easing;
505
+ }
506
+ if (typeof merged.avoidDuplicates !== "boolean") {
507
+ const avoidDuplicates = this.#defaults.avoidDuplicates;
508
+ console.warn(
509
+ `Invalid avoidDuplicates option. Fallback: ${avoidDuplicates}.`
510
+ );
511
+ merged.avoidDuplicates = avoidDuplicates;
512
+ }
513
+ if (typeof merged.manual !== "boolean") {
514
+ const manual = this.#defaults.manual;
515
+ console.warn(`Invalid manual option. Fallback: ${manual}.`);
516
+ merged.manual = manual;
517
+ }
518
+ const mergedSelector = merged.selector;
519
+ const defaultSelector = this.#defaults.selector;
520
+ try {
521
+ document.querySelector(mergedSelector.content);
522
+ } catch {
523
+ const content = defaultSelector.content;
524
+ console.warn(`Invalid content selector. Fallback: '${content}'.`);
525
+ mergedSelector.content = content;
526
+ }
527
+ try {
528
+ document.querySelector(mergedSelector.indicator);
529
+ } catch {
530
+ const indicator = defaultSelector.indicator;
531
+ console.warn(`Invalid indicator selector. Fallback: '${indicator}'.`);
532
+ mergedSelector.indicator = indicator;
533
+ }
534
+ try {
535
+ document.querySelector(mergedSelector.list);
536
+ } catch {
537
+ const list = defaultSelector.list;
538
+ console.warn(`Invalid list selector. Fallback: '${list}'.`);
539
+ mergedSelector.list = list;
540
+ }
541
+ try {
542
+ document.querySelector(mergedSelector.panel);
543
+ } catch {
544
+ const panel = defaultSelector.panel;
545
+ console.warn(`Invalid panel selector. Fallback: '${panel}'.`);
546
+ mergedSelector.panel = panel;
547
+ }
548
+ try {
549
+ document.querySelector(mergedSelector.tab);
550
+ } catch {
551
+ const tab = defaultSelector.tab;
552
+ console.warn(`Invalid tab selector. Fallback: '${tab}'.`);
553
+ mergedSelector.tab = tab;
554
+ }
555
+ if (typeof merged.vertical !== "boolean") {
556
+ const vertical = this.#defaults.vertical;
557
+ console.warn(`Invalid vertical option. Fallback: ${vertical}.`);
558
+ merged.vertical = vertical;
559
+ }
560
+ return merged;
450
561
  }
451
562
  };
452
563
  var TabsIndicator = class {
@@ -521,7 +632,7 @@ var TabsIndicator = class {
521
632
  * Tabs
522
633
  * WAI-ARIA compliant tabs pattern implementation in TypeScript.
523
634
  *
524
- * @version 2.0.13
635
+ * @version 2.0.15
525
636
  * @author Yusuke Kamiyamane
526
637
  * @license MIT
527
638
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/tabs",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
4
4
  "description": "WAI-ARIA compliant tabs pattern implementation in TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -53,8 +53,8 @@
53
53
  "esbuild": true
54
54
  },
55
55
  "dependencies": {
56
- "@y14e/attribute-util": "^2.0.2",
56
+ "@y14e/attribute-utils": "^2.0.5",
57
57
  "@y14e/button": "^1.0.8",
58
- "@y14e/roving-tabindex": "^3.1.22"
58
+ "@y14e/roving-tabindex": "^3.1.25"
59
59
  }
60
60
  }