keystra 0.0.0-stage → 0.1.1

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/LICENSE +21 -0
  3. package/README.md +78 -2
  4. package/dist/chunk-2BLQUBG7.js +816 -0
  5. package/dist/chunk-77GGU3AX.js +135 -0
  6. package/dist/chunk-KDOJARJD.js +29 -0
  7. package/dist/chunk-LYYUOTBP.js +125 -0
  8. package/dist/chunk-S5YVXIMA.js +61 -0
  9. package/dist/chunk-SSIKGDD4.js +255 -0
  10. package/dist/chunk-U7YK6PPT.js +1729 -0
  11. package/dist/chunk-XFNYIPOW.js +253 -0
  12. package/dist/chunk-ZOJRXXQN.js +308 -0
  13. package/dist/core.cjs +2861 -0
  14. package/dist/core.d.cts +41 -0
  15. package/dist/core.d.ts +41 -0
  16. package/dist/core.js +7 -0
  17. package/dist/engine-COPfXXTp.d.ts +229 -0
  18. package/dist/engine-DcbkGRgz.d.cts +229 -0
  19. package/dist/focus.cjs +374 -0
  20. package/dist/focus.d.cts +74 -0
  21. package/dist/focus.d.ts +74 -0
  22. package/dist/focus.js +2 -0
  23. package/dist/index-IZkcWAXP.d.cts +395 -0
  24. package/dist/index-IZkcWAXP.d.ts +395 -0
  25. package/dist/index.cjs +3745 -0
  26. package/dist/index.d.cts +9 -0
  27. package/dist/index.d.ts +9 -0
  28. package/dist/index.global.js +1 -0
  29. package/dist/index.js +9 -0
  30. package/dist/layout-C2-n8aUI.d.ts +17 -0
  31. package/dist/layout-CBzD-87D.d.cts +17 -0
  32. package/dist/navigation.cjs +293 -0
  33. package/dist/navigation.d.cts +33 -0
  34. package/dist/navigation.d.ts +33 -0
  35. package/dist/navigation.js +2 -0
  36. package/dist/patterns.cjs +3505 -0
  37. package/dist/patterns.d.cts +12 -0
  38. package/dist/patterns.d.ts +12 -0
  39. package/dist/patterns.js +7 -0
  40. package/dist/roving-focus-CT7Dm6di.d.ts +63 -0
  41. package/dist/roving-focus-ZQ0v7hLe.d.cts +63 -0
  42. package/dist/selection.cjs +266 -0
  43. package/dist/selection.d.cts +43 -0
  44. package/dist/selection.d.ts +43 -0
  45. package/dist/selection.js +2 -0
  46. package/dist/utils-CkveVeIJ.d.cts +18 -0
  47. package/dist/utils-JmPZTlys.d.ts +18 -0
  48. package/dist/utils.cjs +195 -0
  49. package/dist/utils.d.cts +3 -0
  50. package/dist/utils.d.ts +3 -0
  51. package/dist/utils.js +2 -0
  52. package/package.json +147 -4
