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