@y14e/disclosure-css 2.0.8 → 2.0.10

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/disclosure-css
13
13
  import { Disclosure } from "@y14e/disclosure-css";
14
14
 
15
15
  // CDNs
16
- import { Disclosure } from "https://esm.sh/@y14e/disclosure-css@2.0.8";
16
+ import { Disclosure } from "https://esm.sh/@y14e/disclosure-css@2.0.10";
17
17
  // or
18
- import { Disclosure } from "https://cdn.jsdelivr.net/npm/@y14e/disclosure-css@2.0.8/+esm";
18
+ import { Disclosure } from "https://cdn.jsdelivr.net/npm/@y14e/disclosure-css@2.0.10/+esm";
19
19
  // or
20
- import { Disclosure } from "https://esm.unpkg.com/@y14e/disclosure-css@2.0.8";
20
+ import { Disclosure } from "https://esm.unpkg.com/@y14e/disclosure-css@2.0.10";
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/roving-tabindex/dist/index.js
323
386
  function createRovingTabIndex(container, options = {}) {
@@ -340,56 +403,7 @@ var RovingTabIndex = class _RovingTabIndex {
340
403
  #isDestroyed = false;
341
404
  constructor(container, options = {}) {
342
405
  this.#container = container;
343
- let {
344
- direction = "both",
345
- navigationOnly = false,
346
- noMemory = false,
347
- noStart = false,
348
- selector = "",
349
- typeahead = false,
350
- wrap = false
351
- } = options;
352
- if (!["both", "horizontal", "vertical"].includes(direction)) {
353
- console.warn("Invalid direction option. Fallback: 'both'.");
354
- direction = "both";
355
- }
356
- if (typeof navigationOnly !== "boolean") {
357
- console.warn("Invalid navigationOnly option. Fallback: false.");
358
- navigationOnly = false;
359
- }
360
- if (typeof noMemory !== "boolean") {
361
- console.warn("Invalid noMemory option. Fallback: false.");
362
- noMemory = false;
363
- }
364
- if (typeof noStart !== "boolean") {
365
- console.warn("Invalid noStart option. Fallback: false.");
366
- noStart = false;
367
- }
368
- if (selector !== "") {
369
- try {
370
- document.querySelector(selector);
371
- } catch {
372
- console.warn("Invalid selector. Fallback: no selector string.");
373
- selector = "";
374
- }
375
- }
376
- if (typeof typeahead !== "boolean") {
377
- console.warn("Invalid typeahead option. Fallback: false.");
378
- typeahead = false;
379
- }
380
- if (typeof wrap !== "boolean") {
381
- console.warn("Invalid wrap option. Fallback: false.");
382
- wrap = false;
383
- }
384
- this.#settings = {
385
- direction,
386
- navigationOnly,
387
- noMemory,
388
- noStart,
389
- selector,
390
- typeahead,
391
- wrap
392
- };
406
+ this.#settings = this.#resolveOptions(options);
393
407
  this.#selectorFilter = this.#createSelectorFilter();
394
408
  this.#initialize();
395
409
  }
@@ -577,6 +591,58 @@ var RovingTabIndex = class _RovingTabIndex {
577
591
  skipVisibilityCheck: true
578
592
  });
579
593
  }
594
+ #resolveOptions(options) {
595
+ let {
596
+ direction = "both",
597
+ navigationOnly = false,
598
+ noMemory = false,
599
+ noStart = false,
600
+ selector = "",
601
+ typeahead = false,
602
+ wrap = false
603
+ } = options;
604
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
605
+ console.warn("Invalid direction option. Fallback: 'both'.");
606
+ direction = "both";
607
+ }
608
+ if (typeof navigationOnly !== "boolean") {
609
+ console.warn("Invalid navigationOnly option. Fallback: false.");
610
+ navigationOnly = false;
611
+ }
612
+ if (typeof noMemory !== "boolean") {
613
+ console.warn("Invalid noMemory option. Fallback: false.");
614
+ noMemory = false;
615
+ }
616
+ if (typeof noStart !== "boolean") {
617
+ console.warn("Invalid noStart option. Fallback: false.");
618
+ noStart = false;
619
+ }
620
+ if (selector !== "") {
621
+ try {
622
+ document.querySelector(selector);
623
+ } catch {
624
+ console.warn("Invalid selector. Fallback: no selector string.");
625
+ selector = "";
626
+ }
627
+ }
628
+ if (typeof typeahead !== "boolean") {
629
+ console.warn("Invalid typeahead option. Fallback: false.");
630
+ typeahead = false;
631
+ }
632
+ if (typeof wrap !== "boolean") {
633
+ console.warn("Invalid wrap option. Fallback: false.");
634
+ wrap = false;
635
+ }
636
+ return {
637
+ direction,
638
+ navigationOnly,
639
+ noMemory,
640
+ noStart,
641
+ selector,
642
+ typeahead,
643
+ wrap
644
+ };
645
+ }
580
646
  };
