@y14e/accordion 2.0.12 → 2.0.14

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/accordion
13
13
  import { Accordion } from "@y14e/accordion";
14
14
 
15
15
  // CDNs
16
- import { Accordion } from "https://esm.sh/@y14e/accordion@2.0.12";
16
+ import { Accordion } from "https://esm.sh/@y14e/accordion@2.0.14";
17
17
  // or
18
- import { Accordion } from "https://cdn.jsdelivr.net/npm/@y14e/accordion@2.0.12/+esm";
18
+ import { Accordion } from "https://cdn.jsdelivr.net/npm/@y14e/accordion@2.0.14/+esm";
19
19
  // or
20
- import { Accordion } from "https://esm.unpkg.com/@y14e/accordion@2.0.12";
20
+ import { Accordion } from "https://esm.unpkg.com/@y14e/accordion@2.0.14";
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -4,12 +4,11 @@
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 = {}) {
7
+ if (!isValid(element, name, token)) {
8
+ return;
9
+ }
7
10
  const value = element.getAttribute(name)?.trim();
8
- const {
9
- caseInsensitive = false,
10
- parse = DEFAULT_PARSER,
11
- serialize = DEFAULT_SERIALIZER
12
- } = options;
11
+ const { caseInsensitive, parse, serialize } = resolveOptions(options);
13
12
  const tokens = value ? parse(value).filter(Boolean) : [];
14
13
  if (caseInsensitive) {
15
14
  const lower = token.toLowerCase();
@@ -49,6 +48,47 @@ function saveAttributes(element_or_elements, name_or_names) {
49
48
  });
50
49
  });
51
50
  }
51
+ function isValid(element, name, token) {
52
+ if (!(element instanceof Element)) {
53
+ console.warn("Invalid element");
54
+ return false;
55
+ }
56
+ try {
57
+ document.createElement("div").setAttribute(name, "");
58
+ } catch {
59
+ console.warn(`Invalid attribute name: '${name}'`);
60
+ return false;
61
+ }
62
+ if (typeof token !== "string" || !token.trim()) {
63
+ console.warn("Invalid token");
64
+ return false;
65
+ }
66
+ return true;
67
+ }
68
+ function resolveOptions(options) {
69
+ let {
70
+ caseInsensitive = false,
71
+ parse = DEFAULT_PARSER,
72
+ serialize = DEFAULT_SERIALIZER
73
+ } = options;
74
+ if (typeof caseInsensitive !== "boolean") {
75
+ console.warn("Invalid caseInsensitive option. Fallback: false.");
76
+ caseInsensitive = false;
77
+ }
78
+ if (typeof parse !== "function") {
79
+ console.warn(
80
+ "Invalid parser. Fallback: default parser (splits by whitespace)."
81
+ );
82
+ parse = DEFAULT_PARSER;
83
+ }
84
+ if (typeof serialize !== "function") {
85
+ console.warn(
86
+ "Invalid serializer. Fallback: default serializer (joins by whitespace)."
87
+ );
88
+ serialize = DEFAULT_SERIALIZER;
89
+ }
90
+ return { caseInsensitive, parse, serialize };
91
+ }
52
92
 
53
93
  // node_modules/power-focusable/dist/index.js
54
94
  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"])`;
@@ -61,37 +101,13 @@ function getFocusables(container = document.body, options = {}) {
61
101
  console.warn("Invalid container element. Fallback: <body> element.");
62
102
  container = document.body;
63
103
  }
