@blocknote/mantine 0.39.1 → 0.41.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/src/menu/Menu.tsx CHANGED
@@ -2,19 +2,10 @@ import {
2
2
  CheckIcon as MantineCheckIcon,
3
3
  Menu as MantineMenu,
4
4
  } from "@mantine/core";
5
- import { mergeRefs } from "@mantine/hooks";
6
5
 
7
6
  import { assertEmpty } from "@blocknote/core";
8
7
  import { ComponentProps } from "@blocknote/react";
9
- import {
10
- createContext,
11
- forwardRef,
12
- useCallback,
13
- useContext,
14
- useRef,
15
- useState,
16
- } from "react";
17
- import { HiChevronRight } from "react-icons/hi";
8
+ import { createContext, forwardRef, useContext } from "react";
18
9
 
19
10
  const SubMenuContext = createContext<
20
11
  | {
@@ -24,128 +15,23 @@ const SubMenuContext = createContext<
24
15
  | undefined
25
16
  >(undefined);
26
17
 
27
- // https://github.com/orgs/mantinedev/discussions/2307
28
- // Mantine does not officially support sub menus, so we have to use a workaround
29
- // which uses an unconventional nesting structure:
30
- //
31
- // Conventional nesting structure (used by Ariakit/ShadCN):
32
- // <Menu>
33
- // <MenuTrigger>
34
- // <MenuItem>Find</MenuItem>
35
- // </MenuTrigger>
36
- // <MenuDropdown>
37
- // <MenuItem>Undo</MenuItem>
38
- // <MenuItem>Redo</MenuItem>
39
- // <Menu>
40
- // <MenuTrigger>
41
- // <MenuItem>Find</MenuItem>
42
- // </MenuTrigger>
43
- // <MenuDropdown>
44
- // <MenuItem>Find Next</MenuItem>
45
- // <MenuItem>Find Previous</MenuItem>
46
- // </MenuDropdown>
47
- // </Menu>
48
- // </MenuDropdown>
49
- // </Menu>
50
- //
51
- // Required structure for Mantine:
52
- // <Menu>
53
- // <MenuTrigger>
54
- // <MenuItem>Find</MenuItem>
55
- // </MenuTrigger>
56
- // <MenuDropdown>
57
- // <MenuItem>Undo</MenuItem>
58
- // <MenuItem>Redo</MenuItem>
59
- // <MenuItem>
60
- // <Menu>
61
- // <MenuTrigger>
62
- // <div>Find</div>
63
- // </MenuTrigger>
64
- // <MenuDropdown>
65
- // <MenuItem>Find Next</MenuItem>
66
- // <MenuItem>Find Previous</MenuItem>
67
- // </MenuDropdown>
68
- // </Menu>
69
- // </MenuItem>
70
- // </MenuDropdown>
71
- // </Menu>
72
- const SubMenu = forwardRef<
73
- HTMLButtonElement,
74
- ComponentProps["Generic"]["Menu"]["Root"]
75
- >((props, ref) => {
76
- const {
77
- children,
78
- onOpenChange,
79
- position,
80
- sub, // not used
81
- ...rest
82
- } = props;
83
-
84
- assertEmpty(rest);
85
-
86
- const [opened, setOpened] = useState(false);
87
-
88
- const itemRef = useRef<HTMLButtonElement | null>(null);
89
-
90
- const menuCloseTimer = useRef<ReturnType<typeof setTimeout> | undefined>(
91
- undefined,
92
- );
93
-
94
- const mouseLeave = useCallback(() => {
95
- if (menuCloseTimer.current) {
96
- clearTimeout(menuCloseTimer.current);
97
- }
98
- menuCloseTimer.current = setTimeout(() => {
99
- setOpened(false);
100
- }, 250);
101
- }, []);
102
-
103
- const mouseOver = useCallback(() => {
104
- if (menuCloseTimer.current) {
105
- clearTimeout(menuCloseTimer.current);
106
- }
107
- setOpened(true);
108
- }, []);
109
-
110
- return (
111
- <SubMenuContext.Provider
112
- value={{
113
- onMenuMouseOver: mouseOver,
114
- onMenuMouseLeave: mouseLeave,
115
- }}
116
- >
117
- <MantineMenu.Item
118
- className="bn-menu-item bn-mt-sub-menu-item"
119
- ref={mergeRefs(ref, itemRef)}
120
- onMouseOver={mouseOver}
121
- onMouseLeave={mouseLeave}
122
- >
123
- <MantineMenu
124
- portalProps={{
125
- target: itemRef.current
126
- ? itemRef.current.parentElement!
127
- : undefined,
128
- }}
129
- middlewares={{ flip: true, shift: true, inline: false, size: true }}
130
- trigger={"hover"}
131
- opened={opened}
132
- onChange={onOpenChange}
133
- position={position}
134
- >
135
- {children}
136
- </MantineMenu>
137
- </MantineMenu.Item>
138
- </SubMenuContext.Provider>
139
- );
140
- });
141
-
142
18
  export const Menu = (props: ComponentProps["Generic"]["Menu"]["Root"]) => {
143
19
  const { children, onOpenChange, position, sub, ...rest } = props;
144
20
 
145
21
  assertEmpty(rest);
146
22
 
147
23
  if (sub) {
148
- return <SubMenu {...props} />;
24
+ return (
25
+ <MantineMenu.Sub
26
+ transitionProps={{ duration: 250, exitDelay: 250 }}
27
+ withinPortal={false}
28
+ middlewares={{ flip: true, shift: true, inline: false, size: true }}
29
+ onChange={onOpenChange}
30
+ position={position}
31
+ >
32
+ {children}
33
+ </MantineMenu.Sub>
34
+ );
149
35
  }
150
36
 
151
37
  return (
@@ -173,17 +59,22 @@ export const MenuItem = forwardRef<
173
59
 
174
60
  if (subTrigger) {
175
61
  return (
176
- <div
177
- onClick={(e) => {
178
- e.preventDefault();
179
- e.stopPropagation();
180
- }}
62
+ <MantineMenu.Sub.Item
63
+ className={className}
181
64
  ref={ref}
65
+ leftSection={icon}
66
+ rightSection={
67
+ checked ? (
68
+ <MantineCheckIcon size={10} />
69
+ ) : checked === false ? (
70
+ <div className={"bn-tick-space"} />
71
+ ) : null
72
+ }
73
+ onClick={onClick}
182
74
  {...rest}
183
75
  >
184
76
  {children}
185
- <HiChevronRight size={15} />
186
- </div>
77
+ </MantineMenu.Sub.Item>
187
78
  );
188
79
  }
189
80
 
@@ -218,6 +109,10 @@ export const MenuTrigger = (
218
109
 
219
110
  assertEmpty(rest);
220
111
 
112
+ if (sub) {
113
+ return <MantineMenu.Sub.Target>{children}</MantineMenu.Sub.Target>;
114
+ }
115
+
221
116
  return <MantineMenu.Target>{children}</MantineMenu.Target>;
222
117
  };
223
118
 
@@ -236,6 +131,19 @@ export const MenuDropdown = forwardRef<
236
131
 
237
132
  const ctx = useContext(SubMenuContext);
238
133
 
134
+ if (sub) {
135
+ return (
136
+ <MantineMenu.Sub.Dropdown
137
+ className={className}
138
+ ref={ref}
139
+ onMouseOver={ctx?.onMenuMouseOver}
140
+ onMouseLeave={ctx?.onMenuMouseLeave}
141
+ >
142
+ {children}
143
+ </MantineMenu.Sub.Dropdown>
144
+ );
145
+ }
146
+
239
147
  return (
240
148
  <MantineMenu.Dropdown
241
149
  className={className}