@vizejs/ui 0.345.0 → 0.350.2

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 (96) hide show
  1. package/dist/{button-D7sM9Xmj.d.mts → button-CVX8UBXj.d.mts} +6 -7
  2. package/dist/{button-8BOlFJNu.mjs → button-DT8AKlds.mjs} +2 -2
  3. package/dist/button.d.mts +1 -1
  4. package/dist/button.mjs +1 -1
  5. package/dist/catalog.d.mts +541 -0
  6. package/dist/catalog.mjs +784 -0
  7. package/dist/{checkbox-B4y9GUen.mjs → checkbox-BgIvwjyC.mjs} +2 -2
  8. package/dist/{checkbox-DkwZFC80.d.mts → checkbox-DP3_ko7D.d.mts} +7 -8
  9. package/dist/checkbox.d.mts +1 -1
  10. package/dist/checkbox.mjs +1 -1
  11. package/dist/collection-B_dFZOHO.d.mts +185 -0
  12. package/dist/collection-eHN150dT.mjs +453 -0
  13. package/dist/collection.d.mts +2 -0
  14. package/dist/collection.mjs +2 -0
  15. package/dist/composite-navigation-QINW9GLy.d.mts +115 -0
  16. package/dist/composite-navigation-Skx3LZsv.mjs +354 -0
  17. package/dist/composite-navigation.d.mts +2 -0
  18. package/dist/composite-navigation.mjs +2 -0
  19. package/dist/controllable-state.d.mts +1 -1
  20. package/dist/dismissable-layer-4icKahVs.d.mts +119 -0
  21. package/dist/dismissable-layer-CwG1gtdz.mjs +488 -0
  22. package/dist/dismissable-layer.d.mts +2 -0
  23. package/dist/dismissable-layer.mjs +2 -0
  24. package/dist/focus-CAWi_I-0.mjs +318 -0
  25. package/dist/focus-K6dOifoZ.d.mts +112 -0
  26. package/dist/focus-guards-Bt0C-0qS.d.mts +81 -0
  27. package/dist/focus-guards-DhMPQAT8.mjs +299 -0
  28. package/dist/focus-guards.d.mts +2 -0
  29. package/dist/focus-guards.mjs +2 -0
  30. package/dist/focus-scope-CavhKWx0.d.mts +100 -0
  31. package/dist/focus-scope-D9U1aj67.mjs +340 -0
  32. package/dist/focus-scope-dom-DBwNEWxG.mjs +264 -0
  33. package/dist/focus-scope.d.mts +2 -0
  34. package/dist/focus-scope.mjs +2 -0
  35. package/dist/focus.d.mts +2 -0
  36. package/dist/focus.mjs +2 -0
  37. package/dist/hover-BXwwbSaO.d.mts +80 -0
  38. package/dist/hover.d.mts +2 -0
  39. package/dist/hover.mjs +197 -0
  40. package/dist/id-5OAUyVPd.d.mts +126 -0
  41. package/dist/id-mziSyAse.mjs +137 -0
  42. package/dist/id.d.mts +2 -0
  43. package/dist/id.mjs +2 -0
  44. package/dist/index.d.mts +23 -6
  45. package/dist/index.mjs +21 -5
  46. package/dist/inert-outside-CyqtoKQ4.mjs +346 -0
  47. package/dist/inert-outside-tuHRmaqJ.d.mts +43 -0
  48. package/dist/inert-outside.d.mts +2 -0
  49. package/dist/inert-outside.mjs +2 -0
  50. package/dist/interaction-modality-DOZK0BpZ.mjs +304 -0
  51. package/dist/interaction-modality-jgHKjPFB.d.mts +89 -0
  52. package/dist/interaction-modality.d.mts +2 -0
  53. package/dist/interaction-modality.mjs +2 -0
  54. package/dist/long-press-Dsul69gk.mjs +340 -0
  55. package/dist/long-press-cll6z2K9.d.mts +105 -0
  56. package/dist/long-press.d.mts +2 -0
  57. package/dist/long-press.mjs +2 -0
  58. package/dist/media-pdf.d.mts +1 -1
  59. package/dist/media-pdf.mjs +1 -1
  60. package/dist/media.d.mts +1 -1
  61. package/dist/media.mjs +1 -1
  62. package/dist/move-BOmXDYbh.d.mts +103 -0
  63. package/dist/move-BVvMHzxr.mjs +386 -0
  64. package/dist/move.d.mts +2 -0
  65. package/dist/move.mjs +2 -0
  66. package/dist/press-N_mE3Mgx.mjs +469 -0
  67. package/dist/press-event-Cd2OPpmw.mjs +149 -0
  68. package/dist/press-types-CNqStzJf.d.mts +112 -0
  69. package/dist/press.d.mts +14 -0
  70. package/dist/press.mjs +2 -0
  71. package/dist/{primitive-DJB7pOf3.mjs → primitive-BX31dogp.mjs} +2 -2
  72. package/dist/{primitive-BtvwikH1.d.mts → primitive-C8jW7DLd.d.mts} +3 -4
  73. package/dist/primitive.d.mts +1 -1
  74. package/dist/primitive.mjs +1 -1
  75. package/dist/scroll-lock-BgVtX4wT.d.mts +49 -0
  76. package/dist/scroll-lock-Ckbmm0-J.mjs +313 -0
  77. package/dist/scroll-lock.d.mts +2 -0
  78. package/dist/scroll-lock.mjs +2 -0
  79. package/dist/spatial-navigation-CHj9mDZH.d.mts +106 -0
  80. package/dist/spatial-navigation-D6-UDavU.mjs +301 -0
  81. package/dist/spatial-navigation.d.mts +2 -0
  82. package/dist/spatial-navigation.mjs +2 -0
  83. package/dist/typeahead-B7KDxE_u.mjs +175 -0
  84. package/dist/typeahead-BbgUB2Bj.d.mts +71 -0
  85. package/dist/typeahead.d.mts +2 -0
  86. package/dist/typeahead.mjs +2 -0
  87. package/dist/visually-hidden-BOqfqBFt.d.mts +17 -0
  88. package/dist/{visually-hidden-QENRapzW.mjs → visually-hidden-BwDOx5yf.mjs} +2 -2
  89. package/dist/visually-hidden.d.mts +1 -1
  90. package/dist/visually-hidden.mjs +1 -1
  91. package/package.json +99 -11
  92. package/dist/visually-hidden-BegtnMng.d.mts +0 -19
  93. /package/dist/{_plugin-vue_export-helper-BVN2DL-U.mjs → _plugin-vue_export-helper-BOaGB7Aw.mjs} +0 -0
  94. /package/dist/{controllable-state-DXsYJ3yl.d.mts → controllable-state-BtoxKahh.d.mts} +0 -0
  95. /package/dist/{pdf-source-COxN3A1l.d.mts → pdf-source-BYFK2Pks.d.mts} +0 -0
  96. /package/dist/{pdf-source-C52YE8tp.mjs → pdf-source-zu1LkCeE.mjs} +0 -0