64
- let {
65
- composed = false,
104
+ const {
105
+ composed,
66
106
  filter,
67
107
  include,
68
- skipNegativeTabIndexCheck = false,
69
- skipVisibilityCheck = false
70
- } = options;
71
- if (typeof composed !== "boolean") {
72
- console.warn("Invalid composed option. Fallback: false.");
73
- composed = false;
74
- }
75
- if (typeof filter !== "undefined" && typeof filter !== "function") {
76
- console.warn(
77
- "Invalid filter function. Fallback: no filter function (undefined)."
78
- );
79
- filter = void 0;
80
- }
81
- if (typeof include !== "undefined" && typeof include !== "function") {
82
- console.warn(
83
- "Invalid include function. Fallback: no include function (undefined)."
84
- );
85
- include = void 0;
86
- }
87
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
88
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
89
- skipNegativeTabIndexCheck = false;
90
- }
91
- if (typeof skipVisibilityCheck !== "boolean") {
92
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
93
- skipVisibilityCheck = false;
94
- }
108
+ skipNegativeTabIndexCheck,
109
+ skipVisibilityCheck
110
+ } = resolveOptions2(options);
95
111
  const candidates = [];
96
112
  if (composed || include) {
97
113
  let traverse2 = function(node) {
@@ -135,15 +151,7 @@ function isFocusable(element, options = {}) {
135
151
  console.warn("Invalid element");
136
152
  return false;
137
153
  }
138
- let { skipNegativeTabIndexCheck = false, skipVisibilityCheck = false } = options;
139
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
140
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
141
- skipNegativeTabIndexCheck = false;
142
- }
143
- if (typeof skipVisibilityCheck !== "boolean") {
144
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
145
- skipVisibilityCheck = false;
146
- }
154
+ const { skipNegativeTabIndexCheck, skipVisibilityCheck } = resolveOptions2(options);
147
155
  if (element.hasAttribute("hidden") || isInert(element)) {
148
156
  return false;
149
157
  }
@@ -318,6 +326,61 @@ function isInert(element) {
318
326
  function isUngroupedRadio(element) {
319
327
  return element.type === "radio" && !!element.name;
320
328
  }
329
+ function resolveOptions2(options) {
330
+ let {
331
+ anchor = getActiveElement(),
332
+ composed = false,
333
+ filter,
334
+ include,
335
+ skipNegativeTabIndexCheck = false,
336
+ skipVisibilityCheck = false,
337
+ wrap = false
338
+ } = options;
339
+ if (!(anchor instanceof Element)) {
340
+ const active = getActiveElement();
341
+ if (active instanceof Element) {
342
+ console.warn("Invalid anchor element. Fallback: active element.");
343
+ anchor = active;
344
+ }
345
+ }
346
+ if (typeof composed !== "boolean") {
347
+ console.warn("Invalid composed option. Fallback: false.");
348
+ composed = false;
349
+ }
350
+ if (filter !== void 0 && typeof filter !== "function") {
351
+ console.warn(
352
+ "Invalid filter function. Fallback: no filter function (undefined)."
353
+ );
354
+ filter = void 0;
355
+ }
356
+ if (include !== void 0 && typeof include !== "function") {
357
+ console.warn(
358
+ "Invalid include function. Fallback: no include function (undefined)."
359
+ );
360
+ include = void 0;
361
+ }
362
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
363
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
364
+ skipNegativeTabIndexCheck = false;
365
+ }
366
+ if (typeof skipVisibilityCheck !== "boolean") {
367
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
368
+ skipVisibilityCheck = false;
369
+ }
370
+ if (typeof wrap !== "boolean") {
371
+ console.warn("Invalid wrap option. Fallback: false.");
372
+ wrap = false;
373
+ }
374
+ return {
375
+ anchor,
376
+ composed,
377
+ filter,
378
+ include,
379
+ skipNegativeTabIndexCheck,
380
+ skipVisibilityCheck,
381
+ wrap
382
+ };
383
+ }
321
384
 
322
385
  // node_modules/@y14e/button/dist/index.js
323
386
  var Button = class {
@@ -389,56 +452,7 @@ var RovingTabIndex = class _RovingTabIndex {
389
452
  #isDestroyed = false;
390
453
  constructor(container, options = {}) {
391
454
  this.#container = container;
392
- let {
393
- direction = "both",
394
- navigationOnly = false,
395
- noMemory = false,
396
- noStart = false,
397
- selector = "",
398
- typeahead = false,
399
- wrap = false
400
- } = options;
401
- if (!["both", "horizontal", "vertical"].includes(direction)) {
402
- console.warn("Invalid direction option. Fallback: 'both'.");
403
- direction = "both";
404
- }
405
- if (typeof navigationOnly !== "boolean") {
406
- console.warn("Invalid navigationOnly option. Fallback: false.");
407
- navigationOnly = false;
408
- }
409
- if (typeof noMemory !== "boolean") {
410
- console.warn("Invalid noMemory option. Fallback: false.");
411
- noMemory = false;
412
- }
413
- if (typeof noStart !== "boolean") {
414
- console.warn("Invalid noStart option. Fallback: false.");
415
- noStart = false;
416
- }
417
- if (selector !== "") {
418
- try {
419
- document.querySelector(selector);
420
- } catch {
421
- console.warn("Invalid selector. Fallback: no selector string.");
422
- selector = "";
423
- }
424
- }
425
- if (typeof typeahead !== "boolean") {
426
- console.warn("Invalid typeahead option. Fallback: false.");
427
- typeahead = false;
428
- }
429
- if (typeof wrap !== "boolean") {
430
- console.warn("Invalid wrap option. Fallback: false.");
431
- wrap = false;
432
- }
433
- this.#settings = {
434
- direction,
435
- navigationOnly,
436
- noMemory,
437
- noStart,
438
- selector,
439
- typeahead,
440
- wrap
441
- };
455
+ this.#settings = this.#resolveOptions(options);
442
456
  this.#selectorFilter = this.#createSelectorFilter();
443
457
  this.#initialize();
444
458
  }
@@ -626,6 +640,58 @@ var RovingTabIndex = class _RovingTabIndex {
626
640
  skipVisibilityCheck: true
627
641
  });
628
642
  }
