@vizejs/ui 0.347.7 → 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.
- package/dist/{button-BMIqJ_M5.d.mts → button-CVX8UBXj.d.mts} +6 -7
- package/dist/{button-CaLxP2l2.mjs → button-DT8AKlds.mjs} +2 -2
- package/dist/button.d.mts +1 -1
- package/dist/button.mjs +1 -1
- package/dist/catalog.d.mts +541 -0
- package/dist/catalog.mjs +784 -0
- package/dist/{checkbox-B4y9GUen.mjs → checkbox-BgIvwjyC.mjs} +2 -2
- package/dist/{checkbox-sbhaWekB.d.mts → checkbox-DP3_ko7D.d.mts} +7 -8
- package/dist/checkbox.d.mts +1 -1
- package/dist/checkbox.mjs +1 -1
- package/dist/collection.d.mts +2 -2
- package/dist/collection.mjs +1 -1
- package/dist/composite-navigation-QINW9GLy.d.mts +115 -0
- package/dist/composite-navigation-Skx3LZsv.mjs +354 -0
- package/dist/composite-navigation.d.mts +2 -0
- package/dist/composite-navigation.mjs +2 -0
- package/dist/controllable-state.d.mts +1 -1
- package/dist/dismissable-layer-4icKahVs.d.mts +119 -0
- package/dist/dismissable-layer-CwG1gtdz.mjs +488 -0
- package/dist/dismissable-layer.d.mts +2 -0
- package/dist/dismissable-layer.mjs +2 -0
- package/dist/focus-CAWi_I-0.mjs +318 -0
- package/dist/focus-K6dOifoZ.d.mts +112 -0
- package/dist/focus-guards-Bt0C-0qS.d.mts +81 -0
- package/dist/focus-guards-DhMPQAT8.mjs +299 -0
- package/dist/focus-guards.d.mts +2 -0
- package/dist/focus-guards.mjs +2 -0
- package/dist/focus-scope-CavhKWx0.d.mts +100 -0
- package/dist/focus-scope-D9U1aj67.mjs +340 -0
- package/dist/focus-scope-dom-DBwNEWxG.mjs +264 -0
- package/dist/focus-scope.d.mts +2 -0
- package/dist/focus-scope.mjs +2 -0
- package/dist/focus.d.mts +2 -0
- package/dist/focus.mjs +2 -0
- package/dist/hover-BXwwbSaO.d.mts +80 -0
- package/dist/hover.d.mts +2 -0
- package/dist/hover.mjs +197 -0
- package/dist/{id-BSgJwErt.d.mts → id-5OAUyVPd.d.mts} +2 -3
- package/dist/{id-CPBdeoL3.mjs → id-mziSyAse.mjs} +2 -2
- package/dist/id.d.mts +2 -2
- package/dist/id.mjs +1 -1
- package/dist/index.d.mts +22 -11
- package/dist/index.mjs +21 -10
- package/dist/inert-outside-CyqtoKQ4.mjs +346 -0
- package/dist/inert-outside-tuHRmaqJ.d.mts +43 -0
- package/dist/inert-outside.d.mts +2 -0
- package/dist/inert-outside.mjs +2 -0
- package/dist/interaction-modality.d.mts +2 -2
- package/dist/interaction-modality.mjs +1 -1
- package/dist/long-press-Dsul69gk.mjs +340 -0
- package/dist/{long-press-CRjjjJK2.d.mts → long-press-cll6z2K9.d.mts} +8 -18
- package/dist/long-press.d.mts +2 -2
- package/dist/long-press.mjs +1 -245
- package/dist/media-pdf.d.mts +1 -1
- package/dist/media-pdf.mjs +1 -1
- package/dist/media.d.mts +1 -1
- package/dist/media.mjs +1 -1
- package/dist/move-BOmXDYbh.d.mts +103 -0
- package/dist/move-BVvMHzxr.mjs +386 -0
- package/dist/move.d.mts +2 -0
- package/dist/move.mjs +2 -0
- package/dist/{press-Bp57IOe2.mjs → press-N_mE3Mgx.mjs} +3 -149
- package/dist/press-event-Cd2OPpmw.mjs +149 -0
- package/dist/press.d.mts +1 -1
- package/dist/press.mjs +1 -1
- package/dist/{primitive-BE28SwD7.mjs → primitive-BX31dogp.mjs} +2 -2
- package/dist/{primitive-Bog8qvd8.d.mts → primitive-C8jW7DLd.d.mts} +3 -4
- package/dist/primitive.d.mts +1 -1
- package/dist/primitive.mjs +1 -1
- package/dist/scroll-lock-BgVtX4wT.d.mts +49 -0
- package/dist/scroll-lock-Ckbmm0-J.mjs +313 -0
- package/dist/scroll-lock.d.mts +2 -0
- package/dist/scroll-lock.mjs +2 -0
- package/dist/spatial-navigation-CHj9mDZH.d.mts +106 -0
- package/dist/spatial-navigation-D6-UDavU.mjs +301 -0
- package/dist/spatial-navigation.d.mts +2 -0
- package/dist/spatial-navigation.mjs +2 -0
- package/dist/typeahead-B7KDxE_u.mjs +175 -0
- package/dist/typeahead-BbgUB2Bj.d.mts +71 -0
- package/dist/typeahead.d.mts +2 -0
- package/dist/typeahead.mjs +2 -0
- package/dist/visually-hidden-BOqfqBFt.d.mts +17 -0
- package/dist/{visually-hidden-CTSV3ctZ.mjs → visually-hidden-BwDOx5yf.mjs} +2 -2
- package/dist/visually-hidden.d.mts +1 -1
- package/dist/visually-hidden.mjs +1 -1
- package/package.json +67 -6
- package/dist/visually-hidden-CekDwEwR.d.mts +0 -19
- /package/dist/{_plugin-vue_export-helper-BVN2DL-U.mjs → _plugin-vue_export-helper-BOaGB7Aw.mjs} +0 -0
- /package/dist/{collection-aHZ6Pf0e.d.mts → collection-B_dFZOHO.d.mts} +0 -0
- /package/dist/{collection-CoOROaho.mjs → collection-eHN150dT.mjs} +0 -0
- /package/dist/{controllable-state-B9v6FClp.d.mts → controllable-state-BtoxKahh.d.mts} +0 -0
- /package/dist/{interaction-modality-CO-eQzNy.mjs → interaction-modality-DOZK0BpZ.mjs} +0 -0
- /package/dist/{interaction-modality-tee79ZBZ.d.mts → interaction-modality-jgHKjPFB.d.mts} +0 -0
- /package/dist/{pdf-source-BbZKF_dS.d.mts → pdf-source-BYFK2Pks.d.mts} +0 -0
- /package/dist/{pdf-source-C9zNQd9l.mjs → pdf-source-zu1LkCeE.mjs} +0 -0
- /package/dist/{press-types-B8Ssxqg4.d.mts → press-types-CNqStzJf.d.mts} +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { a as focusableElements, c as documentOrder, i as focusElement, o as isUsableTarget, p as surfaceErrors, s as capture, t as containsComposed } from "./focus-scope-dom-DBwNEWxG.mjs";
|
|
2
|
+
import { getCurrentInstance, getCurrentScope, onMounted, onScopeDispose, shallowReadonly, shallowRef, toValue, watch } from "vue";
|
|
3
|
+
//#region src/focus-guards-internal.ts
|
|
4
|
+
const optionDiagnostic = "VIZE_UI_FOCUS_GUARDS_OPTION";
|
|
5
|
+
/** Resolve an event target without relying on the current realm's Element constructor. */
|
|
6
|
+
function eventElement(value) {
|
|
7
|
+
const candidate = value;
|
|
8
|
+
return candidate?.nodeType === 1 && typeof candidate.getRootNode === "function" ? candidate : null;
|
|
9
|
+
}
|
|
10
|
+
function readBoolean(source, name, fallback) {
|
|
11
|
+
const value = toValue(source);
|
|
12
|
+
if (value === void 0) return fallback;
|
|
13
|
+
if (typeof value !== "boolean") throw new TypeError(`${optionDiagnostic}: ${name} must resolve to a boolean`);
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function readRoot(source) {
|
|
17
|
+
const value = toValue(source);
|
|
18
|
+
if (value === void 0 || value === null) return null;
|
|
19
|
+
const candidate = value;
|
|
20
|
+
if (candidate.nodeType !== 1 || !candidate.ownerDocument) throw new TypeError(`${optionDiagnostic}: root must resolve to an Element or null`);
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
function readBranches(source, document) {
|
|
24
|
+
const value = toValue(source);
|
|
25
|
+
if (value === void 0 || value === null) return [];
|
|
26
|
+
if (!Array.isArray(value)) throw new TypeError(`${optionDiagnostic}: branches must resolve to a readonly Element array`);
|
|
27
|
+
const branches = value;
|
|
28
|
+
for (const branch of branches) {
|
|
29
|
+
if (branch?.nodeType !== 1 || !branch.ownerDocument) throw new TypeError(`${optionDiagnostic}: every branch must be an Element`);
|
|
30
|
+
if (document && branch.ownerDocument !== document) throw new TypeError(`${optionDiagnostic}: branches must share the root Document`);
|
|
31
|
+
}
|
|
32
|
+
return [...new Set(branches)];
|
|
33
|
+
}
|
|
34
|
+
function readTarget(value) {
|
|
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}: fallbackFocus 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
|
+
const root = readRoot(options.root);
|
|
43
|
+
readBranches(options.branches, root?.ownerDocument ?? null);
|
|
44
|
+
readBoolean(options.enabled, "enabled", true);
|
|
45
|
+
readBoolean(options.preventScroll, "preventScroll", true);
|
|
46
|
+
for (const name of [
|
|
47
|
+
"accept",
|
|
48
|
+
"fallbackFocus",
|
|
49
|
+
"onRedirect"
|
|
50
|
+
]) if (options[name] !== void 0 && typeof options[name] !== "function") throw new TypeError(`${optionDiagnostic}: ${name} must be a function`);
|
|
51
|
+
}
|
|
52
|
+
function createRedirectEvent(position, direction, reason, target, relatedTarget, originalEvent) {
|
|
53
|
+
let prevented = false;
|
|
54
|
+
return Object.freeze({
|
|
55
|
+
type: "focus-guard-redirect",
|
|
56
|
+
position,
|
|
57
|
+
direction,
|
|
58
|
+
reason,
|
|
59
|
+
target,
|
|
60
|
+
relatedTarget,
|
|
61
|
+
originalEvent,
|
|
62
|
+
get defaultPrevented() {
|
|
63
|
+
return prevented;
|
|
64
|
+
},
|
|
65
|
+
preventDefault: () => {
|
|
66
|
+
prevented = true;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/focus-guards-stack.ts
|
|
72
|
+
const documentStacks = /* @__PURE__ */ new WeakMap();
|
|
73
|
+
function stackFor(document) {
|
|
74
|
+
let stack = documentStacks.get(document);
|
|
75
|
+
if (!stack) {
|
|
76
|
+
stack = [];
|
|
77
|
+
documentStacks.set(document, stack);
|
|
78
|
+
}
|
|
79
|
+
return stack;
|
|
80
|
+
}
|
|
81
|
+
function recomputeFocusGuards(document) {
|
|
82
|
+
const stack = stackFor(document);
|
|
83
|
+
let owner = null;
|
|
84
|
+
for (let index = stack.length - 1; index >= 0; index--) {
|
|
85
|
+
const token = stack[index];
|
|
86
|
+
if (token?.root?.isConnected && token.readEnabled()) {
|
|
87
|
+
owner = token;
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (const token of stack) token.setTopmost(token === owner);
|
|
92
|
+
}
|
|
93
|
+
function attachFocusGuards(token, root) {
|
|
94
|
+
if (token.document === root.ownerDocument) {
|
|
95
|
+
token.root = root;
|
|
96
|
+
recomputeFocusGuards(root.ownerDocument);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
detachFocusGuards(token);
|
|
100
|
+
token.document = root.ownerDocument;
|
|
101
|
+
token.root = root;
|
|
102
|
+
stackFor(root.ownerDocument).push(token);
|
|
103
|
+
recomputeFocusGuards(root.ownerDocument);
|
|
104
|
+
}
|
|
105
|
+
function detachFocusGuards(token) {
|
|
106
|
+
const document = token.document;
|
|
107
|
+
if (!document) {
|
|
108
|
+
token.root = null;
|
|
109
|
+
token.setTopmost(false);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const stack = stackFor(document);
|
|
113
|
+
const index = stack.indexOf(token);
|
|
114
|
+
if (index >= 0) stack.splice(index, 1);
|
|
115
|
+
token.document = null;
|
|
116
|
+
token.root = null;
|
|
117
|
+
token.setTopmost(false);
|
|
118
|
+
if (stack.length === 0) documentStacks.delete(document);
|
|
119
|
+
else recomputeFocusGuards(document);
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/focus-guards.ts
|
|
123
|
+
const disposedDiagnostic = "VIZE_UI_FOCUS_GUARDS_DISPOSED";
|
|
124
|
+
const rootDiagnostic = "VIZE_UI_FOCUS_GUARDS_ROOT";
|
|
125
|
+
const setupDiagnostic = "VIZE_UI_FOCUS_GUARDS_SETUP";
|
|
126
|
+
/** Optional invisible sentinel preset; consumers remain free to replace every value. */
|
|
127
|
+
const focusGuardPreset = Object.freeze({
|
|
128
|
+
blockSize: "1px",
|
|
129
|
+
borderWidth: "0",
|
|
130
|
+
inlineSize: "1px",
|
|
131
|
+
insetBlockStart: "0",
|
|
132
|
+
insetInlineStart: "0",
|
|
133
|
+
opacity: "0",
|
|
134
|
+
outline: "none",
|
|
135
|
+
padding: "0",
|
|
136
|
+
pointerEvents: "none",
|
|
137
|
+
position: "fixed"
|
|
138
|
+
});
|
|
139
|
+
/** Create an SSR-safe pair of nested, portal-aware focus sentinels. */
|
|
140
|
+
function createFocusGuards(options) {
|
|
141
|
+
validateOptions(options);
|
|
142
|
+
const activeState = shallowRef(false);
|
|
143
|
+
const guardingState = shallowRef(false);
|
|
144
|
+
const token = {
|
|
145
|
+
document: null,
|
|
146
|
+
root: null,
|
|
147
|
+
readEnabled: () => readBoolean(options.enabled, "enabled", true),
|
|
148
|
+
setTopmost: (value) => {
|
|
149
|
+
guardingState.value = value;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
let disposed = false;
|
|
153
|
+
let redirecting = false;
|
|
154
|
+
let tabDirection = null;
|
|
155
|
+
let observer = null;
|
|
156
|
+
const assertAlive = () => {
|
|
157
|
+
if (disposed) throw new Error(`${disposedDiagnostic}: the controller has been disposed`);
|
|
158
|
+
};
|
|
159
|
+
const roots = () => {
|
|
160
|
+
const root = token.root;
|
|
161
|
+
return root ? [root, ...readBranches(options.branches, root.ownerDocument)] : [];
|
|
162
|
+
};
|
|
163
|
+
const candidates = () => documentOrder(roots().flatMap((root) => focusableElements(root, { accept: (element) => !element.hasAttribute("data-vize-focus-guard") && options.accept?.(element) !== false })));
|
|
164
|
+
const fallback = () => {
|
|
165
|
+
const ownedRoots = roots();
|
|
166
|
+
const preferred = readTarget(options.fallbackFocus?.());
|
|
167
|
+
if (preferred && !ownedRoots.some((root) => containsComposed(root, preferred))) throw new Error(`${rootDiagnostic}: fallbackFocus must resolve inside a guarded region`);
|
|
168
|
+
if (preferred?.hasAttribute("data-vize-focus-guard")) return null;
|
|
169
|
+
if (isUsableTarget(preferred)) return preferred;
|
|
170
|
+
const root = token.root;
|
|
171
|
+
return root?.hasAttribute("tabindex") && isUsableTarget(root) ? root : null;
|
|
172
|
+
};
|
|
173
|
+
const owns = (element) => element !== null && roots().some((root) => containsComposed(root, element));
|
|
174
|
+
const onKeydown = (event) => {
|
|
175
|
+
if (event.key === "Tab" && !event.altKey && !event.ctrlKey && !event.metaKey) tabDirection = event.shiftKey ? "backward" : "forward";
|
|
176
|
+
};
|
|
177
|
+
const redirect = (position, originalEvent) => {
|
|
178
|
+
if (!guardingState.value || redirecting) return;
|
|
179
|
+
const related = eventElement(originalEvent.relatedTarget);
|
|
180
|
+
const wrapped = owns(related);
|
|
181
|
+
const direction = wrapped || related ? position === "before" ? wrapped ? "backward" : "forward" : wrapped ? "forward" : "backward" : tabDirection ?? (position === "before" ? "forward" : "backward");
|
|
182
|
+
tabDirection = null;
|
|
183
|
+
const values = candidates();
|
|
184
|
+
const target = (direction === "forward" ? values[0] : values.at(-1)) ?? fallback();
|
|
185
|
+
const event = createRedirectEvent(position, direction, wrapped ? "wrap" : "enter", target, related, originalEvent);
|
|
186
|
+
const errors = [];
|
|
187
|
+
redirecting = true;
|
|
188
|
+
try {
|
|
189
|
+
capture(errors, () => options.onRedirect?.(event));
|
|
190
|
+
if (!event.defaultPrevented && target) capture(errors, () => focusElement(target, readBoolean(options.preventScroll, "preventScroll", true)));
|
|
191
|
+
} finally {
|
|
192
|
+
redirecting = false;
|
|
193
|
+
}
|
|
194
|
+
surfaceErrors(errors, "Focus guard redirection failed");
|
|
195
|
+
};
|
|
196
|
+
const props = (position) => Object.freeze({
|
|
197
|
+
"data-vize-focus-guard": position,
|
|
198
|
+
get tabindex() {
|
|
199
|
+
return guardingState.value ? 0 : -1;
|
|
200
|
+
},
|
|
201
|
+
onFocus: (event) => redirect(position, event)
|
|
202
|
+
});
|
|
203
|
+
const beforeProps = props("before");
|
|
204
|
+
const afterProps = props("after");
|
|
205
|
+
const detachDom = () => {
|
|
206
|
+
observer?.disconnect();
|
|
207
|
+
observer = null;
|
|
208
|
+
token.document?.removeEventListener("keydown", onKeydown, true);
|
|
209
|
+
detachFocusGuards(token);
|
|
210
|
+
};
|
|
211
|
+
const observe = (root) => {
|
|
212
|
+
const Observer = root.ownerDocument.defaultView?.MutationObserver;
|
|
213
|
+
const documentRoot = root.ownerDocument.documentElement;
|
|
214
|
+
if (!Observer || !documentRoot) return;
|
|
215
|
+
observer = new Observer(() => recomputeFocusGuards(root.ownerDocument));
|
|
216
|
+
observer.observe(documentRoot, {
|
|
217
|
+
childList: true,
|
|
218
|
+
subtree: true
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
const refresh = () => {
|
|
222
|
+
assertAlive();
|
|
223
|
+
if (!activeState.value) return;
|
|
224
|
+
const nextRoot = readRoot(options.root);
|
|
225
|
+
readBoolean(options.enabled, "enabled", true);
|
|
226
|
+
readBoolean(options.preventScroll, "preventScroll", true);
|
|
227
|
+
readBranches(options.branches, nextRoot?.ownerDocument ?? null);
|
|
228
|
+
if (nextRoot !== token.root) {
|
|
229
|
+
const sameDocument = nextRoot !== null && token.document === nextRoot.ownerDocument;
|
|
230
|
+
if (sameDocument) attachFocusGuards(token, nextRoot);
|
|
231
|
+
else detachDom();
|
|
232
|
+
if (nextRoot && !sameDocument) {
|
|
233
|
+
attachFocusGuards(token, nextRoot);
|
|
234
|
+
nextRoot.ownerDocument.addEventListener("keydown", onKeydown, true);
|
|
235
|
+
observe(nextRoot);
|
|
236
|
+
}
|
|
237
|
+
} else if (token.document) recomputeFocusGuards(token.document);
|
|
238
|
+
};
|
|
239
|
+
const activate = () => {
|
|
240
|
+
assertAlive();
|
|
241
|
+
if (activeState.value) return;
|
|
242
|
+
activeState.value = true;
|
|
243
|
+
try {
|
|
244
|
+
refresh();
|
|
245
|
+
} catch (error) {
|
|
246
|
+
activeState.value = false;
|
|
247
|
+
detachDom();
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const deactivate = () => {
|
|
252
|
+
assertAlive();
|
|
253
|
+
if (!activeState.value) return;
|
|
254
|
+
try {
|
|
255
|
+
detachDom();
|
|
256
|
+
} finally {
|
|
257
|
+
activeState.value = false;
|
|
258
|
+
tabDirection = null;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
const stopWatch = watch(() => [
|
|
262
|
+
toValue(options.root),
|
|
263
|
+
toValue(options.branches),
|
|
264
|
+
toValue(options.enabled),
|
|
265
|
+
toValue(options.preventScroll)
|
|
266
|
+
], () => {
|
|
267
|
+
if (activeState.value) refresh();
|
|
268
|
+
}, { flush: "sync" });
|
|
269
|
+
return Object.freeze({
|
|
270
|
+
isActive: shallowReadonly(activeState),
|
|
271
|
+
isGuarding: shallowReadonly(guardingState),
|
|
272
|
+
beforeProps,
|
|
273
|
+
afterProps,
|
|
274
|
+
activate,
|
|
275
|
+
deactivate,
|
|
276
|
+
refresh,
|
|
277
|
+
dispose: () => {
|
|
278
|
+
if (disposed) return;
|
|
279
|
+
try {
|
|
280
|
+
detachDom();
|
|
281
|
+
} finally {
|
|
282
|
+
activeState.value = false;
|
|
283
|
+
disposed = true;
|
|
284
|
+
stopWatch();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/** Create, mount-activate, and scope-dispose a focus-guard pair. */
|
|
290
|
+
function useFocusGuards(options) {
|
|
291
|
+
if (!getCurrentScope()) throw new Error(`${setupDiagnostic}: use inside component setup or an active effect scope`);
|
|
292
|
+
const controller = createFocusGuards(options);
|
|
293
|
+
if (getCurrentInstance()) onMounted(controller.activate);
|
|
294
|
+
else controller.activate();
|
|
295
|
+
onScopeDispose(controller.dispose);
|
|
296
|
+
return controller;
|
|
297
|
+
}
|
|
298
|
+
//#endregion
|
|
299
|
+
export { focusGuardPreset as n, useFocusGuards as r, createFocusGuards as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as FocusGuardPosition, c as FocusGuardRedirectEvent, d as FocusGuardsOptions, i as FocusGuardDirection, l as FocusGuardStylePreset, n as focusGuardPreset, o as FocusGuardProps, r as useFocusGuards, s as FocusGuardReason, t as createFocusGuards, u as FocusGuardsController } from "./focus-guards-Bt0C-0qS.mjs";
|
|
2
|
+
export { type FocusGuardDirection, type FocusGuardPosition, type FocusGuardProps, type FocusGuardReason, type FocusGuardRedirectEvent, type FocusGuardStylePreset, type FocusGuardsController, type FocusGuardsOptions, createFocusGuards, focusGuardPreset, useFocusGuards };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { MaybeRefOrGetter, ShallowRef } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/focus-scope-types.d.ts
|
|
4
|
+
/** Preventable lifecycle notification for automatic focus movement. */
|
|
5
|
+
interface FocusScopeAutoFocusEvent {
|
|
6
|
+
readonly type: "mount" | "unmount";
|
|
7
|
+
readonly target: HTMLElement | null;
|
|
8
|
+
readonly defaultPrevented: boolean;
|
|
9
|
+
readonly preventDefault: () => void;
|
|
10
|
+
}
|
|
11
|
+
/** Programmatic movement options shared by the focus manager methods. */
|
|
12
|
+
interface FocusScopeMoveOptions {
|
|
13
|
+
/** Element from which traversal begins. Defaults to the deep active element. */
|
|
14
|
+
readonly from?: Element | null;
|
|
15
|
+
/**
|
|
16
|
+
* Include focusable elements excluded from sequential Tab order.
|
|
17
|
+
*
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
readonly includeProgrammatic?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Wrap traversal at the scope boundary.
|
|
23
|
+
*
|
|
24
|
+
* @default false
|
|
25
|
+
*/
|
|
26
|
+
readonly wrap?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Avoid browser scrolling while focus moves.
|
|
29
|
+
*
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
readonly preventScroll?: boolean;
|
|
33
|
+
/** Additional consumer filter applied after native focusability checks. */
|
|
34
|
+
readonly accept?: (element: HTMLElement) => boolean;
|
|
35
|
+
}
|
|
36
|
+
/** Focus containment, entry, and restoration options for one DOM subtree. */
|
|
37
|
+
interface FocusScopeOptions {
|
|
38
|
+
/** Scope root. It may be `null` during SSR and before mount. */
|
|
39
|
+
readonly root: MaybeRefOrGetter<Element | null | undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* Trap sequential and programmatic focus inside the active, topmost scope.
|
|
42
|
+
*
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
readonly contain?: MaybeRefOrGetter<boolean | undefined>;
|
|
46
|
+
/**
|
|
47
|
+
* Focus an initial target when the activated scope receives a mounted root.
|
|
48
|
+
*
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
readonly autoFocus?: MaybeRefOrGetter<boolean | undefined>;
|
|
52
|
+
/**
|
|
53
|
+
* Restore focus when the scope deactivates.
|
|
54
|
+
*
|
|
55
|
+
* @default false
|
|
56
|
+
*/
|
|
57
|
+
readonly restoreFocus?: MaybeRefOrGetter<boolean | undefined>;
|
|
58
|
+
/** Preferred initial target. It must resolve inside the current scope. */
|
|
59
|
+
readonly initialFocus?: () => HTMLElement | null | undefined;
|
|
60
|
+
/** Explicit restoration target, evaluated at deactivation time. */
|
|
61
|
+
readonly restoreTarget?: () => HTMLElement | null | undefined;
|
|
62
|
+
/** Fallback target when a scope has no tabbable descendants. */
|
|
63
|
+
readonly fallbackFocus?: () => HTMLElement | null | undefined;
|
|
64
|
+
/** Consumer filter applied to automatically discovered focusable descendants. */
|
|
65
|
+
readonly accept?: (element: HTMLElement) => boolean;
|
|
66
|
+
/** Called before automatic entry focus. Call `preventDefault` to retain focus. */
|
|
67
|
+
readonly onMountAutoFocus?: (event: FocusScopeAutoFocusEvent) => void;
|
|
68
|
+
/** Called before automatic restoration. Call `preventDefault` to retain focus. */
|
|
69
|
+
readonly onUnmountAutoFocus?: (event: FocusScopeAutoFocusEvent) => void;
|
|
70
|
+
}
|
|
71
|
+
/** Stable focus traversal interface for one scope. */
|
|
72
|
+
interface FocusScopeManager {
|
|
73
|
+
readonly focusFirst: (options?: FocusScopeMoveOptions) => HTMLElement | null;
|
|
74
|
+
readonly focusLast: (options?: FocusScopeMoveOptions) => HTMLElement | null;
|
|
75
|
+
readonly focusNext: (options?: FocusScopeMoveOptions) => HTMLElement | null;
|
|
76
|
+
readonly focusPrevious: (options?: FocusScopeMoveOptions) => HTMLElement | null;
|
|
77
|
+
}
|
|
78
|
+
/** Lifecycle and traversal controller returned by `createFocusScope`. */
|
|
79
|
+
interface FocusScopeController extends FocusScopeManager {
|
|
80
|
+
/** Whether this controller has been activated and not deactivated. */
|
|
81
|
+
readonly isActive: Readonly<ShallowRef<boolean>>;
|
|
82
|
+
/** Activate once, capture restoration context, and attach when a root exists. */
|
|
83
|
+
readonly activate: () => void;
|
|
84
|
+
/** Deactivate once, detach containment, and restore focus when configured. */
|
|
85
|
+
readonly deactivate: () => void;
|
|
86
|
+
/** Re-read the root and recover containment after imperative DOM changes. */
|
|
87
|
+
readonly refresh: () => void;
|
|
88
|
+
/** Permanently release watches and lifecycle ownership. */
|
|
89
|
+
readonly dispose: () => void;
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/use-focus-scope.d.ts
|
|
93
|
+
/** Create, mount-activate, and scope-dispose a focus scope from Vue setup. */
|
|
94
|
+
declare function useFocusScope(options: FocusScopeOptions): FocusScopeController;
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/focus-scope.d.ts
|
|
97
|
+
/** Create an SSR-safe focus scope with containment, traversal, and restoration. */
|
|
98
|
+
declare function createFocusScope(options: FocusScopeOptions): FocusScopeController;
|
|
99
|
+
//#endregion
|
|
100
|
+
export { FocusScopeManager as a, FocusScopeController as i, useFocusScope as n, FocusScopeMoveOptions as o, FocusScopeAutoFocusEvent as r, FocusScopeOptions as s, createFocusScope as t };
|