@y14e/disclosure-css 2.0.7 → 2.0.9

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.7";
16
+ import { Disclosure } from "https://esm.sh/@y14e/disclosure-css@2.0.9";
17
17
  // or
18
- import { Disclosure } from "https://cdn.jsdelivr.net/npm/@y14e/disclosure-css@2.0.7/+esm";
18
+ import { Disclosure } from "https://cdn.jsdelivr.net/npm/@y14e/disclosure-css@2.0.9/+esm";
19
19
  // or
20
- import { Disclosure } from "https://esm.unpkg.com/@y14e/disclosure-css@2.0.7";
20
+ import { Disclosure } from "https://esm.unpkg.com/@y14e/disclosure-css@2.0.9";
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,45 @@ 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
+ if (!element.hasAttribute(name)) {
57
+ console.warn("Invalid attribute 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
+ }
52
90
 
53
91
  // node_modules/power-focusable/dist/index.js
54
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"])`;
@@ -366,17 +404,9 @@ var RovingTabIndex = class _RovingTabIndex {
366
404
  noStart = false;
367
405
  }
368
406
  if (selector !== "") {
369
- let hasError = false;
370
- if (typeof selector !== "string" || !selector.trim()) {
371
- hasError = true;
372
- } else {
373
- try {
374
- this.#container.querySelector(selector);
375
- } catch {
376
- hasError = true;
377
- }
378
- }
379
- if (hasError) {
407
+ try {
408
+ document.querySelector(selector);
409
+ } catch {
380
410
  console.warn("Invalid selector. Fallback: no selector string.");
381
411
  selector = "";
382
412
  }
@@ -609,8 +639,8 @@ var Disclosure = class _Disclosure {
609
639
  return;
610
640
  }
611
641
  this.#rootElement = root;
612
- this.#defaults = this.#mergeOptions(this.#defaults, _Disclosure.defaults);
613
- this.#settings = this.#mergeOptions(this.#defaults, options);
642
+ this.#defaults = this.#resolveOptions(this.#defaults, _Disclosure.defaults);
643
+ this.#settings = this.#resolveOptions(this.#defaults, options);
614
644
  const NOT_NESTED = ":not(:scope summary + * *)";
615
645
  this.#detailsElements = [
616
646
  ...this.#rootElement.querySelectorAll(
@@ -739,8 +769,14 @@ var Disclosure = class _Disclosure {
739
769
  #isFocusable(element) {
740
770
  return element.tabIndex >= 0;
741
771
  }
742
- #mergeOptions(target, source) {
743
- return { ...target, ...source };
772
+ #resolveOptions(target, source) {
773
+ const merged = { ...target, ...source };
774
+ if (typeof merged.collapsible !== "boolean") {
775
+ const collapsible = this.#defaults.collapsible;
776
+ console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
777
+ merged.collapsible = collapsible;
778
+ }
779
+ return merged;
744
780
  }
745
781
  };
746
782
  /**
@@ -748,7 +784,7 @@ var Disclosure = class _Disclosure {
748
784
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
749
785
  * Using the <details> and <summary> element.
750
786
  *
751
- * @version 2.0.7
787
+ * @version 2.0.9
752
788
  * @author Yusuke Kamiyamane
753
789
  * @license MIT
754
790
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -760,7 +796,7 @@ var Disclosure = class _Disclosure {
760
796
  (**
761
797
  * Attribute Utils
762
798
  *
763
- * @version 2.0.5
799
+ * @version 2.0.6
764
800
  * @author Yusuke Kamiyamane
765
801
  * @license MIT
766
802
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -773,7 +809,7 @@ power-focusable/dist/index.js:
773
809
  * High-precision focus management utility with full composed tree support.
774
810
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
775
811
  *
776
- * @version 4.3.26
812
+ * @version 4.3.28
777
813
  * @author Yusuke Kamiyamane
778
814
  * @license MIT
779
815
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -786,7 +822,7 @@ power-focusable/dist/index.js:
786
822
  * Lightweight roving tabindex utility with fully focus management.
787
823
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
788
824
  *
789
- * @version 3.1.23
825
+ * @version 3.1.25
790
826
  * @author Yusuke Kamiyamane
791
827
  * @license MIT
792
828
  * @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,45 @@ 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
+ if (!element.hasAttribute(name)) {
55
+ console.warn("Invalid attribute name");
56
+ return false;
57
+ }
58
+ if (typeof token !== "string" || !token.trim()) {
59
+ console.warn("Invalid token");
60
+ return false;
61
+ }
62
+ return true;
63
+ }
64
+ function resolveOptions(options) {
65
+ let {
66
+ caseInsensitive = false,
67
+ parse = DEFAULT_PARSER,
68
+ serialize = DEFAULT_SERIALIZER
69
+ } = options;
70
+ if (typeof caseInsensitive !== "boolean") {
71
+ console.warn("Invalid caseInsensitive option. Fallback: false.");
72
+ caseInsensitive = false;
73
+ }
74
+ if (typeof parse !== "function") {
75
+ console.warn(
76
+ "Invalid parser. Fallback: default parser (splits by whitespace)."
77
+ );
78
+ parse = DEFAULT_PARSER;
79
+ }
80
+ if (typeof serialize !== "function") {
81
+ console.warn(
82
+ "Invalid serializer. Fallback: default serializer (joins by whitespace)."
83
+ );
84
+ serialize = DEFAULT_SERIALIZER;
85
+ }
86
+ return { caseInsensitive, parse, serialize };
87
+ }
50
88
 
51
89
  // node_modules/power-focusable/dist/index.js
52
90
  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"])`;
@@ -364,17 +402,9 @@ var RovingTabIndex = class _RovingTabIndex {
364
402
  noStart = false;
365
403
  }
366
404
  if (selector !== "") {
367
- let hasError = false;
368
- if (typeof selector !== "string" || !selector.trim()) {
369
- hasError = true;
370
- } else {
371
- try {
372
- this.#container.querySelector(selector);
373
- } catch {
374
- hasError = true;
375
- }
376
- }
377
- if (hasError) {
405
+ try {
406
+ document.querySelector(selector);
407
+ } catch {
378
408
  console.warn("Invalid selector. Fallback: no selector string.");
379
409
  selector = "";
380
410
  }
@@ -607,8 +637,8 @@ var Disclosure = class _Disclosure {
607
637
  return;
608
638
  }
609
639
  this.#rootElement = root;
610
- this.#defaults = this.#mergeOptions(this.#defaults, _Disclosure.defaults);
611
- this.#settings = this.#mergeOptions(this.#defaults, options);
640
+ this.#defaults = this.#resolveOptions(this.#defaults, _Disclosure.defaults);
641
+ this.#settings = this.#resolveOptions(this.#defaults, options);
612
642
  const NOT_NESTED = ":not(:scope summary + * *)";
613
643
  this.#detailsElements = [
614
644
  ...this.#rootElement.querySelectorAll(
@@ -737,8 +767,14 @@ var Disclosure = class _Disclosure {
737
767
  #isFocusable(element) {
738
768
  return element.tabIndex >= 0;
739
769
  }
740
- #mergeOptions(target, source) {
741
- return { ...target, ...source };
770
+ #resolveOptions(target, source) {
771
+ const merged = { ...target, ...source };
772
+ if (typeof merged.collapsible !== "boolean") {
773
+ const collapsible = this.#defaults.collapsible;
774
+ console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
775
+ merged.collapsible = collapsible;
776
+ }
777
+ return merged;
742
778
  }
743
779
  };
744
780
  /**
@@ -746,7 +782,7 @@ var Disclosure = class _Disclosure {
746
782
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
747
783
  * Using the <details> and <summary> element.
748
784
  *
749
- * @version 2.0.7
785
+ * @version 2.0.9
750
786
  * @author Yusuke Kamiyamane
751
787
  * @license MIT
752
788
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -758,7 +794,7 @@ var Disclosure = class _Disclosure {
758
794
  (**
759
795
  * Attribute Utils
760
796
  *
761
- * @version 2.0.5
797
+ * @version 2.0.6
762
798
  * @author Yusuke Kamiyamane
763
799
  * @license MIT
764
800
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -771,7 +807,7 @@ power-focusable/dist/index.js:
771
807
  * High-precision focus management utility with full composed tree support.
772
808
  * Handles complex focus rules including tabindex ordering, radio groups, inert.
773
809
  *
774
- * @version 4.3.26
810
+ * @version 4.3.28
775
811
  * @author Yusuke Kamiyamane
776
812
  * @license MIT
777
813
  * @copyright Copyright (c) Yusuke Kamiyamane
@@ -784,7 +820,7 @@ power-focusable/dist/index.js:
784
820
  * Lightweight roving tabindex utility with fully focus management.
785
821
  * Designed for accessible menus, tabs, toolbars, and composite widgets.
786
822
  *
787
- * @version 3.1.23
823
+ * @version 3.1.25
788
824
  * @author Yusuke Kamiyamane
789
825
  * @license MIT
790
826
  * @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,8 +175,14 @@ var Disclosure = class _Disclosure {
175
175
  #isFocusable(element) {
176
176
  return element.tabIndex >= 0;
177
177
  }
178
- #mergeOptions(target, source) {
179
- return { ...target, ...source };
178
+ #resolveOptions(target, source) {
179
+ const merged = { ...target, ...source };
180
+ if (typeof merged.collapsible !== "boolean") {
181
+ const collapsible = this.#defaults.collapsible;
182
+ console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
183
+ merged.collapsible = collapsible;
184
+ }
185
+ return merged;
180
186
  }
181
187
  };
182
188
  /**
@@ -184,7 +190,7 @@ var Disclosure = class _Disclosure {
184
190
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
185
191
  * Using the <details> and <summary> element.
186
192
  *
187
- * @version 2.0.7
193
+ * @version 2.0.9
188
194
  * @author Yusuke Kamiyamane
189
195
  * @license MIT
190
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.7
6
+ * @version 2.0.9
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.7
6
+ * @version 2.0.9
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,8 +153,14 @@ var Disclosure = class _Disclosure {
153
153
  #isFocusable(element) {
154
154
  return element.tabIndex >= 0;
155
155
  }
156
- #mergeOptions(target, source) {
157
- return { ...target, ...source };
156
+ #resolveOptions(target, source) {
157
+ const merged = { ...target, ...source };
158
+ if (typeof merged.collapsible !== "boolean") {
159
+ const collapsible = this.#defaults.collapsible;
160
+ console.warn(`Invalid collapsible option. Fallback: ${collapsible}.`);
161
+ merged.collapsible = collapsible;
162
+ }
163
+ return merged;
158
164
  }
159
165
  };
160
166
  /**
@@ -162,7 +168,7 @@ var Disclosure = class _Disclosure {
162
168
  * WAI-ARIA compliant disclosure pattern implementation in TypeScript.
163
169
  * Using the <details> and <summary> element.
164
170
  *
165
- * @version 2.0.7
171
+ * @version 2.0.9
166
172
  * @author Yusuke Kamiyamane
167
173
  * @license MIT
168
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.7",
3
+ "version": "2.0.9",
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.23"
57
+ "@y14e/attribute-utils": "^2.0.6",
58
+ "@y14e/roving-tabindex": "^3.1.25"
59
59
  }
60
60
  }