581
647
 
582
648
  // src/index.ts
@@ -601,8 +667,8 @@ var Disclosure = class _Disclosure {
601
667
  return;
602
668
  }
603
669
  this.#rootElement = root;
604
- this.#defaults = this.#mergeOptions(this.#defaults, _Disclosure.defaults);
605
- this.#settings = this.#mergeOptions(this.#defaults, options);
670
+ this.#defaults = this.#resolveOptions(this.#defaults, _Disclosure.defaults);
671
+ this.#settings = this.#resolveOptions(this.#defaults, options);
606
672
  const NOT_NESTED = ":not(:scope summary + * *)";
607
673
  this.#detailsElements = [
608
674
  ...this.#rootElement.querySelectorAll(
@@ -731,7 +797,7 @@ var Disclosure = class _Disclosure {
731
797
  #isFocusable(element) {
732
798
  return element.tabIndex >= 0;
733
799
  }
734
- #mergeOptions(target, source) {
800
+ #resolveOptions(target, source) {
735
801
  const merged = { ...target, ...source };
736
802
  if (typeof merged.collapsible !== "boolean") {
737
803
  const collapsible = this.#defaults.collapsible;
@@ -746,7 +812,7 @@ var Disclosure = class _Disclosure {
746
812
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
747
813
  * Using the <details> and <summary> element.
748
814
  *
749
- * @version 2.0.8
815
+ * @version 2.0.10
750
816
  * @author Yusuke Kamiyamane
751
817
  * @license MIT
752
818
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -758,7 +824,7 @@ var Disclosure = class _Disclosure {
758
824
  (**
759
825
  * Attribute Utils
760
826
  *
761
- * @version 2.0.5
827
+ * @version 2.0.8
762
828
  * @author Yusuke Kamiyamane
763
829
  * @license MIT
764
830
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -771,7 +837,7 @@ power-focusable/dist/index.js:
771
837
  * High-precision focus management utility with full composed tree support.
772
838
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
773
839
  *
774
- * @version 4.3.28
840
+ * @version 4.3.29
775
841
  * @author Yusuke Kamiyamane
776
842
  * @license MIT
777
843
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -784,7 +850,7 @@ power-focusable/dist/index.js:
784
850
  * Lightweight roving tabindex utility with fully focus management.
785
851
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
786
852
  *
787
- * @version 3.1.25
853
+ * @version 3.1.27
788
854
  * @author Yusuke Kamiyamane
789
855
  * @license MIT
790
856
  * @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/roving-tabindex/dist/index.js
321
384
  function createRovingTabIndex(container, options = {}) {
@@ -338,56 +401,7 @@ var RovingTabIndex = class _RovingTabIndex {
338
401
  #isDestroyed = false;
339
402
  constructor(container, options = {}) {
340
403
  this.#container = container;
341
- let {
342
- direction = "both",
343
- navigationOnly = false,
344
- noMemory = false,
345
- noStart = false,
346
- selector = "",
347
- typeahead = false,
348
- wrap = false
349
- } = options;
350
- if (!["both", "horizontal", "vertical"].includes(direction)) {
351
- console.warn("Invalid direction option. Fallback: 'both'.");
352
- direction = "both";
353
- }
354
- if (typeof navigationOnly !== "boolean") {
355
- console.warn("Invalid navigationOnly option. Fallback: false.");
356
- navigationOnly = false;
357
- }
358
- if (typeof noMemory !== "boolean") {
359
- console.warn("Invalid noMemory option. Fallback: false.");
360
- noMemory = false;
361
- }
362
- if (typeof noStart !== "boolean") {
363
- console.warn("Invalid noStart option. Fallback: false.");
364
- noStart = false;
365
- }
366
- if (selector !== "") {
367
- try {
368
- document.querySelector(selector);
369
- } catch {
370
- console.warn("Invalid selector. Fallback: no selector string.");
371
- selector = "";
372
- }
373
- }
374
- if (typeof typeahead !== "boolean") {
375
- console.warn("Invalid typeahead option. Fallback: false.");
376
- typeahead = false;
377
- }
378
- if (typeof wrap !== "boolean") {
379
- console.warn("Invalid wrap option. Fallback: false.");
380
- wrap = false;
381
- }
382
- this.#settings = {
383
- direction,
384
- navigationOnly,
385
- noMemory,
386
- noStart,
387
- selector,
388
- typeahead,
389
- wrap
390
- };
404
+ this.#settings = this.#resolveOptions(options);
391
405
  this.#selectorFilter = this.#createSelectorFilter();
392
406
  this.#initialize();
393
407
  }
@@ -575,6 +589,58 @@ var RovingTabIndex = class _RovingTabIndex {
575
589
  skipVisibilityCheck: true
576
590
  });
577
591
  }
592
+ #resolveOptions(options) {
593
+ let {
594
+ direction = "both",
595
+ navigationOnly = false,
596
+ noMemory = false,
597
+ noStart = false,
598
+ selector = "",
599
+ typeahead = false,
600
+ wrap = false
601
+ } = options;
602
+ if (!["both", "horizontal", "vertical"].includes(direction)) {
603
+ console.warn("Invalid direction option. Fallback: 'both'.");
604
+ direction = "both";
605
+ }
606
+ if (typeof navigationOnly !== "boolean") {
607
+ console.warn("Invalid navigationOnly option. Fallback: false.");
608
+ navigationOnly = false;
609
+ }
610
+ if (typeof noMemory !== "boolean") {
611
+ console.warn("Invalid noMemory option. Fallback: false.");
612
+ noMemory = false;
613
+ }
614
+ if (typeof noStart !== "boolean") {
615
+ console.warn("Invalid noStart option. Fallback: false.");
616
+ noStart = false;
617
+ }
618
+ if (selector !== "") {
619
+ try {
620
+ document.querySelector(selector);
621
+ } catch {
622
+ console.warn("Invalid selector. Fallback: no selector string.");
623
+ selector = "";
624
+ }
625
+ }
626
+ if (typeof typeahead !== "boolean") {
627
+ console.warn("Invalid typeahead option. Fallback: false.");
628
+ typeahead = false;
629
+ }
630
+ if (typeof wrap !== "boolean") {
631
+ console.warn("Invalid wrap option. Fallback: false.");
632
+ wrap = false;
633
+ }
634
+ return {
635
+ direction,
636
+ navigationOnly,
637
+ noMemory,
638
+ noStart,
639
+ selector,
640
+ typeahead,
641
+ wrap
642
+ };
643
+ }
578
644
  };
579
645
 
580
646
  // src/index.ts
@@ -599,8 +665,8 @@ var Disclosure = class _Disclosure {
599
665
  return;
600
666
  }
601
667
  this.#rootElement = root;
602
- this.#defaults = this.#mergeOptions(this.#defaults, _Disclosure.defaults);
603
- this.#settings = this.#mergeOptions(this.#defaults, options);
668
+ this.#defaults = this.#resolveOptions(this.#defaults, _Disclosure.defaults);
669
+ this.#settings = this.#resolveOptions(this.#defaults, options);
604
670
  const NOT_NESTED = ":not(:scope summary + * *)";
605
671
  this.#detailsElements = [
606
672
  ...this.#rootElement.querySelectorAll(
@@ -729,7 +795,7 @@ var Disclosure = class _Disclosure {
729
795
  #isFocusable(element) {
730
796
  return element.tabIndex >= 0;
731
797
  }
732
- #mergeOptions(target, source) {
798
+ #resolveOptions(target, source) {
733
799
  const merged = { ...target, ...source };
734
800
  if (typeof merged.collapsible !== "boolean") {
735
801
  const collapsible = this.#defaults.collapsible;
@@ -744,7 +810,7 @@ var Disclosure = class _Disclosure {
744
810
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
745
811
  * Using the <details> and <summary> element.
746
812
  *
747
- * @version 2.0.8
813
+ * @version 2.0.10
748
814
  * @author Yusuke Kamiyamane
749
815
  * @license MIT
750
816
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -756,7 +822,7 @@ var Disclosure = class _Disclosure {
756
822
  (**
757
823
  * Attribute Utils
758
824
  *
759
- * @version 2.0.5
825
+ * @version 2.0.8
760
826
  * @author Yusuke Kamiyamane
761
827
  * @license MIT
762
828
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -769,7 +835,7 @@ power-focusable/dist/index.js:
769
835
  * High-precision focus management utility with full composed tree support.
770
836
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
771
837
  *
772
- * @version 4.3.28
838
+ * @version 4.3.29
773
839
  * @author Yusuke Kamiyamane
774
840
  * @license MIT
775
841
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -782,7 +848,7 @@ power-focusable/dist/index.js:
782
848
  * Lightweight roving tabindex utility with fully focus management.
783
849
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
784
850
  *
785
- * @version 3.1.25
851
+ * @version 3.1.27
786
852
  * @author Yusuke Kamiyamane
787
853
  * @license MIT
788
854
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.cjs CHANGED
@@ -45,8 +45,8 @@ var Disclosure = class _Disclosure {
45
45
  return;
46
46
  }
47
47
  this.#rootElement = root;
48
- this.#defaults = this.#mergeOptions(this.#defaults, _Disclosure.defaults);
49
- this.#settings = this.#mergeOptions(this.#defaults, options);
48
+ this.#defaults = this.#resolveOptions(this.#defaults, _Disclosure.defaults);
49
+ this.#settings = this.#resolveOptions(this.#defaults, options);
50
50
  const NOT_NESTED = ":not(:scope summary + * *)";
51
51
  this.#detailsElements = [
52
52
  ...this.#rootElement.querySelectorAll(
@@ -175,7 +175,7 @@ var Disclosure = class _Disclosure {
175
175
  #isFocusable(element) {
176
176
  return element.tabIndex >= 0;
177
177
  }
178
- #mergeOptions(target, source) {
178
+ #resolveOptions(target, source) {
179
179
  const merged = { ...target, ...source };
180
180
  if (typeof merged.collapsible !== "boolean") {
181
181
  const collapsible = this.#defaults.collapsible;
@@ -190,7 +190,7 @@ var Disclosure = class _Disclosure {
190
190
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
191
191
  * Using the <details> and <summary> element.
192
192
  *
193
- * @version 2.0.8
193
+ * @version 2.0.10
194
194
  * @author Yusuke Kamiyamane
195
195
  * @license MIT
196
196
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@
3
3
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
4
4
  * Using the <details> and <summary> element.
5
5
  *
6
- * @version 2.0.8
6
+ * @version 2.0.10
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
4
4
  * Using the <details> and <summary> element.
5
5
  *
6
- * @version 2.0.8
6
+ * @version 2.0.10
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -23,8 +23,8 @@ var Disclosure = class _Disclosure {
23
23
  return;
24
24
  }
25
25
  this.#rootElement = root;
26
- this.#defaults = this.#mergeOptions(this.#defaults, _Disclosure.defaults);
27
- this.#settings = this.#mergeOptions(this.#defaults, options);
26
+ this.#defaults = this.#resolveOptions(this.#defaults, _Disclosure.defaults);
27
+ this.#settings = this.#resolveOptions(this.#defaults, options);
28
28
  const NOT_NESTED = ":not(:scope summary + * *)";
29
29
  this.#detailsElements = [
30
30
  ...this.#rootElement.querySelectorAll(
@@ -153,7 +153,7 @@ var Disclosure = class _Disclosure {
153
153
  #isFocusable(element) {
154
154
  return element.tabIndex >= 0;
155
155
  }
156
- #mergeOptions(target, source) {
156
+ #resolveOptions(target, source) {
157
157
  const merged = { ...target, ...source };
158
158
  if (typeof merged.collapsible !== "boolean") {
159
159
  const collapsible = this.#defaults.collapsible;
@@ -168,7 +168,7 @@ var Disclosure = class _Disclosure {
168
168
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
169
169
  * Using the <details> and <summary> element.
170
170
  *
171
- * @version 2.0.8
171
+ * @version 2.0.10
172
172
  * @author Yusuke Kamiyamane
173
173
  * @license MIT
174
174
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@y14e/disclosure-css",
3
- "version": "2.0.8",
3
+ "version": "2.0.10",
4
4
  "description": "WAI-ARIA compliant disclosure pattern implementation in TypeScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -54,7 +54,7 @@
54
54
  "esbuild": true
55
55
  },
56
56
  "dependencies": {
57
- "@y14e/attribute-utils": "^2.0.5",
58
- "@y14e/roving-tabindex": "^3.1.25"
57
+ "@y14e/attribute-utils": "^2.0.8",
58
+ "@y14e/roving-tabindex": "^3.1.27"
59
59
  }
60
60
  }