sb-floating-panel-vue 5.0.2 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -12
- package/dist/components/SbFloating.vue.d.ts +3 -2
- package/dist/composables/useSbFloating.d.ts +6 -0
- package/dist/index.d.ts +2 -1
- package/dist/sb-floating-panel.es.js +189 -157
- package/dist/sb-floating-panel.umd.js +1 -1
- package/dist/types.d.ts +23 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -65,18 +65,16 @@ import { SbContainer, SbReference, SbFloating } from 'sb-floating-panel-vue';
|
|
|
65
65
|
|
|
66
66
|
### Menu
|
|
67
67
|
|
|
68
|
-
With `role="menu"` the library handles the keyboard: ArrowDown on the trigger opens the menu on its first item, the arrow keys, Home, End and typing move between items, Tab leaves (see [Keyboard](#keyboard)). Activating an item
|
|
68
|
+
With `role="menu"` the library handles the keyboard: ArrowDown on the trigger opens the menu on its first item, the arrow keys, Home, End and typing move between items, Tab leaves (see [Keyboard](#keyboard)). Activating an item runs its `click` handler; with `close-on-select` the menu then closes and focus goes back to the trigger.
|
|
69
69
|
|
|
70
70
|
```vue
|
|
71
71
|
<SbContainer match-width="min">
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
</SbFloating>
|
|
79
|
-
</template>
|
|
72
|
+
<SbReference class="my-trigger">Account</SbReference>
|
|
73
|
+
<SbFloating role="menu" close-on-select class="my-panel">
|
|
74
|
+
<button v-for="item in ['Profile', 'Settings', 'Sign out']" :key="item" type="button" role="menuitem" @click="go(item)">
|
|
75
|
+
{{ item }}
|
|
76
|
+
</button>
|
|
77
|
+
</SbFloating>
|
|
80
78
|
</SbContainer>
|
|
81
79
|
```
|
|
82
80
|
|
|
@@ -174,6 +172,7 @@ The panel, teleported to `body`. It is rendered while open and stays mounted unt
|
|
|
174
172
|
| `zIndex` | `number \| string` | — | `z-index` of the positioned wrapper. Use this, not a `z-*` class on the panel (see [Stacking](#stacking)) |
|
|
175
173
|
| `autoFocus` | `boolean` | `true`, `false` with `role="tooltip"`, the `hover` / `focus` trigger or a text field reference | Once positioned, focuses the first `[autofocus]` or focusable element inside, else the panel itself (a menu: its first item; a listbox: its selected option) |
|
|
176
174
|
| `keyboardNavigation` | `boolean` | `true` | Handles the keyboard model of `role="menu"` and `role="listbox"` panels (see [Keyboard](#keyboard)). No effect with other roles |
|
|
175
|
+
| `closeOnSelect` | `boolean` | `false` | With `role="menu"` / `"listbox"`, activating a `menuitem` / `option` closes the panel (a submenu: with its parent menus) and gives focus back to the reference, after the item's `click` handler. Not for `menuitemcheckbox` / `menuitemradio`, submenu triggers, disabled items or a listbox with `aria-multiselectable="true"`; `event.preventDefault()` in the handler keeps it open |
|
|
177
176
|
|
|
178
177
|
| Event | Description |
|
|
179
178
|
|---------------|----------------------------------------------------------------|
|
|
@@ -182,6 +181,25 @@ The panel, teleported to `body`. It is rendered while open and stays mounted unt
|
|
|
182
181
|
|
|
183
182
|
With a popup role (`dialog`, `alertdialog`, `menu`, `listbox`, `tree`, `grid`), the panel is named after the reference with `aria-labelledby`, unless you pass `aria-label` or `aria-labelledby` yourself. When focus is inside the panel as it closes, it goes back to the reference.
|
|
184
183
|
|
|
184
|
+
### `useSbFloating()`
|
|
185
|
+
|
|
186
|
+
The open state and actions of the closest `SbContainer`, for your own components inside it: a `MenuItem` of your design system can close the menu without `close` passed down from the slot.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import { useSbFloating } from 'sb-floating-panel-vue';
|
|
190
|
+
|
|
191
|
+
const { isOpen, open, close, toggle } = useSbFloating();
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
| Returns | Type | Description |
|
|
195
|
+
|----------|--------------------------|---------------------------|
|
|
196
|
+
| `isOpen` | `Readonly<Ref<boolean>>` | Whether the panel is open |
|
|
197
|
+
| `open` | `() => void` | Opens the panel |
|
|
198
|
+
| `close` | `() => void` | Closes the panel |
|
|
199
|
+
| `toggle` | `() => void` | Toggles the panel |
|
|
200
|
+
|
|
201
|
+
Call it in `setup` of a component rendered inside an `SbContainer` (in the reference, the panel or anywhere in its slot); outside one it throws.
|
|
202
|
+
|
|
185
203
|
### Types
|
|
186
204
|
|
|
187
205
|
```ts
|
|
@@ -197,6 +215,7 @@ import type {
|
|
|
197
215
|
SbAlignment,
|
|
198
216
|
SbStrategy,
|
|
199
217
|
SbFloatingRole,
|
|
218
|
+
UseSbFloatingReturn,
|
|
200
219
|
} from 'sb-floating-panel-vue';
|
|
201
220
|
```
|
|
202
221
|
|
|
@@ -226,7 +245,7 @@ import type {
|
|
|
226
245
|
- A press outside closes the panel; on touch, only a tap does, so starting a scroll keeps it open.
|
|
227
246
|
- Moving focus outside (e.g. tabbing past the last element) closes it.
|
|
228
247
|
- A container nested inside a panel counts as part of it.
|
|
229
|
-
- **What is up to you.** The library does not implement the keyboard model of `tree` and `grid` panels, nor selection: a listbox option or a menu item does what its `click` handler does (e.g. set `aria-selected`
|
|
248
|
+
- **What is up to you.** The library does not implement the keyboard model of `tree` and `grid` panels, nor selection: a listbox option or a menu item does what its `click` handler does (e.g. set `aria-selected`); add `closeOnSelect` to close the panel after it. Use valid structure: items directly inside the `menu` / `listbox`, or inside `ul` / `li` with `role="none"`.
|
|
230
249
|
- <a id="text-field-references"></a>**Text field references.** `<SbReference as="input">` (or `textarea`) stays a text field: no `role="button"`, Enter and Space type as usual, a click opens the panel without closing it, and focus stays in the field when the panel opens. The [combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) (autocomplete with focus kept in the field and `aria-activedescendant`) is not supported: with a `menu` or `listbox` panel the arrow keys move focus into the panel, and the console warns about it in development.
|
|
231
250
|
|
|
232
251
|
---
|
|
@@ -355,9 +374,9 @@ SbContainer ── provides the state ──┬─▶ SbReference
|
|
|
355
374
|
|
|
356
375
|
- `SbReference` and `SbFloating` find their container on their own: you pass no refs, styles or handlers, and never write `.value`.
|
|
357
376
|
- The lookup follows the component tree, not the DOM, so it keeps working although `SbFloating` is teleported to `body`.
|
|
358
|
-
- They can sit at any depth inside the container slot, also inside your own components.
|
|
377
|
+
- They can sit at any depth inside the container slot, also inside your own components, which can read the same state with [`useSbFloating()`](#usesbfloating).
|
|
359
378
|
- Used outside an `SbContainer`, they throw: `[sb-floating-panel-vue] <SbFloating> must be used inside <SbContainer>.`
|
|
360
|
-
- In development, the console warns about a second `SbReference` or `SbFloating` in the same container about an `as` component that renders no single root element
|
|
379
|
+
- In development, the console warns about a second `SbReference` or `SbFloating` in the same container, about an `as` component that renders no single root element, about a text field reference of a `menu` or `listbox` panel, about a `tooltip` opened by click, and, the first time the arrow keys look for them, about a `menu` or `listbox` with no items or with items that cannot take focus. The warnings depend on `process.env.NODE_ENV`, which your bundler replaces: they are left out of production builds.
|
|
361
380
|
|
|
362
381
|
### Nested containers
|
|
363
382
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { TransitionProps } from 'vue';
|
|
2
2
|
import { SbFloatingProps } from '../types';
|
|
3
|
-
declare var
|
|
3
|
+
declare var __VLS_26: {};
|
|
4
4
|
type __VLS_Slots = {} & {
|
|
5
|
-
default?: (props: typeof
|
|
5
|
+
default?: (props: typeof __VLS_26) => any;
|
|
6
6
|
};
|
|
7
7
|
declare const __VLS_base: import('vue').DefineComponent<SbFloatingProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
8
8
|
"after-enter": () => any;
|
|
@@ -18,6 +18,7 @@ declare const __VLS_base: import('vue').DefineComponent<SbFloatingProps, {}, {},
|
|
|
18
18
|
zIndex: string | number;
|
|
19
19
|
autoFocus: boolean;
|
|
20
20
|
keyboardNavigation: boolean;
|
|
21
|
+
closeOnSelect: boolean;
|
|
21
22
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
22
23
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
23
24
|
declare const _default: typeof __VLS_export;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UseSbFloatingReturn } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Open state and actions of the closest `SbContainer`, for your own components inside it
|
|
4
|
+
* (e.g. a `MenuItem` that closes the menu), without passing `close` down from the slot.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useSbFloating(): UseSbFloatingReturn;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as SbContainer } from './components/SbContainer.vue';
|
|
2
2
|
export { default as SbReference } from './components/SbReference.vue';
|
|
3
3
|
export { default as SbFloating } from './components/SbFloating.vue';
|
|
4
|
-
export
|
|
4
|
+
export { useSbFloating } from './composables/useSbFloating';
|
|
5
|
+
export type { SbContainerProps, SbContainerSlotProps, SbContainerExposed, SbReferenceProps, SbFloatingProps, SbTrigger, SbPlacement, SbSide, SbAlignment, SbStrategy, SbFloatingRole, UseSbFloatingReturn, } from './types';
|
|
@@ -1,62 +1,62 @@
|
|
|
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 _,
|
|
2
|
-
import { autoUpdate as
|
|
1
|
+
import { Teleport as e, Transition as t, computed as n, createBlock as r, createCommentVNode as i, createElementBlock as a, createVNode as o, defineComponent as s, inject as c, mergeModels as l, mergeProps as u, nextTick as 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";
|
|
3
3
|
//#region src/utils/warn.ts
|
|
4
|
-
var
|
|
4
|
+
var L = (() => {
|
|
5
5
|
try {
|
|
6
6
|
return process.env.NODE_ENV !== "production";
|
|
7
7
|
} catch {
|
|
8
8
|
return !1;
|
|
9
9
|
}
|
|
10
10
|
})();
|
|
11
|
-
function
|
|
12
|
-
|
|
11
|
+
function R(e) {
|
|
12
|
+
L && console.warn(`[sb-floating-panel-vue] ${e}`);
|
|
13
13
|
}
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region src/composables/useSbFloatingContext.ts
|
|
16
|
-
var
|
|
17
|
-
function
|
|
18
|
-
return ++e.parts[t] > 1 &&
|
|
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
19
|
}
|
|
20
|
-
function
|
|
21
|
-
let t = c(
|
|
20
|
+
function ne(e) {
|
|
21
|
+
let t = c(z, null);
|
|
22
22
|
if (!t) throw Error(`[sb-floating-panel-vue] <${e}> must be used inside <SbContainer>.`);
|
|
23
23
|
return t;
|
|
24
24
|
}
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region src/composables/useSbFloatingPanel.ts
|
|
27
|
-
var
|
|
27
|
+
var V = (e) => `${Math.max(0, e)}px`, re = (e, t) => {
|
|
28
28
|
let [n, r] = e.split("-"), i = t && (n === "top" || n === "bottom"), a = r === "start" ? i ? "100%" : "0%" : r === "end" ? i ? "0%" : "100%" : "50%";
|
|
29
29
|
return n === "top" ? `${a} 100%` : n === "bottom" ? `${a} 0%` : n === "left" ? `100% ${a}` : `0% ${a}`;
|
|
30
30
|
};
|
|
31
|
-
function
|
|
32
|
-
let t =
|
|
33
|
-
let t =
|
|
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({
|
|
34
34
|
padding: t,
|
|
35
35
|
crossAxis: "alignment",
|
|
36
36
|
fallbackAxisSideDirection: "end"
|
|
37
|
-
}), a =
|
|
37
|
+
}), a = ee({
|
|
38
38
|
padding: t,
|
|
39
|
-
limiter:
|
|
39
|
+
limiter: P()
|
|
40
40
|
}), o = [
|
|
41
|
-
|
|
41
|
+
F(C(e.offset)),
|
|
42
42
|
...r ? [i, a] : [a, i],
|
|
43
|
-
|
|
43
|
+
te({
|
|
44
44
|
padding: t,
|
|
45
45
|
apply({ rects: e, elements: t, availableWidth: r, availableHeight: i, placement: a }) {
|
|
46
|
-
let { style: o } = t.floating, s =
|
|
46
|
+
let { style: o } = t.floating, s = V(e.reference.width);
|
|
47
47
|
o.setProperty("--sbf-reference-width", s);
|
|
48
48
|
let c = getComputedStyle(t.floating).direction === "rtl";
|
|
49
|
-
o.setProperty("--sbf-transform-origin",
|
|
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 : "";
|
|
50
50
|
}
|
|
51
51
|
})
|
|
52
52
|
];
|
|
53
|
-
return
|
|
54
|
-
}), { floatingStyles: a, middlewareData: o, placement: s, isPositioned: c, update: l } =
|
|
55
|
-
open: () =>
|
|
56
|
-
placement: () =>
|
|
57
|
-
strategy: () =>
|
|
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
58
|
middleware: i,
|
|
59
|
-
whileElementsMounted:
|
|
59
|
+
whileElementsMounted: j
|
|
60
60
|
}), u = n(() => !!o.value.hide?.referenceHidden);
|
|
61
61
|
return {
|
|
62
62
|
reference: t,
|
|
@@ -75,7 +75,7 @@ function re(e) {
|
|
|
75
75
|
}
|
|
76
76
|
//#endregion
|
|
77
77
|
//#region src/utils/dom.ts
|
|
78
|
-
var
|
|
78
|
+
var ae = "data-sbf-focus-guard", H = [
|
|
79
79
|
"a[href]",
|
|
80
80
|
"button:not([disabled])",
|
|
81
81
|
"input:not([disabled]):not([type=\"hidden\"])",
|
|
@@ -86,25 +86,25 @@ var ie = "data-sbf-focus-guard", H = [
|
|
|
86
86
|
"video[controls]",
|
|
87
87
|
"[tabindex]",
|
|
88
88
|
"[contenteditable=\"true\"]"
|
|
89
|
-
].join(","),
|
|
90
|
-
function
|
|
89
|
+
].join(","), oe = (e) => e.tabIndex >= 0 && !e.hasAttribute("data-sbf-focus-guard") && !e.closest("[inert]") && (e.checkVisibility?.() ?? !0);
|
|
90
|
+
function se(e) {
|
|
91
91
|
let t = e && typeof e == "object" && "$el" in e ? e.$el : e;
|
|
92
92
|
return t instanceof HTMLElement ? t : null;
|
|
93
93
|
}
|
|
94
|
-
function
|
|
94
|
+
function U(e) {
|
|
95
95
|
let t = e instanceof Element ? e.closest(H) : null;
|
|
96
96
|
return !!t && !t.closest("[inert]");
|
|
97
97
|
}
|
|
98
|
-
var
|
|
98
|
+
var ce = (e) => e.matches(H) && !e.closest("[inert]");
|
|
99
99
|
function W(e) {
|
|
100
|
-
return [...e.querySelectorAll(H)].filter(
|
|
100
|
+
return [...e.querySelectorAll(H)].filter(oe);
|
|
101
101
|
}
|
|
102
102
|
function G(e, t) {
|
|
103
103
|
return W(e.ownerDocument).find((n) => !!(e.compareDocumentPosition(n) & Node.DOCUMENT_POSITION_FOLLOWING) && !e.contains(n) && !t(n));
|
|
104
104
|
}
|
|
105
105
|
//#endregion
|
|
106
106
|
//#region src/components/SbContainer.vue?vue&type=script&setup=true&lang.ts
|
|
107
|
-
var K = [],
|
|
107
|
+
var K = [], le = /* @__PURE__ */ s({
|
|
108
108
|
inheritAttrs: !1,
|
|
109
109
|
__name: "SbContainer",
|
|
110
110
|
props: /*@__PURE__*/ l({
|
|
@@ -154,12 +154,12 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
154
154
|
}),
|
|
155
155
|
emits: /*@__PURE__*/ l(["open", "close"], ["update:open"]),
|
|
156
156
|
setup(e, { expose: t, emit: r }) {
|
|
157
|
-
let i = e, a =
|
|
157
|
+
let i = e, a = D(e, "open"), o = r, s = i.defaultOpen, l = n(() => !i.disabled && (a.value ?? s)), u;
|
|
158
158
|
h(() => clearTimeout(u));
|
|
159
159
|
let d = (e) => {
|
|
160
160
|
clearTimeout(u), !(e && i.disabled) && e !== l.value && (a.value = e);
|
|
161
|
-
}, f = () => d(!0), m = () => d(!1), g = () => d(!l.value),
|
|
162
|
-
if (e.pointerType === "touch" || (
|
|
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
163
|
let t = e.type === "pointerenter" || k.contains(e.relatedTarget);
|
|
164
164
|
if (clearTimeout(u), t === l.value) return;
|
|
165
165
|
let { delay: n } = i, r = typeof n == "number" ? {
|
|
@@ -167,7 +167,7 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
167
167
|
close: n
|
|
168
168
|
} : n, a = (t ? r.open : r.close) ?? (t ? 300 : 150);
|
|
169
169
|
u = setTimeout(() => d(t), a);
|
|
170
|
-
},
|
|
170
|
+
}, x = ie({
|
|
171
171
|
isOpen: l,
|
|
172
172
|
placement: () => i.placement,
|
|
173
173
|
strategy: () => i.strategy,
|
|
@@ -175,17 +175,17 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
175
175
|
padding: () => i.padding,
|
|
176
176
|
matchWidth: () => i.matchWidth,
|
|
177
177
|
hideWhenDetached: () => i.hideWhenDetached
|
|
178
|
-
}),
|
|
179
|
-
...
|
|
178
|
+
}), C = /* @__PURE__ */ new Set(), T = c(z, null), k = {
|
|
179
|
+
...x,
|
|
180
180
|
isOpen: l,
|
|
181
|
-
disabled:
|
|
182
|
-
trigger:
|
|
183
|
-
floatingId: `${
|
|
184
|
-
referenceId:
|
|
185
|
-
floatingRole:
|
|
186
|
-
navigation:
|
|
187
|
-
focusRequest:
|
|
188
|
-
parent:
|
|
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,
|
|
189
189
|
skipFocusReturn: !1,
|
|
190
190
|
parts: {
|
|
191
191
|
reference: 0,
|
|
@@ -195,18 +195,18 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
195
195
|
open: f,
|
|
196
196
|
close: m,
|
|
197
197
|
toggle: g,
|
|
198
|
-
hover:
|
|
199
|
-
contains: (e) => e instanceof Node ?
|
|
200
|
-
registerChild: (e) => (
|
|
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))
|
|
201
201
|
};
|
|
202
|
-
|
|
202
|
+
T && h(T.registerChild(k)), _(z, k), p(() => k.isUnmounting = !0);
|
|
203
203
|
let A = (e) => {
|
|
204
204
|
let t = e.composedPath()[0] ?? e.target;
|
|
205
205
|
return K.findLast((e) => e.contains(t)) ?? K[K.length - 1];
|
|
206
206
|
}, j = (e) => {
|
|
207
207
|
e.key === "Escape" && A(e) === k && (!i.closeOnEscape || e.defaultPrevented || e.isComposing || (e.preventDefault(), m()));
|
|
208
208
|
}, M = (e) => {
|
|
209
|
-
k.contains(e) || (k.skipFocusReturn =
|
|
209
|
+
k.contains(e) || (k.skipFocusReturn = U(e), m());
|
|
210
210
|
}, N, P = (e) => {
|
|
211
211
|
if (N?.(), !i.closeOnClickOutside) return;
|
|
212
212
|
let t = e.composedPath()[0] ?? e.target;
|
|
@@ -224,13 +224,13 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
224
224
|
}, F = (e) => {
|
|
225
225
|
i.closeOnFocusOut && (k.contains(e.composedPath()[0] ?? e.target) || m());
|
|
226
226
|
};
|
|
227
|
-
return
|
|
227
|
+
return O(l, (e, t, n) => {
|
|
228
228
|
e && typeof document < "u" && (K.push(k), document.addEventListener("keydown", j), document.addEventListener("pointerdown", P, !0), document.addEventListener("focusin", F), n(() => {
|
|
229
229
|
document.removeEventListener("keydown", j), document.removeEventListener("pointerdown", P, !0), document.removeEventListener("focusin", F), N?.(), K.splice(K.indexOf(k), 1);
|
|
230
230
|
}));
|
|
231
|
-
}, { immediate: !0 }),
|
|
231
|
+
}, { immediate: !0 }), O(l, (e) => o(e ? "open" : "close")), O(x.referenceHidden, (e) => {
|
|
232
232
|
e && i.hideWhenDetached === "close" && m();
|
|
233
|
-
}),
|
|
233
|
+
}), O(() => i.disabled, (e) => {
|
|
234
234
|
e && (a.value ?? s) && (a.value = !1);
|
|
235
235
|
}), t({
|
|
236
236
|
get isOpen() {
|
|
@@ -239,40 +239,40 @@ var K = [], q = /* @__PURE__ */ s({
|
|
|
239
239
|
open: f,
|
|
240
240
|
close: m,
|
|
241
241
|
toggle: g,
|
|
242
|
-
update:
|
|
243
|
-
}), (e, t) =>
|
|
242
|
+
update: x.update
|
|
243
|
+
}), (e, t) => b(e.$slots, "default", {
|
|
244
244
|
isOpen: l.value,
|
|
245
245
|
open: f,
|
|
246
246
|
close: m,
|
|
247
247
|
toggle: g,
|
|
248
|
-
placement:
|
|
249
|
-
side:
|
|
250
|
-
align:
|
|
248
|
+
placement: w(x).placement.value,
|
|
249
|
+
side: w(x).side.value,
|
|
250
|
+
align: w(x).align.value,
|
|
251
251
|
floatingId: k.floatingId,
|
|
252
252
|
referenceId: k.referenceId.value
|
|
253
253
|
});
|
|
254
254
|
}
|
|
255
|
-
}),
|
|
255
|
+
}), q = {
|
|
256
256
|
dialog: "dialog",
|
|
257
257
|
alertdialog: "dialog",
|
|
258
258
|
menu: "menu",
|
|
259
259
|
listbox: "listbox",
|
|
260
260
|
tree: "tree",
|
|
261
261
|
grid: "grid"
|
|
262
|
-
},
|
|
262
|
+
}, J = {
|
|
263
263
|
menu: "[role=\"menuitem\"], [role=\"menuitemcheckbox\"], [role=\"menuitemradio\"]",
|
|
264
264
|
listbox: "[role=\"option\"]"
|
|
265
|
-
},
|
|
266
|
-
function
|
|
267
|
-
return [...e.querySelectorAll(
|
|
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));
|
|
268
268
|
}
|
|
269
|
-
var
|
|
269
|
+
var Y = (e) => e instanceof Element && !!e.closest("input, textarea, select, [contenteditable]:not([contenteditable=\"false\"])"), fe = (e) => getComputedStyle(e).direction === "rtl" ? {
|
|
270
270
|
open: "ArrowLeft",
|
|
271
271
|
close: "ArrowRight"
|
|
272
272
|
} : {
|
|
273
273
|
open: "ArrowRight",
|
|
274
274
|
close: "ArrowLeft"
|
|
275
|
-
},
|
|
275
|
+
}, X = /* @__PURE__ */ s({
|
|
276
276
|
__name: "SbReference",
|
|
277
277
|
props: {
|
|
278
278
|
as: { default: "button" },
|
|
@@ -280,26 +280,26 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
280
280
|
ariaHaspopup: { default: void 0 }
|
|
281
281
|
},
|
|
282
282
|
setup(e) {
|
|
283
|
-
let t = e, i =
|
|
283
|
+
let t = e, i = T(), a = ne("SbReference"), { isOpen: o, disabled: s, floatingId: c, floatingRole: l } = a, u = B(a, "reference", "SbReference"), d = [
|
|
284
284
|
"button",
|
|
285
285
|
"input",
|
|
286
286
|
"textarea",
|
|
287
287
|
"select"
|
|
288
|
-
], f = () => typeof t.as != "string" || d.includes(t.as) || t.as === "a" && i.href != null, h = `${
|
|
289
|
-
|
|
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(() => {
|
|
290
290
|
a.referenceId.value = _.value;
|
|
291
291
|
}), m(() => {
|
|
292
292
|
let e = a.reference.value;
|
|
293
|
-
e ?
|
|
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.");
|
|
294
294
|
}), p(() => {
|
|
295
295
|
a.referenceId.value === _.value && (a.referenceId.value = void 0), u(), !a.parts.reference && !a.isUnmounting && a.close();
|
|
296
296
|
});
|
|
297
|
-
let v = n(() => t.ariaHaspopup ?? (l.value && Object.hasOwn(
|
|
298
|
-
a.reference.value =
|
|
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
299
|
}, S = () => {
|
|
300
|
-
a.trigger.value === "click" && (
|
|
301
|
-
},
|
|
302
|
-
D() && !
|
|
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();
|
|
303
303
|
}, M = (e) => {
|
|
304
304
|
D() && !a.contains(e.relatedTarget) && a.close();
|
|
305
305
|
}, N = (e) => {
|
|
@@ -307,41 +307,41 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
307
307
|
n && (e.preventDefault(), n.focus());
|
|
308
308
|
}, P = (e) => {
|
|
309
309
|
if (a.navigation.value && !s.value && a.trigger.value !== "manual") {
|
|
310
|
-
if (
|
|
310
|
+
if (O()) {
|
|
311
311
|
let t = e.currentTarget;
|
|
312
|
-
return e.key ===
|
|
312
|
+
return e.key === fe(t).open ? "first" : void 0;
|
|
313
313
|
}
|
|
314
314
|
return e.key === "ArrowDown" ? "first" : e.key === "ArrowUp" ? "last" : void 0;
|
|
315
315
|
}
|
|
316
316
|
}, F = (e) => {
|
|
317
|
-
if (e.key === "Tab" && !e.shiftKey && o.value && !
|
|
317
|
+
if (e.key === "Tab" && !e.shiftKey && o.value && !O()) {
|
|
318
318
|
N(e);
|
|
319
319
|
return;
|
|
320
320
|
}
|
|
321
321
|
let t = P(e);
|
|
322
322
|
t ? (e.preventDefault(), a.focusRequest.value = t, a.open()) : f() || e.key !== "Enter" && e.key !== " " || (e.preventDefault(), S());
|
|
323
323
|
};
|
|
324
|
-
return (e, n) => (g(), r(
|
|
324
|
+
return (e, n) => (g(), r(x(t.as), {
|
|
325
325
|
id: _.value,
|
|
326
|
-
ref:
|
|
326
|
+
ref: y,
|
|
327
327
|
type: t.as === "button" ? "button" : void 0,
|
|
328
328
|
role: f() ? void 0 : "button",
|
|
329
|
-
tabindex: f() ? void 0 :
|
|
330
|
-
disabled: t.as === "button" &&
|
|
331
|
-
"aria-disabled": t.as !== "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,
|
|
332
332
|
"aria-haspopup": v.value,
|
|
333
|
-
"aria-expanded":
|
|
334
|
-
"aria-controls":
|
|
335
|
-
"aria-describedby":
|
|
336
|
-
"data-sbf-state":
|
|
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
337
|
onClick: S,
|
|
338
338
|
onKeydown: F,
|
|
339
339
|
onFocusin: j,
|
|
340
340
|
onFocusout: M,
|
|
341
|
-
onPointerenter:
|
|
342
|
-
onPointerleave:
|
|
341
|
+
onPointerenter: w(a).hover,
|
|
342
|
+
onPointerleave: w(a).hover
|
|
343
343
|
}, {
|
|
344
|
-
default:
|
|
344
|
+
default: A(() => [b(e.$slots, "default")]),
|
|
345
345
|
_: 3
|
|
346
346
|
}, 40, [
|
|
347
347
|
"id",
|
|
@@ -359,7 +359,7 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
359
359
|
"onPointerleave"
|
|
360
360
|
]));
|
|
361
361
|
}
|
|
362
|
-
}),
|
|
362
|
+
}), pe = ":disabled, [aria-disabled=\"true\"], [aria-haspopup]:not([aria-haspopup=\"false\"])", me = /* @__PURE__ */ s({
|
|
363
363
|
inheritAttrs: !1,
|
|
364
364
|
__name: "SbFloating",
|
|
365
365
|
props: {
|
|
@@ -378,30 +378,34 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
378
378
|
keyboardNavigation: {
|
|
379
379
|
type: Boolean,
|
|
380
380
|
default: !0
|
|
381
|
+
},
|
|
382
|
+
closeOnSelect: {
|
|
383
|
+
type: Boolean,
|
|
384
|
+
default: !1
|
|
381
385
|
}
|
|
382
386
|
},
|
|
383
387
|
emits: ["after-enter", "after-leave"],
|
|
384
388
|
setup(s, { emit: c }) {
|
|
385
|
-
let l = s, _ = c,
|
|
386
|
-
p(
|
|
387
|
-
let { isOpen:
|
|
388
|
-
|
|
389
|
-
S.floatingRole.value = l.role, S.navigation.value = l.keyboardNavigation &&
|
|
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;
|
|
390
394
|
}), m(() => {
|
|
391
|
-
l.role === "tooltip" && S.trigger.value === "click" &&
|
|
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.");
|
|
392
396
|
});
|
|
393
|
-
let N =
|
|
397
|
+
let N = y(C.value), P = y(null), F = (e) => {
|
|
394
398
|
S.floating.value = e instanceof HTMLElement ? e : null;
|
|
395
399
|
}, ee = (e) => {
|
|
396
|
-
P.value =
|
|
400
|
+
P.value = se(e);
|
|
397
401
|
}, te = n(() => ({
|
|
398
402
|
...S.floatingStyles.value,
|
|
399
403
|
...l.zIndex === void 0 ? {} : { zIndex: l.zIndex }
|
|
400
404
|
})), I = () => ({
|
|
401
|
-
"aria-labelledby": l.role && Object.hasOwn(
|
|
402
|
-
...
|
|
403
|
-
}),
|
|
404
|
-
[
|
|
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]: "",
|
|
405
409
|
tabindex: 0,
|
|
406
410
|
style: {
|
|
407
411
|
position: "fixed",
|
|
@@ -412,73 +416,87 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
412
416
|
}, re = n(() => {
|
|
413
417
|
let { transition: e } = l;
|
|
414
418
|
return e ? typeof e == "string" ? { name: e } : e : { css: !1 };
|
|
415
|
-
}),
|
|
416
|
-
|
|
417
|
-
},
|
|
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) => {
|
|
418
422
|
let t = P.value;
|
|
419
423
|
if (!t) return;
|
|
420
424
|
let n = W(t);
|
|
421
425
|
((e === "first" ? n[0] : n[n.length - 1]) ?? t).focus({ preventScroll: !0 });
|
|
422
|
-
},
|
|
423
|
-
|
|
424
|
-
},
|
|
425
|
-
if (!
|
|
426
|
-
|
|
426
|
+
}, le = (e) => {
|
|
427
|
+
U(e.relatedTarget) ? S.reference.value?.focus() : K("first");
|
|
428
|
+
}, J = (e) => {
|
|
429
|
+
if (!U(e.relatedTarget)) {
|
|
430
|
+
K("last");
|
|
427
431
|
return;
|
|
428
432
|
}
|
|
429
433
|
let t = S.reference.value;
|
|
430
434
|
((t && G(t, (e) => S.contains(e))) ?? t)?.focus();
|
|
431
|
-
},
|
|
435
|
+
}, X = () => {
|
|
432
436
|
let e = S.navigation.value;
|
|
433
|
-
return P.value && e ?
|
|
434
|
-
},
|
|
437
|
+
return P.value && e ? de(P.value, e) : [];
|
|
438
|
+
}, me = {
|
|
439
|
+
menu: "[role=\"menuitem\"]",
|
|
440
|
+
listbox: "[role=\"option\"]"
|
|
441
|
+
}, he = {
|
|
435
442
|
menu: "role=\"menuitem\", \"menuitemcheckbox\" or \"menuitemradio\"",
|
|
436
443
|
listbox: "role=\"option\""
|
|
437
|
-
},
|
|
444
|
+
}, ge = !1, _e = (e) => {
|
|
438
445
|
let t = S.navigation.value;
|
|
439
|
-
if (
|
|
440
|
-
let n = e.length ? e.every(
|
|
441
|
-
n && (
|
|
442
|
-
},
|
|
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) => {
|
|
443
450
|
let t = P.value;
|
|
444
451
|
if (!t) return;
|
|
445
|
-
let n =
|
|
446
|
-
e &&
|
|
447
|
-
},
|
|
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 = () => {
|
|
448
455
|
let e = S.focusRequest.value;
|
|
449
456
|
return S.focusRequest.value = null, e;
|
|
450
457
|
}, Q = "", $;
|
|
451
458
|
h(() => clearTimeout($));
|
|
452
|
-
let
|
|
459
|
+
let ye = (e, t, n) => {
|
|
453
460
|
Q += n.toLowerCase(), clearTimeout($), $ = setTimeout(() => Q = "", 500);
|
|
454
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)];
|
|
455
462
|
return r.length === 1 && t >= 0 && a.push(a.shift()), a.find((e) => e.textContent?.trim().toLowerCase().startsWith(r));
|
|
456
|
-
},
|
|
457
|
-
let
|
|
458
|
-
for (;
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
+
}, be = () => {
|
|
464
|
+
let e = [S];
|
|
465
|
+
for (; e[e.length - 1].parent?.navigation.value === "menu";) e.push(e[e.length - 1].parent);
|
|
466
|
+
return e;
|
|
467
|
+
}, xe = (e, t) => {
|
|
468
|
+
for (let t of e) t.skipFocusReturn = !0, t.close();
|
|
469
|
+
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) => {
|
|
474
|
+
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]);
|
|
477
|
+
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) => {
|
|
463
481
|
let t = S.navigation.value;
|
|
464
|
-
if (!t || e.defaultPrevented || e.isComposing ||
|
|
465
|
-
let n =
|
|
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;
|
|
466
484
|
if ([
|
|
467
485
|
"ArrowDown",
|
|
468
486
|
"ArrowUp",
|
|
469
487
|
"Home",
|
|
470
488
|
"End"
|
|
471
|
-
].includes(e.key) &&
|
|
489
|
+
].includes(e.key) && _e(n), e.key === "ArrowDown") o = n[r < i ? r + 1 : a ? 0 : i];
|
|
472
490
|
else if (e.key === "ArrowUp") o = n[r > 0 ? r - 1 : a || r < 0 ? i : 0];
|
|
473
491
|
else if (e.key === "Home") o = n[0];
|
|
474
492
|
else if (e.key === "End") o = n[i];
|
|
475
493
|
else if (e.key === "Tab" && t === "menu") {
|
|
476
|
-
e.preventDefault(),
|
|
494
|
+
e.preventDefault(), Se(e.shiftKey);
|
|
477
495
|
return;
|
|
478
|
-
} else if (t === "menu" && S.parent?.navigation.value === "menu" && P.value && e.key ===
|
|
496
|
+
} else if (t === "menu" && S.parent?.navigation.value === "menu" && P.value && e.key === fe(P.value).close) {
|
|
479
497
|
e.preventDefault(), S.close();
|
|
480
498
|
return;
|
|
481
|
-
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && (e.key !== " " || Q)) e.preventDefault(), o =
|
|
499
|
+
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && (e.key !== " " || Q)) e.preventDefault(), o = ye(n, r, e.key);
|
|
482
500
|
else if ((e.key === "Enter" || e.key === " ") && e.target === n[r]) {
|
|
483
501
|
let t = n[r];
|
|
484
502
|
if (t.matches("button, a[href], input, summary")) return;
|
|
@@ -487,7 +505,7 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
487
505
|
}
|
|
488
506
|
o && (e.preventDefault(), o.focus());
|
|
489
507
|
};
|
|
490
|
-
return
|
|
508
|
+
return O(C, (e) => {
|
|
491
509
|
let t = S.skipFocusReturn;
|
|
492
510
|
if (S.skipFocusReturn = !1, e) {
|
|
493
511
|
N.value = !0;
|
|
@@ -495,12 +513,12 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
495
513
|
}
|
|
496
514
|
let n = document.activeElement;
|
|
497
515
|
!t && n && S.floating.value?.contains(n) && S.reference.value?.focus({ preventScroll: !0 });
|
|
498
|
-
}),
|
|
516
|
+
}), O(() => C.value && S.isPositioned.value, async (e) => {
|
|
499
517
|
if (!e) return;
|
|
500
|
-
let t =
|
|
501
|
-
(t ||
|
|
502
|
-
}),
|
|
503
|
-
e &&
|
|
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());
|
|
504
522
|
}), (n, s) => (g(), r(e, {
|
|
505
523
|
to: l.teleport || "body",
|
|
506
524
|
disabled: l.teleport === !1
|
|
@@ -508,27 +526,28 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
508
526
|
key: 0,
|
|
509
527
|
ref: F,
|
|
510
528
|
style: f(te.value),
|
|
511
|
-
onPointerenter: s[0] ||= (...e) =>
|
|
512
|
-
onPointerleave: s[1] ||= (...e) =>
|
|
529
|
+
onPointerenter: s[0] ||= (...e) => w(S).hover && w(S).hover(...e),
|
|
530
|
+
onPointerleave: s[1] ||= (...e) => w(S).hover && w(S).hover(...e)
|
|
513
531
|
}, [
|
|
514
|
-
|
|
532
|
+
z.value ? (g(), a("span", u({ key: 0 }, V, { onFocus: le }), null, 16)) : i("", !0),
|
|
515
533
|
o(t, u(re.value, {
|
|
516
534
|
appear: "",
|
|
517
|
-
onBeforeLeave:
|
|
518
|
-
onAfterEnter:
|
|
535
|
+
onBeforeLeave: ie,
|
|
536
|
+
onAfterEnter: H,
|
|
519
537
|
onAfterLeave: oe
|
|
520
538
|
}), {
|
|
521
|
-
default:
|
|
522
|
-
id:
|
|
539
|
+
default: A(() => [w(C) ? (g(), r(x(l.as), u({ key: 0 }, I(), {
|
|
540
|
+
id: w(E),
|
|
523
541
|
ref: ee,
|
|
524
542
|
role: l.role ?? void 0,
|
|
525
|
-
tabindex:
|
|
543
|
+
tabindex: L.value ? -1 : void 0,
|
|
526
544
|
"data-sbf-state": "open",
|
|
527
|
-
"data-sbf-side":
|
|
528
|
-
"data-sbf-align":
|
|
529
|
-
onKeydown:
|
|
545
|
+
"data-sbf-side": w(j),
|
|
546
|
+
"data-sbf-align": w(M),
|
|
547
|
+
onKeydown: we,
|
|
548
|
+
onClick: Ce
|
|
530
549
|
}), {
|
|
531
|
-
default:
|
|
550
|
+
default: A(() => [b(n.$slots, "default")]),
|
|
532
551
|
_: 3
|
|
533
552
|
}, 16, [
|
|
534
553
|
"id",
|
|
@@ -539,9 +558,22 @@ var X = (e) => e instanceof Element && !!e.closest("input, textarea, select, [co
|
|
|
539
558
|
])) : i("", !0)]),
|
|
540
559
|
_: 3
|
|
541
560
|
}, 16),
|
|
542
|
-
|
|
561
|
+
z.value ? (g(), a("span", u({ key: 1 }, V, { onFocus: J }), null, 16)) : i("", !0)
|
|
543
562
|
], 36)) : i("", !0)], 8, ["to", "disabled"]));
|
|
544
563
|
}
|
|
545
564
|
});
|
|
546
565
|
//#endregion
|
|
547
|
-
|
|
566
|
+
//#region src/composables/useSbFloating.ts
|
|
567
|
+
function he() {
|
|
568
|
+
let e = c(z, null);
|
|
569
|
+
if (!e) throw Error("[sb-floating-panel-vue] useSbFloating() must be called in a component inside <SbContainer>.");
|
|
570
|
+
let { isOpen: t, open: n, close: r, toggle: i } = e;
|
|
571
|
+
return {
|
|
572
|
+
isOpen: v(t),
|
|
573
|
+
open: n,
|
|
574
|
+
close: r,
|
|
575
|
+
toggle: i
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
//#endregion
|
|
579
|
+
export { le as SbContainer, me as SbFloating, X as SbReference, he as useSbFloating };
|
|
@@ -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=(()=>{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]`)}var g=e=>e.matches(f)&&!e.closest(`[inert]`);function _(e){return[...e.querySelectorAll(f)].filter(p)}function v(e,t){return _(e.ownerDocument).find(n=>!!(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)&&!e.contains(n)&&!t(n))}var y=[],b=(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)},v=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={...v,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?v.reference.value?.contains(e)||v.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 y.findLast(e=>e.contains(t))??y[y.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`&&(y.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?.(),y.splice(y.indexOf(S),1)}))},{immediate:!0}),(0,t.watch)(l,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 l.value},open:p,close:m,toggle:g,update:v.update}),(e,n)=>(0,t.renderSlot)(e.$slots,`default`,{isOpen:l.value,open:p,close:m,toggle:g,placement:(0,t.unref)(v).placement.value,side:(0,t.unref)(v).side.value,align:(0,t.unref)(v).align.value,floatingId:S.floatingId,referenceId:S.referenceId.value})}}),x={dialog:`dialog`,alertdialog:`dialog`,menu:`menu`,listbox:`listbox`,tree:`tree`,grid:`grid`},S={menu:`[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]`,listbox:`[role="option"]`},C=e=>!!e&&Object.hasOwn(S,e);function w(e,t){return[...e.querySelectorAll(S[t])].filter(n=>n.closest(`[role="${t}"]`)===e&&!n.matches(`:disabled`)&&(n.checkVisibility?.()??!0))}var T=e=>e instanceof Element&&!!e.closest(`input, textarea, select, [contenteditable]:not([contenteditable="false"])`),E=e=>getComputedStyle(e).direction===`rtl`?{open:`ArrowLeft`,close:`ArrowRight`}:{open:`ArrowRight`,close:`ArrowLeft`},D=(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=[`button`,`input`,`textarea`,`select`],h=()=>typeof n.as!=`string`||p.includes(n.as)||n.as===`a`&&r.href!=null,g=`${(0,t.useId)()}-reference`,v=(0,t.computed)(()=>n.id??g);(0,t.watchEffect)(()=>{a.referenceId.value=v.value}),(0,t.onMounted)(()=>{let e=a.reference.value;e?T(e)&&a.navigation.value&&i(`<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.`):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===v.value&&(a.referenceId.value=void 0),f(),!a.parts.reference&&!a.isUnmounting&&a.close()});let y=(0,t.computed)(()=>n.ariaHaspopup??(d.value&&Object.hasOwn(x,d.value)?x[d.value]:void 0)),b=e=>{a.reference.value=m(e)},S=()=>{a.trigger.value===`click`&&(T(a.reference.value)?a.open():a.toggle())},C=(0,t.computed)(()=>d.value===`tooltip`),w=()=>a.trigger.value===`hover`||a.trigger.value===`focus`,D=()=>a.parent?.navigation.value===`menu`,O=e=>{w()&&!D()&&!a.contains(e.relatedTarget)&&a.open()},k=e=>{w()&&!a.contains(e.relatedTarget)&&a.close()},A=e=>{let t=a.floating.value,n=t&&_(t)[0];n&&(e.preventDefault(),n.focus())},j=e=>{if(a.navigation.value&&!l.value&&a.trigger.value!==`manual`){if(D()){let t=e.currentTarget;return e.key===E(t).open?`first`:void 0}return e.key===`ArrowDown`?`first`:e.key===`ArrowUp`?`last`:void 0}},M=e=>{if(e.key===`Tab`&&!e.shiftKey&&c.value&&!D()){A(e);return}let t=j(e);t?(e.preventDefault(),a.focusRequest.value=t,a.open()):h()||e.key!==`Enter`&&e.key!==` `||(e.preventDefault(),S())};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)(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":y.value,"aria-expanded":C.value?void 0:(0,t.unref)(c)?`true`:`false`,"aria-controls":(0,t.unref)(c)&&!C.value?(0,t.unref)(u):void 0,"aria-describedby":(0,t.unref)(c)&&C.value?(0,t.unref)(u):void 0,"data-sbf-state":(0,t.unref)(c)?`open`:`closed`,onClick:S,onKeydown:M,onFocusin:O,onFocusout:k,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`]))}}),O=(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,a=n,c=(0,t.useAttrs)(),l=s(`SbFloating`);(0,t.onBeforeUnmount)(o(l,`floating`,`SbFloating`));let{isOpen:u,floatingId:f,referenceId:p,side:h,align:y}=l;(0,t.watchEffect)(()=>{l.floatingRole.value=r.role,l.navigation.value=r.keyboardNavigation&&C(r.role)?r.role:null}),(0,t.onMounted)(()=>{r.role===`tooltip`&&l.trigger.value===`click`&&i(`<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.`)});let b=(0,t.ref)(u.value),S=(0,t.ref)(null),D=e=>{l.floating.value=e instanceof HTMLElement?e:null},O=e=>{S.value=m(e)},k=(0,t.computed)(()=>({...l.floatingStyles.value,...r.zIndex===void 0?{}:{zIndex:r.zIndex}})),A=()=>({"aria-labelledby":r.role&&Object.hasOwn(x,r.role)&&c[`aria-label`]==null?p.value:void 0,...c}),j=(0,t.computed)(()=>r.autoFocus??(r.role!==`tooltip`&&l.trigger.value!==`hover`&&l.trigger.value!==`focus`&&!T(l.reference.value))),M=(0,t.computed)(()=>u.value&&r.teleport!==!1&&r.role!==`tooltip`),N={[d]:``,tabindex:0,style:{position:`fixed`,opacity:0,outline:`none`,pointerEvents:`none`}},P=(0,t.computed)(()=>{let{transition:e}=r;return e?typeof e==`string`?{name:e}:e:{css:!1}}),F=e=>e.setAttribute(`data-sbf-state`,`closed`),I=()=>a(`after-enter`),L=()=>{u.value||(b.value=!1),a(`after-leave`)},R=e=>e instanceof Node&&!!S.value?.contains(e),z=e=>{let t=S.value;if(!t)return;let n=_(t);((e===`first`?n[0]:n[n.length-1])??t).focus({preventScroll:!0})},B=e=>{R(e.relatedTarget)?l.reference.value?.focus():z(`first`)},V=e=>{if(!R(e.relatedTarget)){z(`last`);return}let t=l.reference.value;((t&&v(t,e=>l.contains(e)))??t)?.focus()},H=()=>{let e=l.navigation.value;return S.value&&e?w(S.value,e):[]},U={menu:`role="menuitem", "menuitemcheckbox" or "menuitemradio"`,listbox:`role="option"`},W=!1,G=e=>{let t=l.navigation.value;if(W||!t)return;let n=e.length?e.every(g)?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 ${U[t]} and must not be disabled.`;n&&(W=!0,i(`<SbFloating role="${t}"> ${n}`))},K=e=>{let t=S.value;if(!t)return;let n=H();e&&G(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]??_(t)[0]??t).focus({preventScroll:!0})},q=()=>{let e=l.focusRequest.value;return l.focusRequest.value=null,e},J=``,Y;(0,t.onScopeDispose)(()=>clearTimeout(Y));let X=(e,t,n)=>{J+=n.toLowerCase(),clearTimeout(Y),Y=setTimeout(()=>J=``,500);let r=[...J].every(e=>e===J[0])?J[0]:J,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))},Z=e=>{let t=l,n=[t];for(;t.parent?.navigation.value===`menu`;)t=t.parent,n.push(t);let r=t.reference.value,i=e?r:(r&&v(r,e=>t.contains(e)))??r;for(let e of n)e.skipFocusReturn=!0,e.close();i?.focus()},Q=e=>{let t=l.navigation.value;if(!t||e.defaultPrevented||e.isComposing||T(e.target))return;let n=H(),r=n.findIndex(t=>t.contains(e.target)),i=n.length-1,a=t===`menu`,o;if([`ArrowDown`,`ArrowUp`,`Home`,`End`].includes(e.key)&&G(n),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(),Z(e.shiftKey);return}else if(t===`menu`&&l.parent?.navigation.value===`menu`&&S.value&&e.key===E(S.value).close){e.preventDefault(),l.close();return}else if(e.key.length===1&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&(e.key!==` `||J))e.preventDefault(),o=X(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)(u,e=>{let t=l.skipFocusReturn;if(l.skipFocusReturn=!1,e){b.value=!0;return}let n=document.activeElement;!t&&n&&l.floating.value?.contains(n)&&l.reference.value?.focus({preventScroll:!0})}),(0,t.watch)(()=>u.value&&l.isPositioned.value,async e=>{if(!e)return;let n=q();(n||j.value)&&(await(0,t.nextTick)(),K(n))}),(0,t.watch)(l.focusRequest,e=>{e&&u.value&&l.isPositioned.value&&K(q())}),(e,n)=>((0,t.openBlock)(),(0,t.createBlock)(t.Teleport,{to:r.teleport||`body`,disabled:r.teleport===!1},[b.value?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{key:0,ref:D,style:(0,t.normalizeStyle)(k.value),onPointerenter:n[0]||=(...e)=>(0,t.unref)(l).hover&&(0,t.unref)(l).hover(...e),onPointerleave:n[1]||=(...e)=>(0,t.unref)(l).hover&&(0,t.unref)(l).hover(...e)},[M.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:0},N,{onFocus:B}),null,16)):(0,t.createCommentVNode)(``,!0),(0,t.createVNode)(t.Transition,(0,t.mergeProps)(P.value,{appear:``,onBeforeLeave:F,onAfterEnter:I,onAfterLeave:L}),{default:(0,t.withCtx)(()=>[(0,t.unref)(u)?((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(r.as),(0,t.mergeProps)({key:0},A(),{id:(0,t.unref)(f),ref:O,role:r.role??void 0,tabindex:j.value?-1:void 0,"data-sbf-state":`open`,"data-sbf-side":(0,t.unref)(h),"data-sbf-align":(0,t.unref)(y),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),M.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:1},N,{onFocus:V}),null,16)):(0,t.createCommentVNode)(``,!0)],36)):(0,t.createCommentVNode)(``,!0)],8,[`to`,`disabled`]))}});e.SbContainer=b,e.SbFloating=O,e.SbReference=D});
|
|
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]`)}var g=e=>e.matches(f)&&!e.closest(`[inert]`);function _(e){return[...e.querySelectorAll(f)].filter(p)}function v(e,t){return _(e.ownerDocument).find(n=>!!(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)&&!e.contains(n)&&!t(n))}var y=[],b=(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)},v=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={...v,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?v.reference.value?.contains(e)||v.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 y.findLast(e=>e.contains(t))??y[y.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`&&(y.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?.(),y.splice(y.indexOf(S),1)}))},{immediate:!0}),(0,t.watch)(l,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 l.value},open:p,close:m,toggle:g,update:v.update}),(e,n)=>(0,t.renderSlot)(e.$slots,`default`,{isOpen:l.value,open:p,close:m,toggle:g,placement:(0,t.unref)(v).placement.value,side:(0,t.unref)(v).side.value,align:(0,t.unref)(v).align.value,floatingId:S.floatingId,referenceId:S.referenceId.value})}}),x={dialog:`dialog`,alertdialog:`dialog`,menu:`menu`,listbox:`listbox`,tree:`tree`,grid:`grid`},S={menu:`[role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"]`,listbox:`[role="option"]`},C=e=>!!e&&Object.hasOwn(S,e);function w(e,t){return[...e.querySelectorAll(S[t])].filter(n=>n.closest(`[role="${t}"]`)===e&&!n.matches(`:disabled`)&&(n.checkVisibility?.()??!0))}var T=e=>e instanceof Element&&!!e.closest(`input, textarea, select, [contenteditable]:not([contenteditable="false"])`),E=e=>getComputedStyle(e).direction===`rtl`?{open:`ArrowLeft`,close:`ArrowRight`}:{open:`ArrowRight`,close:`ArrowLeft`},D=(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=[`button`,`input`,`textarea`,`select`],h=()=>typeof n.as!=`string`||p.includes(n.as)||n.as===`a`&&r.href!=null,g=`${(0,t.useId)()}-reference`,v=(0,t.computed)(()=>n.id??g);(0,t.watchEffect)(()=>{a.referenceId.value=v.value}),(0,t.onMounted)(()=>{let e=a.reference.value;e?T(e)&&a.navigation.value&&i(`<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.`):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===v.value&&(a.referenceId.value=void 0),f(),!a.parts.reference&&!a.isUnmounting&&a.close()});let y=(0,t.computed)(()=>n.ariaHaspopup??(d.value&&Object.hasOwn(x,d.value)?x[d.value]:void 0)),b=e=>{a.reference.value=m(e)},S=()=>{a.trigger.value===`click`&&(T(a.reference.value)?a.open():a.toggle())},C=(0,t.computed)(()=>d.value===`tooltip`),w=()=>a.trigger.value===`hover`||a.trigger.value===`focus`,D=()=>a.parent?.navigation.value===`menu`,O=e=>{w()&&!D()&&!a.contains(e.relatedTarget)&&a.open()},k=e=>{w()&&!a.contains(e.relatedTarget)&&a.close()},A=e=>{let t=a.floating.value,n=t&&_(t)[0];n&&(e.preventDefault(),n.focus())},j=e=>{if(a.navigation.value&&!l.value&&a.trigger.value!==`manual`){if(D()){let t=e.currentTarget;return e.key===E(t).open?`first`:void 0}return e.key===`ArrowDown`?`first`:e.key===`ArrowUp`?`last`:void 0}},M=e=>{if(e.key===`Tab`&&!e.shiftKey&&c.value&&!D()){A(e);return}let t=j(e);t?(e.preventDefault(),a.focusRequest.value=t,a.open()):h()||e.key!==`Enter`&&e.key!==` `||(e.preventDefault(),S())};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)(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":y.value,"aria-expanded":C.value?void 0:(0,t.unref)(c)?`true`:`false`,"aria-controls":(0,t.unref)(c)&&!C.value?(0,t.unref)(u):void 0,"aria-describedby":(0,t.unref)(c)&&C.value?(0,t.unref)(u):void 0,"data-sbf-state":(0,t.unref)(c)?`open`:`closed`,onClick:S,onKeydown:M,onFocusin:O,onFocusout:k,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`]))}}),O=`:disabled, [aria-disabled="true"], [aria-haspopup]:not([aria-haspopup="false"])`,k=(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},closeOnSelect:{type:Boolean,default:!1}},emits:[`after-enter`,`after-leave`],setup(e,{emit:n}){let r=e,a=n,c=(0,t.useAttrs)(),l=s(`SbFloating`);(0,t.onBeforeUnmount)(o(l,`floating`,`SbFloating`));let{isOpen:u,floatingId:f,referenceId:p,side:h,align:y}=l;(0,t.watchEffect)(()=>{l.floatingRole.value=r.role,l.navigation.value=r.keyboardNavigation&&C(r.role)?r.role:null}),(0,t.onMounted)(()=>{r.role===`tooltip`&&l.trigger.value===`click`&&i(`<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.`)});let b=(0,t.ref)(u.value),S=(0,t.ref)(null),D=e=>{l.floating.value=e instanceof HTMLElement?e:null},k=e=>{S.value=m(e)},A=(0,t.computed)(()=>({...l.floatingStyles.value,...r.zIndex===void 0?{}:{zIndex:r.zIndex}})),j=()=>({"aria-labelledby":r.role&&Object.hasOwn(x,r.role)&&c[`aria-label`]==null?p.value:void 0,...c}),M=(0,t.computed)(()=>r.autoFocus??(r.role!==`tooltip`&&l.trigger.value!==`hover`&&l.trigger.value!==`focus`&&!T(l.reference.value))),N=(0,t.computed)(()=>u.value&&r.teleport!==!1&&r.role!==`tooltip`),P={[d]:``,tabindex:0,style:{position:`fixed`,opacity:0,outline:`none`,pointerEvents:`none`}},F=(0,t.computed)(()=>{let{transition:e}=r;return e?typeof e==`string`?{name:e}:e:{css:!1}}),I=e=>e.setAttribute(`data-sbf-state`,`closed`),L=()=>a(`after-enter`),R=()=>{u.value||(b.value=!1),a(`after-leave`)},z=e=>e instanceof Node&&!!S.value?.contains(e),B=e=>{let t=S.value;if(!t)return;let n=_(t);((e===`first`?n[0]:n[n.length-1])??t).focus({preventScroll:!0})},V=e=>{z(e.relatedTarget)?l.reference.value?.focus():B(`first`)},H=e=>{if(!z(e.relatedTarget)){B(`last`);return}let t=l.reference.value;((t&&v(t,e=>l.contains(e)))??t)?.focus()},U=()=>{let e=l.navigation.value;return S.value&&e?w(S.value,e):[]},W={menu:`[role="menuitem"]`,listbox:`[role="option"]`},G={menu:`role="menuitem", "menuitemcheckbox" or "menuitemradio"`,listbox:`role="option"`},K=!1,q=e=>{let t=l.navigation.value;if(K||!t)return;let n=e.length?e.every(g)?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 ${G[t]} and must not be disabled.`;n&&(K=!0,i(`<SbFloating role="${t}"> ${n}`))},J=e=>{let t=S.value;if(!t)return;let n=U();e&&q(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]??_(t)[0]??t).focus({preventScroll:!0})},Y=()=>{let e=l.focusRequest.value;return l.focusRequest.value=null,e},X=``,Z;(0,t.onScopeDispose)(()=>clearTimeout(Z));let ee=(e,t,n)=>{X+=n.toLowerCase(),clearTimeout(Z),Z=setTimeout(()=>X=``,500);let r=[...X].every(e=>e===X[0])?X[0]:X,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))},Q=()=>{let e=[l];for(;e[e.length-1].parent?.navigation.value===`menu`;)e.push(e[e.length-1].parent);return e},$=(e,t)=>{for(let t of e)t.skipFocusReturn=!0,t.close();t?.focus({preventScroll:!0})},te=e=>{let t=Q(),n=t[t.length-1],r=n.reference.value,i=e?r:(r&&v(r,e=>n.contains(e)))??r;$(t,i)},ne=e=>{let{role:t}=r,n=S.value;if(!r.closeOnSelect||e.defaultPrevented||!n||!C(t))return;let i=e.target.closest(W[t]);if(!i||i.closest(`[role="${t}"]`)!==n||i.matches(O)||t===`listbox`&&n.getAttribute(`aria-multiselectable`)===`true`)return;let a=t===`menu`?Q():[l];$(a,a[a.length-1].reference.value)},re=e=>{let t=l.navigation.value;if(!t||e.defaultPrevented||e.isComposing||T(e.target))return;let n=U(),r=n.findIndex(t=>t.contains(e.target)),i=n.length-1,a=t===`menu`,o;if([`ArrowDown`,`ArrowUp`,`Home`,`End`].includes(e.key)&&q(n),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(),te(e.shiftKey);return}else if(t===`menu`&&l.parent?.navigation.value===`menu`&&S.value&&e.key===E(S.value).close){e.preventDefault(),l.close();return}else if(e.key.length===1&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&(e.key!==` `||X))e.preventDefault(),o=ee(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)(u,e=>{let t=l.skipFocusReturn;if(l.skipFocusReturn=!1,e){b.value=!0;return}let n=document.activeElement;!t&&n&&l.floating.value?.contains(n)&&l.reference.value?.focus({preventScroll:!0})}),(0,t.watch)(()=>u.value&&l.isPositioned.value,async e=>{if(!e)return;let n=Y();(n||M.value)&&(await(0,t.nextTick)(),J(n))}),(0,t.watch)(l.focusRequest,e=>{e&&u.value&&l.isPositioned.value&&J(Y())}),(e,n)=>((0,t.openBlock)(),(0,t.createBlock)(t.Teleport,{to:r.teleport||`body`,disabled:r.teleport===!1},[b.value?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{key:0,ref:D,style:(0,t.normalizeStyle)(A.value),onPointerenter:n[0]||=(...e)=>(0,t.unref)(l).hover&&(0,t.unref)(l).hover(...e),onPointerleave:n[1]||=(...e)=>(0,t.unref)(l).hover&&(0,t.unref)(l).hover(...e)},[N.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:0},P,{onFocus:V}),null,16)):(0,t.createCommentVNode)(``,!0),(0,t.createVNode)(t.Transition,(0,t.mergeProps)(F.value,{appear:``,onBeforeLeave:I,onAfterEnter:L,onAfterLeave:R}),{default:(0,t.withCtx)(()=>[(0,t.unref)(u)?((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(r.as),(0,t.mergeProps)({key:0},j(),{id:(0,t.unref)(f),ref:k,role:r.role??void 0,tabindex:M.value?-1:void 0,"data-sbf-state":`open`,"data-sbf-side":(0,t.unref)(h),"data-sbf-align":(0,t.unref)(y),onKeydown:re,onClick:ne}),{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),N.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:1},P,{onFocus:H}),null,16)):(0,t.createCommentVNode)(``,!0)],36)):(0,t.createCommentVNode)(``,!0)],8,[`to`,`disabled`]))}});function A(){let e=(0,t.inject)(a,null);if(!e)throw Error(`[sb-floating-panel-vue] useSbFloating() must be called in a component inside <SbContainer>.`);let{isOpen:n,open:r,close:i,toggle:o}=e;return{isOpen:(0,t.readonly)(n),open:r,close:i,toggle:o}}e.SbContainer=b,e.SbFloating=k,e.SbReference=D,e.useSbFloating=A});
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, TransitionProps } from 'vue';
|
|
1
|
+
import { Component, Ref, TransitionProps } from 'vue';
|
|
2
2
|
/** Side of the reference the panel is placed on. */
|
|
3
3
|
export type SbSide = 'top' | 'right' | 'bottom' | 'left';
|
|
4
4
|
/** Alignment of the panel along the side. */
|
|
@@ -246,4 +246,26 @@ export interface SbFloatingProps {
|
|
|
246
246
|
* @default true
|
|
247
247
|
*/
|
|
248
248
|
keyboardNavigation?: boolean;
|
|
249
|
+
/**
|
|
250
|
+
* With `role="menu"` or `role="listbox"`: activating an item (click, Enter or Space) closes
|
|
251
|
+
* the panel and gives focus back to the reference, after the `click` handler of the item.
|
|
252
|
+
* - Menu: `menuitem` items, not `menuitemcheckbox` / `menuitemradio` nor submenu triggers.
|
|
253
|
+
* The menus it opened from close too.
|
|
254
|
+
* - Listbox: `option` items, unless the listbox is `aria-multiselectable="true"`.
|
|
255
|
+
*
|
|
256
|
+
* Disabled items are left out. Call `event.preventDefault()` in the `click` handler of an
|
|
257
|
+
* item to keep the panel open.
|
|
258
|
+
* @default false
|
|
259
|
+
*/
|
|
260
|
+
closeOnSelect?: boolean;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Returned by `useSbFloating()`: the open state of the closest `SbContainer` and its actions.
|
|
264
|
+
*/
|
|
265
|
+
export interface UseSbFloatingReturn {
|
|
266
|
+
/** Whether the panel is open. */
|
|
267
|
+
isOpen: Readonly<Ref<boolean>>;
|
|
268
|
+
open: () => void;
|
|
269
|
+
close: () => void;
|
|
270
|
+
toggle: () => void;
|
|
249
271
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sb-floating-panel-vue",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
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",
|