sb-floating-panel-vue 4.0.0 → 5.0.1

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