Skip to content

Commit 2839ede

Browse files
authored
refactor: reuse toolbar types and extract mantine context (#1440)
* refactor: reuse toolbar types and extract mantine context * split files for shadcn / mantine * fix
1 parent d653650 commit 2839ede

File tree

10 files changed

+504
-487
lines changed

10 files changed

+504
-487
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {
2+
BlockSchema,
3+
InlineContentSchema,
4+
mergeCSSClasses,
5+
StyleSchema,
6+
} from "@blocknote/core";
7+
import {
8+
BlockNoteViewProps,
9+
BlockNoteViewRaw,
10+
ComponentsContext,
11+
} from "@blocknote/react";
12+
import { components } from "./components.js";
13+
14+
export const BlockNoteView = <
15+
BSchema extends BlockSchema,
16+
ISchema extends InlineContentSchema,
17+
SSchema extends StyleSchema
18+
>(
19+
props: BlockNoteViewProps<BSchema, ISchema, SSchema>
20+
) => {
21+
const { className, ...rest } = props;
22+
23+
return (
24+
<ComponentsContext.Provider value={components}>
25+
<BlockNoteViewRaw
26+
className={mergeCSSClasses("bn-ariakit", className || "")}
27+
{...rest}
28+
/>
29+
</ComponentsContext.Provider>
30+
);
31+
};

packages/ariakit/src/components.ts

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { Components } from "@blocknote/react";
2+
3+
import { Form } from "./input/Form.js";
4+
import { TextInput } from "./input/TextInput.js";
5+
import {
6+
Menu,
7+
MenuDivider,
8+
MenuDropdown,
9+
MenuItem,
10+
MenuLabel,
11+
MenuTrigger,
12+
} from "./menu/Menu.js";
13+
import { Panel } from "./panel/Panel.js";
14+
import { PanelButton } from "./panel/PanelButton.js";
15+
import { PanelFileInput } from "./panel/PanelFileInput.js";
16+
import { PanelTab } from "./panel/PanelTab.js";
17+
import { PanelTextInput } from "./panel/PanelTextInput.js";
18+
import { Popover, PopoverContent, PopoverTrigger } from "./popover/Popover.js";
19+
import { SideMenu } from "./sideMenu/SideMenu.js";
20+
import { SideMenuButton } from "./sideMenu/SideMenuButton.js";
21+
import { GridSuggestionMenu } from "./suggestionMenu/gridSuggestionMenu/GridSuggestionMenu.js";
22+
import { GridSuggestionMenuEmptyItem } from "./suggestionMenu/gridSuggestionMenu/GridSuggestionMenuEmptyItem.js";
23+
import { GridSuggestionMenuItem } from "./suggestionMenu/gridSuggestionMenu/GridSuggestionMenuItem.js";
24+
import { GridSuggestionMenuLoader } from "./suggestionMenu/gridSuggestionMenu/GridSuggestionMenuLoader.js";
25+
import { SuggestionMenu } from "./suggestionMenu/SuggestionMenu.js";
26+
import { SuggestionMenuEmptyItem } from "./suggestionMenu/SuggestionMenuEmptyItem.js";
27+
import { SuggestionMenuItem } from "./suggestionMenu/SuggestionMenuItem.js";
28+
import { SuggestionMenuLabel } from "./suggestionMenu/SuggestionMenuLabel.js";
29+
import { SuggestionMenuLoader } from "./suggestionMenu/SuggestionMenuLoader.js";
30+
import { ExtendButton } from "./tableHandle/ExtendButton.js";
31+
import { TableHandle } from "./tableHandle/TableHandle.js";
32+
import { Toolbar } from "./toolbar/Toolbar.js";
33+
import { ToolbarButton } from "./toolbar/ToolbarButton.js";
34+
import { ToolbarSelect } from "./toolbar/ToolbarSelect.js";
35+
36+
export const components: Components = {
37+
FormattingToolbar: {
38+
Root: Toolbar,
39+
Button: ToolbarButton,
40+
Select: ToolbarSelect,
41+
},
42+
FilePanel: {
43+
Root: Panel,
44+
Button: PanelButton,
45+
FileInput: PanelFileInput,
46+
TabPanel: PanelTab,
47+
TextInput: PanelTextInput,
48+
},
49+
GridSuggestionMenu: {
50+
Root: GridSuggestionMenu,
51+
Item: GridSuggestionMenuItem,
52+
EmptyItem: GridSuggestionMenuEmptyItem,
53+
Loader: GridSuggestionMenuLoader,
54+
},
55+
LinkToolbar: {
56+
Root: Toolbar,
57+
Button: ToolbarButton,
58+
},
59+
SideMenu: {
60+
Root: SideMenu,
61+
Button: SideMenuButton,
62+
},
63+
SuggestionMenu: {
64+
Root: SuggestionMenu,
65+
Item: SuggestionMenuItem,
66+
EmptyItem: SuggestionMenuEmptyItem,
67+
Label: SuggestionMenuLabel,
68+
Loader: SuggestionMenuLoader,
69+
},
70+
TableHandle: {
71+
Root: TableHandle,
72+
ExtendButton: ExtendButton,
73+
},
74+
Generic: {
75+
Toolbar: {
76+
Root: Toolbar,
77+
Button: ToolbarButton,
78+
},
79+
Form: {
80+
Root: Form,
81+
TextInput: TextInput,
82+
},
83+
Menu: {
84+
Root: Menu,
85+
Trigger: MenuTrigger,
86+
Dropdown: MenuDropdown,
87+
Divider: MenuDivider,
88+
Label: MenuLabel,
89+
Item: MenuItem,
90+
},
91+
Popover: {
92+
Root: Popover,
93+
Trigger: PopoverTrigger,
94+
Content: PopoverContent,
95+
},
96+
},
97+
};

packages/ariakit/src/index.tsx

Lines changed: 2 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,4 @@
1-
import {
2-
BlockSchema,
3-
InlineContentSchema,
4-
mergeCSSClasses,
5-
StyleSchema,
6-
} from "@blocknote/core";
7-
import {
8-
BlockNoteViewProps,
9-
BlockNoteViewRaw,
10-
Components,
11-
ComponentsContext,
12-
} from "@blocknote/react";
13-
14-
import { Form } from "./input/Form.js";
15-
import { TextInput } from "./input/TextInput.js";
16-
import {
17-
Menu,
18-
MenuDivider,
19-
MenuDropdown,
20-
MenuItem,
21-
MenuLabel,
22-
MenuTrigger,
23-
} from "./menu/Menu.js";
24-
import { Panel } from "./panel/Panel.js";
25-
import { PanelButton } from "./panel/PanelButton.js";
26-
import { PanelFileInput } from "./panel/PanelFileInput.js";
27-
import { PanelTab } from "./panel/PanelTab.js";
28-
import { PanelTextInput } from "./panel/PanelTextInput.js";
29-
import { Popover, PopoverContent, PopoverTrigger } from "./popover/Popover.js";
30-
import { SideMenu } from "./sideMenu/SideMenu.js";
31-
import { SideMenuButton } from "./sideMenu/SideMenuButton.js";
32-
import { GridSuggestionMenu } from "./suggestionMenu/gridSuggestionMenu/GridSuggestionMenu.js";
33-
import { GridSuggestionMenuEmptyItem } from "./suggestionMenu/gridSuggestionMenu/GridSuggestionMenuEmptyItem.js";
34-
import { GridSuggestionMenuItem } from "./suggestionMenu/gridSuggestionMenu/GridSuggestionMenuItem.js";
35-
import { GridSuggestionMenuLoader } from "./suggestionMenu/gridSuggestionMenu/GridSuggestionMenuLoader.js";
36-
import { SuggestionMenu } from "./suggestionMenu/SuggestionMenu.js";
37-
import { SuggestionMenuEmptyItem } from "./suggestionMenu/SuggestionMenuEmptyItem.js";
38-
import { SuggestionMenuItem } from "./suggestionMenu/SuggestionMenuItem.js";
39-
import { SuggestionMenuLabel } from "./suggestionMenu/SuggestionMenuLabel.js";
40-
import { SuggestionMenuLoader } from "./suggestionMenu/SuggestionMenuLoader.js";
41-
import { ExtendButton } from "./tableHandle/ExtendButton.js";
42-
import { TableHandle } from "./tableHandle/TableHandle.js";
43-
import { Toolbar } from "./toolbar/Toolbar.js";
44-
import { ToolbarButton } from "./toolbar/ToolbarButton.js";
45-
import { ToolbarSelect } from "./toolbar/ToolbarSelect.js";
46-
471
import "./style.css";
482

49-
export const components: Components = {
50-
FormattingToolbar: {
51-
Root: Toolbar,
52-
Button: ToolbarButton,
53-
Select: ToolbarSelect,
54-
},
55-
FilePanel: {
56-
Root: Panel,
57-
Button: PanelButton,
58-
FileInput: PanelFileInput,
59-
TabPanel: PanelTab,
60-
TextInput: PanelTextInput,
61-
},
62-
GridSuggestionMenu: {
63-
Root: GridSuggestionMenu,
64-
Item: GridSuggestionMenuItem,
65-
EmptyItem: GridSuggestionMenuEmptyItem,
66-
Loader: GridSuggestionMenuLoader,
67-
},
68-
LinkToolbar: {
69-
Root: Toolbar,
70-
Button: ToolbarButton,
71-
},
72-
SideMenu: {
73-
Root: SideMenu,
74-
Button: SideMenuButton,
75-
},
76-
SuggestionMenu: {
77-
Root: SuggestionMenu,
78-
Item: SuggestionMenuItem,
79-
EmptyItem: SuggestionMenuEmptyItem,
80-
Label: SuggestionMenuLabel,
81-
Loader: SuggestionMenuLoader,
82-
},
83-
TableHandle: {
84-
Root: TableHandle,
85-
ExtendButton: ExtendButton,
86-
},
87-
Generic: {
88-
Form: {
89-
Root: Form,
90-
TextInput: TextInput,
91-
},
92-
Menu: {
93-
Root: Menu,
94-
Trigger: MenuTrigger,
95-
Dropdown: MenuDropdown,
96-
Divider: MenuDivider,
97-
Label: MenuLabel,
98-
Item: MenuItem,
99-
},
100-
Popover: {
101-
Root: Popover,
102-
Trigger: PopoverTrigger,
103-
Content: PopoverContent,
104-
},
105-
},
106-
};
107-
108-
export const BlockNoteView = <
109-
BSchema extends BlockSchema,
110-
ISchema extends InlineContentSchema,
111-
SSchema extends StyleSchema
112-
>(
113-
props: BlockNoteViewProps<BSchema, ISchema, SSchema>
114-
) => {
115-
const { className, ...rest } = props;
116-
117-
return (
118-
<ComponentsContext.Provider value={components}>
119-
<BlockNoteViewRaw
120-
className={mergeCSSClasses("bn-ariakit", className || "")}
121-
{...rest}
122-
/>
123-
</ComponentsContext.Provider>
124-
);
125-
};
3+
export * from "./BlockNoteView.js";
4+
export * from "./components.js";
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import {
2+
BlockSchema,
3+
InlineContentSchema,
4+
mergeCSSClasses,
5+
StyleSchema,
6+
} from "@blocknote/core";
7+
import {
8+
BlockNoteViewProps,
9+
BlockNoteViewRaw,
10+
ComponentsContext,
11+
useBlockNoteContext,
12+
usePrefersColorScheme,
13+
} from "@blocknote/react";
14+
import { MantineProvider } from "@mantine/core";
15+
import { useCallback } from "react";
16+
import {
17+
applyBlockNoteCSSVariablesFromTheme,
18+
removeBlockNoteCSSVariables,
19+
Theme,
20+
} from "./BlockNoteTheme.js";
21+
import { components } from "./components.js";
22+
import "./style.css";
23+
24+
const mantineTheme = {
25+
// Removes button press effect
26+
activeClassName: "",
27+
};
28+
29+
export const BlockNoteView = <
30+
BSchema extends BlockSchema,
31+
ISchema extends InlineContentSchema,
32+
SSchema extends StyleSchema
33+
>(
34+
props: Omit<BlockNoteViewProps<BSchema, ISchema, SSchema>, "theme"> & {
35+
theme?:
36+
| "light"
37+
| "dark"
38+
| Theme
39+
| {
40+
light: Theme;
41+
dark: Theme;
42+
};
43+
}
44+
) => {
45+
const { className, theme, ...rest } = props;
46+
47+
const existingContext = useBlockNoteContext();
48+
const systemColorScheme = usePrefersColorScheme();
49+
const defaultColorScheme =
50+
existingContext?.colorSchemePreference || systemColorScheme;
51+
52+
const ref = useCallback(
53+
(node: HTMLDivElement | null) => {
54+
if (!node) {
55+
// todo: clean variables?
56+
return;
57+
}
58+
59+
removeBlockNoteCSSVariables(node);
60+
61+
if (typeof theme === "object") {
62+
if ("light" in theme && "dark" in theme) {
63+
applyBlockNoteCSSVariablesFromTheme(
64+
theme[defaultColorScheme === "dark" ? "dark" : "light"],
65+
node
66+
);
67+
return;
68+
}
69+
70+
applyBlockNoteCSSVariablesFromTheme(theme, node);
71+
return;
72+
}
73+
},
74+
[defaultColorScheme, theme]
75+
);
76+
77+
return (
78+
<ComponentsContext.Provider value={components}>
79+
{/* `cssVariablesSelector` scopes Mantine CSS variables to only the editor, */}
80+
{/* as proposed here: https://github.com/orgs/mantinedev/discussions/5685 */}
81+
<MantineProvider
82+
theme={mantineTheme}
83+
cssVariablesSelector=".bn-mantine"
84+
// This gets the element to set `data-mantine-color-scheme` on. Since we
85+
// don't need this attribute (we use our own theming API), we return
86+
// undefined here.
87+
getRootElement={() => undefined}>
88+
<BlockNoteViewRaw
89+
className={mergeCSSClasses("bn-mantine", className || "")}
90+
theme={typeof theme === "object" ? undefined : theme}
91+
{...rest}
92+
ref={ref}
93+
/>
94+
</MantineProvider>
95+
</ComponentsContext.Provider>
96+
);
97+
};

0 commit comments

Comments
 (0)