power-focusable 2.1.2 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -21,7 +21,7 @@ function getFocusables(container = document.body, options = {}) {
21
21
  }
22
22
  } else if (node instanceof HTMLSlotElement) {
23
23
  const assigned = node.assignedElements({ flatten: true });
24
- if (assigned.length > 0) {
24
+ if (assigned.length) {
25
25
  for (let i = 0, l = assigned.length; i < l; i++) {
26
26
  walk2(assigned[i]);
27
27
  }
@@ -64,7 +64,7 @@ function hasFocusable(container = document.body, options = {}) {
64
64
  console.warn("Invalid container element. Fallback: <body> element.");
65
65
  container = document.body;
66
66
  }
67
- return getFocusables(container, options).length > 0;
67
+ return !!getFocusables(container, options).length;
68
68
  }
69
69
  function isFocusable(element) {
70
70
  if (!(element instanceof HTMLElement)) {
@@ -74,9 +74,9 @@ function isFocusable(element) {
74
74
  if (element.hasAttribute("hidden") || element.hasAttribute("inert")) {
75
75
  return false;
76
76
  }
77
- const tabIndex = element.getAttribute("tabindex");
78
- if (tabIndex !== null) {
79
- if (Number(tabIndex) < 0) {
77
+ const index = element.getAttribute("tabindex");
78
+ if (index) {
79
+ if (Number(index) < 0) {
80
80
  return false;
81
81
  }
82
82
  }
@@ -95,15 +95,15 @@ function isFocusable(element) {
95
95
  }
96
96
  return true;
97
97
  }
98
- function getRelativeFocusable(container, offset = 0, options) {
98
+ function getRelativeFocusable(container, offset, options) {
99
99
  const { active: a = null, composed = false, wrap = false } = options;
100
100
  const focusables = getFocusables(container, { composed });
101
101
  const { length } = focusables;
102
- if (length === 0) {
102
+ if (!length) {
103
103
  return null;
104
104
  }
105
105
  const active = a ?? getActiveElement();
106
- if (active === null || !containsDeep(container, active)) {
106
+ if (!active || !containsDeep(container, active)) {
107
107
  return null;
108
108
  }
109
109
  const currentIndex = focusables.indexOf(active);
@@ -118,7 +118,7 @@ function getRelativeFocusable(container, offset = 0, options) {
118
118
  }
119
119
  function containsDeep(container, element) {
120
120
  function walk(node) {
121
- if (node === null) {
121
+ if (!node) {
122
122
  return false;
123
123
  }
124
124
  if (node === container) {
@@ -133,7 +133,7 @@ function containsDeep(container, element) {
133
133
  }
134
134
  function getActiveElement() {
135
135
  function walk(node) {
136
- if (node === null) {
136
+ if (!node) {
137
137
  return null;
138
138
  }
139
139
  const active = node.shadowRoot?.activeElement;
@@ -147,16 +147,16 @@ function getTabIndex(element) {
147
147
  if (cached !== void 0) {
148
148
  return cached;
149
149
  }
150
- const number = Number(element.getAttribute("tabindex"));
151
- tabIndexCache.set(element, number);
152
- return number;
150
+ const index = Number(element.getAttribute("tabindex"));
151
+ tabIndexCache.set(element, index);
152
+ return index;
153
153
  }
154
154
  function isDisabled(element) {
155
155
  return "disabled" in element && element.disabled;
156
156
  }
157
157
  function isDisabledDeep(element) {
158
158
  function walk(node) {
159
- if (node === null) {
159
+ if (!node) {
160
160
  return false;
161
161
  }
162
162
  if (node instanceof ShadowRoot) {
@@ -189,26 +189,22 @@ function normalizeRadioGroup(elements) {
189
189
  let map = null;
190
190
  for (let i = 0, l = elements.length; i < l; i++) {
191
191
  const element = elements[i];
192
- if (element instanceof HTMLInputElement && element.type === "radio" && element.name) {
193
- if (!map) {
194
- map = /* @__PURE__ */ new Map();
195
- }
196
- const key = `${element.form?.id ?? "no-form"}::${element.name}`;
197
- const group = map.get(key) ?? map.set(key, []).get(key);
198
- group[group.length] = element;
192
+ if (!(element instanceof HTMLInputElement) || element.type !== "radio" || !element.name) {
193
+ continue;
194
+ }
195
+ if (!map) {
196
+ map = /* @__PURE__ */ new Map();
199
197
  }
198
+ const key = `${element.form?.id ?? "no-form"}::${element.name}`;
199
+ const group = map.get(key) ?? map.set(key, []).get(key);
200
+ group[group.length] = element;
200
201
  }
201
202
  if (!map) {
202
203
  return elements;
203
204
  }
204
205
  const placeholder = /* @__PURE__ */ new Set();
205
206
  for (const group of map.values()) {
206
- if (group.length > 0) {
207
- const enabled = group.filter(isFocusable);
208
- if (enabled.length > 0) {
209
- placeholder.add(enabled.find((radio) => radio.checked) ?? enabled[0]);
210
- }
211
- }
207
+ placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
212
208
  }
213
209
  return elements.filter((element) => {
214
210
  if (element instanceof HTMLInputElement && element.type === "radio" && element.name) {
@@ -241,7 +237,7 @@ function sortByTabIndex(elements) {
241
237
  * High-precision focus management utility with shadow DOM support.
242
238
  * Handles complex focus rules including tabindex ordering, radio groups, etc.
243
239
  *
244
- * @version 2.1.2
240
+ * @version 2.1.4
245
241
  * @author Yusuke Kamiyamane
246
242
  * @license MIT
247
243
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@
3
3
  * High-precision focus management utility with shadow DOM support.
4
4
  * Handles complex focus rules including tabindex ordering, radio groups, etc.
5
5
  *
6
- * @version 2.1.2
6
+ * @version 2.1.4
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
  * High-precision focus management utility with shadow DOM support.
4
4
  * Handles complex focus rules including tabindex ordering, radio groups, etc.
5
5
  *
6
- * @version 2.1.2
6
+ * @version 2.1.4
7
7
  * @author Yusuke Kamiyamane
8
8
  * @license MIT
9
9
  * @copyright Copyright (c) Yusuke Kamiyamane
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ function getFocusables(container = document.body, options = {}) {
19
19
  }
20
20
  } else if (node instanceof HTMLSlotElement) {
21
21
  const assigned = node.assignedElements({ flatten: true });
22
- if (assigned.length > 0) {
22
+ if (assigned.length) {
23
23
  for (let i = 0, l = assigned.length; i < l; i++) {
24
24
  walk2(assigned[i]);
25
25
  }
@@ -62,7 +62,7 @@ function hasFocusable(container = document.body, options = {}) {
62
62
  console.warn("Invalid container element. Fallback: <body> element.");
63
63
  container = document.body;
64
64
  }
65
- return getFocusables(container, options).length > 0;
65
+ return !!getFocusables(container, options).length;
66
66
  }
67
67
  function isFocusable(element) {
68
68
  if (!(element instanceof HTMLElement)) {
@@ -72,9 +72,9 @@ function isFocusable(element) {
72
72
  if (element.hasAttribute("hidden") || element.hasAttribute("inert")) {
73
73
  return false;
74
74
  }
75
- const tabIndex = element.getAttribute("tabindex");
76
- if (tabIndex !== null) {
77
- if (Number(tabIndex) < 0) {
75
+ const index = element.getAttribute("tabindex");
76
+ if (index) {
77
+ if (Number(index) < 0) {
78
78
  return false;
79
79
  }
80
80
  }
@@ -93,15 +93,15 @@ function isFocusable(element) {
93
93
  }
94
94
  return true;
95
95
  }
96
- function getRelativeFocusable(container, offset = 0, options) {
96
+ function getRelativeFocusable(container, offset, options) {
97
97
  const { active: a = null, composed = false, wrap = false } = options;
98
98
  const focusables = getFocusables(container, { composed });
99
99
  const { length } = focusables;
100
- if (length === 0) {
100
+ if (!length) {
101
101
  return null;
102
102
  }
103
103
  const active = a ?? getActiveElement();
104
- if (active === null || !containsDeep(container, active)) {
104
+ if (!active || !containsDeep(container, active)) {
105
105
  return null;
106
106
  }
107
107
  const currentIndex = focusables.indexOf(active);
@@ -116,7 +116,7 @@ function getRelativeFocusable(container, offset = 0, options) {
116
116
  }
117
117
  function containsDeep(container, element) {
118
118
  function walk(node) {
119
- if (node === null) {
119
+ if (!node) {
120
120
  return false;
121
121
  }
122
122
  if (node === container) {
@@ -131,7 +131,7 @@ function containsDeep(container, element) {
131
131
  }
132
132
  function getActiveElement() {
133
133
  function walk(node) {
134
- if (node === null) {
134
+ if (!node) {
135
135
  return null;
136
136
  }
137
137
  const active = node.shadowRoot?.activeElement;
@@ -145,16 +145,16 @@ function getTabIndex(element) {
145
145
  if (cached !== void 0) {
146
146
  return cached;
147
147
  }
148
- const number = Number(element.getAttribute("tabindex"));
149
- tabIndexCache.set(element, number);
150
- return number;
148
+ const index = Number(element.getAttribute("tabindex"));
149
+ tabIndexCache.set(element, index);
150
+ return index;
151
151
  }
152
152
  function isDisabled(element) {
153
153
  return "disabled" in element && element.disabled;
154
154
  }
155
155
  function isDisabledDeep(element) {
156
156
  function walk(node) {
157
- if (node === null) {
157
+ if (!node) {
158
158
  return false;
159
159
  }
160
160
  if (node instanceof ShadowRoot) {
@@ -187,26 +187,22 @@ function normalizeRadioGroup(elements) {
187
187
  let map = null;
188
188
  for (let i = 0, l = elements.length; i < l; i++) {
189
189
  const element = elements[i];
190
- if (element instanceof HTMLInputElement && element.type === "radio" && element.name) {
191
- if (!map) {
192
- map = /* @__PURE__ */ new Map();
193
- }
194
- const key = `${element.form?.id ?? "no-form"}::${element.name}`;
195
- const group = map.get(key) ?? map.set(key, []).get(key);
196
- group[group.length] = element;
190
+ if (!(element instanceof HTMLInputElement) || element.type !== "radio" || !element.name) {
191
+ continue;
192
+ }
193
+ if (!map) {
194
+ map = /* @__PURE__ */ new Map();
197
195
  }
196
+ const key = `${element.form?.id ?? "no-form"}::${element.name}`;
197
+ const group = map.get(key) ?? map.set(key, []).get(key);
198
+ group[group.length] = element;
198
199
  }
199
200
  if (!map) {
200
201
  return elements;
201
202
  }
202
203
  const placeholder = /* @__PURE__ */ new Set();
203
204
  for (const group of map.values()) {
204
- if (group.length > 0) {
205
- const enabled = group.filter(isFocusable);
206
- if (enabled.length > 0) {
207
- placeholder.add(enabled.find((radio) => radio.checked) ?? enabled[0]);
208
- }
209
- }
205
+ placeholder.add(group.find((radio) => radio.checked) ?? group[0]);
210
206
  }
211
207
  return elements.filter((element) => {
212
208
  if (element instanceof HTMLInputElement && element.type === "radio" && element.name) {
@@ -239,7 +235,7 @@ function sortByTabIndex(elements) {
239
235
  * High-precision focus management utility with shadow DOM support.
240
236
  * Handles complex focus rules including tabindex ordering, radio groups, etc.
241
237
  *
242
- * @version 2.1.2
238
+ * @version 2.1.4
243
239
  * @author Yusuke Kamiyamane
244
240
  * @license MIT
245
241
  * @copyright Copyright (c) Yusuke Kamiyamane
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "power-focusable",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "description": "High-precision focus management utility with shadow DOM support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",