643
+ #resolveOptions(options) {
644
+ let {
645
+ direction = "both",
646
+ navigationOnly = false,
647
+ noMemory = false,
648
+ noStart = false,
649
+ selector = "",
650
+ typeahead = false,
651
+ wrap = false
652
+ } = options;
653
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
654
+ console.warn("Invalid direction option. Fallback: 'both'.");
655
+ direction = "both";
656
+ }
657
+ if (typeof navigationOnly !== "boolean") {
658
+ console.warn("Invalid navigationOnly option. Fallback: false.");
659
+ navigationOnly = false;
660
+ }
661
+ if (typeof noMemory !== "boolean") {
662
+ console.warn("Invalid noMemory option. Fallback: false.");
663
+ noMemory = false;
664
+ }
665
+ if (typeof noStart !== "boolean") {
666
+ console.warn("Invalid noStart option. Fallback: false.");
667
+ noStart = false;
668
+ }
669
+ if (selector !== "") {
670
+ try {
671
+ document.querySelector(selector);
672
+ } catch {
673
+ console.warn("Invalid selector. Fallback: no selector string.");
674
+ selector = "";
675
+ }
676
+ }
677
+ if (typeof typeahead !== "boolean") {
678
+ console.warn("Invalid typeahead option. Fallback: false.");
679
+ typeahead = false;
680
+ }
681
+ if (typeof wrap !== "boolean") {
682
+ console.warn("Invalid wrap option. Fallback: false.");
683
+ wrap = false;
684
+ }
685
+ return {
686
+ direction,
687
+ navigationOnly,
688
+ noMemory,
689
+ noStart,
690
+ selector,
691
+ typeahead,
692
+ wrap
693
+ };
694
+ }
629
695
  };
630
696
 
631
697
  // src/index.ts
@@ -895,7 +961,8 @@ var Accordion = class _Accordion {
895
961
  };
896
962
  const mergedAnimation = merged.animation;
897
963
  const duration = mergedAnimation.duration;