@@ -0,0 +1,253 @@
1
+ // src/navigation/directional.ts
2
+ function actionToDirection(action) {
3
+ switch (action) {
4
+ case "up":
5
+ return "up";
6
+ case "down":
7
+ return "down";
8
+ case "left":
9
+ return "left";
10
+ case "right":
11
+ return "right";
12
+ default:
13
+ return null;
14
+ }
15
+ }
16
+ function createDirectionalStrategy(options = {}) {
17
+ const crossWeight = options.crossAxisWeight ?? 2;
18
+ return (context) => {
19
+ const direction = context.direction ?? actionToDirection(context.action);
20
+ if (!direction) return null;
21
+ const items = context.items;
22
+ const total = items.length;
23
+ if (total === 0) return -1;
24
+ const from = context.index;
25
+ if (from < 0 || from >= total) {
26
+ return direction === "down" || direction === "right" ? 0 : total - 1;
27
+ }
28
+ const current = items[from];
29
+ if (!current) return null;
30
+ const origin = context.rectOf(current);
31
+ const ox = origin.left + origin.width / 2;
32
+ const oy = origin.top + origin.height / 2;
33
+ const horizontal = direction === "left" || direction === "right";
34
+ const sign = direction === "right" || direction === "down" ? 1 : -1;
35
+ let bestIndex = -1;
36
+ let bestScore = Infinity;
37
+ let nearestIndex = -1;
38
+ let nearestDistance = Infinity;
39
+ for (let i = 0; i < total; i++) {
40
+ if (i === from) continue;
41
+ const element = items[i];
42
+ const rect = context.rectOf(element);
43
+ if (rect.width === 0 && rect.height === 0) continue;
44
+ const dx = rect.left + rect.width / 2 - ox;
45
+ const dy = rect.top + rect.height / 2 - oy;
46
+ const distance = Math.hypot(dx, dy);
47
+ if (distance < nearestDistance) {
48
+ nearestDistance = distance;
49
+ nearestIndex = i;
50
+ }
51
+ const primary = (horizontal ? dx : dy) * sign;
52
+ if (primary <= 0) continue;
53
+ const cross = Math.abs(horizontal ? dy : dx);
54
+ if (cross > primary) continue;
55
+ const score = primary + cross * crossWeight;
56
+ if (score < bestScore) {
57
+ bestScore = score;
58
+ bestIndex = i;
59
+ }
60
+ }
61
+ if (bestIndex !== -1) return bestIndex;
62
+ const allowFallback = options.wrapFallback ?? context.loop;
63
+ return allowFallback ? nearestIndex : null;
64
+ };
65
+ }
66
+
67
+ // src/navigation/grid.ts
68
+ function computeGridInfo(context) {
69
+ const items = context.items;
70
+ const total = items.length;
71
+ if (total === 0) return { starts: [0], columns: 1 };
72
+ const starts = [0];
73
+ let rowTop = context.rectOf(items[0]).top;
74
+ let currentColumns = 1;
75
+ let maxColumns = 1;
76
+ for (let i = 1; i < total; i++) {
77
+ const rect = context.rectOf(items[i]);
78
+ if (Math.abs(rect.top - rowTop) < 2) {
79
+ currentColumns++;
80
+ continue;
81
+ }
82
+ maxColumns = Math.max(maxColumns, currentColumns);
83
+ currentColumns = 1;
84
+ rowTop = rect.top;
85
+ starts.push(i);
86
+ }
87
+ return { starts, columns: Math.max(maxColumns, currentColumns) };
88
+ }
89
+ function declaredInfo(total, columns) {
90
+ const starts = [];
91
+ for (let start = 0; start < total; start += columns) starts.push(start);
92
+ if (starts.length === 0) starts.push(0);
93
+ return { starts, columns };
94
+ }
95
+ function rowOf(info, index) {
96
+ const starts = info.starts;
97
+ let row = 0;
98
+ for (let i = 0; i < starts.length; i++) {
99
+ if (starts[i] <= index) row = i;
100
+ else break;
101
+ }
102
+ return row;
103
+ }
104
+ function rowStart(info, row) {
105
+ return info.starts[row] ?? 0;
106
+ }
107
+ function rowEnd(info, row, total) {
108
+ return row + 1 < info.starts.length ? info.starts[row + 1] - 1 : total - 1;
109
+ }
110
+ function createGridStrategy(options = {}) {
111
+ const maintainColumn = options.maintainColumn !== false;
112
+ const rowHomeEnd = options.rowHomeEnd === true;
113
+ const declared = options.columns && options.columns > 0 ? options.columns : 0;
114
+ let cachedVersion = -1;
115
+ let cachedItems = null;
116
+ let cached = { starts: [0], columns: 1 };
117
+ return (context) => {
118
+ const items = context.items;
119
+ const total = items.length;
120
+ if (total === 0) return -1;
121
+ const columns = declared || context.columns;
122
+ const index = context.index;
123
+ const direction = context.direction ?? directionFromAction(context.action);
124
+ if (!direction) {
125
+ if (context.action === "first") {
126
+ if (!rowHomeEnd || index < 0) return 0;
127
+ const info2 = infoFor(context, columns, total);
128
+ return rowStart(info2, rowOf(info2, index));
129
+ }
130
+ if (context.action === "last") {
131
+ if (!rowHomeEnd || index < 0) return total - 1;
132
+ const info2 = infoFor(context, columns, total);
133
+ return rowEnd(info2, rowOf(info2, index), total);
134
+ }
135
+ return null;
136
+ }
137
+ if (index < 0 || index >= total) {
138
+ return direction === "down" || direction === "right" ? 0 : total - 1;
139
+ }
140
+ const info = infoFor(context, columns, total);
141
+ const row = rowOf(info, index);
142
+ const start = rowStart(info, row);
143
+ const end = rowEnd(info, row, total);
144
+ if (direction === "left" || direction === "right") {
145
+ const next = index + (direction === "right" ? 1 : -1);
146
+ if (next >= start && next <= end) return next;
147
+ if (!context.loop) return index;
148
+ return direction === "right" ? start : end;
149
+ }
150
+ const rowDelta = direction === "down" ? 1 : -1;
151
+ let targetRow = row + rowDelta;
152
+ if (targetRow < 0 || targetRow >= info.starts.length) {
153
+ if (!context.loop) return index;
154
+ targetRow = targetRow < 0 ? info.starts.length - 1 : 0;
155
+ }
156
+ const targetStart = rowStart(info, targetRow);
157
+ const targetEnd = rowEnd(info, targetRow, total);
158
+ if (columns > 0 && !maintainColumn) return targetStart;
159
+ if (columns > 0) {
160
+ const column = index - start;
161
+ const candidate = targetStart + column;
162
+ return candidate <= targetEnd ? candidate : targetEnd;
163
+ }
164
+ const current = context.rectOf(items[index]);
165
+ return nearestInRow(context, targetStart, targetEnd, current.left + current.width / 2);
166
+ function infoFor(ctx, cols, count) {
167
+ if (cols > 0) return declaredInfo(count, cols);
168
+ if (cachedVersion === ctx.version && cachedItems === ctx.items) return cached;
169
+ cached = computeGridInfo(ctx);
170
+ cachedVersion = ctx.version;
171
+ cachedItems = ctx.items;
172
+ return cached;
173
+ }
174
+ };
175
+ }
176
+ function nearestInRow(context, start, end, targetX) {
177
+ let best = start;
178
+ let bestDistance = Infinity;
179
+ for (let i = start; i <= end; i++) {
180
+ const element = context.items[i];
181
+ if (!element) continue;
182
+ const rect = context.rectOf(element);
183
+ const distance = Math.abs(rect.left + rect.width / 2 - targetX);
184
+ if (distance < bestDistance) {
185
+ bestDistance = distance;
186
+ best = i;
187
+ }
188
+ }
189
+ return best;
190
+ }
191
+ function directionFromAction(action) {
192
+ switch (action) {
193
+ case "up":
194
+ case "previous":
195
+ return "up";
196
+ case "down":
197
+ case "next":
198
+ return "down";
199
+ case "left":
200
+ return "left";
201
+ case "right":
202
+ return "right";
203
+ default:
204
+ return null;
205
+ }
206
+ }
207
+
208
+ // src/navigation/sequential.ts
209
+ function findNextIndex(total, from, step, loop, clamp = true) {
210
+ if (total === 0 || step === 0) return -1;
211
+ if (from < 0 || from >= total) {
212
+ return step > 0 ? 0 : total - 1;
213
+ }
214
+ const next = from + step;
215
+ if (loop) return (next % total + total) % total;
216
+ if (next < 0) return clamp ? 0 : -1;
217
+ if (next >= total) return clamp ? total - 1 : -1;
218
+ return next;
219
+ }
220
+ function actionDelta(action, direction) {
221
+ if (direction) {
222
+ if (direction === "down" || direction === "right") return 1;
223
+ if (direction === "up" || direction === "left") return -1;
224
+ return 0;
225
+ }
226
+ switch (action) {
227
+ case "next":
228
+ case "down":
229
+ case "right":
230
+ return 1;
231
+ case "previous":
232
+ case "up":
233
+ case "left":
234
+ return -1;
235
+ default:
236
+ return 0;
237
+ }
238
+ }
239
+ function createSequentialStrategy(axis = "both") {
240
+ return (context) => {
241
+ const { action, direction, index, items, loop } = context;
242
+ const delta = actionDelta(action, direction);
243
+ if (delta === 0) return null;
244
+ const isVerticalAction = direction !== null ? direction === "up" || direction === "down" : action === "up" || action === "down";
245
+ if (axis === "vertical" && !isVerticalAction && direction !== null) return null;
246
+ if (axis === "horizontal" && isVerticalAction) return null;
247
+ return findNextIndex(items.length, index, delta, loop);
248
+ };
249
+ }
250
+ var verticalStrategy = /* @__PURE__ */ createSequentialStrategy("vertical");
251
+ var horizontalStrategy = /* @__PURE__ */ createSequentialStrategy("horizontal");
252
+
253
+ export { actionDelta, actionToDirection, createDirectionalStrategy, createGridStrategy, createSequentialStrategy, directionFromAction, findNextIndex, horizontalStrategy, verticalStrategy };
@@ -0,0 +1,308 @@
1
+ import { contains, ensureId, focusElement, isHidden, isDisabled } from './chunk-77GGU3AX.js';
2
+
3
+ // src/focus/roving-focus.ts
4
+ var RovingTabindex = class {
5
+ constructor(options = {}) {
6
+ this.current = /* @__PURE__ */ new WeakMap();
7
+ this.originals = /* @__PURE__ */ new Map();
8
+ this.active = null;
9
+ this.respectNegative = options.respectNegative !== false;
10
+ this.disabled = options.disabled === true;
11
+ }
12
+ get activeElement() {
13
+ return this.active;
14
+ }
15
+ sync(element, others) {
16
+ if (this.disabled) return;
17
+ const desired = element ? this.desiredFor(element) : null;
18
+ for (let i = 0; i < others.length; i++) {
19
+ const item = others[i];
20
+ if (item === element) continue;
21
+ this.write(item, "-1");
22
+ }
23
+ this.active = element;
24
+ if (element && desired !== null) this.write(element, desired);
25
+ this.forgetDetached(others.length);
26
+ }
27
+ move(element) {
28
+ if (this.disabled) return;
29
+ const desired = this.desiredFor(element);
30
+ if (this.active && this.active !== element) this.write(this.active, "-1");
31
+ this.active = element;
32
+ this.write(element, desired);
33
+ }
34
+ forgetDetached(live) {
35
+ if (this.originals.size <= live) return;
36
+ for (const element of this.originals.keys()) {
37
+ if (!element.isConnected) this.originals.delete(element);
38
+ }
39
+ }
40
+ authoredTabStop(items) {
41
+ for (let i = 0; i < items.length; i++) {
42
+ const item = items[i];
43
+ const authored = this.originals.has(item) ? this.originals.get(item) : item.getAttribute("tabindex");
44
+ if (authored === "0") return item;
45
+ }
46
+ return null;
47
+ }
48
+ apply(element) {
49
+ if (this.disabled) return;
50
+ this.active = element;
51
+ if (element) this.write(element, this.desiredFor(element));
52
+ }
53
+ desiredFor(element) {
54
+ if (this.respectNegative) {
55
+ const authored = this.originals.has(element) ? this.originals.get(element) : element.getAttribute("tabindex");
56
+ if (authored === "-1") return "-1";
57
+ }
58
+ return "0";
59
+ }
60
+ write(element, value) {
61
+ if (this.current.get(element) === value) return;
62
+ if (!this.originals.has(element)) this.originals.set(element, element.getAttribute("tabindex"));
63
+ element.setAttribute("tabindex", value);
64
+ this.current.set(element, value);
65
+ }
66
+ restore() {
67
+ for (const [element, value] of this.originals) {
68
+ if (value === null) element.removeAttribute("tabindex");
69
+ else element.setAttribute("tabindex", value);
70
+ this.current.delete(element);
71
+ }
72
+ this.originals.clear();
73
+ this.active = null;
74
+ }
75
+ get touched() {
76
+ return this.originals.size;
77
+ }
78
+ };
79
+
80
+ // src/focus/focus-manager.ts
81
+ var FocusManager = class {
82
+ constructor(options = {}) {
83
+ this.items = [];
84
+ this.activeElement = null;
85
+ this.activeIndex = -1;
86
+ this.outsideElement = null;
87
+ this.lastInsideElement = null;
88
+ this.lastKnownIndex = 0;
89
+ this.cleared = false;
90
+ this.started = false;
91
+ this.container = null;
92
+ this.markedOption = null;
93
+ this.options = options;
94
+ this.virtual = options.virtual === true;
95
+ const roving = options.roving;
96
+ this.rovingEnabled = roving !== false && (typeof roving !== "object" || roving.enabled !== false);
97
+ this.roving = new RovingTabindex({
98
+ disabled: !this.rovingEnabled,
99
+ respectNegative: typeof roving === "object" ? roving.force !== true : true
100
+ });
101
+ }
102
+ get element() {
103
+ return this.activeElement;
104
+ }
105
+ get index() {
106
+ return this.activeIndex;
107
+ }
108
+ get focusedIndex() {
109
+ if (this.activeIndex < 0) return -1;
110
+ if (this.virtual) return this.activeIndex;
111
+ if (typeof document === "undefined") return this.activeIndex;
112
+ const active = document.activeElement;
113
+ const current = this.activeElement;
114
+ if (!current) return -1;
115
+ if (active === current) return this.activeIndex;
116
+ if (active && contains(current, active)) return this.activeIndex;
117
+ return -1;
118
+ }
119
+ get previousElement() {
120
+ return this.outsideElement;
121
+ }
122
+ get lastFocused() {
123
+ return this.lastInsideElement;
124
+ }
125
+ sync(items, container) {
126
+ const previous = this.activeElement;
127
+ if (this.activeIndex >= 0) this.lastKnownIndex = this.activeIndex;
128
+ this.items = items;
129
+ if (container !== void 0) this.container = container;
130
+ if (previous) {
131
+ const index = items.indexOf(previous);
132
+ if (index !== -1 && this.isUsable(previous)) {
133
+ this.activeIndex = index;
134
+ this.promote(previous, items);
135
+ return index;
136
+ }
137
+ }
138
+ const fromDocument = previous || !this.cleared ? this.readActiveFromDocument(container) : -1;
139
+ if (fromDocument >= 0) {
140
+ const element = items[fromDocument];
141
+ this.activeElement = element;
142
+ this.activeIndex = fromDocument;
143
+ this.lastInsideElement = element;
144
+ this.lastKnownIndex = fromDocument;
145
+ this.promote(element, items);
146
+ return fromDocument;
147
+ }
148
+ this.activeElement = null;
149
+ this.activeIndex = -1;
150
+ let candidate = null;
151
+ if (previous && items.length > 0) {
152
+ const previousIndex = this.lastKnownIndex;
153
+ candidate = items[Math.min(previousIndex, items.length - 1)] ?? items[0] ?? null;
154
+ } else if (!this.started && items.length > 0) {
155
+ candidate = this.roving.authoredTabStop(items) ?? items[0] ?? null;
156
+ const index = candidate ? items.indexOf(candidate) : -1;
157
+ if (index > 0 && candidate && this.isUsable(candidate)) {
158
+ this.activeElement = candidate;
159
+ this.activeIndex = index;
160
+ this.lastInsideElement = candidate;
161
+ this.lastKnownIndex = index;
162
+ }
163
+ } else {
164
+ candidate = items[0] ?? null;
165
+ }
166
+ this.started = true;
167
+ this.promote(candidate, items);
168
+ return this.activeIndex;
169
+ }
170
+ promote(element, items) {
171
+ this.roving.sync(this.virtual ? null : element, items);
172
+ this.writeActiveDescendant(this.virtual ? element : null);
173
+ }
174
+ writeActiveDescendant(element) {
175
+ if (!this.virtual) return;
176
+ this.markOption(element);
177
+ const owner = this.options.descendantOwner?.() ?? null;
178
+ if (!owner) return;
179
+ if (!element) {
180
+ if (owner.hasAttribute("aria-activedescendant")) owner.removeAttribute("aria-activedescendant");
181
+ return;
182
+ }
183
+ const id = ensureId(element, "keystra-item");
184
+ if (owner.getAttribute("aria-activedescendant") !== id) {
185
+ owner.setAttribute("aria-activedescendant", id);
186
+ }
187
+ }
188
+ markOption(element) {
189
+ if (this.markedOption === element) return;
190
+ if (this.markedOption) this.markedOption.setAttribute("aria-selected", "false");
191
+ this.markedOption = element?.getAttribute("role") === "option" ? element : null;
192
+ if (this.markedOption) this.markedOption.setAttribute("aria-selected", "true");
193
+ }
194
+ observe(element, container) {
195
+ if (!element) return;
196
+ if (container && !contains(container, element)) return;
197
+ const index = this.items.indexOf(element);
198
+ if (index === -1) return;
199
+ const item = this.items[index];
200
+ this.activeElement = item;
201
+ this.activeIndex = index;
202
+ this.lastInsideElement = item;
203
+ this.lastKnownIndex = index;
204
+ if (!this.virtual) this.roving.apply(item);
205
+ this.writeActiveDescendant(item);
206
+ }
207
+ focusIndex(index, action = null, preventScroll, moveFocus = true) {
208
+ const items = this.items;
209
+ if (index < 0 || index >= items.length) return null;
210
+ const element = items[index];
211
+ if (!this.isUsable(element)) return null;
212
+ const previous = this.activeElement;
213
+ if (previous && previous !== element) {
214
+ const previousIndex = items.indexOf(previous);
215
+ if (previousIndex !== -1) this.options.onBlur?.(previous, previousIndex);
216
+ }
217
+ this.captureOutside(previous);
218
+ this.activeElement = element;
219
+ this.activeIndex = index;
220
+ this.cleared = false;
221
+ this.lastInsideElement = element;
222
+ this.lastKnownIndex = index;
223
+ if (this.virtual) this.writeActiveDescendant(element);
224
+ else this.roving.move(element);
225
+ if (moveFocus && !this.virtual) {
226
+ focusElement(element, preventScroll ?? this.options.preventScroll !== false);
227
+ }
228
+ this.options.onFocus?.(element, index, action);
229
+ return element;
230
+ }
231
+ setActiveIndex(index) {
232
+ const element = index >= 0 ? this.items[index] ?? null : null;
233
+ this.activeElement = element;
234
+ this.activeIndex = element ? index : -1;
235
+ if (element) {
236
+ this.cleared = false;
237
+ this.lastInsideElement = element;
238
+ this.lastKnownIndex = index;
239
+ } else {
240
+ this.cleared = index < 0;
241
+ }
242
+ this.promote(element ?? this.items[0] ?? null, this.items);
243
+ }
244
+ focusElement(element, action = null) {
245
+ if (!element) return false;
246
+ const index = this.items.indexOf(element);
247
+ if (index === -1) return false;
248
+ return this.focusIndex(index, action) !== null;
249
+ }
250
+ restore() {
251
+ const target = this.outsideElement;
252
+ if (target && typeof target.focus === "function" && !isHidden(target) && !isDisabled(target)) {
253
+ focusElement(target, this.options.preventScroll !== false);
254
+ return true;
255
+ }
256
+ if (this.virtual) return false;
257
+ if (this.lastInsideElement && this.items.indexOf(this.lastInsideElement) !== -1) {
258
+ return this.focusElement(this.lastInsideElement);
259
+ }
260
+ return this.focusIndex(this.activeIndex) !== null;
261
+ }
262
+ remember(element) {
263
+ if (element) this.outsideElement = element;
264
+ }
265
+ clear() {
266
+ this.activeElement = null;
267
+ this.activeIndex = -1;
268
+ this.items = [];
269
+ this.lastInsideElement = null;
270
+ this.lastKnownIndex = 0;
271
+ }
272
+ dispose() {
273
+ this.writeActiveDescendant(null);
274
+ this.roving.restore();
275
+ this.clear();
276
+ this.outsideElement = null;
277
+ }
278
+ isUsable(element) {
279
+ if (!element) return false;
280
+ if (isDisabled(element, this.options.disabledSelector ?? null)) return false;
281
+ if (this.options.skipHidden !== false && isHidden(element)) return false;
282
+ return true;
283
+ }
284
+ captureOutside(current) {
285
+ if (typeof document === "undefined") return;
286
+ const active = document.activeElement;
287
+ if (!active || active === document.body || active === document.documentElement) return;
288
+ if (current && active === current) return;
289
+ if (this.items.indexOf(active) !== -1) return;
290
+ if (this.container && contains(this.container, active)) return;
291
+ this.outsideElement = active;
292
+ }
293
+ readActiveFromDocument(container) {
294
+ if (typeof document === "undefined") return -1;
295
+ const active = document.activeElement;
296
+ if (!active || active === document.body) return -1;
297
+ const index = this.items.indexOf(active);
298
+ if (index !== -1) return index;
299
+ if (container) {
300
+ for (let i = 0; i < this.items.length; i++) {
301
+ if (contains(this.items[i], active)) return i;
302
+ }
303
+ }
304
+ return -1;
305
+ }
306
+ };
307
+
308
+ export { FocusManager, RovingTabindex };