sb-floating-panel-vue 5.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,7 +1,7 @@
1
1
  import { InjectionKey, Ref } from 'vue';
2
- import { FloatingPanel } from './composables/useSbFloatingPanel';
3
- import { NavigableRole } from './focus';
4
- import { SbTrigger } from './types';
2
+ import { SbTrigger } from '../types';
3
+ import { NavigableRole } from '../utils/navigation';
4
+ import { FloatingPanel } from './useSbFloatingPanel';
5
5
  /**
6
6
  * State shared by `SbContainer` with `SbReference` and `SbFloating`.
7
7
  */
@@ -39,14 +39,7 @@ export interface SbFloatingContext extends FloatingPanel {
39
39
  /** Registers a nested container; returns the function that unregisters it. */
40
40
  registerChild: (child: SbFloatingContext) => () => void;
41
41
  }
42
- /**
43
- * Panel roles that make the reference a popup trigger, with their `aria-haspopup` value.
44
- * Panels with these roles are also named after the reference.
45
- */
46
- export declare const POPUP_ROLES: Record<string, 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid'>;
47
42
  export declare const sbFloatingContextKey: InjectionKey<SbFloatingContext>;
48
- /** Element of a template ref: a component gives its instance, whose root element is `$el`. */
49
- export declare function toElement(el: unknown): HTMLElement | null;
50
43
  /** Counts a mounted part of the container, warning about a second one; returns the release. */
51
44
  export declare function claimPart(context: SbFloatingContext, part: 'reference' | 'floating', component: string): () => void;
52
45
  export declare function useSbFloatingContext(component: string): SbFloatingContext;