898
- const defaultAnimation = this.#defaults.animation;
964
+ const defaults = this.#defaults;
965
+ const defaultAnimation = defaults.animation;
899
966
  if (typeof duration !== "number" || Number.isNaN(duration)) {
900
967
  const duration2 = defaultAnimation.duration;
901
968
  console.warn(`Invalid animation duration. Fallback: ${duration2} (ms).`);
@@ -911,12 +978,12 @@ var Accordion = class _Accordion {
911
978
  mergedAnimation.easing = easing;
912
979
  }
913
980
  if (typeof merged.collapsible !== "boolean") {
914
- const collapsible = this.#defaults.collapsible;
981
+ const collapsible = defaults.collapsible;
915
982
  console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
916
983
  merged.collapsible = collapsible;
917
984
  }
918
985
  const mergedSelector = merged.selector;
919
- const defaultSelector = this.#defaults.selector;
986
+ const defaultSelector = defaults.selector;
920
987
  try {
921
988
  document.querySelector(mergedSelector.content);
922
989
  } catch {
@@ -951,7 +1018,7 @@ function waitAnimationFinish(animation) {
951
1018
  * Accordion
952
1019
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
953
1020
  *
954
- * @version 2.0.12
1021
+ * @version 2.0.14
955
1022
  * @author Yusuke Kamiyamane
956
1023
  * @license MIT
957
1024
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -963,7 +1030,7 @@ function waitAnimationFinish(animation) {
963
1030
  (**
964
1031
  * Attribute Utils
965
1032
  *
966
- * @version 2.0.5
1033
+ * @version 2.0.8
967
1034
  * @author Yusuke Kamiyamane
968
1035
  * @license MIT
969
1036
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -976,7 +1043,7 @@ power-focusable/dist/index.js:
976
1043
  * High-precision focus management utility with full composed tree support.
977
1044
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
978
1045
  *
979
- * @version 4.3.28
1046
+ * @version 4.3.29
980
1047
  * @author Yusuke Kamiyamane
981
1048
  * @license MIT
982
1049
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -1000,7 +1067,7 @@ power-focusable/dist/index.js:
1000
1067
  * Lightweight roving tabindex utility with fully focus management.
1001
1068
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1002
1069
  *
1003
- * @version 3.1.25
1070
+ * @version 3.1.27
1004
1071
  * @author Yusuke Kamiyamane
1005
1072
  * @license MIT
1006
1073
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -2,12 +2,11 @@
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 = {}) {
5
+ if (!isValid(element, name, token)) {
6
+ return;
7
+ }
5
8
  const value = element.getAttribute(name)?.trim();
6
- const {
7
- caseInsensitive = false,
8
- parse = DEFAULT_PARSER,
9
- serialize = DEFAULT_SERIALIZER
10
- } = options;
9
+ const { caseInsensitive, parse, serialize } = resolveOptions(options);
11
10
  const tokens = value ? parse(value).filter(Boolean) : [];
12
11
  if (caseInsensitive) {
13
12
  const lower = token.toLowerCase();
@@ -47,6 +46,47 @@ function saveAttributes(element_or_elements, name_or_names) {
47
46
  });
48
47
  });
49
48
  }
49
+ function isValid(element, name, token) {
50
+ if (!(element instanceof Element)) {
51
+ console.warn("Invalid element");
52
+ return false;
53
+ }
54
+ try {
55
+ document.createElement("div").setAttribute(name, "");
56
+ } catch {
57
+ console.warn(`Invalid attribute name: '${name}'`);
58
+ return false;
59
+ }
60
+ if (typeof token !== "string" || !token.trim()) {
61
+ console.warn("Invalid token");
62
+ return false;
63
+ }
64
+ return true;
65
+ }
66
+ function resolveOptions(options) {
67
+ let {
68
+ caseInsensitive = false,
69
+ parse = DEFAULT_PARSER,
70
+ serialize = DEFAULT_SERIALIZER
71
+ } = options;
72
+ if (typeof caseInsensitive !== "boolean") {
73
+ console.warn("Invalid caseInsensitive option. Fallback: false.");
74
+ caseInsensitive = false;
75
+ }
76
+ if (typeof parse !== "function") {
77
+ console.warn(
78
+ "Invalid parser. Fallback: default parser (splits by whitespace)."
79
+ );
80
+ parse = DEFAULT_PARSER;
81
+ }
82
+ if (typeof serialize !== "function") {
83
+ console.warn(
84
+ "Invalid serializer. Fallback: default serializer (joins by whitespace)."
85
+ );
86
+ serialize = DEFAULT_SERIALIZER;
87
+ }
88
+ return { caseInsensitive, parse, serialize };
89
+ }
50
90
 
51
91
  // node_modules/power-focusable/dist/index.js
52
92
  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"])`;
@@ -59,37 +99,13 @@ function getFocusables(container = document.body, options = {}) {
59
99
  console.warn("Invalid container element. Fallback: <body> element.");
60
100
  container = document.body;
61
101
  }
62
- let {
63
- composed = false,
102
+ const {
103
+ composed,
64
104
  filter,
65
105
  include,
66
- skipNegativeTabIndexCheck = false,
67
- skipVisibilityCheck = false
68
- } = options;
69
- if (typeof composed !== "boolean") {
70
- console.warn("Invalid composed option. Fallback: false.");
71
- composed = false;
72
- }
73
- if (typeof filter !== "undefined" && typeof filter !== "function") {
74
- console.warn(
75
- "Invalid filter function. Fallback: no filter function (undefined)."
76
- );
77
- filter = void 0;
78
- }
79
- if (typeof include !== "undefined" && typeof include !== "function") {
80
- console.warn(
81
- "Invalid include function. Fallback: no include function (undefined)."
82
- );
83
- include = void 0;
84
- }
85
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
86
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
87
- skipNegativeTabIndexCheck = false;
88
- }
89
- if (typeof skipVisibilityCheck !== "boolean") {
90
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
91
- skipVisibilityCheck = false;
92
- }
106
+ skipNegativeTabIndexCheck,
107
+ skipVisibilityCheck
108
+ } = resolveOptions2(options);
93
109
  const candidates = [];
94
110
  if (composed || include) {
95
111
  let traverse2 = function(node) {
@@ -133,15 +149,7 @@ function isFocusable(element, options = {}) {
133
149
  console.warn("Invalid element");
134
150
  return false;
135
151
  }
136
- let { skipNegativeTabIndexCheck = false, skipVisibilityCheck = false } = options;
137
- if (typeof skipNegativeTabIndexCheck !== "boolean") {
138
- console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
139
- skipNegativeTabIndexCheck = false;
140
- }
141
- if (typeof skipVisibilityCheck !== "boolean") {
142
- console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
143
- skipVisibilityCheck = false;
144
- }
152
+ const { skipNegativeTabIndexCheck, skipVisibilityCheck } = resolveOptions2(options);
145
153
  if (element.hasAttribute("hidden") || isInert(element)) {
146
154
  return false;
147
155
  }
@@ -316,6 +324,61 @@ function isInert(element) {
316
324
  function isUngroupedRadio(element) {
317
325
  return element.type === "radio" && !!element.name;
318
326
  }
327
+ function resolveOptions2(options) {
328
+ let {
329
+ anchor = getActiveElement(),
330
+ composed = false,
331
+ filter,
332
+ include,
333
+ skipNegativeTabIndexCheck = false,
334
+ skipVisibilityCheck = false,
335
+ wrap = false
336
+ } = options;
337
+ if (!(anchor instanceof Element)) {
338
+ const active = getActiveElement();
339
+ if (active instanceof Element) {
340
+ console.warn("Invalid anchor element. Fallback: active element.");
341
+ anchor = active;
342
+ }
343
+ }
344
+ if (typeof composed !== "boolean") {
345
+ console.warn("Invalid composed option. Fallback: false.");
346
+ composed = false;
347
+ }
348
+ if (filter !== void 0 && typeof filter !== "function") {
349
+ console.warn(
350
+ "Invalid filter function. Fallback: no filter function (undefined)."
351
+ );
352
+ filter = void 0;
353
+ }
354
+ if (include !== void 0 && typeof include !== "function") {
355
+ console.warn(
356
+ "Invalid include function. Fallback: no include function (undefined)."
357
+ );
358
+ include = void 0;
359
+ }
360
+ if (typeof skipNegativeTabIndexCheck !== "boolean") {
361
+ console.warn("Invalid skipNegativeTabIndexCheck option. Fallback: false.");
362
+ skipNegativeTabIndexCheck = false;
363
+ }
364
+ if (typeof skipVisibilityCheck !== "boolean") {
365
+ console.warn("Invalid skipVisibilityCheck option. Fallback: false.");
366
+ skipVisibilityCheck = false;
367
+ }
368
+ if (typeof wrap !== "boolean") {
369
+ console.warn("Invalid wrap option. Fallback: false.");
370
+ wrap = false;
371
+ }
372
+ return {
373
+ anchor,
374
+ composed,
375
+ filter,
376
+ include,
377
+ skipNegativeTabIndexCheck,
378
+ skipVisibilityCheck,
379
+ wrap
380
+ };
381
+ }
319
382
 
320
383
  // node_modules/@y14e/button/dist/index.js
321
384
  var Button = class {
@@ -387,56 +450,7 @@ var RovingTabIndex = class _RovingTabIndex {
387
450
  #isDestroyed = false;
388
451
  constructor(container, options = {}) {
389
452
  this.#container = container;
390
- let {
391
- direction = "both",
392
- navigationOnly = false,
393
- noMemory = false,
394
- noStart = false,
395
- selector = "",
396
- typeahead = false,
397
- wrap = false
398
- } = options;
399
- if (!["both", "horizontal", "vertical"].includes(direction)) {
400
- console.warn("Invalid direction option. Fallback: 'both'.");
401
- direction = "both";
402
- }
403
- if (typeof navigationOnly !== "boolean") {
404
- console.warn("Invalid navigationOnly option. Fallback: false.");
405
- navigationOnly = false;
406
- }
407
- if (typeof noMemory !== "boolean") {
408
- console.warn("Invalid noMemory option. Fallback: false.");
409
- noMemory = false;
410
- }
411
- if (typeof noStart !== "boolean") {
412
- console.warn("Invalid noStart option. Fallback: false.");
413
- noStart = false;
414
- }
415
- if (selector !== "") {
416
- try {
417
- document.querySelector(selector);
418
- } catch {
419
- console.warn("Invalid selector. Fallback: no selector string.");
420
- selector = "";
421
- }
422
- }
423
- if (typeof typeahead !== "boolean") {
424
- console.warn("Invalid typeahead option. Fallback: false.");
425
- typeahead = false;
426
- }
427
- if (typeof wrap !== "boolean") {
428
- console.warn("Invalid wrap option. Fallback: false.");
429
- wrap = false;
430
- }
431
- this.#settings = {
432
- direction,
433
- navigationOnly,
434
- noMemory,
435
- noStart,
436
- selector,
437
- typeahead,
438
- wrap
439
- };
453
+ this.#settings = this.#resolveOptions(options);
440
454
  this.#selectorFilter = this.#createSelectorFilter();
441
455
  this.#initialize();
442
456
  }
@@ -624,6 +638,58 @@ var RovingTabIndex = class _RovingTabIndex {
624
638
  skipVisibilityCheck: true
625
639
  });
626
640
  }
641
+ #resolveOptions(options) {
642
+ let {
643
+ direction = "both",
644
+ navigationOnly = false,
645
+ noMemory = false,
646
+ noStart = false,
647
+ selector = "",
648
+ typeahead = false,
649
+ wrap = false
650
+ } = options;
651
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
652
+ console.warn("Invalid direction option. Fallback: 'both'.");
653
+ direction = "both";
654
+ }
655
+ if (typeof navigationOnly !== "boolean") {
656
+ console.warn("Invalid navigationOnly option. Fallback: false.");
657
+ navigationOnly = false;
658
+ }
659
+ if (typeof noMemory !== "boolean") {
660
+ console.warn("Invalid noMemory option. Fallback: false.");
661
+ noMemory = false;
662
+ }
663
+ if (typeof noStart !== "boolean") {
664
+ console.warn("Invalid noStart option. Fallback: false.");
665
+ noStart = false;
666
+ }
667
+ if (selector !== "") {
668
+ try {
669
+ document.querySelector(selector);
670
+ } catch {
671
+ console.warn("Invalid selector. Fallback: no selector string.");
672
+ selector = "";
673
+ }
674
+ }
675
+ if (typeof typeahead !== "boolean") {
676
+ console.warn("Invalid typeahead option. Fallback: false.");
677
+ typeahead = false;
678
+ }
679
+ if (typeof wrap !== "boolean") {
680
+ console.warn("Invalid wrap option. Fallback: false.");
681
+ wrap = false;
682
+ }
683
+ return {
684
+ direction,
685
+ navigationOnly,
686
+ noMemory,
687
+ noStart,
688
+ selector,
689
+ typeahead,
690
+ wrap
691
+ };
692
+ }
627
693
  };
