sb-floating-panel-vue 5.0.3 → 5.2.0
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/README.md +133 -80
- package/dist/components/SbContainer.vue.d.ts +7 -7
- package/dist/components/SbFloating.vue.d.ts +3 -2
- package/dist/composables/useSbFloating.d.ts +6 -0
- package/dist/composables/useSbFloatingContext.d.ts +20 -2
- package/dist/index.d.ts +2 -1
- package/dist/sb-floating-panel.es.js +308 -249
- package/dist/sb-floating-panel.umd.js +1 -1
- package/dist/types.d.ts +48 -3
- package/dist/utils/dom.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,62 +1,103 @@
|
|
|
1
|
-
import { Teleport as e, Transition as t, computed as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createVNode as o, defineComponent as s, inject as c, mergeModels as l, mergeProps as u, nextTick as
|
|
2
|
-
import { autoUpdate as
|
|
1
|
+
import { Teleport as e, Transition as t, computed as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createVNode as o, defineComponent as s, inject as c, mergeModels as l, mergeProps as u, nextTick as ee, normalizeStyle as d, onBeforeUnmount as f, onMounted as p, onScopeDispose as m, openBlock as h, provide as g, readonly as _, ref as v, renderSlot as te, resolveDynamicComponent as y, toRef as b, toValue as x, unref as S, useAttrs as C, useId as w, useModel as T, watch as E, watchEffect as D, withCtx as O } from "vue";
|
|
2
|
+
import { autoUpdate as k, flip as A, hide as j, limitShift as M, offset as N, shift as P, size as F, useFloating as ne } from "@floating-ui/vue";
|
|
3
|
+
//#region src/utils/dom.ts
|
|
4
|
+
var re = "data-sbf-focus-guard", I = [
|
|
5
|
+
"a[href]",
|
|
6
|
+
"button:not([disabled])",
|
|
7
|
+
"input:not([disabled]):not([type=\"hidden\"])",
|
|
8
|
+
"select:not([disabled])",
|
|
9
|
+
"textarea:not([disabled])",
|
|
10
|
+
"summary",
|
|
11
|
+
"audio[controls]",
|
|
12
|
+
"video[controls]",
|
|
13
|
+
"[tabindex]",
|
|
14
|
+
"[contenteditable=\"true\"]"
|
|
15
|
+
].join(","), L = (e) => e.tabIndex >= 0 && !e.hasAttribute("data-sbf-focus-guard") && !e.closest("[inert]") && (e.checkVisibility?.() ?? !0);
|
|
16
|
+
function ie(e) {
|
|
17
|
+
let t = e && typeof e == "object" && "$el" in e ? e.$el : e;
|
|
18
|
+
return t instanceof HTMLElement ? t : null;
|
|
19
|
+
}
|
|
20
|
+
function R(e) {
|
|
21
|
+
let t = e instanceof Element ? e.closest(I) : null;
|
|
22
|
+
return !!t && !t.closest("[inert]");
|
|
23
|
+
}
|
|
24
|
+
function ae(e) {
|
|
25
|
+
try {
|
|
26
|
+
return e.matches(":focus-visible");
|
|
27
|
+
} catch {
|
|
28
|
+
return !0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
var oe = (e) => e.matches(I) && !e.closest("[inert]");
|
|
32
|
+
function z(e) {
|
|
33
|
+
return [...e.querySelectorAll(I)].filter(L);
|
|
34
|
+
}
|
|
35
|
+
function B(e, t) {
|
|
36
|
+
return z(e.ownerDocument).find((n) => !!(e.compareDocumentPosition(n) & Node.DOCUMENT_POSITION_FOLLOWING) && !e.contains(n) && !t(n));
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
3
39
|
//#region src/utils/warn.ts
|
|
4
|
-
var
|
|
40
|
+
var se = (() => {
|
|
5
41
|
try {
|
|
6
42
|
return process.env.NODE_ENV !== "production";
|
|
7
43
|
} catch {
|
|
8
44
|
return !1;
|
|
9
45
|
}
|
|
10
46
|
})();
|
|
11
|
-
function
|
|
12
|
-
|
|
47
|
+
function V(e) {
|
|
48
|
+
se && console.warn(`[sb-floating-panel-vue] ${e}`);
|
|
13
49
|
}
|
|
14
50
|
//#endregion
|
|
15
51
|
//#region src/composables/useSbFloatingContext.ts
|
|
16
|
-
var
|
|
17
|
-
function
|
|
18
|
-
|
|
52
|
+
var H = (e) => e.parent?.navigation.value === "menu";
|
|
53
|
+
function U(e, t) {
|
|
54
|
+
let n = document.activeElement, r = e.reference.value;
|
|
55
|
+
return !n || !r || r.contains(n) || !e.contains(n) ? !1 : ((t ? r : B(r, (t) => e.contains(t)))?.focus({ preventScroll: !0 }), !0);
|
|
19
56
|
}
|
|
20
|
-
|
|
21
|
-
|
|
57
|
+
var W = Symbol("SbFloatingContext");
|
|
58
|
+
function ce(e, t, n) {
|
|
59
|
+
return ++e.parts[t] > 1 && V(`<SbContainer> has more than one <${n}>: they share one open state and position, so only the last one works. Use one SbContainer for each panel.`), () => e.parts[t]--;
|
|
60
|
+
}
|
|
61
|
+
function le(e) {
|
|
62
|
+
let t = c(W, null);
|
|
22
63
|
if (!t) throw Error(`[sb-floating-panel-vue] <${e}> must be used inside <SbContainer>.`);
|
|
23
64
|
return t;
|
|
24
65
|
}
|
|
25
66
|
//#endregion
|
|
26
67
|
//#region src/composables/useSbFloatingPanel.ts
|
|
27
|
-
var
|
|
68
|
+
var G = (e) => `${Math.max(0, e)}px`, K = (e, t) => {
|
|
28
69
|
let [n, r] = e.split("-"), i = t && (n === "top" || n === "bottom"), a = r === "start" ? i ? "100%" : "0%" : r === "end" ? i ? "0%" : "100%" : "50%";
|
|
29
70
|
return n === "top" ? `${a} 100%` : n === "bottom" ? `${a} 0%` : n === "left" ? `100% ${a}` : `0% ${a}`;
|
|
30
71
|
};
|
|
31
|
-
function
|
|
72
|
+
function q(e) {
|
|
32
73
|
let t = v(null), r = v(null), i = n(() => {
|
|
33
|
-
let t =
|
|
74
|
+
let t = x(e.padding), n = x(e.matchWidth), r = x(e.placement).includes("-"), i = A({
|
|
34
75
|
padding: t,
|
|
35
76
|
crossAxis: "alignment",
|
|
36
77
|
fallbackAxisSideDirection: "end"
|
|
37
|
-
}), a =
|
|
78
|
+
}), a = P({
|
|
38
79
|
padding: t,
|
|
39
|
-
limiter:
|
|
80
|
+
limiter: M()
|
|
40
81
|
}), o = [
|
|
41
|
-
|
|
82
|
+
N(x(e.offset)),
|
|
42
83
|
...r ? [i, a] : [a, i],
|
|
43
|
-
|
|
84
|
+
F({
|
|
44
85
|
padding: t,
|
|
45
86
|
apply({ rects: e, elements: t, availableWidth: r, availableHeight: i, placement: a }) {
|
|
46
|
-
let { style: o } = t.floating, s =
|
|
87
|
+
let { style: o } = t.floating, s = G(e.reference.width);
|
|
47
88
|
o.setProperty("--sbf-reference-width", s);
|
|
48
89
|
let c = getComputedStyle(t.floating).direction === "rtl";
|
|
49
|
-
o.setProperty("--sbf-transform-origin",
|
|
90
|
+
o.setProperty("--sbf-transform-origin", K(a, c)), o.setProperty("--sbf-available-width", G(r)), o.setProperty("--sbf-available-height", G(i)), o.width = n === !0 ? s : "", o.minWidth = n === "min" ? s : "";
|
|
50
91
|
}
|
|
51
92
|
})
|
|
52
93
|
];
|
|
53
|
-
return
|
|
54
|
-
}), { floatingStyles: a, middlewareData: o, placement: s, isPositioned: c, update: l } =
|
|
55
|
-
open: () =>
|
|
56
|
-
placement: () =>
|
|
57
|
-
strategy: () =>
|
|
94
|
+
return x(e.hideWhenDetached) && o.push(j({ padding: t })), o;
|
|
95
|
+
}), { floatingStyles: a, middlewareData: o, placement: s, isPositioned: c, update: l } = ne(t, r, {
|
|
96
|
+
open: () => x(e.isOpen),
|
|
97
|
+
placement: () => x(e.placement),
|
|
98
|
+
strategy: () => x(e.strategy),
|
|
58
99
|
middleware: i,
|
|
59
|
-
whileElementsMounted:
|
|
100
|
+
whileElementsMounted: k
|
|
60
101
|
}), u = n(() => !!o.value.hide?.referenceHidden);
|
|
61
102
|
return {
|
|
62
103
|
reference: t,
|
|
@@ -74,37 +115,11 @@ function re(e) {
|
|
|
74
115
|
};
|
|
75
116
|
}
|
|
76
117
|
//#endregion
|
|
77
|
-
//#region src/utils/dom.ts
|
|
78
|
-
var ie = "data-sbf-focus-guard", H = [
|
|
79
|
-
"a[href]",
|
|
80
|
-
"button:not([disabled])",
|
|
81
|
-
"input:not([disabled]):not([type=\"hidden\"])",
|
|
82
|
-
"select:not([disabled])",
|
|
83
|
-
"textarea:not([disabled])",
|
|
84
|
-
"summary",
|
|
85
|
-
"audio[controls]",
|
|
86
|
-
"video[controls]",
|
|
87
|
-
"[tabindex]",
|
|
88
|
-
"[contenteditable=\"true\"]"
|
|
89
|
-
].join(","), ae = (e) => e.tabIndex >= 0 && !e.hasAttribute("data-sbf-focus-guard") && !e.closest("[inert]") && (e.checkVisibility?.() ?? !0);
|
|
90
|
-
function U(e) {
|
|
91
|
-
let t = e && typeof e == "object" && "$el" in e ? e.$el : e;
|
|
92
|
-
return t instanceof HTMLElement ? t : null;
|
|
93
|
-
}
|
|
94
|
-
function oe(e) {
|
|
95
|
-
let t = e instanceof Element ? e.closest(H) : null;
|
|
96
|
-
return !!t && !t.closest("[inert]");
|
|
97
|
-
}
|
|
98
|
-
var se = (e) => e.matches(H) && !e.closest("[inert]");
|
|
99
|
-
function W(e) {
|
|
100
|
-
return [...e.querySelectorAll(H)].filter(ae);
|
|
101
|
-
}
|
|
102
|
-
function G(e, t) {
|
|
103
|
-
return W(e.ownerDocument).find((n) => !!(e.compareDocumentPosition(n) & Node.DOCUMENT_POSITION_FOLLOWING) && !e.contains(n) && !t(n));
|
|
104
|
-
}
|
|
105
|
-
//#endregion
|
|
106
118
|
//#region src/components/SbContainer.vue?vue&type=script&setup=true&lang.ts
|
|
107
|
-
var
|
|
119
|
+
var J = [], Y = {
|
|
120
|
+
open: 300,
|
|
121
|
+
close: 150
|
|
122
|
+
}, X = /* @__PURE__ */ s({
|
|
108
123
|
inheritAttrs: !1,
|
|
109
124
|
__name: "SbContainer",
|
|
110
125
|
props: /*@__PURE__*/ l({
|
|
@@ -129,10 +144,7 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
129
144
|
default: !1
|
|
130
145
|
},
|
|
131
146
|
trigger: { default: "click" },
|
|
132
|
-
delay: { default: () => ({
|
|
133
|
-
open: 300,
|
|
134
|
-
close: 150
|
|
135
|
-
}) },
|
|
147
|
+
delay: { default: () => ({ ...Y }) },
|
|
136
148
|
closeOnEscape: {
|
|
137
149
|
type: Boolean,
|
|
138
150
|
default: !0
|
|
@@ -154,20 +166,17 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
154
166
|
}),
|
|
155
167
|
emits: /*@__PURE__*/ l(["open", "close"], ["update:open"]),
|
|
156
168
|
setup(e, { expose: t, emit: r }) {
|
|
157
|
-
let i = e, a =
|
|
158
|
-
|
|
159
|
-
let d = (e) => {
|
|
160
|
-
clearTimeout(u), !(e && i.disabled) && e !== l.value && (a.value = e);
|
|
161
|
-
},
|
|
169
|
+
let i = e, a = T(e, "open"), o = r, s = i.defaultOpen, l = n(() => !i.disabled && (a.value ?? s)), u;
|
|
170
|
+
m(() => clearTimeout(u));
|
|
171
|
+
let d, p = ((e, t) => {
|
|
172
|
+
clearTimeout(u), !(e && i.disabled) && e !== l.value && (d = t, a.value = e, ee(() => d = void 0));
|
|
173
|
+
}), h = () => p(!0, "api"), _ = () => p(!1, "api"), y = () => p(!l.value, "api"), x = (e) => {
|
|
162
174
|
if (e.pointerType === "touch" || (O?.hover(e), i.trigger !== "hover")) return;
|
|
163
175
|
let t = e.type === "pointerenter" || k.contains(e.relatedTarget);
|
|
164
176
|
if (clearTimeout(u), t === l.value) return;
|
|
165
|
-
let { delay: n } = i, r = typeof n == "number" ?
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
} : n, a = (t ? r.open : r.close) ?? (t ? 300 : 150);
|
|
169
|
-
u = setTimeout(() => d(t), a);
|
|
170
|
-
}, S = re({
|
|
177
|
+
let { delay: n } = i, r = t ? "open" : "close", a = typeof n == "number" ? n : n[r] ?? Y[r];
|
|
178
|
+
u = setTimeout(() => p(t, "hover"), a);
|
|
179
|
+
}, C = q({
|
|
171
180
|
isOpen: l,
|
|
172
181
|
placement: () => i.placement,
|
|
173
182
|
strategy: () => i.strategy,
|
|
@@ -175,12 +184,12 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
175
184
|
padding: () => i.padding,
|
|
176
185
|
matchWidth: () => i.matchWidth,
|
|
177
186
|
hideWhenDetached: () => i.hideWhenDetached
|
|
178
|
-
}),
|
|
179
|
-
...
|
|
187
|
+
}), D = /* @__PURE__ */ new Set(), O = c(W, null), k = {
|
|
188
|
+
...C,
|
|
180
189
|
isOpen: l,
|
|
181
|
-
disabled:
|
|
182
|
-
trigger:
|
|
183
|
-
floatingId: `${
|
|
190
|
+
disabled: b(i, "disabled"),
|
|
191
|
+
trigger: b(i, "trigger"),
|
|
192
|
+
floatingId: `${w()}-floating`,
|
|
184
193
|
referenceId: v(),
|
|
185
194
|
floatingRole: v("dialog"),
|
|
186
195
|
navigation: v(null),
|
|
@@ -192,21 +201,24 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
192
201
|
floating: 0
|
|
193
202
|
},
|
|
194
203
|
isUnmounting: !1,
|
|
195
|
-
open:
|
|
196
|
-
close:
|
|
197
|
-
toggle:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
open: h,
|
|
205
|
+
close: _,
|
|
206
|
+
toggle: y,
|
|
207
|
+
setOpen: p,
|
|
208
|
+
hover: x,
|
|
209
|
+
contains: (e) => e instanceof Node ? C.reference.value?.contains(e) || C.floating.value?.contains(e) ? !0 : [...D].some((t) => t.contains(e)) : !1,
|
|
210
|
+
registerChild: (e) => (D.add(e), () => D.delete(e))
|
|
201
211
|
};
|
|
202
|
-
O &&
|
|
212
|
+
O && m(O.registerChild(k)), g(W, k), f(() => {
|
|
213
|
+
k.isUnmounting = !0, U(k, !1);
|
|
214
|
+
});
|
|
203
215
|
let A = (e) => {
|
|
204
216
|
let t = e.composedPath()[0] ?? e.target;
|
|
205
|
-
return
|
|
217
|
+
return J.findLast((e) => e.contains(t)) ?? J[J.length - 1];
|
|
206
218
|
}, j = (e) => {
|
|
207
|
-
e.key === "Escape" && A(e) === k && (!i.closeOnEscape || e.defaultPrevented || e.isComposing || (e.preventDefault(),
|
|
219
|
+
e.key === "Escape" && A(e) === k && (!i.closeOnEscape || e.defaultPrevented || e.isComposing || (e.preventDefault(), p(!1, "escape")));
|
|
208
220
|
}, M = (e) => {
|
|
209
|
-
k.contains(e) || (k.skipFocusReturn =
|
|
221
|
+
k.contains(e) || (k.skipFocusReturn = R(e), p(!1, "outside"));
|
|
210
222
|
}, N, P = (e) => {
|
|
211
223
|
if (N?.(), !i.closeOnClickOutside) return;
|
|
212
224
|
let t = e.composedPath()[0] ?? e.target;
|
|
@@ -222,57 +234,60 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
222
234
|
document.removeEventListener("click", n, !0), N = void 0;
|
|
223
235
|
};
|
|
224
236
|
}, F = (e) => {
|
|
225
|
-
i.closeOnFocusOut && (k.contains(e.composedPath()[0] ?? e.target) ||
|
|
237
|
+
i.closeOnFocusOut && (k.contains(e.composedPath()[0] ?? e.target) || p(!1, "focus-out"));
|
|
226
238
|
};
|
|
227
|
-
return
|
|
228
|
-
e && typeof document < "u" && (
|
|
229
|
-
document.removeEventListener("keydown", j), document.removeEventListener("pointerdown", P, !0), document.removeEventListener("focusin", F), N?.(),
|
|
239
|
+
return E(l, (e, t, n) => {
|
|
240
|
+
e && typeof document < "u" && (J.push(k), document.addEventListener("keydown", j), document.addEventListener("pointerdown", P, !0), document.addEventListener("focusin", F), n(() => {
|
|
241
|
+
document.removeEventListener("keydown", j), document.removeEventListener("pointerdown", P, !0), document.removeEventListener("focusin", F), N?.(), J.splice(J.indexOf(k), 1);
|
|
230
242
|
}));
|
|
231
|
-
}, { immediate: !0 }),
|
|
232
|
-
e && i.
|
|
233
|
-
|
|
243
|
+
}, { immediate: !0 }), E(l, (e) => {
|
|
244
|
+
let t = d ?? (!e && i.disabled ? "disabled" : "api");
|
|
245
|
+
d = void 0, o(e ? "open" : "close", t);
|
|
246
|
+
}), E(C.referenceHidden, (e) => {
|
|
247
|
+
e && i.hideWhenDetached === "close" && p(!1, "detached");
|
|
248
|
+
}), E(() => i.disabled, (e) => {
|
|
234
249
|
e && (a.value ?? s) && (a.value = !1);
|
|
235
250
|
}), t({
|
|
236
251
|
get isOpen() {
|
|
237
252
|
return l.value;
|
|
238
253
|
},
|
|
239
|
-
open:
|
|
240
|
-
close:
|
|
241
|
-
toggle:
|
|
242
|
-
update:
|
|
243
|
-
}), (e, t) =>
|
|
254
|
+
open: h,
|
|
255
|
+
close: _,
|
|
256
|
+
toggle: y,
|
|
257
|
+
update: C.update
|
|
258
|
+
}), (e, t) => te(e.$slots, "default", {
|
|
244
259
|
isOpen: l.value,
|
|
245
|
-
open:
|
|
246
|
-
close:
|
|
247
|
-
toggle:
|
|
248
|
-
placement: C
|
|
249
|
-
side: C
|
|
250
|
-
align: C
|
|
260
|
+
open: h,
|
|
261
|
+
close: _,
|
|
262
|
+
toggle: y,
|
|
263
|
+
placement: S(C).placement.value,
|
|
264
|
+
side: S(C).side.value,
|
|
265
|
+
align: S(C).align.value,
|
|
251
266
|
floatingId: k.floatingId,
|
|
252
267
|
referenceId: k.referenceId.value
|
|
253
268
|
});
|
|
254
269
|
}
|
|
255
|
-
}),
|
|
270
|
+
}), ue = {
|
|
256
271
|
dialog: "dialog",
|
|
257
272
|
alertdialog: "dialog",
|
|
258
273
|
menu: "menu",
|
|
259
274
|
listbox: "listbox",
|
|
260
275
|
tree: "tree",
|
|
261
276
|
grid: "grid"
|
|
262
|
-
},
|
|
277
|
+
}, Z = {
|
|
263
278
|
menu: "[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]",
|
|
264
279
|
listbox: "[role=\"option\"]"
|
|
265
|
-
},
|
|
266
|
-
function
|
|
267
|
-
return [...e.querySelectorAll(
|
|
280
|
+
}, de = (e) => !!e && Object.hasOwn(Z, e);
|
|
281
|
+
function fe(e, t) {
|
|
282
|
+
return [...e.querySelectorAll(Z[t])].filter((n) => n.closest(`[role="${t}"]`) === e && !n.matches(":disabled") && (n.checkVisibility?.() ?? !0));
|
|
268
283
|
}
|
|
269
|
-
var
|
|
284
|
+
var Q = (e) => e instanceof Element && !!e.closest("input, textarea, select, [contenteditable]:not([contenteditable=\"false\"])"), pe = (e) => getComputedStyle(e).direction === "rtl" ? {
|
|
270
285
|
open: "ArrowLeft",
|
|
271
286
|
close: "ArrowRight"
|
|
272
287
|
} : {
|
|
273
288
|
open: "ArrowRight",
|
|
274
289
|
close: "ArrowLeft"
|
|
275
|
-
},
|
|
290
|
+
}, me = /* @__PURE__ */ s({
|
|
276
291
|
__name: "SbReference",
|
|
277
292
|
props: {
|
|
278
293
|
as: { default: "button" },
|
|
@@ -280,68 +295,70 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
280
295
|
ariaHaspopup: { default: void 0 }
|
|
281
296
|
},
|
|
282
297
|
setup(e) {
|
|
283
|
-
let t = e, i =
|
|
298
|
+
let t = e, i = C(), a = le("SbReference"), { isOpen: o, disabled: s, floatingId: c, floatingRole: l } = a, u = ce(a, "reference", "SbReference"), ee = [
|
|
284
299
|
"button",
|
|
285
300
|
"input",
|
|
286
301
|
"textarea",
|
|
287
302
|
"select"
|
|
288
|
-
],
|
|
289
|
-
|
|
290
|
-
a.referenceId.value =
|
|
291
|
-
}), m(() => {
|
|
292
|
-
let e = a.reference.value;
|
|
293
|
-
e ? X(e) && a.navigation.value && L(`<SbReference> is a text field with a role="${a.navigation.value}" panel: the arrow keys move focus into the panel, so typing stops there. The combobox pattern (focus kept in the field with aria-activedescendant) is not supported.`) : L("<SbReference> rendered no element, so the panel cannot be positioned: a component in `as` must render a single root element.");
|
|
303
|
+
], d = () => typeof t.as != "string" || ee.includes(t.as) || t.as === "a" && i.href != null, m = `${w()}-reference`, g = n(() => t.id ?? m);
|
|
304
|
+
D(() => {
|
|
305
|
+
a.referenceId.value = g.value;
|
|
294
306
|
}), p(() => {
|
|
295
|
-
|
|
307
|
+
let e = a.reference.value;
|
|
308
|
+
e ? Q(e) && a.navigation.value && V(`<SbReference> is a text field with a role="${a.navigation.value}" panel: the arrow keys move focus into the panel, so typing stops there. The combobox pattern (focus kept in the field with aria-activedescendant) is not supported.`) : V("<SbReference> rendered no element, so the panel cannot be positioned: a component in `as` must render a single root element.");
|
|
309
|
+
}), f(() => {
|
|
310
|
+
a.referenceId.value === g.value && (a.referenceId.value = void 0), u(), !a.parts.reference && !a.isUnmounting && (a.skipFocusReturn = U(a, !1), a.setOpen(!1, "api"));
|
|
296
311
|
});
|
|
297
|
-
let
|
|
298
|
-
a.reference.value =
|
|
299
|
-
},
|
|
300
|
-
a.trigger.value === "click" && (
|
|
301
|
-
},
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
},
|
|
306
|
-
|
|
312
|
+
let _ = n(() => t.ariaHaspopup ?? (l.value && Object.hasOwn(ue, l.value) ? ue[l.value] : void 0)), v = (e) => {
|
|
313
|
+
a.reference.value = ie(e);
|
|
314
|
+
}, b = () => {
|
|
315
|
+
a.trigger.value === "click" && (Q(a.reference.value) ? a.setOpen(!0, "trigger") : a.setOpen(!o.value, "trigger"));
|
|
316
|
+
}, x = n(() => l.value === "tooltip"), T = () => a.trigger.value === "hover" || a.trigger.value === "focus", E = (e) => {
|
|
317
|
+
if (!T() || H(a) || a.contains(e.relatedTarget)) return;
|
|
318
|
+
let t = e.target;
|
|
319
|
+
(a.trigger.value === "focus" || ae(t)) && a.setOpen(!0, "focus");
|
|
320
|
+
}, k = (e) => {
|
|
321
|
+
T() && !a.contains(e.relatedTarget) && a.setOpen(!1, "focus-out");
|
|
322
|
+
}, A = (e) => {
|
|
323
|
+
let t = a.floating.value, n = t && z(t)[0];
|
|
307
324
|
n && (e.preventDefault(), n.focus());
|
|
308
|
-
},
|
|
325
|
+
}, j = (e) => {
|
|
309
326
|
if (a.navigation.value && !s.value && a.trigger.value !== "manual") {
|
|
310
|
-
if (
|
|
327
|
+
if (H(a)) {
|
|
311
328
|
let t = e.currentTarget;
|
|
312
|
-
return e.key ===
|
|
329
|
+
return e.key === pe(t).open ? "first" : void 0;
|
|
313
330
|
}
|
|
314
331
|
return e.key === "ArrowDown" ? "first" : e.key === "ArrowUp" ? "last" : void 0;
|
|
315
332
|
}
|
|
316
|
-
},
|
|
317
|
-
if (e.key === "Tab" && !e.shiftKey && o.value && !
|
|
318
|
-
|
|
333
|
+
}, M = (e) => {
|
|
334
|
+
if (e.key === "Tab" && !e.shiftKey && o.value && !H(a)) {
|
|
335
|
+
A(e);
|
|
319
336
|
return;
|
|
320
337
|
}
|
|
321
|
-
let t =
|
|
322
|
-
t ? (e.preventDefault(), a.focusRequest.value = t, a.
|
|
338
|
+
let t = j(e);
|
|
339
|
+
t ? (e.preventDefault(), a.focusRequest.value = t, a.setOpen(!0, "trigger")) : d() || e.key !== "Enter" && e.key !== " " || (e.preventDefault(), b());
|
|
323
340
|
};
|
|
324
|
-
return (e, n) => (
|
|
325
|
-
id:
|
|
326
|
-
ref:
|
|
341
|
+
return (e, n) => (h(), r(y(t.as), {
|
|
342
|
+
id: g.value,
|
|
343
|
+
ref: v,
|
|
327
344
|
type: t.as === "button" ? "button" : void 0,
|
|
328
|
-
role:
|
|
329
|
-
tabindex:
|
|
330
|
-
disabled: t.as === "button" &&
|
|
331
|
-
"aria-disabled": t.as !== "button" &&
|
|
332
|
-
"aria-haspopup":
|
|
333
|
-
"aria-expanded":
|
|
334
|
-
"aria-controls":
|
|
335
|
-
"aria-describedby":
|
|
336
|
-
"data-sbf-state":
|
|
337
|
-
onClick:
|
|
338
|
-
onKeydown:
|
|
339
|
-
onFocusin:
|
|
340
|
-
onFocusout:
|
|
341
|
-
onPointerenter:
|
|
342
|
-
onPointerleave:
|
|
345
|
+
role: d() ? void 0 : "button",
|
|
346
|
+
tabindex: d() ? void 0 : S(s) ? -1 : 0,
|
|
347
|
+
disabled: t.as === "button" && S(s) ? !0 : void 0,
|
|
348
|
+
"aria-disabled": t.as !== "button" && S(s) ? "true" : void 0,
|
|
349
|
+
"aria-haspopup": _.value,
|
|
350
|
+
"aria-expanded": x.value ? void 0 : S(o) ? "true" : "false",
|
|
351
|
+
"aria-controls": S(o) && !x.value ? S(c) : void 0,
|
|
352
|
+
"aria-describedby": S(o) && x.value ? S(c) : void 0,
|
|
353
|
+
"data-sbf-state": S(o) ? "open" : "closed",
|
|
354
|
+
onClick: b,
|
|
355
|
+
onKeydown: M,
|
|
356
|
+
onFocusin: E,
|
|
357
|
+
onFocusout: k,
|
|
358
|
+
onPointerenter: S(a).hover,
|
|
359
|
+
onPointerleave: S(a).hover
|
|
343
360
|
}, {
|
|
344
|
-
default:
|
|
361
|
+
default: O(() => [te(e.$slots, "default")]),
|
|
345
362
|
_: 3
|
|
346
363
|
}, 40, [
|
|
347
364
|
"id",
|
|
@@ -359,7 +376,7 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
359
376
|
"onPointerleave"
|
|
360
377
|
]));
|
|
361
378
|
}
|
|
362
|
-
}),
|
|
379
|
+
}), he = ":disabled, [aria-disabled=\"true\"], [aria-haspopup]:not([aria-haspopup=\"false\"])", ge = /* @__PURE__ */ s({
|
|
363
380
|
inheritAttrs: !1,
|
|
364
381
|
__name: "SbFloating",
|
|
365
382
|
props: {
|
|
@@ -378,30 +395,36 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
378
395
|
keyboardNavigation: {
|
|
379
396
|
type: Boolean,
|
|
380
397
|
default: !0
|
|
398
|
+
},
|
|
399
|
+
closeOnSelect: {
|
|
400
|
+
type: Boolean,
|
|
401
|
+
default: !1
|
|
381
402
|
}
|
|
382
403
|
},
|
|
383
404
|
emits: ["after-enter", "after-leave"],
|
|
384
405
|
setup(s, { emit: c }) {
|
|
385
|
-
let l = s,
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
l.role
|
|
406
|
+
let l = s, g = c, _ = C(), b = le("SbFloating");
|
|
407
|
+
f(ce(b, "floating", "SbFloating")), f(() => {
|
|
408
|
+
b.isUnmounting || U(b, !0);
|
|
409
|
+
});
|
|
410
|
+
let { isOpen: x, floatingId: w, referenceId: T, side: k, align: A } = b;
|
|
411
|
+
D(() => {
|
|
412
|
+
b.floatingRole.value = l.role, b.navigation.value = l.keyboardNavigation && de(l.role) ? l.role : null;
|
|
413
|
+
}), p(() => {
|
|
414
|
+
l.role === "tooltip" && b.trigger.value === "click" && V("<SbFloating role=\"tooltip\"> opens on click: a tooltip shows on hover and focus. Set trigger=\"hover\" or \"focus\" on SbContainer, or use another role for a panel opened by click.");
|
|
392
415
|
});
|
|
393
|
-
let
|
|
394
|
-
|
|
395
|
-
},
|
|
396
|
-
|
|
397
|
-
},
|
|
398
|
-
...
|
|
416
|
+
let j = v(x.value), M = v(null), N = (e) => {
|
|
417
|
+
b.floating.value = e instanceof HTMLElement ? e : null;
|
|
418
|
+
}, P = (e) => {
|
|
419
|
+
M.value = ie(e);
|
|
420
|
+
}, F = n(() => ({
|
|
421
|
+
...b.floatingStyles.value,
|
|
399
422
|
...l.zIndex === void 0 ? {} : { zIndex: l.zIndex }
|
|
400
|
-
})),
|
|
401
|
-
"aria-labelledby": l.role && Object.hasOwn(
|
|
402
|
-
...
|
|
403
|
-
}),
|
|
404
|
-
[
|
|
423
|
+
})), ne = () => ({
|
|
424
|
+
"aria-labelledby": l.role && Object.hasOwn(ue, l.role) && _["aria-label"] == null ? T.value : void 0,
|
|
425
|
+
..._
|
|
426
|
+
}), I = n(() => l.autoFocus ?? (l.role !== "tooltip" && b.trigger.value !== "hover" && b.trigger.value !== "focus" && !Q(b.reference.value))), L = n(() => x.value && l.teleport !== !1 && l.role !== "tooltip"), R = {
|
|
427
|
+
[re]: "",
|
|
405
428
|
tabindex: 0,
|
|
406
429
|
style: {
|
|
407
430
|
position: "fixed",
|
|
@@ -409,76 +432,98 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
409
432
|
outline: "none",
|
|
410
433
|
pointerEvents: "none"
|
|
411
434
|
}
|
|
412
|
-
},
|
|
435
|
+
}, ae = n(() => {
|
|
413
436
|
let { transition: e } = l;
|
|
414
437
|
return e ? typeof e == "string" ? { name: e } : e : { css: !1 };
|
|
415
|
-
}),
|
|
416
|
-
|
|
417
|
-
}, K = (e) => e instanceof Node && !!
|
|
418
|
-
let t =
|
|
438
|
+
}), se = (e) => e.setAttribute("data-sbf-state", "closed"), W = () => g("after-enter"), G = () => {
|
|
439
|
+
x.value || (j.value = !1), g("after-leave");
|
|
440
|
+
}, K = (e) => e instanceof Node && !!M.value?.contains(e), q = (e) => {
|
|
441
|
+
let t = M.value;
|
|
419
442
|
if (!t) return;
|
|
420
|
-
let n =
|
|
443
|
+
let n = z(t);
|
|
421
444
|
((e === "first" ? n[0] : n[n.length - 1]) ?? t).focus({ preventScroll: !0 });
|
|
445
|
+
}, J = (e) => {
|
|
446
|
+
K(e.relatedTarget) ? b.reference.value?.focus() : q("first");
|
|
422
447
|
}, Y = (e) => {
|
|
423
|
-
K(e.relatedTarget) ? S.reference.value?.focus() : q("first");
|
|
424
|
-
}, de = (e) => {
|
|
425
448
|
if (!K(e.relatedTarget)) {
|
|
426
449
|
q("last");
|
|
427
450
|
return;
|
|
428
451
|
}
|
|
429
|
-
let t =
|
|
430
|
-
((t &&
|
|
431
|
-
},
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
452
|
+
let t = b.reference.value;
|
|
453
|
+
((t && B(t, (e) => b.contains(e))) ?? t)?.focus();
|
|
454
|
+
}, X = (e) => {
|
|
455
|
+
if (e.key !== "Tab" || !e.shiftKey || e.defaultPrevented) return;
|
|
456
|
+
let t = b.reference.value;
|
|
457
|
+
t && M.value && z(M.value).length && (e.composedPath()[0] ?? e.target) === B(t, (e) => b.contains(e)) && (e.preventDefault(), q("last"));
|
|
458
|
+
};
|
|
459
|
+
E(L, (e, t, n) => {
|
|
460
|
+
e && typeof document < "u" && (document.addEventListener("keydown", X), n(() => document.removeEventListener("keydown", X)));
|
|
461
|
+
}, { immediate: !0 });
|
|
462
|
+
let Z = () => {
|
|
463
|
+
let e = b.navigation.value;
|
|
464
|
+
return M.value && e ? fe(M.value, e) : [];
|
|
465
|
+
}, me = {
|
|
466
|
+
menu: "[role=\"menuitem\"]",
|
|
467
|
+
listbox: "[role=\"option\"]"
|
|
468
|
+
}, ge = {
|
|
435
469
|
menu: "role=\"menuitem\", \"menuitemcheckbox\" or \"menuitemradio\"",
|
|
436
470
|
listbox: "role=\"option\""
|
|
437
|
-
},
|
|
438
|
-
let t =
|
|
439
|
-
if (
|
|
440
|
-
let n = e.length ? e.every(
|
|
441
|
-
n && (
|
|
442
|
-
},
|
|
443
|
-
let t =
|
|
471
|
+
}, _e = !1, ve = (e) => {
|
|
472
|
+
let t = b.navigation.value;
|
|
473
|
+
if (_e || !t) return;
|
|
474
|
+
let n = e.length ? e.every(oe) ? null : "has items that cannot take focus, so the arrow keys cannot move to them: make each one a button, or give it tabindex=\"-1\"." : `has no items the arrow keys can move to: items need ${ge[t]} and must not be disabled.`;
|
|
475
|
+
n && (_e = !0, V(`<SbFloating role="${t}"> ${n}`));
|
|
476
|
+
}, ye = (e) => {
|
|
477
|
+
let t = M.value;
|
|
444
478
|
if (!t) return;
|
|
445
479
|
let n = Z();
|
|
446
|
-
e &&
|
|
447
|
-
},
|
|
448
|
-
let e =
|
|
449
|
-
return
|
|
450
|
-
},
|
|
451
|
-
|
|
452
|
-
let
|
|
453
|
-
|
|
454
|
-
let r = [
|
|
480
|
+
e && ve(n), (n.find((e) => e.getAttribute("aria-selected") === "true") ?? (e === "last" ? n[n.length - 1] : e ? n[0] : void 0) ?? t.querySelector("[autofocus]") ?? n[0] ?? z(t)[0] ?? t).focus({ preventScroll: !0 });
|
|
481
|
+
}, be = () => {
|
|
482
|
+
let e = b.focusRequest.value;
|
|
483
|
+
return b.focusRequest.value = null, e;
|
|
484
|
+
}, $ = "", xe;
|
|
485
|
+
m(() => clearTimeout(xe));
|
|
486
|
+
let Se = (e, t, n) => {
|
|
487
|
+
$ += n.toLowerCase(), clearTimeout(xe), xe = setTimeout(() => $ = "", 500);
|
|
488
|
+
let r = [...$].every((e) => e === $[0]) ? $[0] : $, i = Math.max(t, 0), a = [...e.slice(i), ...e.slice(0, i)];
|
|
455
489
|
return r.length === 1 && t >= 0 && a.push(a.shift()), a.find((e) => e.textContent?.trim().toLowerCase().startsWith(r));
|
|
456
|
-
},
|
|
457
|
-
let
|
|
458
|
-
for (;
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
490
|
+
}, Ce = () => {
|
|
491
|
+
let e = [b];
|
|
492
|
+
for (; H(e[e.length - 1]);) e.push(e[e.length - 1].parent);
|
|
493
|
+
return e;
|
|
494
|
+
}, we = (e, t, n) => {
|
|
495
|
+
for (let t of e) t.skipFocusReturn = !0, t.setOpen(!1, n);
|
|
496
|
+
t?.focus({ preventScroll: !0 });
|
|
497
|
+
}, Te = (e) => {
|
|
498
|
+
let t = Ce(), n = t[t.length - 1], r = n.reference.value, i = e ? r : (r && B(r, (e) => n.contains(e))) ?? r;
|
|
499
|
+
we(t, i, "focus-out");
|
|
500
|
+
}, Ee = (e) => {
|
|
501
|
+
let { role: t } = l, n = M.value;
|
|
502
|
+
if (!l.closeOnSelect || e.defaultPrevented || !n || !de(t)) return;
|
|
503
|
+
let r = e.target.closest(me[t]);
|
|
504
|
+
if (!r || r.closest(`[role="${t}"]`) !== n || r.matches(he) || t === "listbox" && n.getAttribute("aria-multiselectable") === "true") return;
|
|
505
|
+
let i = t === "menu" ? Ce() : [b];
|
|
506
|
+
we(i, i[i.length - 1].reference.value, "select");
|
|
507
|
+
}, De = (e) => {
|
|
508
|
+
let t = b.navigation.value;
|
|
509
|
+
if (!t || e.defaultPrevented || e.isComposing || Q(e.target)) return;
|
|
465
510
|
let n = Z(), r = n.findIndex((t) => t.contains(e.target)), i = n.length - 1, a = t === "menu", o;
|
|
466
511
|
if ([
|
|
467
512
|
"ArrowDown",
|
|
468
513
|
"ArrowUp",
|
|
469
514
|
"Home",
|
|
470
515
|
"End"
|
|
471
|
-
].includes(e.key) &&
|
|
516
|
+
].includes(e.key) && ve(n), e.key === "ArrowDown") o = n[r < i ? r + 1 : a ? 0 : i];
|
|
472
517
|
else if (e.key === "ArrowUp") o = n[r > 0 ? r - 1 : a || r < 0 ? i : 0];
|
|
473
518
|
else if (e.key === "Home") o = n[0];
|
|
474
519
|
else if (e.key === "End") o = n[i];
|
|
475
520
|
else if (e.key === "Tab" && t === "menu") {
|
|
476
|
-
e.preventDefault(),
|
|
521
|
+
e.preventDefault(), Te(e.shiftKey);
|
|
477
522
|
return;
|
|
478
|
-
} else if (t === "menu" &&
|
|
479
|
-
e.preventDefault(),
|
|
523
|
+
} else if (t === "menu" && H(b) && M.value && e.key === pe(M.value).close) {
|
|
524
|
+
e.preventDefault(), b.setOpen(!1, "escape");
|
|
480
525
|
return;
|
|
481
|
-
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && (e.key !== " " ||
|
|
526
|
+
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && (e.key !== " " || $)) e.preventDefault(), o = Se(n, r, e.key);
|
|
482
527
|
else if ((e.key === "Enter" || e.key === " ") && e.target === n[r]) {
|
|
483
528
|
let t = n[r];
|
|
484
529
|
if (t.matches("button, a[href], input, summary")) return;
|
|
@@ -487,48 +532,49 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
487
532
|
}
|
|
488
533
|
o && (e.preventDefault(), o.focus());
|
|
489
534
|
};
|
|
490
|
-
return
|
|
491
|
-
let t =
|
|
492
|
-
if (
|
|
493
|
-
|
|
535
|
+
return E(x, (e) => {
|
|
536
|
+
let t = b.skipFocusReturn;
|
|
537
|
+
if (b.skipFocusReturn = !1, e) {
|
|
538
|
+
j.value = !0;
|
|
494
539
|
return;
|
|
495
540
|
}
|
|
496
541
|
let n = document.activeElement;
|
|
497
|
-
!t && n &&
|
|
498
|
-
}),
|
|
542
|
+
!t && n && b.floating.value?.contains(n) && b.reference.value?.focus({ preventScroll: !0 });
|
|
543
|
+
}), E(() => x.value && b.isPositioned.value, async (e) => {
|
|
499
544
|
if (!e) return;
|
|
500
|
-
let t =
|
|
501
|
-
(t ||
|
|
502
|
-
}),
|
|
503
|
-
e &&
|
|
504
|
-
}), (n, s) => (
|
|
545
|
+
let t = be();
|
|
546
|
+
(t || I.value) && (await ee(), ye(t));
|
|
547
|
+
}), E(b.focusRequest, (e) => {
|
|
548
|
+
e && x.value && b.isPositioned.value && ye(be());
|
|
549
|
+
}), (n, s) => (h(), r(e, {
|
|
505
550
|
to: l.teleport || "body",
|
|
506
551
|
disabled: l.teleport === !1
|
|
507
|
-
}, [
|
|
552
|
+
}, [j.value ? (h(), a("div", {
|
|
508
553
|
key: 0,
|
|
509
|
-
ref:
|
|
510
|
-
style:
|
|
511
|
-
onPointerenter: s[0] ||= (...e) =>
|
|
512
|
-
onPointerleave: s[1] ||= (...e) =>
|
|
554
|
+
ref: N,
|
|
555
|
+
style: d(F.value),
|
|
556
|
+
onPointerenter: s[0] ||= (...e) => S(b).hover && S(b).hover(...e),
|
|
557
|
+
onPointerleave: s[1] ||= (...e) => S(b).hover && S(b).hover(...e)
|
|
513
558
|
}, [
|
|
514
|
-
|
|
515
|
-
o(t, u(
|
|
559
|
+
L.value ? (h(), a("span", u({ key: 0 }, R, { onFocus: J }), null, 16)) : i("", !0),
|
|
560
|
+
o(t, u(ae.value, {
|
|
516
561
|
appear: "",
|
|
517
|
-
onBeforeLeave:
|
|
518
|
-
onAfterEnter:
|
|
519
|
-
onAfterLeave:
|
|
562
|
+
onBeforeLeave: se,
|
|
563
|
+
onAfterEnter: W,
|
|
564
|
+
onAfterLeave: G
|
|
520
565
|
}), {
|
|
521
|
-
default:
|
|
522
|
-
id:
|
|
523
|
-
ref:
|
|
566
|
+
default: O(() => [S(x) ? (h(), r(y(l.as), u({ key: 0 }, ne(), {
|
|
567
|
+
id: S(w),
|
|
568
|
+
ref: P,
|
|
524
569
|
role: l.role ?? void 0,
|
|
525
|
-
tabindex:
|
|
570
|
+
tabindex: I.value ? -1 : void 0,
|
|
526
571
|
"data-sbf-state": "open",
|
|
527
|
-
"data-sbf-side":
|
|
528
|
-
"data-sbf-align":
|
|
529
|
-
onKeydown:
|
|
572
|
+
"data-sbf-side": S(k),
|
|
573
|
+
"data-sbf-align": S(A),
|
|
574
|
+
onKeydown: De,
|
|
575
|
+
onClick: Ee
|
|
530
576
|
}), {
|
|
531
|
-
default:
|
|
577
|
+
default: O(() => [te(n.$slots, "default")]),
|
|
532
578
|
_: 3
|
|
533
579
|
}, 16, [
|
|
534
580
|
"id",
|
|
@@ -539,9 +585,22 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
539
585
|
])) : i("", !0)]),
|
|
540
586
|
_: 3
|
|
541
587
|
}, 16),
|
|
542
|
-
|
|
588
|
+
L.value ? (h(), a("span", u({ key: 1 }, R, { onFocus: Y }), null, 16)) : i("", !0)
|
|
543
589
|
], 36)) : i("", !0)], 8, ["to", "disabled"]));
|
|
544
590
|
}
|
|
545
591
|
});
|
|
546
592
|
//#endregion
|
|
547
|
-
|
|
593
|
+
//#region src/composables/useSbFloating.ts
|
|
594
|
+
function _e() {
|
|
595
|
+
let e = c(W, null);
|
|
596
|
+
if (!e) throw Error("[sb-floating-panel-vue] useSbFloating() must be called in a component inside <SbContainer>.");
|
|
597
|
+
let { isOpen: t, open: n, close: r, toggle: i } = e;
|
|
598
|
+
return {
|
|
599
|
+
isOpen: _(t),
|
|
600
|
+
open: n,
|
|
601
|
+
close: r,
|
|
602
|
+
toggle: i
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
//#endregion
|
|
606
|
+
export { X as SbContainer, ge as SbFloating, me as SbReference, _e as useSbFloating };
|