@@ -0,0 +1,340 @@
1
+ import { a as focusableElements, c as documentOrder, d as readTarget, f as resolveMoveOptions, i as focusElement, l as readBoolean, m as validateOptions, n as createAutoFocusEvent, o as isUsableTarget, p as surfaceErrors, r as deepActiveElement, s as capture, t as containsComposed, u as readRoot } from "./focus-scope-dom-DBwNEWxG.mjs";
2
+ import { getCurrentInstance, getCurrentScope, onMounted, onScopeDispose, shallowReadonly, shallowRef, toValue, watch } from "vue";
3
+ //#region src/focus-scope-manager.ts
4
+ /** Create stable traversal methods while keeping controller lifecycle orchestration focused. */
5
+ function createFocusScopeManager({ assertAlive, list, root }) {
6
+ const move = (position, values) => {
7
+ assertAlive();
8
+ const scopeRoot = root();
9
+ if (!scopeRoot) return null;
10
+ const options = resolveMoveOptions(values);
11
+ const candidates = list(scopeRoot, options);
12
+ let target;
13
+ if (position === "first") target = candidates[0];
14
+ else if (position === "last") target = candidates.at(-1);
15
+ else {
16
+ const from = "from" in options ? options.from : deepActiveElement(scopeRoot.ownerDocument);
17
+ const index = from ? candidates.indexOf(from) : -1;
18
+ if (position === "next") target = candidates[index + 1] ?? (options.wrap ? candidates[0] : void 0);
19
+ else target = index < 0 ? candidates.at(-1) : candidates[index - 1] ?? (options.wrap ? candidates.at(-1) : void 0);
20
+ }
21
+ if (target) focusElement(target, options.preventScroll);
22
+ return target ?? null;
23
+ };
24
+ return Object.freeze({
25
+ focusFirst: (options) => move("first", options),
26
+ focusLast: (options) => move("last", options),
27
+ focusNext: (options) => move("next", options),
28
+ focusPrevious: (options) => move("previous", options)
29
+ });
30
+ }
31
+ //#endregion
32
+ //#region src/focus-scope-stack.ts
33
+ const documentScopes = /* @__PURE__ */ new WeakMap();
34
+ function scopesFor(document) {
35
+ let scopes = documentScopes.get(document);
36
+ if (!scopes) {
37
+ scopes = [];
38
+ documentScopes.set(document, scopes);
39
+ }
40
+ return scopes;
41
+ }
42
+ function attachScope(token, root) {
43
+ if (token.document === root.ownerDocument) {
44
+ token.root = root;
45
+ return;
46
+ }
47
+ detachScope(token);
48
+ token.document = root.ownerDocument;
49
+ token.root = root;
50
+ scopesFor(root.ownerDocument).push(token);
51
+ }
52
+ function detachScope(token) {
53
+ const document = token.document;
54
+ if (document) {
55
+ const scopes = scopesFor(document);
56
+ const index = scopes.indexOf(token);
57
+ if (index >= 0) scopes.splice(index, 1);
58
+ }
59
+ token.document = null;
60
+ token.root = null;
61
+ }
62
+ function containmentOwner(document) {
63
+ const scopes = scopesFor(document);
64
+ for (let index = scopes.length - 1; index >= 0; index--) {
65
+ const token = scopes[index];
66
+ try {
67
+ if (token?.readContain()) return token;
68
+ } catch {}
69
+ }
70
+ return null;
71
+ }
72
+ function rootsOwnedBy(token) {
73
+ const document = token.document;
74
+ if (!document) return [];
75
+ const scopes = scopesFor(document);
76
+ const index = scopes.indexOf(token);
77
+ if (index < 0) return [];
78
+ return scopes.slice(index).flatMap(({ root }) => root ? [root] : []);
79
+ }
80
+ function parentScope(token) {
81
+ const document = token.document;
82
+ if (!document) return null;
83
+ const scopes = scopesFor(document);
84
+ const index = scopes.indexOf(token);
85
+ return index > 0 ? scopes[index - 1] ?? null : null;
86
+ }
87
+ //#endregion
88
+ //#region src/use-focus-scope.ts
89
+ const setupDiagnostic = "VIZE_UI_FOCUS_SCOPE_SETUP";
90
+ /** Create, mount-activate, and scope-dispose a focus scope from Vue setup. */
91
+ function useFocusScope(options) {
92
+ if (!getCurrentScope()) throw new Error(`${setupDiagnostic}: use inside component setup or an active effect scope`);
93
+ const controller = createFocusScope(options);
94
+ if (getCurrentInstance()) onMounted(controller.activate);
95
+ else controller.activate();
96
+ onScopeDispose(controller.dispose);
97
+ return controller;
98
+ }
99
+ //#endregion
100
+ //#region src/focus-scope.ts
101
+ const disposedDiagnostic = "VIZE_UI_FOCUS_SCOPE_DISPOSED";
102
+ const rootDiagnostic = "VIZE_UI_FOCUS_SCOPE_ROOT";
103
+ /** Create an SSR-safe focus scope with containment, traversal, and restoration. */
104
+ function createFocusScope(options) {
105
+ validateOptions(options);
106
+ const activeState = shallowRef(false);
107
+ const token = {
108
+ document: null,
109
+ root: null,
110
+ lastFocused: null,
111
+ readContain: () => readBoolean(options.contain, "contain")
112
+ };
113
+ let disposed = false;
114
+ let observer = null;
115
+ let capturedTarget = null;
116
+ let restoreCandidates = [];
117
+ let restoreIndex = -1;
118
+ let restorationCaptured = false;
119
+ let entryHandled = false;
120
+ let guarding = false;
121
+ const assertAlive = () => {
122
+ if (disposed) throw new Error(`${disposedDiagnostic}: the controller has been disposed`);
123
+ };
124
+ const root = () => token.root ?? readRoot(options.root);
125
+ const accepted = (element, local) => options.accept?.(element) !== false && local?.(element) !== false;
126
+ const list = (scopeRoot, values) => {
127
+ const resolved = resolveMoveOptions(values);
128
+ return focusableElements(scopeRoot, {
129
+ includeProgrammatic: resolved.includeProgrammatic,
130
+ accept: (element) => accepted(element, resolved.accept)
131
+ });
132
+ };
133
+ const focusFallback = (scopeRoot) => {
134
+ const candidate = readTarget(options.fallbackFocus?.(), "fallbackFocus");
135
+ if (candidate && !containsComposed(scopeRoot, candidate)) throw new Error(`${rootDiagnostic}: fallbackFocus must resolve inside the scope`);
136
+ if (isUsableTarget(candidate)) return candidate;
137
+ const htmlRoot = scopeRoot;
138
+ return htmlRoot.namespaceURI === "http://www.w3.org/1999/xhtml" && typeof htmlRoot.focus === "function" && htmlRoot.hasAttribute("tabindex") && isUsableTarget(htmlRoot) ? htmlRoot : null;
139
+ };
140
+ const manager = createFocusScopeManager({
141
+ assertAlive,
142
+ list,
143
+ root
144
+ });
145
+ const ownedCandidates = () => documentOrder(rootsOwnedBy(token).flatMap((ownedRoot) => list(ownedRoot)));
146
+ const recover = () => {
147
+ if (guarding || token.document === null || containmentOwner(token.document) !== token) return;
148
+ const roots = rootsOwnedBy(token);
149
+ const active = deepActiveElement(token.document);
150
+ if (isUsableTarget(active) && roots.some((ownedRoot) => containsComposed(ownedRoot, active))) return;
151
+ const candidates = ownedCandidates();
152
+ const target = (token.lastFocused && roots.some((ownedRoot) => containsComposed(ownedRoot, token.lastFocused)) && isUsableTarget(token.lastFocused) ? token.lastFocused : candidates[0]) ?? (token.root ? focusFallback(token.root) : null);
153
+ if (!target) return;
154
+ guarding = true;
155
+ try {
156
+ focusElement(target);
157
+ } finally {
158
+ guarding = false;
159
+ }
160
+ };
161
+ const onFocusin = (event) => {
162
+ if (token.document === null || containmentOwner(token.document) !== token) return;
163
+ const target = event.composedPath?.()[0] ?? event.target;
164
+ if (isUsableTarget(target) && rootsOwnedBy(token).some((ownedRoot) => containsComposed(ownedRoot, target))) {
165
+ token.lastFocused = target;
166
+ return;
167
+ }
168
+ recover();
169
+ };
170
+ const onKeydown = (event) => {
171
+ if (event.key !== "Tab" || event.altKey || event.ctrlKey || event.metaKey || event.defaultPrevented || token.document === null || containmentOwner(token.document) !== token) return;
172
+ const candidates = ownedCandidates();
173
+ const current = deepActiveElement(token.document);
174
+ const index = current ? candidates.indexOf(current) : -1;
175
+ const target = event.shiftKey ? index <= 0 ? candidates.at(-1) : void 0 : index < 0 || index === candidates.length - 1 ? candidates[0] : void 0;
176
+ if (target) {
177
+ event.preventDefault();
178
+ focusElement(target);
179
+ } else if (candidates.length === 0 && token.root) {
180
+ event.preventDefault();
181
+ const fallback = focusFallback(token.root);
182
+ if (fallback) focusElement(fallback);
183
+ }
184
+ };
185
+ const detachDom = () => {
186
+ observer?.disconnect();
187
+ observer = null;
188
+ token.document?.removeEventListener("focusin", onFocusin, true);
189
+ token.document?.removeEventListener("keydown", onKeydown, true);
190
+ detachScope(token);
191
+ };
192
+ const observe = (scopeRoot) => {
193
+ observer?.disconnect();
194
+ observer = null;
195
+ const Observer = scopeRoot.ownerDocument.defaultView?.MutationObserver;
196
+ if (!Observer) return;
197
+ observer = new Observer(recover);
198
+ observer.observe(scopeRoot, {
199
+ subtree: true,
200
+ childList: true,
201
+ attributes: true,
202
+ attributeFilter: [
203
+ "aria-hidden",
204
+ "class",
205
+ "contenteditable",
206
+ "controls",
207
+ "disabled",
208
+ "hidden",
209
+ "href",
210
+ "inert",
211
+ "open",
212
+ "style",
213
+ "tabindex",
214
+ "type"
215
+ ]
216
+ });
217
+ const documentRoot = scopeRoot.ownerDocument.documentElement;
218
+ if (documentRoot && documentRoot !== scopeRoot) observer.observe(documentRoot, {
219
+ childList: true,
220
+ subtree: true
221
+ });
222
+ };
223
+ const captureRestoration = (scopeRoot) => {
224
+ if (restorationCaptured) return;
225
+ restorationCaptured = true;
226
+ capturedTarget = deepActiveElement(scopeRoot.ownerDocument);
227
+ if (!readBoolean(options.restoreFocus, "restoreFocus")) return;
228
+ const body = scopeRoot.ownerDocument.body;
229
+ restoreCandidates = body ? focusableElements(body) : [];
230
+ restoreIndex = capturedTarget ? restoreCandidates.indexOf(capturedTarget) : -1;
231
+ };
232
+ const enter = (scopeRoot, errors) => {
233
+ if (entryHandled || !readBoolean(options.autoFocus, "autoFocus")) return;
234
+ entryHandled = true;
235
+ let target = readTarget(options.initialFocus?.(), "initialFocus");
236
+ if (target && !containsComposed(scopeRoot, target)) throw new Error(`${rootDiagnostic}: initialFocus must resolve inside the scope`);
237
+ if (!isUsableTarget(target)) target = null;
238
+ target = target ?? list(scopeRoot, { includeProgrammatic: true })[0] ?? focusFallback(scopeRoot);
239
+ const event = createAutoFocusEvent("mount", target);
240
+ capture(errors, () => options.onMountAutoFocus?.(event));
241
+ if (!event.defaultPrevented && target) capture(errors, () => focusElement(target));
242
+ };
243
+ const refresh = () => {
244
+ assertAlive();
245
+ if (!activeState.value) return;
246
+ const nextRoot = readRoot(options.root);
247
+ if (nextRoot !== token.root) {
248
+ const sameDocument = nextRoot !== null && token.document === nextRoot.ownerDocument;
249
+ if (!sameDocument) detachDom();
250
+ if (nextRoot) {
251
+ captureRestoration(nextRoot);
252
+ attachScope(token, nextRoot);
253
+ if (!sameDocument) {
254
+ nextRoot.ownerDocument.addEventListener("focusin", onFocusin, true);
255
+ nextRoot.ownerDocument.addEventListener("keydown", onKeydown, true);
256
+ }
257
+ observe(nextRoot);
258
+ const errors = [];
259
+ capture(errors, () => enter(nextRoot, errors));
260
+ surfaceErrors(errors, "Focus scope entry failed");
261
+ }
262
+ }
263
+ recover();
264
+ };
265
+ const activate = () => {
266
+ assertAlive();
267
+ if (activeState.value) return;
268
+ activeState.value = true;
269
+ try {
270
+ refresh();
271
+ } catch (error) {
272
+ activeState.value = false;
273
+ detachDom();
274
+ throw error;
275
+ }
276
+ };
277
+ const deactivate = () => {
278
+ assertAlive();
279
+ if (!activeState.value) return;
280
+ const errors = [];
281
+ const scopeRoot = token.root;
282
+ const document = token.document;
283
+ const active = document ? deepActiveElement(document) : null;
284
+ const closingRoots = rootsOwnedBy(token);
285
+ let shouldRestore = false;
286
+ capture(errors, () => {
287
+ const contain = readBoolean(options.contain, "contain");
288
+ shouldRestore = readBoolean(options.restoreFocus, "restoreFocus") && (!scopeRoot || contain || containsComposed(scopeRoot, active) || !scopeRoot.isConnected && active === document?.body);
289
+ });
290
+ const parent = parentScope(token);
291
+ detachDom();
292
+ activeState.value = false;
293
+ if (shouldRestore) {
294
+ let target = null;
295
+ capture(errors, () => {
296
+ target = readTarget(options.restoreTarget?.(), "restoreTarget") ?? capturedTarget;
297
+ });
298
+ if (!isUsableTarget(target)) {
299
+ const usableOutside = (candidate) => isUsableTarget(candidate) && !closingRoots.some((closingRoot) => containsComposed(closingRoot, candidate));
300
+ const after = restoreCandidates.slice(restoreIndex + 1).find(usableOutside);
301
+ const before = restoreCandidates.slice(0, Math.max(0, restoreIndex)).reverse().find(usableOutside);
302
+ const parentTarget = parent?.lastFocused ?? null;
303
+ target = after ?? before ?? (isUsableTarget(parentTarget) ? parentTarget : null);
304
+ }
305
+ const event = createAutoFocusEvent("unmount", target);
306
+ capture(errors, () => options.onUnmountAutoFocus?.(event));
307
+ const restoreDestination = target;
308
+ if (!event.defaultPrevented && isUsableTarget(restoreDestination)) capture(errors, () => focusElement(restoreDestination));
309
+ }
310
+ capturedTarget = null;
311
+ restoreCandidates = [];
312
+ restoreIndex = -1;
313
+ restorationCaptured = false;
314
+ entryHandled = false;
315
+ token.lastFocused = null;
316
+ surfaceErrors(errors, "Focus scope restoration failed");
317
+ };
318
+ const stopRootWatch = watch(() => toValue(options.root), () => {
319
+ if (activeState.value) refresh();
320
+ }, { flush: "sync" });
321
+ return Object.freeze({
322
+ ...manager,
323
+ isActive: shallowReadonly(activeState),
324
+ activate,
325
+ deactivate,
326
+ refresh,
327
+ dispose: () => {
328
+ if (disposed) return;
329
+ try {
330
+ deactivate();
331
+ } finally {
332
+ disposed = true;
333
+ stopRootWatch();
334
+ detachDom();
335
+ }
336
+ }
337
+ });
338
+ }
339
+ //#endregion
340
+ export { useFocusScope as n, createFocusScope as t };
@@ -0,0 +1,264 @@
1
+ import { toValue } from "vue";
2
+ //#region src/focus-scope-internal.ts
3
+ const optionDiagnostic = "VIZE_UI_FOCUS_SCOPE_OPTION";
4
+ const rootDiagnostic = "VIZE_UI_FOCUS_SCOPE_ROOT";
5
+ function capture(errors, callback) {
6
+ try {
7
+ callback();
8
+ } catch (error) {
9
+ errors.push(error);
10
+ }
11
+ }
12
+ function surfaceErrors(errors, message) {
13
+ if (errors.length === 1) throw errors[0];
14
+ if (errors.length < 2) return;
15
+ const Aggregate = globalThis.AggregateError;
16
+ if (typeof Aggregate === "function") throw new Aggregate(errors, message);
17
+ const fallback = Object.assign(new Error(message), { errors: [...errors] });
18
+ fallback.name = "AggregateError";
19
+ throw fallback;
20
+ }
21
+ function readBoolean(source, name) {
22
+ const value = toValue(source);
23
+ if (value === void 0) return false;
24
+ if (typeof value !== "boolean") throw new TypeError(`${optionDiagnostic}: ${name} must resolve to a boolean`);
25
+ return value;
26
+ }
27
+ function readRoot(source) {
28
+ const value = toValue(source);
29
+ if (value === void 0 || value === null) return null;
30
+ const candidate = value;
31
+ if (candidate.nodeType !== 1 || !candidate.ownerDocument) throw new TypeError(`${rootDiagnostic}: root must resolve to an Element or null`);
32
+ return value;
33
+ }
34
+ function readTarget(value, name) {
35
+ if (value === void 0 || value === null) return null;
36
+ const candidate = value;
37
+ if (candidate.nodeType !== 1 || candidate.namespaceURI !== "http://www.w3.org/1999/xhtml" || typeof candidate.focus !== "function") throw new TypeError(`${optionDiagnostic}: ${name} must resolve to an HTMLElement or null`);
38
+ return value;
39
+ }
40
+ function validateOptions(options) {
41
+ if (!options || typeof options !== "object" || Array.isArray(options)) throw new TypeError(`${optionDiagnostic}: options must be an object`);
42
+ readRoot(options.root);
43
+ readBoolean(options.contain, "contain");
44
+ readBoolean(options.autoFocus, "autoFocus");
45
+ readBoolean(options.restoreFocus, "restoreFocus");
46
+ for (const name of [
47
+ "initialFocus",
48
+ "restoreTarget",
49
+ "fallbackFocus",
50
+ "accept",
51
+ "onMountAutoFocus",
52
+ "onUnmountAutoFocus"
53
+ ]) if (options[name] !== void 0 && typeof options[name] !== "function") throw new TypeError(`${optionDiagnostic}: ${name} must be a function`);
54
+ }
55
+ function resolveMoveOptions(value) {
56
+ const options = value ?? {};
57
+ if (!options || typeof options !== "object" || Array.isArray(options)) throw new TypeError(`${optionDiagnostic}: focus movement options must be an object`);
58
+ for (const name of [
59
+ "includeProgrammatic",
60
+ "preventScroll",
61
+ "wrap"
62
+ ]) {
63
+ const current = options[name];
64
+ if (current !== void 0 && typeof current !== "boolean") throw new TypeError(`${optionDiagnostic}: ${name} must be a boolean`);
65
+ }
66
+ if (options.accept !== void 0 && typeof options.accept !== "function") throw new TypeError(`${optionDiagnostic}: accept must be a function`);
67
+ return {
68
+ ...options,
69
+ includeProgrammatic: options.includeProgrammatic ?? false,
70
+ preventScroll: options.preventScroll ?? true,
71
+ wrap: options.wrap ?? false
72
+ };
73
+ }
74
+ /** Order positive tabindex values first and ascending, leaving ties to the caller. */
75
+ function comparePositiveTabindex(left, right) {
76
+ const leftPositive = left.tabIndex > 0;
77
+ const rightPositive = right.tabIndex > 0;
78
+ if (leftPositive && rightPositive) return left.tabIndex - right.tabIndex;
79
+ if (leftPositive !== rightPositive) return leftPositive ? -1 : 1;
80
+ return 0;
81
+ }
82
+ function documentOrder(elements) {
83
+ const unique = [...new Set(elements)];
84
+ const order = new Map(unique.map((element, index) => [element, index]));
85
+ return unique.sort((left, right) => {
86
+ const precedence = comparePositiveTabindex(left, right);
87
+ if (precedence !== 0) return precedence;
88
+ const position = left.compareDocumentPosition(right);
89
+ if (position & 1) return (order.get(left) ?? 0) - (order.get(right) ?? 0);
90
+ return position & 4 ? -1 : 1;
91
+ });
92
+ }
93
+ //#endregion
94
+ //#region src/focus-scope-dom.ts
95
+ const focusableSelector = [
96
+ "a[href]",
97
+ "area[href]",
98
+ "audio[controls]",
99
+ "button",
100
+ "embed",
101
+ "iframe",
102
+ "input",
103
+ "object",
104
+ "select",
105
+ "summary",
106
+ "textarea",
107
+ "video[controls]",
108
+ "[contenteditable]",
109
+ "[tabindex]"
110
+ ].join(",");
111
+ function composedParent(element) {
112
+ if (element.assignedSlot) return element.assignedSlot;
113
+ if (element.parentElement) return element.parentElement;
114
+ return element.getRootNode().host ?? null;
115
+ }
116
+ function containsComposed(root, element) {
117
+ let current = element;
118
+ while (current) {
119
+ if (root === current || root.contains(current)) return true;
120
+ current = composedParent(current);
121
+ }
122
+ return false;
123
+ }
124
+ function deepActiveElement(document) {
125
+ let active = document.activeElement;
126
+ while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
127
+ return active;
128
+ }
129
+ function isHidden(element, boundary, checkComputedStyle, computedHidden = /* @__PURE__ */ new Map()) {
130
+ let current = element;
131
+ while (current) {
132
+ const html = current;
133
+ if (html.hidden || html.getAttribute("aria-hidden") === "true" || html.hasAttribute("inert") || html.inert === true) return true;
134
+ if (html.localName === "details" && !html.hasAttribute("open")) {
135
+ const summary = Array.from(html.children).find(({ localName }) => localName === "summary");
136
+ if (!summary || summary !== element && !summary.contains(element)) return true;
137
+ }
138
+ if (html.style.display === "none" || html.style.visibility === "hidden" || html.style.visibility === "collapse") return true;
139
+ if (checkComputedStyle) {
140
+ let hidden = computedHidden.get(current);
141
+ if (hidden === void 0) {
142
+ const style = html.ownerDocument.defaultView?.getComputedStyle(html);
143
+ hidden = style?.display === "none" || style?.visibility === "hidden" || style?.visibility === "collapse";
144
+ computedHidden.set(current, hidden);
145
+ }
146
+ if (hidden) return true;
147
+ }
148
+ if (current === boundary) break;
149
+ current = composedParent(current);
150
+ }
151
+ return false;
152
+ }
153
+ function hasStyleSheets(element) {
154
+ return [element.ownerDocument, element.getRootNode()].some((scope) => (scope.styleSheets?.length ?? 0) + (scope.adoptedStyleSheets?.length ?? 0) > 0);
155
+ }
156
+ function isDisabled(element) {
157
+ if (element.disabled === true) return true;
158
+ let current = element.parentElement;
159
+ while (current) {
160
+ const html = current;
161
+ if ((html.localName === "optgroup" || html.localName === "select") && html.disabled === true) return true;
162
+ if (html.localName === "fieldset" && html.disabled === true) {
163
+ const firstLegend = Array.from(html.children).find(({ localName }) => localName === "legend");
164
+ if (!firstLegend || firstLegend !== element && !firstLegend.contains(element)) return true;
165
+ }
166
+ current = current.parentElement;
167
+ }
168
+ return false;
169
+ }
170
+ function isNativeFocusable(element) {
171
+ const name = element.localName;
172
+ if (name === "input") return element.type !== "hidden";
173
+ if (name === "a" || name === "area") return element.hasAttribute("href");
174
+ if (name === "audio" || name === "video") return element.hasAttribute("controls");
175
+ if (name === "button" || name === "embed" || name === "iframe" || name === "object" || name === "select" || name === "textarea") return true;
176
+ if (name === "summary") {
177
+ const details = element.parentElement;
178
+ return details?.localName === "details" && Array.from(details.children).find(({ localName }) => localName === "summary") === element;
179
+ }
180
+ const contenteditable = element.getAttribute("contenteditable");
181
+ return element.isContentEditable || contenteditable === "" || contenteditable === "true" || contenteditable === "plaintext-only";
182
+ }
183
+ function isProgrammaticallyFocusable(element) {
184
+ if (element.localName === "input" && element.type.toLowerCase() === "hidden") return false;
185
+ return element.matches(focusableSelector) && (element.hasAttribute("tabindex") || isNativeFocusable(element));
186
+ }
187
+ function isRadioTabbable(element, candidates) {
188
+ if (element.localName !== "input" || element.type !== "radio") return true;
189
+ const radio = element;
190
+ if (!radio.name || radio.checked) return true;
191
+ const group = candidates.filter((candidate) => {
192
+ const input = candidate;
193
+ return candidate.localName === "input" && input.type === "radio" && input.name === radio.name && input.form === radio.form && candidate.getRootNode() === radio.getRootNode();
194
+ });
195
+ return !group.some(({ checked }) => checked) && group[0] === radio;
196
+ }
197
+ function collectElements(root) {
198
+ const elements = [];
199
+ const seen = /* @__PURE__ */ new Set();
200
+ const visitElement = (element) => {
201
+ if (seen.has(element)) return;
202
+ seen.add(element);
203
+ if (element.namespaceURI === "http://www.w3.org/1999/xhtml" && typeof element.focus === "function") elements.push(element);
204
+ const slot = element;
205
+ if (slot.localName === "slot" && typeof slot.assignedElements === "function") {
206
+ const assigned = slot.assignedElements({ flatten: true });
207
+ if (assigned.length > 0) {
208
+ for (const child of assigned) visitElement(child);
209
+ return;
210
+ }
211
+ }
212
+ const children = element.shadowRoot?.children ?? element.children;
213
+ for (const child of children) visitElement(child);
214
+ };
215
+ const children = root.shadowRoot?.children ?? root.children;
216
+ for (const child of children) visitElement(child);
217
+ return elements;
218
+ }
219
+ function focusableElements(root, options = {}) {
220
+ const document = root.ownerDocument;
221
+ const checkComputedStyle = hasStyleSheets(root);
222
+ const visibilityBoundary = document.documentElement ?? root;
223
+ const computedHidden = /* @__PURE__ */ new Map();
224
+ const candidates = collectElements(root).filter((element) => {
225
+ if (!isProgrammaticallyFocusable(element) || isDisabled(element) || isHidden(element, visibilityBoundary, checkComputedStyle, computedHidden)) return false;
226
+ const tabindex = element.getAttribute("tabindex");
227
+ const explicit = tabindex !== null && Number(tabindex) >= 0;
228
+ const native = isNativeFocusable(element);
229
+ const programmatic = tabindex !== null || native;
230
+ const sequential = tabindex === null ? native || element.tabIndex >= 0 : explicit;
231
+ return (options.includeProgrammatic ? programmatic : sequential) && options.accept?.(element) !== false;
232
+ });
233
+ return candidates.filter((element) => options.includeProgrammatic ? true : isRadioTabbable(element, candidates)).map((element, order) => ({
234
+ element,
235
+ order
236
+ })).sort((left, right) => comparePositiveTabindex(left.element, right.element) || left.order - right.order).map(({ element }) => element);
237
+ }
238
+ function focusElement(element, preventScroll = true) {
239
+ try {
240
+ element.focus({ preventScroll });
241
+ } catch {
242
+ element.focus();
243
+ }
244
+ }
245
+ function isUsableTarget(element) {
246
+ if (element?.isConnected !== true || element.nodeType !== 1 || element.namespaceURI !== "http://www.w3.org/1999/xhtml" || !isProgrammaticallyFocusable(element) || isDisabled(element)) return false;
247
+ const boundary = element.ownerDocument.documentElement;
248
+ return !boundary || !isHidden(element, boundary, hasStyleSheets(element));
249
+ }
250
+ function createAutoFocusEvent(type, target) {
251
+ let prevented = false;
252
+ return Object.freeze({
253
+ type,
254
+ target,
255
+ get defaultPrevented() {
256
+ return prevented;
257
+ },
258
+ preventDefault: () => {
259
+ prevented = true;
260
+ }
261
+ });
262
+ }
263
+ //#endregion
264
+ export { focusableElements as a, documentOrder as c, readTarget as d, resolveMoveOptions as f, focusElement as i, readBoolean as l, validateOptions as m, createAutoFocusEvent as n, isUsableTarget as o, surfaceErrors as p, deepActiveElement as r, capture as s, containsComposed as t, readRoot as u };
@@ -0,0 +1,2 @@
1
+ import { a as FocusScopeManager, i as FocusScopeController, n as useFocusScope, o as FocusScopeMoveOptions, r as FocusScopeAutoFocusEvent, s as FocusScopeOptions, t as createFocusScope } from "./focus-scope-CavhKWx0.mjs";
2
+ export { type FocusScopeAutoFocusEvent, type FocusScopeController, type FocusScopeManager, type FocusScopeMoveOptions, type FocusScopeOptions, createFocusScope, useFocusScope };
@@ -0,0 +1,2 @@
1
+ import { n as useFocusScope, t as createFocusScope } from "./focus-scope-D9U1aj67.mjs";
2
+ export { createFocusScope, useFocusScope };
@@ -0,0 +1,2 @@
1
+ import { a as useFocusRing, c as FocusController, d as FocusOptions, f as FocusProps, h as FocusWithinOptions, i as useFocus, l as FocusEvent, m as FocusRingOptions, n as createFocusRing, o as useFocusWithin, p as FocusRingController, r as createFocusWithin, s as FocusChangeReason, t as createFocus, u as FocusMode } from "./focus-K6dOifoZ.mjs";
2
+ export { type FocusChangeReason, type FocusController, type FocusEvent, type FocusMode, type FocusOptions, type FocusProps, type FocusRingController, type FocusRingOptions, type FocusWithinOptions, createFocus, createFocusRing, createFocusWithin, useFocus, useFocusRing, useFocusWithin };
package/dist/focus.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { a as useFocusRing, i as useFocus, n as createFocusRing, o as useFocusWithin, r as createFocusWithin, t as createFocus } from "./focus-CAWi_I-0.mjs";
2
+ export { createFocus, createFocusRing, createFocusWithin, useFocus, useFocusRing, useFocusWithin };