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