@@ -1,11 +1,34 @@
1
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";
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 I = (e) => `${Math.max(0, e)}px`, L = (e, t) => {
27
+ var H = (e) => `${Math.max(0, e)}px`, te = (e, t) => {
5
28
  let [n, r] = e.split("-"), i = t && (n === "top" || n === "bottom"), a = r === "start" ? i ? "100%" : "0%" : r === "end" ? i ? "0%" : "100%" : "50%";
6
29
  return n === "top" ? `${a} 100%` : n === "bottom" ? `${a} 0%` : n === "left" ? `100% ${a}` : `0% ${a}`;
7
30
  };
8
- function R(e) {
31
+ function ne(e) {
9
32
  let t = v(null), r = v(null), i = n(() => {
10
33
  let t = S(e.padding), n = S(e.matchWidth), r = S(e.placement).includes("-"), i = j({
11
34
  padding: t,
@@ -20,15 +43,15 @@ function R(e) {
20
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 = I(e.reference.width);
46
+ let { style: o } = t.floating, s = H(e.reference.width);
24
47
  o.setProperty("--sbf-reference-width", s);
25
48
  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 : "";
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 : "";
27
50
  }
28
51
  })
29
52
  ];
30
53
  return S(e.hideWhenDetached) && o.push(M({ padding: t })), o;
31
- }), { floatingStyles: a, middlewareData: o, placement: s, isPositioned: c, update: l } = te(t, r, {
54
+ }), { floatingStyles: a, middlewareData: o, placement: s, isPositioned: c, update: l } = I(t, r, {
32
55
  open: () => S(e.isOpen),
33
56
  placement: () => S(e.placement),
34
57
  strategy: () => S(e.strategy),
@@ -51,42 +74,8 @@ function R(e) {
51
74
  };
52
75
  }
53
76
  //#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
66
- //#region src/context.ts
67
- var V = {
68
- dialog: "dialog",
69
- alertdialog: "dialog",
70
- menu: "menu",
71
- listbox: "listbox",
72
- tree: "tree",
73
- grid: "grid"
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);
84
- if (!t) throw Error(`[sb-floating-panel-vue] <${e}> must be used inside <SbContainer>.`);
85
- return t;
86
- }
87
- //#endregion
88
- //#region src/focus.ts
89
- var ae = "data-sbf-focus-guard", U = [
77
+ //#region src/utils/dom.ts
78
+ var re = "data-sbf-focus-guard", U = [
90
79
  "a[href]",
91
80
  "button:not([disabled])",
92
81
  "input:not([disabled]):not([type=\"hidden\"])",
@@ -98,6 +87,10 @@ var ae = "data-sbf-focus-guard", U = [
98
87
  "[tabindex]",
99
88
  "[contenteditable=\"true\"]"
100
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
+ }
101
94
  function G(e) {
102
95
  let t = e instanceof Element ? e.closest(U) : null;
103
96
  return !!t && !t.closest("[inert]");
@@ -105,26 +98,12 @@ function G(e) {
105
98
  function K(e) {
106
99
  return [...e.querySelectorAll(U)].filter(W);
107
100
  }
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));
114
- }
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) {
101
+ function ae(e, t) {
123
102
  return K(e.ownerDocument).find((n) => !!(e.compareDocumentPosition(n) & Node.DOCUMENT_POSITION_FOLLOWING) && !e.contains(n) && !t(n));
124
103
  }
125
104
  //#endregion
126
105
  //#region src/components/SbContainer.vue?vue&type=script&setup=true&lang.ts
127
- var J = [], Y = /* @__PURE__ */ s({
106
+ var q = [], oe = /* @__PURE__ */ s({
128
107
  inheritAttrs: !1,
129
108
  __name: "SbContainer",
130
109
  props: /*@__PURE__*/ l({
@@ -179,15 +158,15 @@ var J = [], Y = /* @__PURE__ */ s({
179
158
  let d = (e) => {
180
159
  clearTimeout(u), !(e && i.disabled) && e !== l.value && (a.value = e);
181
160
  }, 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";
161
+ if (e.pointerType === "touch" || (O?.hover(e), i.trigger !== "hover")) return;
162
+ let t = e.type === "pointerenter" || k.contains(e.relatedTarget);
184
163
  if (clearTimeout(u), t === l.value) return;
185
164
  let { delay: n } = i, r = typeof n == "number" ? {
186
165
  open: n,
187
166
  close: n
188
167
  } : n, a = (t ? r.open : r.close) ?? (t ? 300 : 150);
189
168
  u = setTimeout(() => d(t), a);
190
- }, S = R({
169
+ }, S = ne({
191
170
  isOpen: l,
192
171
  placement: () => i.placement,
193
172
  strategy: () => i.strategy,
@@ -195,7 +174,7 @@ var J = [], Y = /* @__PURE__ */ s({
195
174
  padding: () => i.padding,
196
175
  matchWidth: () => i.matchWidth,
197
176
  hideWhenDetached: () => i.hideWhenDetached
198
- }), w = /* @__PURE__ */ new Set(), O = c(H, null), k = {
177
+ }), w = /* @__PURE__ */ new Set(), O = c(z, null), k = {
199
178
  ...S,
200
179
  isOpen: l,
201
180
  disabled: x(i, "disabled"),
@@ -219,10 +198,10 @@ var J = [], Y = /* @__PURE__ */ s({
219
198
  contains: (e) => e instanceof Node ? S.reference.value?.contains(e) || S.floating.value?.contains(e) ? !0 : [...w].some((t) => t.contains(e)) : !1,
220
199
  registerChild: (e) => (w.add(e), () => w.delete(e))
221
200
  };
222
- O && h(O.registerChild(k)), _(H, k), p(() => k.isUnmounting = !0);
201
+ O && h(O.registerChild(k)), _(z, k), p(() => k.isUnmounting = !0);
223
202
  let A = (e) => {
224
203
  let t = e.composedPath()[0] ?? e.target;
225
- return J.findLast((e) => e.contains(t)) ?? J[J.length - 1];
204
+ return q.findLast((e) => e.contains(t)) ?? q[q.length - 1];
226
205
  }, j = (e) => {
227
206
  e.key === "Escape" && A(e) === k && (!i.closeOnEscape || e.defaultPrevented || e.isComposing || (e.preventDefault(), m()));
228
207
  }, M = (e) => {
@@ -245,8 +224,8 @@ var J = [], Y = /* @__PURE__ */ s({
245
224
  i.closeOnFocusOut && (k.contains(e.composedPath()[0] ?? e.target) || m());
246
225
  };
247
226
  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);
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);
250
229
  }));
251
230
  }, { immediate: !0 }), D(l, (e) => o(e ? "open" : "close")), D(S.referenceHidden, (e) => {
252
231
  e && i.hideWhenDetached === "close" && m();
@@ -272,7 +251,27 @@ var J = [], Y = /* @__PURE__ */ s({
272
251
  referenceId: k.referenceId.value
273
252
  });
274
253
  }
275
- }), X = /* @__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({
276
275
  __name: "SbReference",
277
276
  props: {
278
277
  as: { default: "button" },
@@ -280,41 +279,40 @@ var J = [], Y = /* @__PURE__ */ s({
280
279
  ariaHaspopup: { default: void 0 }
281
280
  },
282
281
  setup(e) {
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);
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);
284
283
  O(() => {
285
284
  a.referenceId.value = h.value;
286
285
  }), 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.");
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.");
288
287
  }), p(() => {
289
288
  a.referenceId.value === h.value && (a.referenceId.value = void 0), u(), !a.parts.reference && !a.isUnmounting && a.close();
290
289
  });
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);
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);
293
292
  }, x = () => {
294
293
  a.trigger.value === "click" && a.toggle();
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();
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();
299
296
  }, j = (e) => {
297
+ E() && !a.contains(e.relatedTarget) && a.close();
298
+ }, M = (e) => {
300
299
  let t = a.floating.value, n = t && K(t)[0];
301
300
  n && (e.preventDefault(), n.focus());
302
- }, M = (e) => {
301
+ }, N = (e) => {
303
302
  if (a.navigation.value && !s.value && a.trigger.value !== "manual") {
304
- if (a.parent?.navigation.value === "menu") {
303
+ if (D()) {
305
304
  let t = e.currentTarget;
306
- return e.key === le(t).open ? "first" : void 0;
305
+ return e.key === ue(t).open ? "first" : void 0;
307
306
  }
308
307
  return e.key === "ArrowDown" ? "first" : e.key === "ArrowUp" ? "last" : void 0;
309
308
  }
310
- }, N = (e) => {
311
- let t = a.parent?.navigation.value === "menu";
312
- if (e.key === "Tab" && !e.shiftKey && o.value && !t) {
313
- j(e);
309
+ }, P = (e) => {
310
+ if (e.key === "Tab" && !e.shiftKey && o.value && !D()) {
311
+ M(e);
314
312
  return;
315
313
  }
316
- let n = M(e);
317
- n ? (e.preventDefault(), a.focusRequest.value = n, a.open()) : d() || e.key !== "Enter" && e.key !== " " || (e.preventDefault(), x());
314
+ let t = N(e);
315
+ t ? (e.preventDefault(), a.focusRequest.value = t, a.open()) : d() || e.key !== "Enter" && e.key !== " " || (e.preventDefault(), x());
318
316
  };
319
317
  return (e, n) => (g(), r(b(t.as), {
320
318
  id: h.value,
@@ -330,9 +328,9 @@ var J = [], Y = /* @__PURE__ */ s({
330
328
  "aria-describedby": C(o) && S.value ? C(c) : void 0,
331
329
  "data-sbf-state": C(o) ? "open" : "closed",
332
330
  onClick: x,
333
- onKeydown: N,
334
- onFocusin: D,
335
- onFocusout: A,
331
+ onKeydown: P,
332
+ onFocusin: A,
333
+ onFocusout: j,
336
334
  onPointerenter: C(a).hover,
337
335
  onPointerleave: C(a).hover
338
336
  }, {
@@ -377,24 +375,24 @@ var J = [], Y = /* @__PURE__ */ s({
377
375
  },
378
376
  emits: ["after-enter", "after-leave"],
379
377
  setup(s, { emit: c }) {
380
- let l = s, m = c, _ = w(), x = ie("SbFloating");
381
- p(re(x, "floating", "SbFloating"));
378
+ let l = s, m = c, _ = w(), x = V("SbFloating");
379
+ p(B(x, "floating", "SbFloating"));
382
380
  let { isOpen: S, floatingId: T, referenceId: E, side: A, align: j } = x;
383
381
  O(() => {
384
- x.floatingRole.value = l.role, x.navigation.value = l.keyboardNavigation && oe(l.role) ? l.role : null;
382
+ x.floatingRole.value = l.role, x.navigation.value = l.keyboardNavigation && se(l.role) ? l.role : null;
385
383
  });
386
384
  let M = v(S.value), N = v(null), P = (e) => {
387
385
  x.floating.value = e instanceof HTMLElement ? e : null;
388
386
  }, F = (e) => {
389
- N.value = ne(e);
387
+ N.value = ie(e);
390
388
  }, ee = n(() => ({
391
389
  ...x.floatingStyles.value,
392
390
  ...l.zIndex === void 0 ? {} : { zIndex: l.zIndex }
393
- })), te = () => ({
394
- "aria-labelledby": l.role && Object.hasOwn(V, l.role) && _["aria-label"] == null ? E.value : void 0,
391
+ })), I = () => ({
392
+ "aria-labelledby": l.role && Object.hasOwn(J, l.role) && _["aria-label"] == null ? E.value : void 0,
395
393
  ..._
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]: "",
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]: "",
398
396
  tabindex: 0,
399
397
  style: {
400
398
  position: "fixed",
@@ -402,10 +400,10 @@ var J = [], Y = /* @__PURE__ */ s({
402
400
  outline: "none",
403
401
  pointerEvents: "none"
404
402
  }
405
- }, z = n(() => {
403
+ }, H = n(() => {
406
404
  let { transition: e } = l;
407
405
  return e ? typeof e == "string" ? { name: e } : e : { css: !1 };
408
- }), B = (e) => e.setAttribute("data-sbf-state", "closed"), H = () => m("after-enter"), U = () => {
406
+ }), te = (e) => e.setAttribute("data-sbf-state", "closed"), ne = () => m("after-enter"), U = () => {
409
407
  S.value || (M.value = !1), m("after-leave");
410
408
  }, W = (e) => e instanceof Node && !!N.value?.contains(e), G = (e) => {
411
409
  let t = N.value;
@@ -414,16 +412,16 @@ var J = [], Y = /* @__PURE__ */ s({
414
412
  ((e === "first" ? n[0] : n[n.length - 1]) ?? t).focus({ preventScroll: !0 });
415
413
  }, q = (e) => {
416
414
  W(e.relatedTarget) ? x.reference.value?.focus() : G("first");
417
- }, J = (e) => {
415
+ }, oe = (e) => {
418
416
  if (!W(e.relatedTarget)) {
419
417
  G("last");
420
418
  return;
421
419
  }
422
420
  let t = x.reference.value;
423
- ((t && ue(t, (e) => x.contains(e))) ?? t)?.focus();
421
+ ((t && ae(t, (e) => x.contains(e))) ?? t)?.focus();
424
422
  }, Y = () => {
425
423
  let e = x.navigation.value;
426
- return N.value && e ? se(N.value, e) : [];
424
+ return N.value && e ? ce(N.value, e) : [];
427
425
  }, X = (e) => {
428
426
  let t = N.value;
429
427
  if (!t) return;
@@ -441,12 +439,12 @@ var J = [], Y = /* @__PURE__ */ s({
441
439
  }, fe = (e) => {
442
440
  let t = x, n = [t];
443
441
  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;
442
+ let r = t.reference.value, i = e ? r : (r && ae(r, (e) => t.contains(e))) ?? r;
445
443
  for (let e of n) e.skipFocusReturn = !0, e.close();
446
444
  i?.focus();
447
445
  }, pe = (e) => {
448
446
  let t = x.navigation.value;
449
- if (!t || e.defaultPrevented || e.isComposing || ce(e.target)) return;
447
+ if (!t || e.defaultPrevented || e.isComposing || le(e.target)) return;
450
448
  let n = Y(), r = n.findIndex((t) => t.contains(e.target)), i = n.length - 1, a = t === "menu", o;
451
449
  if (e.key === "ArrowDown") o = n[r < i ? r + 1 : a ? 0 : i];
452
450
  else if (e.key === "ArrowUp") o = n[r > 0 ? r - 1 : a || r < 0 ? i : 0];
@@ -455,7 +453,7 @@ var J = [], Y = /* @__PURE__ */ s({
455
453
  else if (e.key === "Tab" && t === "menu") {
456
454
  e.preventDefault(), fe(e.shiftKey);
457
455
  return;
458
- } else if (t === "menu" && x.parent?.navigation.value === "menu" && N.value && e.key === le(N.value).close) {
456
+ } else if (t === "menu" && x.parent?.navigation.value === "menu" && N.value && e.key === ue(N.value).close) {
459
457
  e.preventDefault(), x.close();
460
458
  return;
461
459
  } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && (e.key !== " " || Q)) e.preventDefault(), o = de(n, r, e.key);
@@ -478,7 +476,7 @@ var J = [], Y = /* @__PURE__ */ s({
478
476
  }), D(() => S.value && x.isPositioned.value, async (e) => {
479
477
  if (!e) return;
480
478
  let t = Z();
481
- (t || I.value) && (await d(), X(t));
479
+ (t || L.value) && (await d(), X(t));
482
480
  }), D(x.focusRequest, (e) => {
483
481
  e && S.value && x.isPositioned.value && X(Z());
484
482
  }), (n, s) => (g(), r(e, {
@@ -491,18 +489,18 @@ var J = [], Y = /* @__PURE__ */ s({
491
489
  onPointerenter: s[0] ||= (...e) => C(x).hover && C(x).hover(...e),
492
490
  onPointerleave: s[1] ||= (...e) => C(x).hover && C(x).hover(...e)
493
491
  }, [
494
- L.value ? (g(), a("span", u({ key: 0 }, R, { onFocus: q }), null, 16)) : i("", !0),
495
- o(t, u(z.value, {
492
+ R.value ? (g(), a("span", u({ key: 0 }, z, { onFocus: q }), null, 16)) : i("", !0),
493
+ o(t, u(H.value, {
496
494
  appear: "",
497
- onBeforeLeave: B,
498
- onAfterEnter: H,
495
+ onBeforeLeave: te,
496
+ onAfterEnter: ne,
499
497
  onAfterLeave: U
500
498
  }), {
501
- default: k(() => [C(S) ? (g(), r(b(l.as), u({ key: 0 }, te(), {
499
+ default: k(() => [C(S) ? (g(), r(b(l.as), u({ key: 0 }, I(), {
502
500
  id: C(T),
503
501
  ref: F,
504
502
  role: l.role ?? void 0,
505
- tabindex: I.value ? -1 : void 0,
503
+ tabindex: L.value ? -1 : void 0,
506
504
  "data-sbf-state": "open",
507
505
  "data-sbf-side": C(A),
508
506
  "data-sbf-align": C(j),
@@ -519,9 +517,9 @@ var J = [], Y = /* @__PURE__ */ s({
519
517
  ])) : i("", !0)]),
520
518
  _: 3
521
519
  }, 16),
522
- L.value ? (g(), a("span", u({ key: 1 }, R, { onFocus: J }), null, 16)) : i("", !0)
520
+ R.value ? (g(), a("span", u({ key: 1 }, z, { onFocus: oe }), null, 16)) : i("", !0)
523
521
  ], 36)) : i("", !0)], 8, ["to", "disabled"]));
524
522
  }
525
523
  });
526
524
  //#endregion
527
- export { Y as SbContainer, Z as SbFloating, X as SbReference };
525
+ export { oe as SbContainer, Z as SbFloating, X as SbReference };
@@ -1 +1 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("vue"),require("@floating-ui/vue")):typeof define==`function`&&define.amd?define([`exports`,`vue`,`@floating-ui/vue`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.SbFloatingPanelVue={},e.Vue,e.FloatingUIVue))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=e=>`${Math.max(0,e)}px`,i=(e,t)=>{let[n,r]=e.split(`-`),i=t&&(n===`top`||n===`bottom`),a=r===`start`?i?`100%`:`0%`:r===`end`?i?`0%`:`100%`:`50%`;return n===`top`?`${a} 100%`:n===`bottom`?`${a} 0%`:n===`left`?`100% ${a}`:`0% ${a}`};function a(e){let a=(0,t.ref)(null),o=(0,t.ref)(null),s=(0,t.computed)(()=>{let a=(0,t.toValue)(e.padding),o=(0,t.toValue)(e.matchWidth),s=(0,t.toValue)(e.placement).includes(`-`),c=(0,n.flip)({padding:a,crossAxis:`alignment`,fallbackAxisSideDirection:`end`}),l=(0,n.shift)({padding:a,limiter:(0,n.limitShift)()}),u=[(0,n.offset)((0,t.toValue)(e.offset)),...s?[c,l]:[l,c],(0,n.size)({padding:a,apply({rects:e,elements:t,availableWidth:n,availableHeight:a,placement:s}){let{style:c}=t.floating,l=r(e.reference.width);c.setProperty(`--sbf-reference-width`,l);let u=getComputedStyle(t.floating).direction===`rtl`;c.setProperty(`--sbf-transform-origin`,i(s,u)),c.setProperty(`--sbf-available-width`,r(n)),c.setProperty(`--sbf-available-height`,r(a)),c.width=o===!0?l:``,c.minWidth=o===`min`?l:``}})];return(0,t.toValue)(e.hideWhenDetached)&&u.push((0,n.hide)({padding:a})),u}),{floatingStyles:c,middlewareData:l,placement:u,isPositioned:d,update:f}=(0,n.useFloating)(a,o,{open:()=>(0,t.toValue)(e.isOpen),placement:()=>(0,t.toValue)(e.placement),strategy:()=>(0,t.toValue)(e.strategy),middleware:s,whileElementsMounted:n.autoUpdate}),p=(0,t.computed)(()=>!!l.value.hide?.referenceHidden);return{reference:a,floating:o,floatingStyles:(0,t.computed)(()=>({...c.value,...p.value?{visibility:`hidden`}:{}})),placement:u,side:(0,t.computed)(()=>u.value.split(`-`)[0]),align:(0,t.computed)(()=>u.value.split(`-`)[1]),isPositioned:d,referenceHidden:p,update:f}}var o=(()=>{try{return process.env.NODE_ENV!==`production`}catch{return!1}})();function s(e){o&&console.warn(`[sb-floating-panel-vue] ${e}`)}var c={dialog:`dialog`,alertdialog:`dialog`,menu:`menu`,listbox:`listbox`,tree:`tree`,grid:`grid`},l=Symbol(`SbFloatingContext`);function u(e){let t=e&&typeof e==`object`&&`$el`in e?e.$el:e;return t instanceof HTMLElement?t:null}function d(e,t,n){return++e.parts[t]>1&&s(`<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]--}function f(e){let n=(0,t.inject)(l,null);if(!n)throw Error(`[sb-floating-panel-vue] <${e}> must be used inside <SbContainer>.`);return n}var p=`data-sbf-focus-guard`,m=[`a[href]`,`button:not([disabled])`,`input:not([disabled]):not([type="hidden"])`,`select:not([disabled])`,`textarea:not([disabled])`,`summary`,`audio[controls]`,`video[controls]`,`[tabindex]`,`[contenteditable="true"]`].join(`,`),h=e=>e.tabIndex>=0&&!e.hasAttribute(`data-sbf-focus-guard`)&&!e.closest(`[inert]`)&&(e.checkVisibility?.()??!0);function g(e){let t=e instanceof Element?e.closest(m):null;return!!t&&!t.closest(`[inert]`)}function _(e){return[...e.querySelectorAll(m)].filter(h)}var v={menu:`[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]`,listbox:`[role="option"]`},y=e=>!!e&&Object.hasOwn(v,e);function b(e,t){return[...e.querySelectorAll(v[t])].filter(n=>n.closest(`[role="${t}"]`)===e&&!n.matches(`:disabled`)&&(n.checkVisibility?.()??!0))}var x=e=>e instanceof Element&&!!e.closest(`input, textarea, select, [contenteditable]:not([contenteditable="false"])`),S=e=>getComputedStyle(e).direction===`rtl`?{open:`ArrowLeft`,close:`ArrowRight`}:{open:`ArrowRight`,close:`ArrowLeft`};function C(e,t){return _(e.ownerDocument).find(n=>!!(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)&&!e.contains(n)&&!t(n))}var w=[],T=(0,t.defineComponent)({inheritAttrs:!1,__name:`SbContainer`,props:(0,t.mergeModels)({placement:{default:`bottom-start`},strategy:{default:`absolute`},offset:{default:8},padding:{default:8},matchWidth:{type:[Boolean,String],default:!1},hideWhenDetached:{type:[Boolean,String],default:!1},defaultOpen:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},trigger:{default:`click`},delay:{default:()=>({open:300,close:150})},closeOnEscape:{type:Boolean,default:!0},closeOnClickOutside:{type:Boolean,default:!0},closeOnFocusOut:{type:Boolean,default:!0}},{open:{type:Boolean,default:void 0},openModifiers:{}}),emits:(0,t.mergeModels)([`open`,`close`],[`update:open`]),setup(e,{expose:n,emit:r}){let i=e,o=(0,t.useModel)(e,`open`),s=r,c=i.defaultOpen,u=(0,t.computed)(()=>!i.disabled&&(o.value??c)),d;(0,t.onScopeDispose)(()=>clearTimeout(d));let f=e=>{clearTimeout(d),!(e&&i.disabled)&&e!==u.value&&(o.value=e)},p=()=>f(!0),m=()=>f(!1),h=()=>f(!u.value),_=e=>{if(i.trigger!==`hover`||e.pointerType===`touch`)return;let t=e.type===`pointerenter`;if(clearTimeout(d),t===u.value)return;let{delay:n}=i,r=typeof n==`number`?{open:n,close:n}:n,a=(t?r.open:r.close)??(t?300:150);d=setTimeout(()=>f(t),a)},v=a({isOpen:u,placement:()=>i.placement,strategy:()=>i.strategy,offset:()=>i.offset,padding:()=>i.padding,matchWidth:()=>i.matchWidth,hideWhenDetached:()=>i.hideWhenDetached}),y=new Set,b=(0,t.inject)(l,null),x={...v,isOpen:u,disabled:(0,t.toRef)(i,`disabled`),trigger:(0,t.toRef)(i,`trigger`),floatingId:`${(0,t.useId)()}-floating`,referenceId:(0,t.ref)(),floatingRole:(0,t.ref)(`dialog`),navigation:(0,t.ref)(null),focusRequest:(0,t.ref)(null),parent:b,skipFocusReturn:!1,parts:{reference:0,floating:0},isUnmounting:!1,open:p,close:m,toggle:h,hover:_,contains:e=>e instanceof Node?v.reference.value?.contains(e)||v.floating.value?.contains(e)?!0:[...y].some(t=>t.contains(e)):!1,registerChild:e=>(y.add(e),()=>y.delete(e))};b&&(0,t.onScopeDispose)(b.registerChild(x)),(0,t.provide)(l,x),(0,t.onBeforeUnmount)(()=>x.isUnmounting=!0);let S=e=>{let t=e.composedPath()[0]??e.target;return w.findLast(e=>e.contains(t))??w[w.length-1]},C=e=>{e.key===`Escape`&&S(e)===x&&(!i.closeOnEscape||e.defaultPrevented||e.isComposing||(e.preventDefault(),m()))},T=e=>{x.contains(e)||(x.skipFocusReturn=g(e),m())},E,D=e=>{if(E?.(),!i.closeOnClickOutside)return;let t=e.composedPath()[0]??e.target;if(e.pointerType!==`touch`){T(t);return}if(x.contains(t))return;let n=e=>{E?.(),T(e.composedPath()[0]??e.target)};document.addEventListener(`click`,n,!0),E=()=>{document.removeEventListener(`click`,n,!0),E=void 0}},O=e=>{i.closeOnFocusOut&&(x.contains(e.composedPath()[0]??e.target)||m())};return(0,t.watch)(u,(e,t,n)=>{e&&typeof document<`u`&&(w.push(x),document.addEventListener(`keydown`,C),document.addEventListener(`pointerdown`,D,!0),document.addEventListener(`focusin`,O),n(()=>{document.removeEventListener(`keydown`,C),document.removeEventListener(`pointerdown`,D,!0),document.removeEventListener(`focusin`,O),E?.(),w.splice(w.indexOf(x),1)}))},{immediate:!0}),(0,t.watch)(u,e=>s(e?`open`:`close`)),(0,t.watch)(v.referenceHidden,e=>{e&&i.hideWhenDetached===`close`&&m()}),(0,t.watch)(()=>i.disabled,e=>{e&&(o.value??c)&&(o.value=!1)}),n({get isOpen(){return u.value},open:p,close:m,toggle:h,update:v.update}),(e,n)=>(0,t.renderSlot)(e.$slots,`default`,{isOpen:u.value,open:p,close:m,toggle:h,placement:(0,t.unref)(v).placement.value,side:(0,t.unref)(v).side.value,align:(0,t.unref)(v).align.value,floatingId:x.floatingId,referenceId:x.referenceId.value})}}),E=(0,t.defineComponent)({__name:`SbReference`,props:{as:{default:`button`},id:{default:void 0},ariaHaspopup:{default:void 0}},setup(e){let n=e,r=(0,t.useAttrs)(),i=f(`SbReference`),{isOpen:a,disabled:o,floatingId:l,floatingRole:p}=i,m=d(i,`reference`,`SbReference`),h=()=>typeof n.as!=`string`||n.as===`button`||n.as===`a`&&r.href!=null,g=`${(0,t.useId)()}-reference`,v=(0,t.computed)(()=>n.id??g);(0,t.watchEffect)(()=>{i.referenceId.value=v.value}),(0,t.onMounted)(()=>{i.reference.value||s("<SbReference> rendered no element, so the panel cannot be positioned: a component in `as` must render a single root element.")}),(0,t.onBeforeUnmount)(()=>{i.referenceId.value===v.value&&(i.referenceId.value=void 0),m(),!i.parts.reference&&!i.isUnmounting&&i.close()});let y=(0,t.computed)(()=>n.ariaHaspopup??(p.value&&Object.hasOwn(c,p.value)?c[p.value]:void 0)),b=e=>{i.reference.value=u(e)},x=()=>{i.trigger.value===`click`&&i.toggle()},C=(0,t.computed)(()=>p.value===`tooltip`),w=()=>i.trigger.value===`hover`||i.trigger.value===`focus`,T=e=>{w()&&!i.contains(e.relatedTarget)&&i.open()},E=e=>{w()&&!i.contains(e.relatedTarget)&&i.close()},D=e=>{let t=i.floating.value,n=t&&_(t)[0];n&&(e.preventDefault(),n.focus())},O=e=>{if(i.navigation.value&&!o.value&&i.trigger.value!==`manual`){if(i.parent?.navigation.value===`menu`){let t=e.currentTarget;return e.key===S(t).open?`first`:void 0}return e.key===`ArrowDown`?`first`:e.key===`ArrowUp`?`last`:void 0}},k=e=>{let t=i.parent?.navigation.value===`menu`;if(e.key===`Tab`&&!e.shiftKey&&a.value&&!t){D(e);return}let n=O(e);n?(e.preventDefault(),i.focusRequest.value=n,i.open()):h()||e.key!==`Enter`&&e.key!==` `||(e.preventDefault(),x())};return(e,r)=>((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(n.as),{id:v.value,ref:b,type:n.as===`button`?`button`:void 0,role:h()?void 0:`button`,tabindex:h()?void 0:(0,t.unref)(o)?-1:0,disabled:n.as===`button`&&(0,t.unref)(o)?!0:void 0,"aria-disabled":n.as!==`button`&&(0,t.unref)(o)?`true`:void 0,"aria-haspopup":y.value,"aria-expanded":C.value?void 0:(0,t.unref)(a)?`true`:`false`,"aria-controls":(0,t.unref)(a)&&!C.value?(0,t.unref)(l):void 0,"aria-describedby":(0,t.unref)(a)&&C.value?(0,t.unref)(l):void 0,"data-sbf-state":(0,t.unref)(a)?`open`:`closed`,onClick:x,onKeydown:k,onFocusin:T,onFocusout:E,onPointerenter:(0,t.unref)(i).hover,onPointerleave:(0,t.unref)(i).hover},{default:(0,t.withCtx)(()=>[(0,t.renderSlot)(e.$slots,`default`)]),_:3},40,[`id`,`type`,`role`,`tabindex`,`disabled`,`aria-disabled`,`aria-haspopup`,`aria-expanded`,`aria-controls`,`aria-describedby`,`data-sbf-state`,`onPointerenter`,`onPointerleave`]))}}),D=(0,t.defineComponent)({inheritAttrs:!1,__name:`SbFloating`,props:{as:{default:`div`},role:{default:`dialog`},transition:{default:void 0},teleport:{type:[String,Boolean],default:`body`},zIndex:{default:void 0},autoFocus:{type:Boolean,default:void 0},keyboardNavigation:{type:Boolean,default:!0}},emits:[`after-enter`,`after-leave`],setup(e,{emit:n}){let r=e,i=n,a=(0,t.useAttrs)(),o=f(`SbFloating`);(0,t.onBeforeUnmount)(d(o,`floating`,`SbFloating`));let{isOpen:s,floatingId:l,referenceId:m,side:h,align:g}=o;(0,t.watchEffect)(()=>{o.floatingRole.value=r.role,o.navigation.value=r.keyboardNavigation&&y(r.role)?r.role:null});let v=(0,t.ref)(s.value),w=(0,t.ref)(null),T=e=>{o.floating.value=e instanceof HTMLElement?e:null},E=e=>{w.value=u(e)},D=(0,t.computed)(()=>({...o.floatingStyles.value,...r.zIndex===void 0?{}:{zIndex:r.zIndex}})),O=()=>({"aria-labelledby":r.role&&Object.hasOwn(c,r.role)&&a[`aria-label`]==null?m.value:void 0,...a}),k=(0,t.computed)(()=>r.autoFocus??(r.role!==`tooltip`&&o.trigger.value!==`hover`&&o.trigger.value!==`focus`)),A=(0,t.computed)(()=>s.value&&r.teleport!==!1&&r.role!==`tooltip`),j={[p]:``,tabindex:0,style:{position:`fixed`,opacity:0,outline:`none`,pointerEvents:`none`}},M=(0,t.computed)(()=>{let{transition:e}=r;return e?typeof e==`string`?{name:e}:e:{css:!1}}),N=e=>e.setAttribute(`data-sbf-state`,`closed`),P=()=>i(`after-enter`),F=()=>{s.value||(v.value=!1),i(`after-leave`)},I=e=>e instanceof Node&&!!w.value?.contains(e),L=e=>{let t=w.value;if(!t)return;let n=_(t);((e===`first`?n[0]:n[n.length-1])??t).focus({preventScroll:!0})},R=e=>{I(e.relatedTarget)?o.reference.value?.focus():L(`first`)},z=e=>{if(!I(e.relatedTarget)){L(`last`);return}let t=o.reference.value;((t&&C(t,e=>o.contains(e)))??t)?.focus()},B=()=>{let e=o.navigation.value;return w.value&&e?b(w.value,e):[]},V=e=>{let t=w.value;if(!t)return;let n=B();(n.find(e=>e.getAttribute(`aria-selected`)===`true`)??(e===`last`?n[n.length-1]:e?n[0]:void 0)??t.querySelector(`[autofocus]`)??n[0]??_(t)[0]??t).focus({preventScroll:!0})},H=()=>{let e=o.focusRequest.value;return o.focusRequest.value=null,e},U=``,W;(0,t.onScopeDispose)(()=>clearTimeout(W));let G=(e,t,n)=>{U+=n.toLowerCase(),clearTimeout(W),W=setTimeout(()=>U=``,500);let r=[...U].every(e=>e===U[0])?U[0]:U,i=Math.max(t,0),a=[...e.slice(i),...e.slice(0,i)];return r.length===1&&t>=0&&a.push(a.shift()),a.find(e=>e.textContent?.trim().toLowerCase().startsWith(r))},K=e=>{let t=o,n=[t];for(;t.parent?.navigation.value===`menu`;)t=t.parent,n.push(t);let r=t.reference.value,i=e?r:(r&&C(r,e=>t.contains(e)))??r;for(let e of n)e.skipFocusReturn=!0,e.close();i?.focus()},q=e=>{let t=o.navigation.value;if(!t||e.defaultPrevented||e.isComposing||x(e.target))return;let n=B(),r=n.findIndex(t=>t.contains(e.target)),i=n.length-1,a=t===`menu`,s;if(e.key===`ArrowDown`)s=n[r<i?r+1:a?0:i];else if(e.key===`ArrowUp`)s=n[r>0?r-1:a||r<0?i:0];else if(e.key===`Home`)s=n[0];else if(e.key===`End`)s=n[i];else if(e.key===`Tab`&&t===`menu`){e.preventDefault(),K(e.shiftKey);return}else if(t===`menu`&&o.parent?.navigation.value===`menu`&&w.value&&e.key===S(w.value).close){e.preventDefault(),o.close();return}else if(e.key.length===1&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&(e.key!==` `||U))e.preventDefault(),s=G(n,r,e.key);else if((e.key===`Enter`||e.key===` `)&&e.target===n[r]){let t=n[r];if(t.matches(`button, a[href], input, summary`))return;e.preventDefault(),t.getAttribute(`aria-disabled`)!==`true`&&t.click();return}s&&(e.preventDefault(),s.focus())};return(0,t.watch)(s,e=>{let t=o.skipFocusReturn;if(o.skipFocusReturn=!1,e){v.value=!0;return}let n=document.activeElement;!t&&n&&o.floating.value?.contains(n)&&o.reference.value?.focus({preventScroll:!0})}),(0,t.watch)(()=>s.value&&o.isPositioned.value,async e=>{if(!e)return;let n=H();(n||k.value)&&(await(0,t.nextTick)(),V(n))}),(0,t.watch)(o.focusRequest,e=>{e&&s.value&&o.isPositioned.value&&V(H())}),(e,n)=>((0,t.openBlock)(),(0,t.createBlock)(t.Teleport,{to:r.teleport||`body`,disabled:r.teleport===!1},[v.value?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{key:0,ref:T,style:(0,t.normalizeStyle)(D.value),onPointerenter:n[0]||=(...e)=>(0,t.unref)(o).hover&&(0,t.unref)(o).hover(...e),onPointerleave:n[1]||=(...e)=>(0,t.unref)(o).hover&&(0,t.unref)(o).hover(...e)},[A.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:0},j,{onFocus:R}),null,16)):(0,t.createCommentVNode)(``,!0),(0,t.createVNode)(t.Transition,(0,t.mergeProps)(M.value,{appear:``,onBeforeLeave:N,onAfterEnter:P,onAfterLeave:F}),{default:(0,t.withCtx)(()=>[(0,t.unref)(s)?((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(r.as),(0,t.mergeProps)({key:0},O(),{id:(0,t.unref)(l),ref:E,role:r.role??void 0,tabindex:k.value?-1:void 0,"data-sbf-state":`open`,"data-sbf-side":(0,t.unref)(h),"data-sbf-align":(0,t.unref)(g),onKeydown:q}),{default:(0,t.withCtx)(()=>[(0,t.renderSlot)(e.$slots,`default`)]),_:3},16,[`id`,`role`,`tabindex`,`data-sbf-side`,`data-sbf-align`])):(0,t.createCommentVNode)(``,!0)]),_:3},16),A.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:1},j,{onFocus:z}),null,16)):(0,t.createCommentVNode)(``,!0)],36)):(0,t.createCommentVNode)(``,!0)],8,[`to`,`disabled`]))}});e.SbContainer=T,e.SbFloating=D,e.SbReference=E});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("vue"),require("@floating-ui/vue")):typeof define==`function`&&define.amd?define([`exports`,`vue`,`@floating-ui/vue`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.SbFloatingPanelVue={},e.Vue,e.FloatingUIVue))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=(()=>{try{return process.env.NODE_ENV!==`production`}catch{return!1}})();function i(e){r&&console.warn(`[sb-floating-panel-vue] ${e}`)}var a=Symbol(`SbFloatingContext`);function o(e,t,n){return++e.parts[t]>1&&i(`<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]--}function s(e){let n=(0,t.inject)(a,null);if(!n)throw Error(`[sb-floating-panel-vue] <${e}> must be used inside <SbContainer>.`);return n}var c=e=>`${Math.max(0,e)}px`,l=(e,t)=>{let[n,r]=e.split(`-`),i=t&&(n===`top`||n===`bottom`),a=r===`start`?i?`100%`:`0%`:r===`end`?i?`0%`:`100%`:`50%`;return n===`top`?`${a} 100%`:n===`bottom`?`${a} 0%`:n===`left`?`100% ${a}`:`0% ${a}`};function u(e){let r=(0,t.ref)(null),i=(0,t.ref)(null),a=(0,t.computed)(()=>{let r=(0,t.toValue)(e.padding),i=(0,t.toValue)(e.matchWidth),a=(0,t.toValue)(e.placement).includes(`-`),o=(0,n.flip)({padding:r,crossAxis:`alignment`,fallbackAxisSideDirection:`end`}),s=(0,n.shift)({padding:r,limiter:(0,n.limitShift)()}),u=[(0,n.offset)((0,t.toValue)(e.offset)),...a?[o,s]:[s,o],(0,n.size)({padding:r,apply({rects:e,elements:t,availableWidth:n,availableHeight:r,placement:a}){let{style:o}=t.floating,s=c(e.reference.width);o.setProperty(`--sbf-reference-width`,s);let u=getComputedStyle(t.floating).direction===`rtl`;o.setProperty(`--sbf-transform-origin`,l(a,u)),o.setProperty(`--sbf-available-width`,c(n)),o.setProperty(`--sbf-available-height`,c(r)),o.width=i===!0?s:``,o.minWidth=i===`min`?s:``}})];return(0,t.toValue)(e.hideWhenDetached)&&u.push((0,n.hide)({padding:r})),u}),{floatingStyles:o,middlewareData:s,placement:u,isPositioned:d,update:f}=(0,n.useFloating)(r,i,{open:()=>(0,t.toValue)(e.isOpen),placement:()=>(0,t.toValue)(e.placement),strategy:()=>(0,t.toValue)(e.strategy),middleware:a,whileElementsMounted:n.autoUpdate}),p=(0,t.computed)(()=>!!s.value.hide?.referenceHidden);return{reference:r,floating:i,floatingStyles:(0,t.computed)(()=>({...o.value,...p.value?{visibility:`hidden`}:{}})),placement:u,side:(0,t.computed)(()=>u.value.split(`-`)[0]),align:(0,t.computed)(()=>u.value.split(`-`)[1]),isPositioned:d,referenceHidden:p,update:f}}var d=`data-sbf-focus-guard`,f=[`a[href]`,`button:not([disabled])`,`input:not([disabled]):not([type="hidden"])`,`select:not([disabled])`,`textarea:not([disabled])`,`summary`,`audio[controls]`,`video[controls]`,`[tabindex]`,`[contenteditable="true"]`].join(`,`),p=e=>e.tabIndex>=0&&!e.hasAttribute(`data-sbf-focus-guard`)&&!e.closest(`[inert]`)&&(e.checkVisibility?.()??!0);function m(e){let t=e&&typeof e==`object`&&`$el`in e?e.$el:e;return t instanceof HTMLElement?t:null}function h(e){let t=e instanceof Element?e.closest(f):null;return!!t&&!t.closest(`[inert]`)}function g(e){return[...e.querySelectorAll(f)].filter(p)}function _(e,t){return g(e.ownerDocument).find(n=>!!(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)&&!e.contains(n)&&!t(n))}var v=[],y=(0,t.defineComponent)({inheritAttrs:!1,__name:`SbContainer`,props:(0,t.mergeModels)({placement:{default:`bottom-start`},strategy:{default:`absolute`},offset:{default:8},padding:{default:8},matchWidth:{type:[Boolean,String],default:!1},hideWhenDetached:{type:[Boolean,String],default:!1},defaultOpen:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},trigger:{default:`click`},delay:{default:()=>({open:300,close:150})},closeOnEscape:{type:Boolean,default:!0},closeOnClickOutside:{type:Boolean,default:!0},closeOnFocusOut:{type:Boolean,default:!0}},{open:{type:Boolean,default:void 0},openModifiers:{}}),emits:(0,t.mergeModels)([`open`,`close`],[`update:open`]),setup(e,{expose:n,emit:r}){let i=e,o=(0,t.useModel)(e,`open`),s=r,c=i.defaultOpen,l=(0,t.computed)(()=>!i.disabled&&(o.value??c)),d;(0,t.onScopeDispose)(()=>clearTimeout(d));let f=e=>{clearTimeout(d),!(e&&i.disabled)&&e!==l.value&&(o.value=e)},p=()=>f(!0),m=()=>f(!1),g=()=>f(!l.value),_=e=>{if(e.pointerType===`touch`||(x?.hover(e),i.trigger!==`hover`))return;let t=e.type===`pointerenter`||S.contains(e.relatedTarget);if(clearTimeout(d),t===l.value)return;let{delay:n}=i,r=typeof n==`number`?{open:n,close:n}:n,a=(t?r.open:r.close)??(t?300:150);d=setTimeout(()=>f(t),a)},y=u({isOpen:l,placement:()=>i.placement,strategy:()=>i.strategy,offset:()=>i.offset,padding:()=>i.padding,matchWidth:()=>i.matchWidth,hideWhenDetached:()=>i.hideWhenDetached}),b=new Set,x=(0,t.inject)(a,null),S={...y,isOpen:l,disabled:(0,t.toRef)(i,`disabled`),trigger:(0,t.toRef)(i,`trigger`),floatingId:`${(0,t.useId)()}-floating`,referenceId:(0,t.ref)(),floatingRole:(0,t.ref)(`dialog`),navigation:(0,t.ref)(null),focusRequest:(0,t.ref)(null),parent:x,skipFocusReturn:!1,parts:{reference:0,floating:0},isUnmounting:!1,open:p,close:m,toggle:g,hover:_,contains:e=>e instanceof Node?y.reference.value?.contains(e)||y.floating.value?.contains(e)?!0:[...b].some(t=>t.contains(e)):!1,registerChild:e=>(b.add(e),()=>b.delete(e))};x&&(0,t.onScopeDispose)(x.registerChild(S)),(0,t.provide)(a,S),(0,t.onBeforeUnmount)(()=>S.isUnmounting=!0);let C=e=>{let t=e.composedPath()[0]??e.target;return v.findLast(e=>e.contains(t))??v[v.length-1]},w=e=>{e.key===`Escape`&&C(e)===S&&(!i.closeOnEscape||e.defaultPrevented||e.isComposing||(e.preventDefault(),m()))},T=e=>{S.contains(e)||(S.skipFocusReturn=h(e),m())},E,D=e=>{if(E?.(),!i.closeOnClickOutside)return;let t=e.composedPath()[0]??e.target;if(e.pointerType!==`touch`){T(t);return}if(S.contains(t))return;let n=e=>{E?.(),T(e.composedPath()[0]??e.target)};document.addEventListener(`click`,n,!0),E=()=>{document.removeEventListener(`click`,n,!0),E=void 0}},O=e=>{i.closeOnFocusOut&&(S.contains(e.composedPath()[0]??e.target)||m())};return(0,t.watch)(l,(e,t,n)=>{e&&typeof document<`u`&&(v.push(S),document.addEventListener(`keydown`,w),document.addEventListener(`pointerdown`,D,!0),document.addEventListener(`focusin`,O),n(()=>{document.removeEventListener(`keydown`,w),document.removeEventListener(`pointerdown`,D,!0),document.removeEventListener(`focusin`,O),E?.(),v.splice(v.indexOf(S),1)}))},{immediate:!0}),(0,t.watch)(l,e=>s(e?`open`:`close`)),(0,t.watch)(y.referenceHidden,e=>{e&&i.hideWhenDetached===`close`&&m()}),(0,t.watch)(()=>i.disabled,e=>{e&&(o.value??c)&&(o.value=!1)}),n({get isOpen(){return l.value},open:p,close:m,toggle:g,update:y.update}),(e,n)=>(0,t.renderSlot)(e.$slots,`default`,{isOpen:l.value,open:p,close:m,toggle:g,placement:(0,t.unref)(y).placement.value,side:(0,t.unref)(y).side.value,align:(0,t.unref)(y).align.value,floatingId:S.floatingId,referenceId:S.referenceId.value})}}),b={dialog:`dialog`,alertdialog:`dialog`,menu:`menu`,listbox:`listbox`,tree:`tree`,grid:`grid`},x={menu:`[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]`,listbox:`[role="option"]`},S=e=>!!e&&Object.hasOwn(x,e);function C(e,t){return[...e.querySelectorAll(x[t])].filter(n=>n.closest(`[role="${t}"]`)===e&&!n.matches(`:disabled`)&&(n.checkVisibility?.()??!0))}var w=e=>e instanceof Element&&!!e.closest(`input, textarea, select, [contenteditable]:not([contenteditable="false"])`),T=e=>getComputedStyle(e).direction===`rtl`?{open:`ArrowLeft`,close:`ArrowRight`}:{open:`ArrowRight`,close:`ArrowLeft`},E=(0,t.defineComponent)({__name:`SbReference`,props:{as:{default:`button`},id:{default:void 0},ariaHaspopup:{default:void 0}},setup(e){let n=e,r=(0,t.useAttrs)(),a=s(`SbReference`),{isOpen:c,disabled:l,floatingId:u,floatingRole:d}=a,f=o(a,`reference`,`SbReference`),p=()=>typeof n.as!=`string`||n.as===`button`||n.as===`a`&&r.href!=null,h=`${(0,t.useId)()}-reference`,_=(0,t.computed)(()=>n.id??h);(0,t.watchEffect)(()=>{a.referenceId.value=_.value}),(0,t.onMounted)(()=>{a.reference.value||i("<SbReference> rendered no element, so the panel cannot be positioned: a component in `as` must render a single root element.")}),(0,t.onBeforeUnmount)(()=>{a.referenceId.value===_.value&&(a.referenceId.value=void 0),f(),!a.parts.reference&&!a.isUnmounting&&a.close()});let v=(0,t.computed)(()=>n.ariaHaspopup??(d.value&&Object.hasOwn(b,d.value)?b[d.value]:void 0)),y=e=>{a.reference.value=m(e)},x=()=>{a.trigger.value===`click`&&a.toggle()},S=(0,t.computed)(()=>d.value===`tooltip`),C=()=>a.trigger.value===`hover`||a.trigger.value===`focus`,w=()=>a.parent?.navigation.value===`menu`,E=e=>{C()&&!w()&&!a.contains(e.relatedTarget)&&a.open()},D=e=>{C()&&!a.contains(e.relatedTarget)&&a.close()},O=e=>{let t=a.floating.value,n=t&&g(t)[0];n&&(e.preventDefault(),n.focus())},k=e=>{if(a.navigation.value&&!l.value&&a.trigger.value!==`manual`){if(w()){let t=e.currentTarget;return e.key===T(t).open?`first`:void 0}return e.key===`ArrowDown`?`first`:e.key===`ArrowUp`?`last`:void 0}},A=e=>{if(e.key===`Tab`&&!e.shiftKey&&c.value&&!w()){O(e);return}let t=k(e);t?(e.preventDefault(),a.focusRequest.value=t,a.open()):p()||e.key!==`Enter`&&e.key!==` `||(e.preventDefault(),x())};return(e,r)=>((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(n.as),{id:_.value,ref:y,type:n.as===`button`?`button`:void 0,role:p()?void 0:`button`,tabindex:p()?void 0:(0,t.unref)(l)?-1:0,disabled:n.as===`button`&&(0,t.unref)(l)?!0:void 0,"aria-disabled":n.as!==`button`&&(0,t.unref)(l)?`true`:void 0,"aria-haspopup":v.value,"aria-expanded":S.value?void 0:(0,t.unref)(c)?`true`:`false`,"aria-controls":(0,t.unref)(c)&&!S.value?(0,t.unref)(u):void 0,"aria-describedby":(0,t.unref)(c)&&S.value?(0,t.unref)(u):void 0,"data-sbf-state":(0,t.unref)(c)?`open`:`closed`,onClick:x,onKeydown:A,onFocusin:E,onFocusout:D,onPointerenter:(0,t.unref)(a).hover,onPointerleave:(0,t.unref)(a).hover},{default:(0,t.withCtx)(()=>[(0,t.renderSlot)(e.$slots,`default`)]),_:3},40,[`id`,`type`,`role`,`tabindex`,`disabled`,`aria-disabled`,`aria-haspopup`,`aria-expanded`,`aria-controls`,`aria-describedby`,`data-sbf-state`,`onPointerenter`,`onPointerleave`]))}}),D=(0,t.defineComponent)({inheritAttrs:!1,__name:`SbFloating`,props:{as:{default:`div`},role:{default:`dialog`},transition:{default:void 0},teleport:{type:[String,Boolean],default:`body`},zIndex:{default:void 0},autoFocus:{type:Boolean,default:void 0},keyboardNavigation:{type:Boolean,default:!0}},emits:[`after-enter`,`after-leave`],setup(e,{emit:n}){let r=e,i=n,a=(0,t.useAttrs)(),c=s(`SbFloating`);(0,t.onBeforeUnmount)(o(c,`floating`,`SbFloating`));let{isOpen:l,floatingId:u,referenceId:f,side:p,align:h}=c;(0,t.watchEffect)(()=>{c.floatingRole.value=r.role,c.navigation.value=r.keyboardNavigation&&S(r.role)?r.role:null});let v=(0,t.ref)(l.value),y=(0,t.ref)(null),x=e=>{c.floating.value=e instanceof HTMLElement?e:null},E=e=>{y.value=m(e)},D=(0,t.computed)(()=>({...c.floatingStyles.value,...r.zIndex===void 0?{}:{zIndex:r.zIndex}})),O=()=>({"aria-labelledby":r.role&&Object.hasOwn(b,r.role)&&a[`aria-label`]==null?f.value:void 0,...a}),k=(0,t.computed)(()=>r.autoFocus??(r.role!==`tooltip`&&c.trigger.value!==`hover`&&c.trigger.value!==`focus`)),A=(0,t.computed)(()=>l.value&&r.teleport!==!1&&r.role!==`tooltip`),j={[d]:``,tabindex:0,style:{position:`fixed`,opacity:0,outline:`none`,pointerEvents:`none`}},M=(0,t.computed)(()=>{let{transition:e}=r;return e?typeof e==`string`?{name:e}:e:{css:!1}}),N=e=>e.setAttribute(`data-sbf-state`,`closed`),P=()=>i(`after-enter`),F=()=>{l.value||(v.value=!1),i(`after-leave`)},I=e=>e instanceof Node&&!!y.value?.contains(e),L=e=>{let t=y.value;if(!t)return;let n=g(t);((e===`first`?n[0]:n[n.length-1])??t).focus({preventScroll:!0})},R=e=>{I(e.relatedTarget)?c.reference.value?.focus():L(`first`)},z=e=>{if(!I(e.relatedTarget)){L(`last`);return}let t=c.reference.value;((t&&_(t,e=>c.contains(e)))??t)?.focus()},B=()=>{let e=c.navigation.value;return y.value&&e?C(y.value,e):[]},V=e=>{let t=y.value;if(!t)return;let n=B();(n.find(e=>e.getAttribute(`aria-selected`)===`true`)??(e===`last`?n[n.length-1]:e?n[0]:void 0)??t.querySelector(`[autofocus]`)??n[0]??g(t)[0]??t).focus({preventScroll:!0})},H=()=>{let e=c.focusRequest.value;return c.focusRequest.value=null,e},U=``,W;(0,t.onScopeDispose)(()=>clearTimeout(W));let G=(e,t,n)=>{U+=n.toLowerCase(),clearTimeout(W),W=setTimeout(()=>U=``,500);let r=[...U].every(e=>e===U[0])?U[0]:U,i=Math.max(t,0),a=[...e.slice(i),...e.slice(0,i)];return r.length===1&&t>=0&&a.push(a.shift()),a.find(e=>e.textContent?.trim().toLowerCase().startsWith(r))},K=e=>{let t=c,n=[t];for(;t.parent?.navigation.value===`menu`;)t=t.parent,n.push(t);let r=t.reference.value,i=e?r:(r&&_(r,e=>t.contains(e)))??r;for(let e of n)e.skipFocusReturn=!0,e.close();i?.focus()},q=e=>{let t=c.navigation.value;if(!t||e.defaultPrevented||e.isComposing||w(e.target))return;let n=B(),r=n.findIndex(t=>t.contains(e.target)),i=n.length-1,a=t===`menu`,o;if(e.key===`ArrowDown`)o=n[r<i?r+1:a?0:i];else if(e.key===`ArrowUp`)o=n[r>0?r-1:a||r<0?i:0];else if(e.key===`Home`)o=n[0];else if(e.key===`End`)o=n[i];else if(e.key===`Tab`&&t===`menu`){e.preventDefault(),K(e.shiftKey);return}else if(t===`menu`&&c.parent?.navigation.value===`menu`&&y.value&&e.key===T(y.value).close){e.preventDefault(),c.close();return}else if(e.key.length===1&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&(e.key!==` `||U))e.preventDefault(),o=G(n,r,e.key);else if((e.key===`Enter`||e.key===` `)&&e.target===n[r]){let t=n[r];if(t.matches(`button, a[href], input, summary`))return;e.preventDefault(),t.getAttribute(`aria-disabled`)!==`true`&&t.click();return}o&&(e.preventDefault(),o.focus())};return(0,t.watch)(l,e=>{let t=c.skipFocusReturn;if(c.skipFocusReturn=!1,e){v.value=!0;return}let n=document.activeElement;!t&&n&&c.floating.value?.contains(n)&&c.reference.value?.focus({preventScroll:!0})}),(0,t.watch)(()=>l.value&&c.isPositioned.value,async e=>{if(!e)return;let n=H();(n||k.value)&&(await(0,t.nextTick)(),V(n))}),(0,t.watch)(c.focusRequest,e=>{e&&l.value&&c.isPositioned.value&&V(H())}),(e,n)=>((0,t.openBlock)(),(0,t.createBlock)(t.Teleport,{to:r.teleport||`body`,disabled:r.teleport===!1},[v.value?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{key:0,ref:x,style:(0,t.normalizeStyle)(D.value),onPointerenter:n[0]||=(...e)=>(0,t.unref)(c).hover&&(0,t.unref)(c).hover(...e),onPointerleave:n[1]||=(...e)=>(0,t.unref)(c).hover&&(0,t.unref)(c).hover(...e)},[A.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:0},j,{onFocus:R}),null,16)):(0,t.createCommentVNode)(``,!0),(0,t.createVNode)(t.Transition,(0,t.mergeProps)(M.value,{appear:``,onBeforeLeave:N,onAfterEnter:P,onAfterLeave:F}),{default:(0,t.withCtx)(()=>[(0,t.unref)(l)?((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(r.as),(0,t.mergeProps)({key:0},O(),{id:(0,t.unref)(u),ref:E,role:r.role??void 0,tabindex:k.value?-1:void 0,"data-sbf-state":`open`,"data-sbf-side":(0,t.unref)(p),"data-sbf-align":(0,t.unref)(h),onKeydown:q}),{default:(0,t.withCtx)(()=>[(0,t.renderSlot)(e.$slots,`default`)]),_:3},16,[`id`,`role`,`tabindex`,`data-sbf-side`,`data-sbf-align`])):(0,t.createCommentVNode)(``,!0)]),_:3},16),A.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:1},j,{onFocus:z}),null,16)):(0,t.createCommentVNode)(``,!0)],36)):(0,t.createCommentVNode)(``,!0)],8,[`to`,`disabled`]))}});e.SbContainer=y,e.SbFloating=D,e.SbReference=E});
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Panel roles that make the reference a popup trigger, with their `aria-haspopup` value.
3
+ * Panels with these roles are also named after the reference.
4
+ */
5
+ export declare const POPUP_ROLES: Record<string, 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid'>;
@@ -0,0 +1,10 @@
1
+ /** Marks the hidden elements placed around a teleported panel to keep the Tab order. */
2
+ export declare const FOCUS_GUARD_ATTRIBUTE = "data-sbf-focus-guard";
3
+ /** Element of a template ref: a component gives its instance, whose root element is `$el`. */
4
+ export declare function toElement(el: unknown): HTMLElement | null;
5
+ /** Whether pressing `target` moves focus to it (or to a focusable ancestor). */
6
+ export declare function isFocusable(target: EventTarget | null): boolean;
7
+ /** Elements reachable with Tab inside `root`, in document order (focus guards excluded). */
8
+ export declare function getTabbables(root: ParentNode): HTMLElement[];
9
+ /** First element reachable with Tab after `anchor` in document order, skipping the excluded ones. */
10
+ export declare function getNextTabbable(anchor: Element, exclude: (el: HTMLElement) => boolean): HTMLElement | undefined;
@@ -1,9 +1,3 @@
1
- /** Marks the hidden elements placed around a teleported panel to keep the Tab order. */
2
- export declare const FOCUS_GUARD_ATTRIBUTE = "data-sbf-focus-guard";
3
- /** Whether pressing `target` moves focus to it (or to a focusable ancestor). */
4
- export declare function isFocusable(target: EventTarget | null): boolean;
5
- /** Elements reachable with Tab inside `root`, in document order (focus guards excluded). */
6
- export declare function getTabbables(root: ParentNode): HTMLElement[];
7
1
  /** Panel roles whose keyboard model the components handle, with the selector of their items. */
8
2
  export declare const ITEM_SELECTORS: {
9
3
  readonly menu: "[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]";
@@ -20,5 +14,3 @@ export declare const submenuKeys: (el: Element) => {
20
14
  open: string;
21
15
  close: string;
22
16
  };
23
- /** First element reachable with Tab after `anchor` in document order, skipping the excluded ones. */
24
- export declare function getNextTabbable(anchor: Element, exclude: (el: HTMLElement) => boolean): HTMLElement | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sb-floating-panel-vue",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "description": "Headless Vue 3 floating panel components (dropdowns, popovers, menus) powered by @floating-ui/vue: positioning, accessibility and open state handled, zero CSS shipped.",
5
5
  "keywords": [
6
6
  "vue",
File without changes