@sit-onyx/headless 1.0.0-beta.19 → 1.0.0-beta.20
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/package.json
CHANGED
|
@@ -25,7 +25,7 @@ describe("useOutsideClick", () => {
|
|
|
25
25
|
useOutsideClick({ inside, onOutsideClick });
|
|
26
26
|
|
|
27
27
|
// ACT
|
|
28
|
-
const event = new MouseEvent("
|
|
28
|
+
const event = new MouseEvent("mousedown", { bubbles: true });
|
|
29
29
|
outside.value.dispatchEvent(event);
|
|
30
30
|
|
|
31
31
|
// ASSERT
|
|
@@ -53,7 +53,7 @@ describe("useOutsideClick", () => {
|
|
|
53
53
|
const onOutsideClick = vi.fn();
|
|
54
54
|
useOutsideClick({ inside, onOutsideClick });
|
|
55
55
|
// ACT
|
|
56
|
-
const event = new MouseEvent("
|
|
56
|
+
const event = new MouseEvent("mousedown", { bubbles: true });
|
|
57
57
|
inside[0].dispatchEvent(event);
|
|
58
58
|
inside[1].dispatchEvent(event);
|
|
59
59
|
// ASSERT
|
|
@@ -79,7 +79,7 @@ describe("useOutsideClick", () => {
|
|
|
79
79
|
useOutsideClick({ inside, disabled, onOutsideClick });
|
|
80
80
|
|
|
81
81
|
// ACT
|
|
82
|
-
const event = new MouseEvent("
|
|
82
|
+
const event = new MouseEvent("mousedown", { bubbles: true });
|
|
83
83
|
outside.value.dispatchEvent(event);
|
|
84
84
|
// ASSERT
|
|
85
85
|
expect(onOutsideClick).toHaveBeenCalledTimes(1);
|
|
@@ -88,7 +88,7 @@ describe("useOutsideClick", () => {
|
|
|
88
88
|
// ACT
|
|
89
89
|
disabled.value = true;
|
|
90
90
|
await vi.runAllTimersAsync();
|
|
91
|
-
const event2 = new MouseEvent("
|
|
91
|
+
const event2 = new MouseEvent("mousedown", { bubbles: true });
|
|
92
92
|
outside.value.dispatchEvent(event2);
|
|
93
93
|
// ASSERT
|
|
94
94
|
expect(onOutsideClick).toHaveBeenCalledTimes(1);
|
|
@@ -49,7 +49,7 @@ export const useOutsideClick = <TCheckOnTab extends boolean | undefined>({
|
|
|
49
49
|
if (isOutsideClick(event.target)) onOutsideClick(event);
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
useGlobalEventListener({ type: "
|
|
52
|
+
useGlobalEventListener({ type: "mousedown", listener: clickListener, disabled });
|
|
53
53
|
|
|
54
54
|
if (checkOnTab) {
|
|
55
55
|
const keydownListener = async (event: KeyboardEvent) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, useId, watch, type Ref } from "vue";
|
|
1
|
+
import { computed, toValue, useId, watch, type MaybeRef, type Ref } from "vue";
|
|
2
2
|
import { createBuilder, createElRef } from "../../utils/builder";
|
|
3
3
|
import { debounce } from "../../utils/timer";
|
|
4
4
|
import { useGlobalEventListener } from "../helpers/useGlobalListener";
|
|
@@ -6,9 +6,15 @@ import { useOutsideClick } from "../helpers/useOutsideClick";
|
|
|
6
6
|
|
|
7
7
|
type CreateMenuButtonOptions = {
|
|
8
8
|
isExpanded: Readonly<Ref<boolean>>;
|
|
9
|
-
trigger: Readonly<
|
|
9
|
+
trigger: Readonly<MaybeRef<"hover" | "click">>;
|
|
10
10
|
onToggle: () => void;
|
|
11
11
|
disabled?: Readonly<Ref<boolean>>;
|
|
12
|
+
/**
|
|
13
|
+
* Whether the menu button opens to the top or bottom. Defines the keyboard navigation behavior (e.g. Arrow up and down).
|
|
14
|
+
*
|
|
15
|
+
* @default "bottom"
|
|
16
|
+
*/
|
|
17
|
+
position?: MaybeRef<"top" | "bottom">;
|
|
12
18
|
};
|
|
13
19
|
|
|
14
20
|
/**
|
|
@@ -21,6 +27,8 @@ export const createMenuButton = createBuilder((options: CreateMenuButtonOptions)
|
|
|
21
27
|
const menuRef = createElRef<HTMLElement>();
|
|
22
28
|
const buttonId = useId();
|
|
23
29
|
|
|
30
|
+
const position = computed(() => toValue(options.position) ?? "bottom");
|
|
31
|
+
|
|
24
32
|
useGlobalEventListener({
|
|
25
33
|
type: "keydown",
|
|
26
34
|
listener: (e) => e.key === "Escape" && setExpanded(false),
|
|
@@ -57,6 +65,7 @@ export const createMenuButton = createBuilder((options: CreateMenuButtonOptions)
|
|
|
57
65
|
const menuItems = Array.from(currentMenu.querySelectorAll<HTMLElement>('[role="menuitem"]'))
|
|
58
66
|
// filter out nested children
|
|
59
67
|
.filter((item) => item.closest('[role="menu"]') === currentMenu);
|
|
68
|
+
if (position.value === "top") menuItems.reverse();
|
|
60
69
|
let nextIndex = 0;
|
|
61
70
|
|
|
62
71
|
if (currentMenuItem) {
|
|
@@ -85,11 +94,11 @@ export const createMenuButton = createBuilder((options: CreateMenuButtonOptions)
|
|
|
85
94
|
switch (event.key) {
|
|
86
95
|
case "ArrowDown":
|
|
87
96
|
event.preventDefault();
|
|
88
|
-
focusRelativeItem("next");
|
|
97
|
+
focusRelativeItem(position.value === "bottom" ? "next" : "prev");
|
|
89
98
|
break;
|
|
90
99
|
case "ArrowUp":
|
|
91
100
|
event.preventDefault();
|
|
92
|
-
focusRelativeItem("prev");
|
|
101
|
+
focusRelativeItem(position.value === "bottom" ? "prev" : "next");
|
|
93
102
|
break;
|
|
94
103
|
case "Home":
|
|
95
104
|
event.preventDefault();
|
|
@@ -113,7 +122,7 @@ export const createMenuButton = createBuilder((options: CreateMenuButtonOptions)
|
|
|
113
122
|
};
|
|
114
123
|
|
|
115
124
|
const triggerEvents = computed(() => {
|
|
116
|
-
if (options.trigger
|
|
125
|
+
if (toValue(options.trigger) !== "hover") return;
|
|
117
126
|
return {
|
|
118
127
|
onMouseenter: () => setExpanded(true),
|
|
119
128
|
onMouseleave: () => setExpanded(false, true),
|
|
@@ -143,7 +152,9 @@ export const createMenuButton = createBuilder((options: CreateMenuButtonOptions)
|
|
|
143
152
|
"aria-haspopup": true,
|
|
144
153
|
onFocus: () => setExpanded(true, true),
|
|
145
154
|
onClick: () =>
|
|
146
|
-
options.trigger
|
|
155
|
+
toValue(options.trigger) == "click"
|
|
156
|
+
? setExpanded(!options.isExpanded.value)
|
|
157
|
+
: undefined,
|
|
147
158
|
id: buttonId,
|
|
148
159
|
disabled: options.disabled?.value,
|
|
149
160
|
}) as const,
|