@blocknote/mantine 0.13.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.
Files changed (54) hide show
  1. package/LICENSE +373 -0
  2. package/dist/blocknote-mantine.js +1532 -0
  3. package/dist/blocknote-mantine.js.map +1 -0
  4. package/dist/blocknote-mantine.umd.cjs +28 -0
  5. package/dist/blocknote-mantine.umd.cjs.map +1 -0
  6. package/dist/style.css +1 -0
  7. package/dist/webpack-stats.json +1 -0
  8. package/package.json +88 -0
  9. package/src/BlockNoteTheme.ts +153 -0
  10. package/src/defaultThemes.ts +159 -0
  11. package/src/form/TextInput.tsx +44 -0
  12. package/src/index.tsx +172 -0
  13. package/src/mantineStyles.css +138 -0
  14. package/src/menu/Menu.tsx +252 -0
  15. package/src/panel/Panel.tsx +50 -0
  16. package/src/panel/PanelButton.tsx +26 -0
  17. package/src/panel/PanelFileInput.tsx +26 -0
  18. package/src/panel/PanelTab.tsx +18 -0
  19. package/src/panel/PanelTextInput.tsx +27 -0
  20. package/src/popover/Popover.tsx +53 -0
  21. package/src/sideMenu/SideMenu.tsx +20 -0
  22. package/src/sideMenu/SideMenuButton.tsx +57 -0
  23. package/src/style.css +490 -0
  24. package/src/suggestionMenu/SuggestionMenu.tsx +25 -0
  25. package/src/suggestionMenu/SuggestionMenuEmptyItem.tsx +22 -0
  26. package/src/suggestionMenu/SuggestionMenuItem.tsx +47 -0
  27. package/src/suggestionMenu/SuggestionMenuLabel.tsx +20 -0
  28. package/src/suggestionMenu/SuggestionMenuLoader.tsx +20 -0
  29. package/src/tableHandle/TableHandle.tsx +37 -0
  30. package/src/toolbar/Toolbar.tsx +36 -0
  31. package/src/toolbar/ToolbarButton.tsx +106 -0
  32. package/src/toolbar/ToolbarSelect.tsx +69 -0
  33. package/types/src/BlockNoteTheme.d.ts +33 -0
  34. package/types/src/defaultThemes.d.ts +143 -0
  35. package/types/src/form/TextInput.d.ts +13 -0
  36. package/types/src/index.d.ts +14 -0
  37. package/types/src/menu/Menu.d.ts +24 -0
  38. package/types/src/panel/Panel.d.ts +12 -0
  39. package/types/src/panel/PanelButton.d.ts +11 -0
  40. package/types/src/panel/PanelFileInput.d.ts +7 -0
  41. package/types/src/panel/PanelTab.d.ts +5 -0
  42. package/types/src/panel/PanelTextInput.d.ts +8 -0
  43. package/types/src/popover/Popover.d.ts +9 -0
  44. package/types/src/sideMenu/SideMenu.d.ts +5 -0
  45. package/types/src/sideMenu/SideMenuButton.d.ts +15 -0
  46. package/types/src/suggestionMenu/SuggestionMenu.d.ts +6 -0
  47. package/types/src/suggestionMenu/SuggestionMenuEmptyItem.d.ts +5 -0
  48. package/types/src/suggestionMenu/SuggestionMenuItem.d.ts +8 -0
  49. package/types/src/suggestionMenu/SuggestionMenuLabel.d.ts +5 -0
  50. package/types/src/suggestionMenu/SuggestionMenuLoader.d.ts +5 -0
  51. package/types/src/tableHandle/TableHandle.d.ts +14 -0
  52. package/types/src/toolbar/Toolbar.d.ts +10 -0
  53. package/types/src/toolbar/ToolbarButton.d.ts +12 -0
  54. package/types/src/toolbar/ToolbarSelect.d.ts +12 -0
