@basic-ui/core 0.0.46 → 0.0.48
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/build/cjs/index.js +106 -12
- package/build/cjs/index.js.map +1 -1
- package/build/esm/Menu/ContextMenuTrigger.d.ts +11 -0
- package/build/esm/Menu/ContextMenuTrigger.js +60 -0
- package/build/esm/Menu/ContextMenuTrigger.js.map +1 -0
- package/build/esm/Menu/Menu.js +21 -4
- package/build/esm/Menu/Menu.js.map +1 -1
- package/build/esm/Menu/MenuButton.js +5 -3
- package/build/esm/Menu/MenuButton.js.map +1 -1
- package/build/esm/Menu/MenuItem.js +4 -2
- package/build/esm/Menu/MenuItem.js.map +1 -1
- package/build/esm/Menu/MenuList.js +28 -9
- package/build/esm/Menu/MenuList.js.map +1 -1
- package/build/esm/Menu/MenuPopover.js +9 -3
- package/build/esm/Menu/MenuPopover.js.map +1 -1
- package/build/esm/Menu/context.d.ts +7 -3
- package/build/esm/Menu/context.js.map +1 -1
- package/build/esm/Menu/index.d.ts +1 -0
- package/build/esm/Menu/index.js +1 -0
- package/build/esm/Menu/index.js.map +1 -1
- package/build/tsconfig-build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/Menu/ContextMenu.story.tsx +73 -0
- package/src/Menu/ContextMenuTrigger.tsx +76 -0
- package/src/Menu/Menu.story.tsx +2 -2
- package/src/Menu/Menu.tsx +19 -3
- package/src/Menu/MenuButton.tsx +4 -3
- package/src/Menu/MenuComplex.story.tsx +2 -2
- package/src/Menu/MenuItem.tsx +3 -1
- package/src/Menu/MenuList.tsx +38 -13
- package/src/Menu/MenuPopover.tsx +11 -3
- package/src/Menu/context.ts +8 -2
- package/src/Menu/index.ts +1 -0
package/src/Menu/MenuButton.tsx
CHANGED
|
@@ -21,6 +21,7 @@ export const MenuButton = forwardRef<HTMLButtonElement, MenuButtonProps>(
|
|
|
21
21
|
function MenuButton(props, forwardedRef) {
|
|
22
22
|
const {
|
|
23
23
|
as: Comp = 'button',
|
|
24
|
+
innerAs,
|
|
24
25
|
id: preferredId,
|
|
25
26
|
onClick,
|
|
26
27
|
onKeyDown,
|
|
@@ -48,7 +49,7 @@ export const MenuButton = forwardRef<HTMLButtonElement, MenuButtonProps>(
|
|
|
48
49
|
// Used to make it open at the end or begining of the list
|
|
49
50
|
openWithArrowKeyRef.current = e.key;
|
|
50
51
|
}
|
|
51
|
-
onChange
|
|
52
|
+
onChange(e, true);
|
|
52
53
|
e.preventDefault();
|
|
53
54
|
}
|
|
54
55
|
};
|
|
@@ -58,13 +59,13 @@ export const MenuButton = forwardRef<HTMLButtonElement, MenuButtonProps>(
|
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
60
61
|
buttonRef.current = e.currentTarget;
|
|
61
|
-
|
|
62
|
-
onChange && onChange(e, !open);
|
|
62
|
+
onChange(e, !open);
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
return (
|
|
66
66
|
<Comp
|
|
67
67
|
ref={forwardedRef}
|
|
68
|
+
as={innerAs}
|
|
68
69
|
id={buttonId}
|
|
69
70
|
role="button"
|
|
70
71
|
type="button"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MouseEvent } from 'react';
|
|
1
|
+
import type { MouseEvent, ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
import { Menu, MenuButton, MenuItem, MenuList, MenuPopover } from '.';
|
|
4
4
|
import { countryList } from './fixtures/countryList';
|
|
@@ -8,7 +8,7 @@ export default {
|
|
|
8
8
|
title: 'components/Menu/Complex',
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const Wrapper = ({ children }) => {
|
|
11
|
+
const Wrapper = ({ children }: { children: ReactNode }) => {
|
|
12
12
|
const handleLinkClick = (e: MouseEvent<HTMLAnchorElement>) => {
|
|
13
13
|
console.log('Clicked ' + e.currentTarget.innerText);
|
|
14
14
|
e.preventDefault();
|
package/src/Menu/MenuItem.tsx
CHANGED
|
@@ -26,6 +26,7 @@ export const MenuItem = forwardRef<any, MenuItemProps>(function MenuItem(
|
|
|
26
26
|
) {
|
|
27
27
|
const {
|
|
28
28
|
as: Comp = 'li',
|
|
29
|
+
innerAs,
|
|
29
30
|
disabled,
|
|
30
31
|
onSelect,
|
|
31
32
|
onClick,
|
|
@@ -42,7 +43,7 @@ export const MenuItem = forwardRef<any, MenuItemProps>(function MenuItem(
|
|
|
42
43
|
const handleSelect = wrapEvent(
|
|
43
44
|
onSelect,
|
|
44
45
|
(e: KeyboardEvent<HTMLLIElement> | MouseEvent<HTMLLIElement>) => {
|
|
45
|
-
onChange
|
|
46
|
+
onChange(e, false);
|
|
46
47
|
buttonRef.current?.focus();
|
|
47
48
|
e.preventDefault();
|
|
48
49
|
}
|
|
@@ -69,6 +70,7 @@ export const MenuItem = forwardRef<any, MenuItemProps>(function MenuItem(
|
|
|
69
70
|
return (
|
|
70
71
|
<Comp
|
|
71
72
|
ref={assignMultipleRefs(ref, forwardedRef)}
|
|
73
|
+
as={innerAs}
|
|
72
74
|
id={disabled ? undefined : itemId}
|
|
73
75
|
data-menu-item=""
|
|
74
76
|
data-highlighted={isActive ? '' : undefined}
|
package/src/Menu/MenuList.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { HTMLAttributes, ElementType, KeyboardEvent } from 'react';
|
|
2
2
|
import {
|
|
3
|
+
useCallback,
|
|
3
4
|
forwardRef,
|
|
4
5
|
useEffect,
|
|
5
6
|
useRef,
|
|
@@ -27,17 +28,25 @@ export const MenuList = forwardRef<HTMLUListElement, MenuListProps>(
|
|
|
27
28
|
function MenuList(props, forwardedRef) {
|
|
28
29
|
const {
|
|
29
30
|
as: Comp = 'ul',
|
|
31
|
+
innerAs,
|
|
30
32
|
onKeyDown,
|
|
31
33
|
id: preferredId,
|
|
32
34
|
defaultActiveItemValue,
|
|
33
35
|
...otherProps
|
|
34
36
|
} = props;
|
|
35
37
|
|
|
38
|
+
const interactedOutside = useRef(false);
|
|
36
39
|
const itemSearchStr = useRef('');
|
|
37
40
|
const itemSearchClearTimeout = useRef<ReturnType<typeof setTimeout>>();
|
|
38
41
|
|
|
39
|
-
const {
|
|
40
|
-
|
|
42
|
+
const {
|
|
43
|
+
menuListIdRef,
|
|
44
|
+
buttonRef,
|
|
45
|
+
onChange,
|
|
46
|
+
openWithArrowKeyRef,
|
|
47
|
+
open,
|
|
48
|
+
isContextMenu,
|
|
49
|
+
} = useMenuContext();
|
|
41
50
|
|
|
42
51
|
const [navigationItem, setNavigationItem] = useState<
|
|
43
52
|
HTMLElement | undefined
|
|
@@ -89,26 +98,40 @@ export const MenuList = forwardRef<HTMLUListElement, MenuListProps>(
|
|
|
89
98
|
defaultActiveItemValue,
|
|
90
99
|
]);
|
|
91
100
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
const handleClickOutside = useCallback(
|
|
102
|
+
(e: PointerEvent) => {
|
|
103
|
+
if (!interactedOutside.current) {
|
|
104
|
+
// First interaction should be ignored, because
|
|
105
|
+
// this is what triggered the context menu to open
|
|
106
|
+
interactedOutside.current = true;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (isContextMenu.current) {
|
|
111
|
+
if (e.button === 0) {
|
|
112
|
+
onChange(e as any, false);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
if (
|
|
116
|
+
e.target instanceof HTMLElement &&
|
|
117
|
+
e.target !== buttonRef.current &&
|
|
118
|
+
!buttonRef.current?.contains(e.target)
|
|
119
|
+
) {
|
|
120
|
+
onChange(e as any, false);
|
|
121
|
+
}
|
|
101
122
|
}
|
|
102
123
|
e.preventDefault();
|
|
103
124
|
},
|
|
104
|
-
|
|
125
|
+
[buttonRef, isContextMenu, onChange]
|
|
105
126
|
);
|
|
106
127
|
|
|
128
|
+
useOnClickOutside(menuListRef, handleClickOutside, open);
|
|
129
|
+
|
|
107
130
|
function handleKeyDown(e: KeyboardEvent<HTMLUListElement>) {
|
|
108
131
|
switch (e.key) {
|
|
109
132
|
case 'Escape':
|
|
110
133
|
case 'Tab': {
|
|
111
|
-
onChange
|
|
134
|
+
onChange(e, false);
|
|
112
135
|
e.preventDefault(); // prevents focusing on next element, because we will be handling it
|
|
113
136
|
itemSearchStr.current = '';
|
|
114
137
|
buttonRef.current?.focus();
|
|
@@ -192,6 +215,7 @@ export const MenuList = forwardRef<HTMLUListElement, MenuListProps>(
|
|
|
192
215
|
}
|
|
193
216
|
|
|
194
217
|
if (!open) {
|
|
218
|
+
interactedOutside.current = false;
|
|
195
219
|
return null;
|
|
196
220
|
}
|
|
197
221
|
|
|
@@ -204,6 +228,7 @@ export const MenuList = forwardRef<HTMLUListElement, MenuListProps>(
|
|
|
204
228
|
>
|
|
205
229
|
<Comp
|
|
206
230
|
ref={assignMultipleRefs(forwardedRef, menuListRef)}
|
|
231
|
+
as={innerAs}
|
|
207
232
|
id={menuListIdRef.current}
|
|
208
233
|
role="menu"
|
|
209
234
|
aria-labelledby={buttonRef.current?.id}
|
package/src/Menu/MenuPopover.tsx
CHANGED
|
@@ -13,15 +13,23 @@ export interface MenuPopoverProps extends Omit<PopperProps, 'anchorEl'> {
|
|
|
13
13
|
|
|
14
14
|
export const MenuPopover = forwardRef<HTMLDivElement, MenuPopoverProps>(
|
|
15
15
|
function MenuPopover(props, forwardedRef) {
|
|
16
|
-
const { as = 'div', ...otherProps } = props;
|
|
17
|
-
const { buttonRef, open } = useMenuContext();
|
|
16
|
+
const { as = 'div', innerAs, ...otherProps } = props;
|
|
17
|
+
const { buttonRef, open, offsetFn, isContextMenu } = useMenuContext();
|
|
18
18
|
|
|
19
19
|
if (!open) {
|
|
20
20
|
return null;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
|
-
<Popper
|
|
24
|
+
<Popper
|
|
25
|
+
as={as}
|
|
26
|
+
innerAs={innerAs}
|
|
27
|
+
ref={forwardedRef}
|
|
28
|
+
anchorEl={buttonRef}
|
|
29
|
+
offsetFn={offsetFn}
|
|
30
|
+
placement={isContextMenu.current ? 'bottom-start' : undefined}
|
|
31
|
+
{...otherProps}
|
|
32
|
+
/>
|
|
25
33
|
);
|
|
26
34
|
}
|
|
27
35
|
);
|
package/src/Menu/context.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { OffsetsFunction } from '@popperjs/core/lib/modifiers/offset';
|
|
1
2
|
import type {
|
|
3
|
+
Dispatch,
|
|
2
4
|
KeyboardEvent,
|
|
3
5
|
MouseEvent,
|
|
4
6
|
MutableRefObject,
|
|
5
7
|
PointerEvent,
|
|
8
|
+
SetStateAction,
|
|
6
9
|
} from 'react';
|
|
7
10
|
import { createContext, useContext } from 'react';
|
|
8
11
|
|
|
@@ -10,10 +13,10 @@ export type ItemObject = { text: string; value: any; id: string | undefined };
|
|
|
10
13
|
|
|
11
14
|
// MenuRoot
|
|
12
15
|
export interface MenuContextProps {
|
|
13
|
-
buttonRef: MutableRefObject<
|
|
16
|
+
buttonRef: MutableRefObject<HTMLElement | null>;
|
|
14
17
|
menuListIdRef: MutableRefObject<undefined | string>;
|
|
15
18
|
openWithArrowKeyRef: MutableRefObject<string | null>;
|
|
16
|
-
onChange
|
|
19
|
+
onChange: (
|
|
17
20
|
e:
|
|
18
21
|
| KeyboardEvent<HTMLElement>
|
|
19
22
|
| MouseEvent<HTMLElement>
|
|
@@ -21,6 +24,9 @@ export interface MenuContextProps {
|
|
|
21
24
|
isOpen: boolean
|
|
22
25
|
) => void;
|
|
23
26
|
open: boolean;
|
|
27
|
+
offsetFn: OffsetsFunction | undefined;
|
|
28
|
+
setOffsetFn: Dispatch<SetStateAction<OffsetsFunction | undefined>>;
|
|
29
|
+
isContextMenu: MutableRefObject<boolean>;
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
const menuContext = createContext<MenuContextProps>(null as any);
|