@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.
- package/dist/{button-D7sM9Xmj.d.mts → button-CVX8UBXj.d.mts} +6 -7
- package/dist/{button-8BOlFJNu.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-DkwZFC80.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-B_dFZOHO.d.mts +185 -0
- package/dist/collection-eHN150dT.mjs +453 -0
- package/dist/collection.d.mts +2 -0
- package/dist/collection.mjs +2 -0
- 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-5OAUyVPd.d.mts +126 -0
- package/dist/id-mziSyAse.mjs +137 -0
- package/dist/id.d.mts +2 -0
- package/dist/id.mjs +2 -0
- package/dist/index.d.mts +23 -6
- package/dist/index.mjs +21 -5
- 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-DOZK0BpZ.mjs +304 -0
- package/dist/interaction-modality-jgHKjPFB.d.mts +89 -0
- package/dist/interaction-modality.d.mts +2 -0
- package/dist/interaction-modality.mjs +2 -0
- package/dist/long-press-Dsul69gk.mjs +340 -0
- package/dist/long-press-cll6z2K9.d.mts +105 -0
- package/dist/long-press.d.mts +2 -0
- package/dist/long-press.mjs +2 -0
- 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-N_mE3Mgx.mjs +469 -0
- package/dist/press-event-Cd2OPpmw.mjs +149 -0
- package/dist/press-types-CNqStzJf.d.mts +112 -0
- package/dist/press.d.mts +14 -0
- package/dist/press.mjs +2 -0
- package/dist/{primitive-DJB7pOf3.mjs → primitive-BX31dogp.mjs} +2 -2
- package/dist/{primitive-BtvwikH1.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-QENRapzW.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 +99 -11
- package/dist/visually-hidden-BegtnMng.d.mts +0 -19
- /package/dist/{_plugin-vue_export-helper-BVN2DL-U.mjs → _plugin-vue_export-helper-BOaGB7Aw.mjs} +0 -0
- /package/dist/{controllable-state-DXsYJ3yl.d.mts → controllable-state-BtoxKahh.d.mts} +0 -0
- /package/dist/{pdf-source-COxN3A1l.d.mts → pdf-source-BYFK2Pks.d.mts} +0 -0
- /package/dist/{pdf-source-C52YE8tp.mjs → pdf-source-zu1LkCeE.mjs} +0 -0
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { getCurrentInstance, getCurrentScope, onMounted, onScopeDispose, shallowReadonly, shallowRef, toValue, watch } from "vue";
|
|
2
|
+
//#region src/dismissable-layer-internal.ts
|
|
3
|
+
const optionDiagnostic = "VIZE_UI_DISMISSABLE_LAYER_OPTION";
|
|
4
|
+
const rootDiagnostic = "VIZE_UI_DISMISSABLE_LAYER_ROOT";
|
|
5
|
+
/** Resolve an event target without assuming it comes from the current realm. */
|
|
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(`${rootDiagnostic}: root must resolve to an Element or null`);
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
function readBranches(source, document) {
|
|
24
|
+
const value = toValue(source) ?? [];
|
|
25
|
+
if (!Array.isArray(value)) throw new TypeError(`${optionDiagnostic}: branches must resolve to an array of Elements`);
|
|
26
|
+
return validateBranches(value, document);
|
|
27
|
+
}
|
|
28
|
+
function validateBranches(source, document) {
|
|
29
|
+
const unique = [...new Set(source)];
|
|
30
|
+
for (const branch of unique) {
|
|
31
|
+
const candidate = branch;
|
|
32
|
+
if (candidate.nodeType !== 1 || !candidate.ownerDocument) throw new TypeError(`${optionDiagnostic}: branches must contain only Elements`);
|
|
33
|
+
if (document && candidate.ownerDocument !== document) throw new TypeError(`${optionDiagnostic}: branches must share the root Document`);
|
|
34
|
+
}
|
|
35
|
+
return unique;
|
|
36
|
+
}
|
|
37
|
+
function validateOptions(options) {
|
|
38
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) throw new TypeError(`${optionDiagnostic}: options must be an object`);
|
|
39
|
+
const root = readRoot(options.root);
|
|
40
|
+
readBranches(options.branches, root?.ownerDocument ?? null);
|
|
41
|
+
readBoolean(options.enabled, "enabled", true);
|
|
42
|
+
readBoolean(options.outsidePointerDown, "outsidePointerDown", true);
|
|
43
|
+
readBoolean(options.outsideFocus, "outsideFocus", true);
|
|
44
|
+
readBoolean(options.escapeKey, "escapeKey", true);
|
|
45
|
+
for (const name of [
|
|
46
|
+
"onPointerDownOutside",
|
|
47
|
+
"onFocusOutside",
|
|
48
|
+
"onInteractOutside",
|
|
49
|
+
"onEscapeKeyDown",
|
|
50
|
+
"onDismiss"
|
|
51
|
+
]) if (options[name] !== void 0 && typeof options[name] !== "function") throw new TypeError(`${optionDiagnostic}: ${name} must be a function`);
|
|
52
|
+
}
|
|
53
|
+
function modifier(event, key) {
|
|
54
|
+
return key in event ? Boolean(event[key]) : false;
|
|
55
|
+
}
|
|
56
|
+
function eventPoint(event) {
|
|
57
|
+
if ("clientX" in event && "clientY" in event) return {
|
|
58
|
+
x: Number(event.clientX),
|
|
59
|
+
y: Number(event.clientY)
|
|
60
|
+
};
|
|
61
|
+
if ("changedTouches" in event) {
|
|
62
|
+
const touch = Array.from(event.changedTouches)[0];
|
|
63
|
+
if (touch) return {
|
|
64
|
+
x: touch.clientX,
|
|
65
|
+
y: touch.clientY
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
function pointerTypeOf(event) {
|
|
71
|
+
if ("changedTouches" in event) return "touch";
|
|
72
|
+
if ("pointerType" in event) {
|
|
73
|
+
if (event.pointerId === -1 && event.pointerType === "") return "virtual";
|
|
74
|
+
if (event.pointerType === "mouse" || event.pointerType === "pen") return event.pointerType;
|
|
75
|
+
if (event.pointerType === "touch") return "touch";
|
|
76
|
+
return "pointer";
|
|
77
|
+
}
|
|
78
|
+
return "mouse";
|
|
79
|
+
}
|
|
80
|
+
function preventable() {
|
|
81
|
+
let prevented = false;
|
|
82
|
+
return {
|
|
83
|
+
get defaultPrevented() {
|
|
84
|
+
return prevented;
|
|
85
|
+
},
|
|
86
|
+
preventDefault: () => {
|
|
87
|
+
prevented = true;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** Build an immutable outside pointer event that is stable after native dispatch mutates. */
|
|
92
|
+
function createPointerDownOutsideEvent(originalEvent, target) {
|
|
93
|
+
const point = eventPoint(originalEvent);
|
|
94
|
+
const prevention = preventable();
|
|
95
|
+
return Object.freeze({
|
|
96
|
+
type: "pointer-down-outside",
|
|
97
|
+
reason: "pointer-down-outside",
|
|
98
|
+
target,
|
|
99
|
+
originalEvent,
|
|
100
|
+
pointerType: pointerTypeOf(originalEvent),
|
|
101
|
+
x: point?.x ?? null,
|
|
102
|
+
y: point?.y ?? null,
|
|
103
|
+
altKey: modifier(originalEvent, "altKey"),
|
|
104
|
+
ctrlKey: modifier(originalEvent, "ctrlKey"),
|
|
105
|
+
metaKey: modifier(originalEvent, "metaKey"),
|
|
106
|
+
shiftKey: modifier(originalEvent, "shiftKey"),
|
|
107
|
+
get defaultPrevented() {
|
|
108
|
+
return prevention.defaultPrevented;
|
|
109
|
+
},
|
|
110
|
+
preventDefault: prevention.preventDefault
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/** Build an immutable outside focus event that preserves related-target evidence. */
|
|
114
|
+
function createFocusOutsideEvent(originalEvent, target) {
|
|
115
|
+
const prevention = preventable();
|
|
116
|
+
return Object.freeze({
|
|
117
|
+
type: "focus-outside",
|
|
118
|
+
reason: "focus-outside",
|
|
119
|
+
target,
|
|
120
|
+
relatedTarget: eventElement(originalEvent.relatedTarget),
|
|
121
|
+
originalEvent,
|
|
122
|
+
get defaultPrevented() {
|
|
123
|
+
return prevention.defaultPrevented;
|
|
124
|
+
},
|
|
125
|
+
preventDefault: prevention.preventDefault
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/** Build an immutable Escape event before dismissal is committed. */
|
|
129
|
+
function createEscapeKeyDownEvent(originalEvent, target) {
|
|
130
|
+
const prevention = preventable();
|
|
131
|
+
return Object.freeze({
|
|
132
|
+
type: "escape-key",
|
|
133
|
+
reason: "escape-key",
|
|
134
|
+
target,
|
|
135
|
+
originalEvent,
|
|
136
|
+
altKey: modifier(originalEvent, "altKey"),
|
|
137
|
+
ctrlKey: modifier(originalEvent, "ctrlKey"),
|
|
138
|
+
metaKey: modifier(originalEvent, "metaKey"),
|
|
139
|
+
shiftKey: modifier(originalEvent, "shiftKey"),
|
|
140
|
+
get defaultPrevented() {
|
|
141
|
+
return prevention.defaultPrevented;
|
|
142
|
+
},
|
|
143
|
+
preventDefault: prevention.preventDefault
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/** Build the final immutable dismissal notification. */
|
|
147
|
+
function createDismissEvent(reason, originalEvent, target) {
|
|
148
|
+
return Object.freeze({
|
|
149
|
+
type: "dismiss",
|
|
150
|
+
reason,
|
|
151
|
+
target,
|
|
152
|
+
originalEvent
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/dismissable-layer-stack.ts
|
|
157
|
+
const documentStates = /* @__PURE__ */ new WeakMap();
|
|
158
|
+
function composedParent(element) {
|
|
159
|
+
if (element.assignedSlot) return element.assignedSlot;
|
|
160
|
+
if (element.parentElement) return element.parentElement;
|
|
161
|
+
return element.getRootNode().host ?? null;
|
|
162
|
+
}
|
|
163
|
+
function containsComposed(root, element) {
|
|
164
|
+
let current = element;
|
|
165
|
+
while (current) {
|
|
166
|
+
if (root === current || root.contains(current)) return true;
|
|
167
|
+
current = composedParent(current);
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
function stackFor(document) {
|
|
172
|
+
let state = documentStates.get(document);
|
|
173
|
+
if (!state) {
|
|
174
|
+
state = {
|
|
175
|
+
document,
|
|
176
|
+
lastPointerTime: Number.NEGATIVE_INFINITY,
|
|
177
|
+
observer: null,
|
|
178
|
+
queued: false,
|
|
179
|
+
releaseListeners: [],
|
|
180
|
+
tokens: []
|
|
181
|
+
};
|
|
182
|
+
documentStates.set(document, state);
|
|
183
|
+
}
|
|
184
|
+
return state;
|
|
185
|
+
}
|
|
186
|
+
function rootsFor(token) {
|
|
187
|
+
const root = token.root;
|
|
188
|
+
if (!root?.isConnected || !token.readEnabled()) return [];
|
|
189
|
+
return [...new Set([root, ...token.readBranches()])].filter((branch) => branch.isConnected);
|
|
190
|
+
}
|
|
191
|
+
function topLayer(state) {
|
|
192
|
+
for (let index = state.tokens.length - 1; index >= 0; index--) {
|
|
193
|
+
const token = state.tokens[index];
|
|
194
|
+
if (token && rootsFor(token).length > 0) return token;
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
function targetElement(event) {
|
|
199
|
+
const path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
200
|
+
for (const item of path) {
|
|
201
|
+
const element = item;
|
|
202
|
+
if (element.nodeType === 1 && typeof element.getRootNode === "function") return element;
|
|
203
|
+
}
|
|
204
|
+
const target = event.target;
|
|
205
|
+
return target?.nodeType === 1 && typeof target.getRootNode === "function" ? target : null;
|
|
206
|
+
}
|
|
207
|
+
function eventInside(event, target, roots) {
|
|
208
|
+
const path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
209
|
+
return roots.some((root) => path.includes(root) || containsComposed(root, target));
|
|
210
|
+
}
|
|
211
|
+
function recomputeDismissableLayers(document) {
|
|
212
|
+
const state = stackFor(document);
|
|
213
|
+
const owner = topLayer(state);
|
|
214
|
+
for (const token of state.tokens) token.setTopLayer(token === owner);
|
|
215
|
+
}
|
|
216
|
+
function routePointerDown(state, event) {
|
|
217
|
+
if (event.defaultPrevented) return;
|
|
218
|
+
const owner = topLayer(state);
|
|
219
|
+
if (!owner?.readOutsidePointerDown()) return;
|
|
220
|
+
const target = targetElement(event);
|
|
221
|
+
if (!target || eventInside(event, target, rootsFor(owner))) return;
|
|
222
|
+
owner.handlePointerDownOutside(event, target);
|
|
223
|
+
}
|
|
224
|
+
function routeFocusIn(state, event) {
|
|
225
|
+
const owner = topLayer(state);
|
|
226
|
+
if (!owner?.readOutsideFocus()) return;
|
|
227
|
+
const target = targetElement(event);
|
|
228
|
+
if (!target || eventInside(event, target, rootsFor(owner))) return;
|
|
229
|
+
owner.handleFocusOutside(event, target);
|
|
230
|
+
}
|
|
231
|
+
function routeEscape(state, event) {
|
|
232
|
+
if (event.key !== "Escape" || event.defaultPrevented || event.isComposing) return;
|
|
233
|
+
const owner = topLayer(state);
|
|
234
|
+
if (!owner?.readEscapeKey()) return;
|
|
235
|
+
owner.handleEscapeKeyDown(event, targetElement(event));
|
|
236
|
+
}
|
|
237
|
+
function observe(state) {
|
|
238
|
+
if (state.observer) return;
|
|
239
|
+
const Observer = state.document.defaultView?.MutationObserver;
|
|
240
|
+
const root = state.document.documentElement;
|
|
241
|
+
if (!Observer || !root) return;
|
|
242
|
+
state.observer = new Observer(() => {
|
|
243
|
+
if (state.queued) return;
|
|
244
|
+
state.queued = true;
|
|
245
|
+
queueMicrotask(() => {
|
|
246
|
+
state.queued = false;
|
|
247
|
+
if (state.tokens.length > 0) recomputeDismissableLayers(state.document);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
state.observer.observe(root, {
|
|
251
|
+
childList: true,
|
|
252
|
+
subtree: true
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function addDocumentListeners(state) {
|
|
256
|
+
if (state.releaseListeners.length > 0) return;
|
|
257
|
+
const document = state.document;
|
|
258
|
+
const listen = (type, callback, options) => {
|
|
259
|
+
document.addEventListener(type, callback, options);
|
|
260
|
+
state.releaseListeners.push(() => document.removeEventListener(type, callback, options));
|
|
261
|
+
};
|
|
262
|
+
listen("pointerdown", ((event) => {
|
|
263
|
+
state.lastPointerTime = event.timeStamp;
|
|
264
|
+
routePointerDown(state, event);
|
|
265
|
+
}), true);
|
|
266
|
+
listen("mousedown", ((event) => {
|
|
267
|
+
const view = document.defaultView;
|
|
268
|
+
const elapsed = event.timeStamp - state.lastPointerTime;
|
|
269
|
+
if (view && "PointerEvent" in view && elapsed >= 0 && elapsed < 800) return;
|
|
270
|
+
routePointerDown(state, event);
|
|
271
|
+
}), true);
|
|
272
|
+
listen("touchstart", ((event) => {
|
|
273
|
+
const view = document.defaultView;
|
|
274
|
+
if (view && "PointerEvent" in view) return;
|
|
275
|
+
routePointerDown(state, event);
|
|
276
|
+
}), true);
|
|
277
|
+
listen("focusin", ((event) => routeFocusIn(state, event)), true);
|
|
278
|
+
listen("keydown", ((event) => routeEscape(state, event)));
|
|
279
|
+
}
|
|
280
|
+
function removeDocumentListeners(state) {
|
|
281
|
+
for (const release of state.releaseListeners.splice(0)) release();
|
|
282
|
+
}
|
|
283
|
+
function attachDismissableLayer(token, root) {
|
|
284
|
+
if (token.document === root.ownerDocument) {
|
|
285
|
+
token.root = root;
|
|
286
|
+
recomputeDismissableLayers(root.ownerDocument);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
detachDismissableLayer(token);
|
|
290
|
+
const state = stackFor(root.ownerDocument);
|
|
291
|
+
const wasEmpty = state.tokens.length === 0;
|
|
292
|
+
token.document = root.ownerDocument;
|
|
293
|
+
token.root = root;
|
|
294
|
+
state.tokens.push(token);
|
|
295
|
+
if (wasEmpty) {
|
|
296
|
+
addDocumentListeners(state);
|
|
297
|
+
observe(state);
|
|
298
|
+
}
|
|
299
|
+
recomputeDismissableLayers(root.ownerDocument);
|
|
300
|
+
}
|
|
301
|
+
function detachDismissableLayer(token) {
|
|
302
|
+
const document = token.document;
|
|
303
|
+
if (!document) {
|
|
304
|
+
token.root = null;
|
|
305
|
+
token.setTopLayer(false);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const state = stackFor(document);
|
|
309
|
+
const index = state.tokens.indexOf(token);
|
|
310
|
+
if (index >= 0) state.tokens.splice(index, 1);
|
|
311
|
+
token.document = null;
|
|
312
|
+
token.root = null;
|
|
313
|
+
token.setTopLayer(false);
|
|
314
|
+
if (state.tokens.length === 0) {
|
|
315
|
+
removeDocumentListeners(state);
|
|
316
|
+
state.observer?.disconnect();
|
|
317
|
+
state.observer = null;
|
|
318
|
+
documentStates.delete(document);
|
|
319
|
+
} else recomputeDismissableLayers(document);
|
|
320
|
+
}
|
|
321
|
+
function refreshDismissableLayer(token) {
|
|
322
|
+
if (token.document) recomputeDismissableLayers(token.document);
|
|
323
|
+
}
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/dismissable-layer.ts
|
|
326
|
+
const disposedDiagnostic = "VIZE_UI_DISMISSABLE_LAYER_DISPOSED";
|
|
327
|
+
const setupDiagnostic = "VIZE_UI_DISMISSABLE_LAYER_SETUP";
|
|
328
|
+
function capture(errors, callback) {
|
|
329
|
+
try {
|
|
330
|
+
callback();
|
|
331
|
+
} catch (error) {
|
|
332
|
+
errors.push(error);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function surfaceErrors(errors, message) {
|
|
336
|
+
if (errors.length === 1) throw errors[0];
|
|
337
|
+
if (errors.length < 2) return;
|
|
338
|
+
throw new AggregateError(errors, message);
|
|
339
|
+
}
|
|
340
|
+
/** Create an SSR-safe, document-scoped dismissal layer for overlays and popups. */
|
|
341
|
+
function createDismissableLayer(options) {
|
|
342
|
+
validateOptions(options);
|
|
343
|
+
const activeState = shallowRef(false);
|
|
344
|
+
const topLayerState = shallowRef(false);
|
|
345
|
+
const registeredBranches = /* @__PURE__ */ new Set();
|
|
346
|
+
const token = {
|
|
347
|
+
document: null,
|
|
348
|
+
root: null,
|
|
349
|
+
readBranches: () => readAllBranches(token.document),
|
|
350
|
+
readEnabled: () => readBoolean(options.enabled, "enabled", true),
|
|
351
|
+
readEscapeKey: () => readBoolean(options.escapeKey, "escapeKey", true),
|
|
352
|
+
readOutsideFocus: () => readBoolean(options.outsideFocus, "outsideFocus", true),
|
|
353
|
+
readOutsidePointerDown: () => readBoolean(options.outsidePointerDown, "outsidePointerDown", true),
|
|
354
|
+
handleEscapeKeyDown: (originalEvent, target) => {
|
|
355
|
+
const event = createEscapeKeyDownEvent(originalEvent, target);
|
|
356
|
+
const errors = [];
|
|
357
|
+
capture(errors, () => options.onEscapeKeyDown?.(event));
|
|
358
|
+
dismissIfAllowed(errors, event.defaultPrevented, "escape-key", originalEvent, target);
|
|
359
|
+
surfaceErrors(errors, "Dismissable layer Escape callbacks failed");
|
|
360
|
+
},
|
|
361
|
+
handleFocusOutside: (originalEvent, target) => {
|
|
362
|
+
const event = createFocusOutsideEvent(originalEvent, target);
|
|
363
|
+
const errors = [];
|
|
364
|
+
capture(errors, () => options.onFocusOutside?.(event));
|
|
365
|
+
notifyOutside(errors, event);
|
|
366
|
+
dismissIfAllowed(errors, event.defaultPrevented, "focus-outside", originalEvent, target);
|
|
367
|
+
surfaceErrors(errors, "Dismissable layer focus callbacks failed");
|
|
368
|
+
},
|
|
369
|
+
handlePointerDownOutside: (originalEvent, target) => {
|
|
370
|
+
const event = createPointerDownOutsideEvent(originalEvent, target);
|
|
371
|
+
const errors = [];
|
|
372
|
+
capture(errors, () => options.onPointerDownOutside?.(event));
|
|
373
|
+
notifyOutside(errors, event);
|
|
374
|
+
dismissIfAllowed(errors, event.defaultPrevented, "pointer-down-outside", originalEvent, target);
|
|
375
|
+
surfaceErrors(errors, "Dismissable layer pointer callbacks failed");
|
|
376
|
+
},
|
|
377
|
+
setTopLayer: (value) => {
|
|
378
|
+
topLayerState.value = value;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
let disposed = false;
|
|
382
|
+
const assertAlive = () => {
|
|
383
|
+
if (disposed) throw new Error(`${disposedDiagnostic}: the controller has been disposed`);
|
|
384
|
+
};
|
|
385
|
+
const readAllBranches = (document) => {
|
|
386
|
+
const reactiveBranches = readBranches(options.branches, document);
|
|
387
|
+
const imperativeBranches = validateBranches([...registeredBranches], document);
|
|
388
|
+
return [...new Set([...reactiveBranches, ...imperativeBranches])];
|
|
389
|
+
};
|
|
390
|
+
const notifyOutside = (errors, event) => {
|
|
391
|
+
capture(errors, () => options.onInteractOutside?.(event));
|
|
392
|
+
};
|
|
393
|
+
const dismissIfAllowed = (errors, defaultPrevented, reason, originalEvent, target) => {
|
|
394
|
+
if (errors.length > 0 || defaultPrevented) return;
|
|
395
|
+
capture(errors, () => options.onDismiss?.(createDismissEvent(reason, originalEvent, target)));
|
|
396
|
+
};
|
|
397
|
+
const refresh = () => {
|
|
398
|
+
assertAlive();
|
|
399
|
+
if (!activeState.value) return;
|
|
400
|
+
const nextRoot = readRoot(options.root);
|
|
401
|
+
readBoolean(options.enabled, "enabled", true);
|
|
402
|
+
readBoolean(options.escapeKey, "escapeKey", true);
|
|
403
|
+
readBoolean(options.outsideFocus, "outsideFocus", true);
|
|
404
|
+
readBoolean(options.outsidePointerDown, "outsidePointerDown", true);
|
|
405
|
+
readAllBranches(nextRoot?.ownerDocument ?? null);
|
|
406
|
+
if (nextRoot !== token.root) if (nextRoot) attachDismissableLayer(token, nextRoot);
|
|
407
|
+
else detachDismissableLayer(token);
|
|
408
|
+
else refreshDismissableLayer(token);
|
|
409
|
+
};
|
|
410
|
+
const activate = () => {
|
|
411
|
+
assertAlive();
|
|
412
|
+
if (activeState.value) return;
|
|
413
|
+
activeState.value = true;
|
|
414
|
+
try {
|
|
415
|
+
refresh();
|
|
416
|
+
} catch (error) {
|
|
417
|
+
activeState.value = false;
|
|
418
|
+
detachDismissableLayer(token);
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
const deactivate = () => {
|
|
423
|
+
assertAlive();
|
|
424
|
+
if (!activeState.value) return;
|
|
425
|
+
try {
|
|
426
|
+
detachDismissableLayer(token);
|
|
427
|
+
} finally {
|
|
428
|
+
activeState.value = false;
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
const stopWatch = watch(() => [
|
|
432
|
+
toValue(options.root),
|
|
433
|
+
toValue(options.branches),
|
|
434
|
+
toValue(options.enabled),
|
|
435
|
+
toValue(options.escapeKey),
|
|
436
|
+
toValue(options.outsideFocus),
|
|
437
|
+
toValue(options.outsidePointerDown)
|
|
438
|
+
], () => {
|
|
439
|
+
if (activeState.value) refresh();
|
|
440
|
+
}, { flush: "sync" });
|
|
441
|
+
const registerBranch = (branch) => {
|
|
442
|
+
assertAlive();
|
|
443
|
+
validateBranches([branch], token.document);
|
|
444
|
+
registeredBranches.add(branch);
|
|
445
|
+
if (activeState.value) refresh();
|
|
446
|
+
let released = false;
|
|
447
|
+
return () => {
|
|
448
|
+
if (released) return;
|
|
449
|
+
released = true;
|
|
450
|
+
registeredBranches.delete(branch);
|
|
451
|
+
if (!disposed && activeState.value) refresh();
|
|
452
|
+
};
|
|
453
|
+
};
|
|
454
|
+
const layerProps = Object.freeze({ "data-vize-dismissable-layer": "" });
|
|
455
|
+
const branchProps = Object.freeze({ "data-vize-dismissable-branch": "" });
|
|
456
|
+
return Object.freeze({
|
|
457
|
+
isActive: shallowReadonly(activeState),
|
|
458
|
+
isTopLayer: shallowReadonly(topLayerState),
|
|
459
|
+
layerProps,
|
|
460
|
+
branchProps,
|
|
461
|
+
registerBranch,
|
|
462
|
+
activate,
|
|
463
|
+
deactivate,
|
|
464
|
+
refresh,
|
|
465
|
+
dispose: () => {
|
|
466
|
+
if (disposed) return;
|
|
467
|
+
try {
|
|
468
|
+
detachDismissableLayer(token);
|
|
469
|
+
} finally {
|
|
470
|
+
activeState.value = false;
|
|
471
|
+
disposed = true;
|
|
472
|
+
registeredBranches.clear();
|
|
473
|
+
stopWatch();
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
/** Create, mount-activate, and scope-dispose a dismissable overlay layer. */
|
|
479
|
+
function useDismissableLayer(options) {
|
|
480
|
+
if (!getCurrentScope()) throw new Error(`${setupDiagnostic}: use inside component setup or an active effect scope`);
|
|
481
|
+
const controller = createDismissableLayer(options);
|
|
482
|
+
if (getCurrentInstance()) onMounted(controller.activate);
|
|
483
|
+
else controller.activate();
|
|
484
|
+
onScopeDispose(controller.dispose);
|
|
485
|
+
return controller;
|
|
486
|
+
}
|
|
487
|
+
//#endregion
|
|
488
|
+
export { useDismissableLayer as n, createDismissableLayer as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as DismissableLayerDismissEvent, c as DismissableLayerFocusOutsideEvent, d as DismissableLayerOutsideReason, f as DismissableLayerPointerDownOutsideEvent, i as DismissableLayerController, l as DismissableLayerInteractOutsideEvent, m as DismissableLayerProps, n as useDismissableLayer, o as DismissableLayerDismissReason, p as DismissableLayerPointerType, r as DismissableLayerBranchProps, s as DismissableLayerEscapeKeyDownEvent, t as createDismissableLayer, u as DismissableLayerOptions } from "./dismissable-layer-4icKahVs.mjs";
|
|
2
|
+
export { type DismissableLayerBranchProps, type DismissableLayerController, type DismissableLayerDismissEvent, type DismissableLayerDismissReason, type DismissableLayerEscapeKeyDownEvent, type DismissableLayerFocusOutsideEvent, type DismissableLayerInteractOutsideEvent, type DismissableLayerOptions, type DismissableLayerOutsideReason, type DismissableLayerPointerDownOutsideEvent, type DismissableLayerPointerType, type DismissableLayerProps, createDismissableLayer, useDismissableLayer };
|