628
694
 
629
695
  // src/index.ts
@@ -893,7 +959,8 @@ var Accordion = class _Accordion {
893
959
  };
894
960
  const mergedAnimation = merged.animation;
895
961
  const duration = mergedAnimation.duration;
896
- const defaultAnimation = this.#defaults.animation;
962
+ const defaults = this.#defaults;
963
+ const defaultAnimation = defaults.animation;
897
964
  if (typeof duration !== "number" || Number.isNaN(duration)) {
898
965
  const duration2 = defaultAnimation.duration;
899
966
  console.warn(`Invalid animation duration. Fallback: ${duration2} (ms).`);
@@ -909,12 +976,12 @@ var Accordion = class _Accordion {
909
976
  mergedAnimation.easing = easing;
910
977
  }
911
978
  if (typeof merged.collapsible !== "boolean") {
912
- const collapsible = this.#defaults.collapsible;
979
+ const collapsible = defaults.collapsible;
913
980
  console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
914
981
  merged.collapsible = collapsible;
915
982
  }
916
983
  const mergedSelector = merged.selector;
917
- const defaultSelector = this.#defaults.selector;
984
+ const defaultSelector = defaults.selector;
918
985
  try {
919
986
  document.querySelector(mergedSelector.content);
920
987
  } catch {
@@ -949,7 +1016,7 @@ function waitAnimationFinish(animation) {
949
1016
  * Accordion
950
1017
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
951
1018
  *
952
- * @version 2.0.12
1019
+ * @version 2.0.14
953
1020
  * @author Yusuke Kamiyamane
954
1021
  * @license MIT
955
1022
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -961,7 +1028,7 @@ function waitAnimationFinish(animation) {
961
1028
  (**
962
1029
  * Attribute Utils
963
1030
  *
964
- * @version 2.0.5
1031
+ * @version 2.0.8
965
1032
  * @author Yusuke Kamiyamane
966
1033
  * @license MIT
967
1034
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -974,7 +1041,7 @@ power-focusable/dist/index.js:
974
1041
  * High-precision focus management utility with full composed tree support.
975
1042
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
976
1043
  *
977
- * @version 4.3.28
1044
+ * @version 4.3.29
978
1045
  * @author Yusuke Kamiyamane
979
1046
  * @license MIT
980
1047
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -998,7 +1065,7 @@ power-focusable/dist/index.js:
998
1065
  * Lightweight roving tabindex utility with fully focus management.
999
1066
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
1000
1067
  *
1001
- * @version 3.1.25
1068
+ * @version 3.1.27
1002
1069
  * @author Yusuke Kamiyamane
1003
1070
  * @license MIT
1004
1071
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -291,7 +291,8 @@ var Accordion = class _Accordion {
291
291
  };
292
292
  const mergedAnimation = merged.animation;
293
293
  const duration = mergedAnimation.duration;
294
- const defaultAnimation = this.#defaults.animation;
294
+ const defaults = this.#defaults;
295
+ const defaultAnimation = defaults.animation;
295
296
  if (typeof duration !== "number" || Number.isNaN(duration)) {
296
297
  const duration2 = defaultAnimation.duration;
297
298
  console.warn(`Invalid animation duration. Fallback: ${duration2} (ms).`);
@@ -307,12 +308,12 @@ var Accordion = class _Accordion {
307
308
  mergedAnimation.easing = easing;
308
309
  }
309
310
  if (typeof merged.collapsible !== "boolean") {
310
- const collapsible = this.#defaults.collapsible;
311
+ const collapsible = defaults.collapsible;
311
312
  console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
312
313
  merged.collapsible = collapsible;
313
314
  }
314
315
  const mergedSelector = merged.selector;
315
- const defaultSelector = this.#defaults.selector;
316
+ const defaultSelector = defaults.selector;
316
317
  try {
317
318
  document.querySelector(mergedSelector.content);
318
319
  } catch {
@@ -347,7 +348,7 @@ function waitAnimationFinish(animation) {
347
348
  * Accordion
348
349
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
349
350
  *
350
- * @version 2.0.12
351
+ * @version 2.0.14
351
352
  * @author Yusuke Kamiyamane
352
353
  * @license MIT
353
354
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Accordion
3
3
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.12
5
+ * @version 2.0.14
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
  * Accordion
3
3
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
4
4
  *
5
- * @version 2.0.12
5
+ * @version 2.0.14
6
6
  * @author Yusuke Kamiyamane
7
7
  * @license MIT
8
8
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -269,7 +269,8 @@ var Accordion = class _Accordion {
269
269
  };
270
270
  const mergedAnimation = merged.animation;
271
271
  const duration = mergedAnimation.duration;
272
- const defaultAnimation = this.#defaults.animation;
272
+ const defaults = this.#defaults;
273
+ const defaultAnimation = defaults.animation;
273
274
  if (typeof duration !== "number" || Number.isNaN(duration)) {
274
275
  const duration2 = defaultAnimation.duration;
275
276
  console.warn(`Invalid animation duration. Fallback: ${duration2} (ms).`);
@@ -285,12 +286,12 @@ var Accordion = class _Accordion {
285
286
  mergedAnimation.easing = easing;
286
287
  }
287
288
  if (typeof merged.collapsible !== "boolean") {
288
- const collapsible = this.#defaults.collapsible;
289
+ const collapsible = defaults.collapsible;
289
290
  console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
290
291
  merged.collapsible = collapsible;
291
292
  }
292
293
  const mergedSelector = merged.selector;
293
- const defaultSelector = this.#defaults.selector;
294
+ const defaultSelector = defaults.selector;
294
295
  try {
295
296
  document.querySelector(mergedSelector.content);
296
297
  } catch {
@@ -325,7 +326,7 @@ function waitAnimationFinish(animation) {
325
326
  * Accordion
326
327
  * WAI-ARIA compliant accordion pattern implementation in TypeScript.
327
328
  *
328
- * @version 2.0.12
329
+ * @version 2.0.14
329
330
  * @author Yusuke Kamiyamane
330
331
  * @license MIT
331
332
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/accordion",
3
- "version": "2.0.12",
3
+ "version": "2.0.14",
4
4
  "description": "WAI-ARIA compliant accordion pattern implementation in TypeScript",
5
5
  "keywords": [
6
6
  "a11y",
@@ -54,8 +54,8 @@
54
54
  "esbuild": true
55
55
  },
56
56
  "dependencies": {
57
- "@y14e/attribute-utils": "^2.0.5",
57
+ "@y14e/attribute-utils": "^2.0.8",
58
58
  "@y14e/button": "^1.0.8",
59
- "@y14e/roving-tabindex": "^3.1.25"
59
+ "@y14e/roving-tabindex": "^3.1.27"
60
60
  }
61
61
  }