@@ -0,0 +1,252 @@
1
+ import * as Mantine from "@mantine/core";
2
+
3
+ import { assertEmpty } from "@blocknote/core";
4
+ import { ComponentProps } from "@blocknote/react";
5
+ import {
6
+ createContext,
7
+ forwardRef,
8
+ useCallback,
9
+ useContext,
10
+ useRef,
11
+ useState,
12
+ } from "react";
13
+ import { HiChevronRight } from "react-icons/hi";
14
+
15
+ const SubMenuContext = createContext<
16
+ | {
17
+ onMenuMouseOver: () => void;
18
+ onMenuMouseLeave: () => void;
19
+ }
20
+ | undefined
21
+ >(undefined);
22
+
23
+ // https://github.com/orgs/mantinedev/discussions/2307
24
+ // Mantine does not officially support sub menus, so we have to use a workaround
25
+ // which uses an unconventional nesting structure:
26
+ //
27
+ // Conventional nesting structure (used by Ariakit/ShadCN):
28
+ // <Menu>
29
+ // <MenuTrigger>
30
+ // <MenuItem>Find</MenuItem>
31
+ // </MenuTrigger>
32
+ // <MenuDropdown>
33
+ // <MenuItem>Undo</MenuItem>
34
+ // <MenuItem>Redo</MenuItem>
35
+ // <Menu>
36
+ // <MenuTrigger>
37
+ // <MenuItem>Find</MenuItem>
38
+ // </MenuTrigger>
39
+ // <MenuDropdown>
40
+ // <MenuItem>Find Next</MenuItem>
41
+ // <MenuItem>Find Previous</MenuItem>
42
+ // </MenuDropdown>
43
+ // </Menu>
44
+ // </MenuDropdown>
45
+ // </Menu>
46
+ //
47
+ // Required structure for Mantine:
48
+ // <Menu>
49
+ // <MenuTrigger>
50
+ // <MenuItem>Find</MenuItem>
51
+ // </MenuTrigger>
52
+ // <MenuDropdown>
53
+ // <MenuItem>Undo</MenuItem>
54
+ // <MenuItem>Redo</MenuItem>
55
+ // <MenuItem>
56
+ // <Menu>
57
+ // <MenuTrigger>
58
+ // <div>Find</div>
59
+ // </MenuTrigger>
60
+ // <MenuDropdown>
61
+ // <MenuItem>Find Next</MenuItem>
62
+ // <MenuItem>Find Previous</MenuItem>
63
+ // </MenuDropdown>
64
+ // </Menu>
65
+ // </MenuItem>
66
+ // </MenuDropdown>
67
+ // </Menu>
68
+ const SubMenu = forwardRef<
69
+ HTMLButtonElement,
70
+ ComponentProps["Generic"]["Menu"]["Root"]
71
+ >((props, ref) => {
72
+ const {
73
+ children,
74
+ onOpenChange,
75
+ position,
76
+ sub, // not used
77
+ ...rest
78
+ } = props;
79
+
80
+ assertEmpty(rest);
81
+
82
+ const [opened, setOpened] = useState(false);
83
+
84
+ const menuCloseTimer = useRef<ReturnType<typeof setTimeout> | undefined>();
85
+
86
+ const mouseLeave = useCallback(() => {
87
+ if (menuCloseTimer.current) {
88
+ clearTimeout(menuCloseTimer.current);
89
+ }
90
+ menuCloseTimer.current = setTimeout(() => {
91
+ setOpened(false);
92
+ }, 250);
93
+ }, []);
94
+
95
+ const mouseOver = useCallback(() => {
96
+ if (menuCloseTimer.current) {
97
+ clearTimeout(menuCloseTimer.current);
98
+ }
99
+ setOpened(true);
100
+ }, []);
101
+
102
+ return (
103
+ <SubMenuContext.Provider
104
+ value={{
105
+ onMenuMouseOver: mouseOver,
106
+ onMenuMouseLeave: mouseLeave,
107
+ }}>
108
+ <Mantine.Menu.Item
109
+ className="bn-menu-item bn-mt-sub-menu-item"
110
+ ref={ref}
111
+ onMouseOver={mouseOver}
112
+ onMouseLeave={mouseLeave}>
113
+ <Mantine.Menu
114
+ withinPortal={false}
115
+ middlewares={{ flip: true, shift: true, inline: false, size: true }}
116
+ trigger={"hover"}
117
+ opened={opened}
118
+ onClose={() => onOpenChange?.(false)}
119
+ onOpen={() => onOpenChange?.(true)}
120
+ position={position}>
121
+ {children}
122
+ </Mantine.Menu>
123
+ </Mantine.Menu.Item>
124
+ </SubMenuContext.Provider>
125
+ );
126
+ });
127
+
128
+ export const Menu = (props: ComponentProps["Generic"]["Menu"]["Root"]) => {
129
+ const { children, onOpenChange, position, sub, ...rest } = props;
130
+
131
+ assertEmpty(rest);
132
+
133
+ if (sub) {
134
+ return <SubMenu {...props} />;
135
+ }
136
+
137
+ return (
138
+ <Mantine.Menu
139
+ withinPortal={false}
140
+ middlewares={{ flip: true, shift: true, inline: false, size: true }}
141
+ onClose={() => onOpenChange?.(false)}
142
+ onOpen={() => onOpenChange?.(true)}
143
+ position={position}>
144
+ {children}
145
+ </Mantine.Menu>
146
+ );
147
+ };
148
+
149
+ export const MenuItem = forwardRef<
150
+ HTMLButtonElement & HTMLDivElement,
151
+ ComponentProps["Generic"]["Menu"]["Item"]
152
+ >((props, ref) => {
153
+ const { className, children, icon, checked, subTrigger, onClick, ...rest } =
154
+ props;
155
+
156
+ // false, because rest props can be added by mantine when button is used as a trigger
157
+ // assertEmpty in this case is only used at typescript level, not runtime level
158
+ assertEmpty(rest, false);
159
+
160
+ if (subTrigger) {
161
+ return (
162
+ <div ref={ref} {...rest}>
163
+ {children}
164
+ <HiChevronRight size={15} />
165
+ </div>
166
+ );
167
+ }
168
+
169
+ return (
170
+ <Mantine.Menu.Item
171
+ className={className}
172
+ ref={ref}
173
+ leftSection={icon}
174
+ rightSection={
175
+ checked ? (
176
+ <Mantine.CheckIcon size={10} />
177
+ ) : checked === false ? (
178
+ <div className={"bn-tick-space"} />
179
+ ) : null
180
+ }
181
+ onClick={onClick}
182
+ {...rest}>
183
+ {children}
184
+ </Mantine.Menu.Item>
185
+ );
186
+ });
187
+
188
+ export const MenuTrigger = (
189
+ props: ComponentProps["Generic"]["Menu"]["Trigger"]
190
+ ) => {
191
+ const {
192
+ children,
193
+ sub, // unused
194
+ ...rest
195
+ } = props;
196
+
197
+ assertEmpty(rest);
198
+
199
+ return <Mantine.Menu.Target>{children}</Mantine.Menu.Target>;
200
+ };
201
+
202
+ export const MenuDropdown = forwardRef<
203
+ HTMLDivElement,
204
+ ComponentProps["Generic"]["Menu"]["Dropdown"]
205
+ >((props, ref) => {
206
+ const {
207
+ className,
208
+ children,
209
+ sub, //unused
210
+ ...rest
211
+ } = props;
212
+
213
+ assertEmpty(rest);
214
+
215
+ const ctx = useContext(SubMenuContext);
216
+
217
+ return (
218
+ <Mantine.Menu.Dropdown
219
+ className={className}
220
+ ref={ref}
221
+ onMouseOver={ctx?.onMenuMouseOver}
222
+ onMouseLeave={ctx?.onMenuMouseLeave}>
223
+ {children}
224
+ </Mantine.Menu.Dropdown>
225
+ );
226
+ });
227
+
228
+ export const MenuDivider = forwardRef<
229
+ HTMLDivElement,
230
+ ComponentProps["Generic"]["Menu"]["Divider"]
231
+ >((props, ref) => {
232
+ const { className, ...rest } = props;
233
+
234
+ assertEmpty(rest);
235
+
236
+ return <Mantine.Menu.Divider className={className} ref={ref} />;
237
+ });
238
+
239
+ export const MenuLabel = forwardRef<
240
+ HTMLDivElement,
241
+ ComponentProps["Generic"]["Menu"]["Label"]
242
+ >((props, ref) => {
243
+ const { className, children, ...rest } = props;
244
+
245
+ assertEmpty(rest);
246
+
247
+ return (
248
+ <Mantine.Menu.Label className={className} ref={ref}>
249
+ {children}
250
+ </Mantine.Menu.Label>
251
+ );
252
+ });
@@ -0,0 +1,50 @@
1
+ import * as Mantine from "@mantine/core";
2
+
3
+ import { assertEmpty } from "@blocknote/core";
4
+ import { ComponentProps } from "@blocknote/react";
5
+ import { forwardRef } from "react";
6
+
7
+ export const Panel = forwardRef<
8
+ HTMLDivElement,
9
+ ComponentProps["ImagePanel"]["Root"]
10
+ >((props, ref) => {
11
+ const {
12
+ className,
13
+ tabs,
14
+ defaultOpenTab,
15
+ openTab,
16
+ setOpenTab,
17
+ loading,
18
+ ...rest
19
+ } = props;
20
+
21
+ assertEmpty(rest);
22
+
23
+ return (
24
+ <Mantine.Group className={className} ref={ref}>
25
+ <Mantine.Tabs
26
+ value={openTab}
27
+ defaultValue={defaultOpenTab}
28
+ onChange={setOpenTab as any}>
29
+ {loading && <Mantine.LoadingOverlay visible={loading} />}
30
+
31
+ <Mantine.Tabs.List>
32
+ {tabs.map((tab) => (
33
+ <Mantine.Tabs.Tab
34
+ data-test={`${tab.name.toLowerCase()}-tab`}
35
+ value={tab.name}
36
+ key={tab.name}>
37
+ {tab.name}
38
+ </Mantine.Tabs.Tab>
39
+ ))}
40
+ </Mantine.Tabs.List>
41
+
42
+ {tabs.map((tab) => (
43
+ <Mantine.Tabs.Panel value={tab.name} key={tab.name}>
44
+ {tab.tabPanel}
45
+ </Mantine.Tabs.Panel>
46
+ ))}
47
+ </Mantine.Tabs>
48
+ </Mantine.Group>
49
+ );
50
+ });
@@ -0,0 +1,26 @@
1
+ import * as Mantine from "@mantine/core";
2
+
3
+ import { assertEmpty } from "@blocknote/core";
4
+ import { ComponentProps } from "@blocknote/react";
5
+ import { forwardRef } from "react";
6
+
7
+ export const PanelButton = forwardRef<
8
+ HTMLButtonElement,
9
+ ComponentProps["ImagePanel"]["Button"]
10
+ >((props, ref) => {
11
+ const { className, children, onClick, label, ...rest } = props;
12
+
13
+ assertEmpty(rest);
14
+
15
+ return (
16
+ <Mantine.Button
17
+ size={"xs"}
18
+ aria-label={label}
19
+ className={className}
20
+ ref={ref}
21
+ onClick={onClick}
22
+ {...rest}>
23
+ {children}
24
+ </Mantine.Button>
25
+ );
26
+ });
@@ -0,0 +1,26 @@
1
+ import * as Mantine from "@mantine/core";
2
+
3
+ import { assertEmpty } from "@blocknote/core";
4
+ import { ComponentProps } from "@blocknote/react";
5
+ import { forwardRef } from "react";
6
+
7
+ export const PanelFileInput = forwardRef<
8
+ HTMLButtonElement,
9
+ ComponentProps["ImagePanel"]["FileInput"]
10
+ >((props, ref) => {
11
+ const { className, value, placeholder, onChange, ...rest } = props;
12
+
13
+ assertEmpty(rest);
14
+
15
+ return (
16
+ <Mantine.FileInput
17
+ size={"xs"}
18
+ className={className}
19
+ ref={ref}
20
+ value={value}
21
+ placeholder={placeholder}
22
+ onChange={onChange}
23
+ {...rest}
24
+ />
25
+ );
26
+ });
@@ -0,0 +1,18 @@
1
+ import { assertEmpty } from "@blocknote/core";
2
+ import { ComponentProps } from "@blocknote/react";
3
+ import { forwardRef } from "react";
4
+
5
+ export const PanelTab = forwardRef<
6
+ HTMLDivElement,
7
+ ComponentProps["ImagePanel"]["TabPanel"]
8
+ >((props, ref) => {
9
+ const { className, children, ...rest } = props;
10
+
11
+ assertEmpty(rest);
12
+
13
+ return (
14
+ <div className={className} ref={ref}>
15
+ {children}
16
+ </div>
17
+ );
18
+ });
@@ -0,0 +1,27 @@
1
+ import * as Mantine from "@mantine/core";
2
+
3
+ import { assertEmpty } from "@blocknote/core";
4
+ import { ComponentProps } from "@blocknote/react";
5
+ import { forwardRef } from "react";
6
+
7
+ export const PanelTextInput = forwardRef<
8
+ HTMLInputElement,
9
+ ComponentProps["ImagePanel"]["TextInput"]
10
+ >((props, ref) => {
11
+ const { className, value, placeholder, onKeyDown, onChange, ...rest } = props;
12
+
13
+ assertEmpty(rest);
14
+
15
+ return (
16
+ <Mantine.TextInput
17
+ size={"xs"}
18
+ data-test={"embed-input"}
19
+ className={className}
20
+ ref={ref}
21
+ value={value}
22
+ placeholder={placeholder}
23
+ onKeyDown={onKeyDown}
24
+ onChange={onChange}
25
+ />
26
+ );
27
+ });
@@ -0,0 +1,53 @@
1
+ import * as Mantine from "@mantine/core";
2
+
3
+ import { assertEmpty } from "@blocknote/core";
4
+ import { ComponentProps } from "@blocknote/react";
5
+ import { forwardRef } from "react";
6
+
7
+ export const Popover = (
8
+ props: ComponentProps["Generic"]["Popover"]["Root"]
9
+ ) => {
10
+ const { children, opened, position, ...rest } = props;
11
+
12
+ assertEmpty(rest);
13
+
14
+ return (
15
+ <Mantine.Popover
16
+ withinPortal={false}
17
+ zIndex={10000}
18
+ opened={opened}
19
+ position={position}>
20
+ {children}
21
+ </Mantine.Popover>
22
+ );
23
+ };
24
+
25
+ export const PopoverTrigger = (
26
+ props: ComponentProps["Generic"]["Popover"]["Trigger"]
27
+ ) => {
28
+ const { children, ...rest } = props;
29
+
30
+ assertEmpty(rest);
31
+
32
+ return <Mantine.PopoverTarget>{children}</Mantine.PopoverTarget>;
33
+ };
34
+
35
+ export const PopoverContent = forwardRef<
36
+ HTMLDivElement,
37
+ ComponentProps["Generic"]["Popover"]["Content"]
38
+ >((props, ref) => {
39
+ const {
40
+ className,
41
+ children,
42
+ variant, // unused
43
+ ...rest
44
+ } = props;
45
+
46
+ assertEmpty(rest);
47
+
48
+ return (
49
+ <Mantine.PopoverDropdown className={className} ref={ref}>
50
+ {children}
51
+ </Mantine.PopoverDropdown>
52
+ );
53
+ });
@@ -0,0 +1,20 @@
1
+ import * as Mantine from "@mantine/core";
2
+
3
+ import { assertEmpty } from "@blocknote/core";
4
+ import { ComponentProps } from "@blocknote/react";
5
+ import { forwardRef } from "react";
6
+
7
+ export const SideMenu = forwardRef<
8
+ HTMLDivElement,
9
+ ComponentProps["SideMenu"]["Root"]
10
+ >((props, ref) => {
11
+ const { className, children, ...rest } = props;
12
+
13
+ assertEmpty(rest);
14
+
15
+ return (
16
+ <Mantine.Group align={"center"} gap={0} className={className} ref={ref}>
17
+ {children}
18
+ </Mantine.Group>
19
+ );
20
+ });
@@ -0,0 +1,57 @@
1
+ import * as Mantine from "@mantine/core";
2
+
3
+ import { assertEmpty } from "@blocknote/core";
4
+ import { ComponentProps } from "@blocknote/react";
5
+ import { forwardRef } from "react";
6
+
7
+ export const SideMenuButton = forwardRef<
8
+ HTMLButtonElement,
9
+ ComponentProps["SideMenu"]["Button"]
10
+ >((props, ref) => {
11
+ const {
12
+ className,
13
+ children,
14
+ icon,
15
+ onClick,
16
+ onDragEnd,
17
+ onDragStart,
18
+ draggable,
19
+ label,
20
+ ...rest
21
+ } = props;
22
+
23
+ // false, because rest props can be added by mantine when button is used as a trigger
24
+ // assertEmpty in this case is only used at typescript level, not runtime level
25
+ assertEmpty(rest, false);
26
+
27
+ if (icon) {
28
+ return (
29
+ <Mantine.ActionIcon
30
+ size={24}
31
+ className={className}
32
+ ref={ref}
33
+ onClick={onClick}
34
+ onDragEnd={onDragEnd}
35
+ onDragStart={onDragStart}
36
+ draggable={draggable}
37
+ aria-label={label}
38
+ {...rest}>
39
+ {icon}
40
+ </Mantine.ActionIcon>
41
+ );
42
+ }
43
+
44
+ return (
45
+ <Mantine.Button
46
+ className={className}
47
+ ref={ref}
48
+ onClick={onClick}
49
+ onDragEnd={onDragEnd}
50
+ onDragStart={onDragStart}
51
+ draggable={draggable}
52
+ aria-label={label}
53
+ {...rest}>
54
+ {children}
55
+ </Mantine.Button>
56
+ );
57
+ });