Skip to content

Commit 8ecb21b

Browse files
Refactor/cleanup mount system (#567)
* cleanup mount system * demo * wip * fix build * fix * fix light / dark mode * clean examples * clean examples * docs * misc * refs * better errors * add default block / partialblock types * wip: examples * fix theme * update interop examples * Small fixes --------- Co-authored-by: Matthew Lipski <[email protected]>
1 parent fe45267 commit 8ecb21b

File tree

213 files changed

+1761
-1191
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

213 files changed

+1761
-1191
lines changed

docs/components/example/ExampleBlock.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
import { AiFillGithub, AiFillCodeSandboxCircle } from "react-icons/ai";
1+
import dynamic from "next/dynamic";
2+
import { AiFillCodeSandboxCircle, AiFillGithub } from "react-icons/ai";
23

34
import { examples } from "./generated/exampleComponents.gen";
45
import "./styles.css";
56

7+
68
const baseGitHubURL =
79
"https://github.com/TypeCellOS/BlockNote/tree/main/examples/";
810
const baseCodeSandboxURL =
911
"https://githubbox.com/TypeCellOS/BlockNote/tree/main/examples/";
1012

13+
const ExampleWrapper = dynamic(() => import("./ExampleWrapper"), {
14+
ssr: false,
15+
});
16+
1117
export function ExampleBlock(props: {
1218
name: keyof typeof examples;
1319
children: any;
@@ -16,8 +22,7 @@ export function ExampleBlock(props: {
1622
// if (!example) {
1723
// throw new Error("invalid example");
1824
// }
19-
const example = examples[props.name];
20-
const App = example.App;
25+
2126

2227
return (
2328
<div className="nx-bg-primary-700/5 dark:nx-bg-primary-300/10 mt-6 rounded-lg p-4">
@@ -40,7 +45,7 @@ export function ExampleBlock(props: {
4045
</button>
4146
</div>
4247
<div className={"h-64 overflow-scroll rounded-lg"}>
43-
<App />
48+
<ExampleWrapper name={props.name} />
4449
</div>
4550
{props.children}
4651
</div>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"use client";
2+
import { BlockNoteContext } from "@blocknote/react";
3+
import { useTheme } from "nextra-theme-docs";
4+
import { examples } from "./generated/exampleComponents.gen";
5+
6+
export default function ThemedExample(props: { name: keyof typeof examples }) {
7+
const example = examples[props.name];
8+
const App = example.App;
9+
const { theme } = useTheme();
10+
11+
return (
12+
<BlockNoteContext.Provider
13+
value={{ colorSchemePreference: theme === "dark" ? "dark" : "light" }}>
14+
<App />
15+
</BlockNoteContext.Provider>
16+
);
17+
}

docs/components/pages/landing/hero/Demo.tsx

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
22
import { BlockNoteView, useBlockNote } from "@blocknote/react";
33
import "@blocknote/react/style.css";
4-
import { useEffect, useMemo, useState } from "react";
4+
import { useMemo } from "react";
55
import YPartyKitProvider from "y-partykit/provider";
66
import * as Y from "yjs";
77

88
import "./styles.css";
99

10-
const html = document.getElementsByTagName("html")[0];
11-
const getTheme = () => (html.className.includes("dark") ? "dark" : "light");
12-
1310
const colors = [
1411
"#958DF1",
1512
"#F98181",
@@ -56,8 +53,10 @@ function getUTCDateYYYYMMDD() {
5653
return `${year}${formattedMonth}${formattedDay}`;
5754
}
5855

59-
export function ReactBlockNote() {
60-
const [theme, setTheme] = useState<"dark" | "light">(() => getTheme());
56+
export function ReactBlockNote(props: {
57+
theme: "light" | "dark";
58+
}) {
59+
6160

6261
const [doc, provider] = useMemo(() => {
6362
console.log("create");
@@ -86,39 +85,24 @@ export function ReactBlockNote() {
8685
[],
8786
);
8887

89-
useEffect(() => {
90-
let shownAlert = false;
91-
const listener = () => {
92-
if (!shownAlert) {
93-
alert(
94-
"Text you enter in this demo is displayed publicly on the internet to show multiplayer features. Be kind :)",
95-
);
96-
shownAlert = true;
97-
}
98-
};
99-
editor?.domElement?.addEventListener("focus", listener);
100-
return () => {
101-
editor?.domElement?.removeEventListener("focus", listener);
102-
};
103-
}, [editor?.domElement]);
104-
105-
useEffect(() => {
106-
const observer = new MutationObserver((mutationList) => {
107-
mutationList.forEach(function (mutation) {
108-
if (
109-
mutation.type === "attributes" &&
110-
mutation.attributeName === "class"
111-
) {
112-
setTheme(getTheme());
113-
}
114-
});
115-
});
116-
observer.observe(html, { attributes: true });
117-
118-
return () => observer.disconnect();
119-
}, []);
120-
121-
return <BlockNoteView editor={editor} theme={theme} />;
88+
// TODO
89+
// useEffect(() => {
90+
// let shownAlert = false;
91+
// const listener = () => {
92+
// if (!shownAlert) {
93+
// alert(
94+
// "Text you enter in this demo is displayed publicly on the internet to show multiplayer features. Be kind :)",
95+
// );
96+
// shownAlert = true;
97+
// }
98+
// };
99+
// editor?.domElement?.addEventListener("focus", listener);
100+
// return () => {
101+
// editor?.domElement?.removeEventListener("focus", listener);
102+
// };
103+
// }, [editor?.domElement]);
104+
105+
return <BlockNoteView editor={editor} theme={props.theme} />;
122106
}
123107

124108
export default ReactBlockNote;

docs/components/pages/landing/hero/Hero.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
// import { PackLogo } from "../../logos/PackLogo";
22

33
import dynamic from "next/dynamic";
4-
import { FadeIn } from "../shared/FadeIn";
5-
import { HeroText, SectionSubtext } from "../../home-shared/Headings";
64
import Image from "next/image";
5+
import { HeroText, SectionSubtext } from "../../home-shared/Headings";
6+
import { FadeIn } from "../shared/FadeIn";
77

8-
import tryHereImageLight from "../../../../public/img/assets/try.svg";
8+
import { useTheme } from "nextra-theme-docs";
99
import tryHereImageDark from "../../../../public/img/assets/try.dark.svg";
10+
import tryHereImageLight from "../../../../public/img/assets/try.svg";
1011

1112
const Demo = dynamic(() => import("@/components/pages/landing/hero/Demo"), {
1213
ssr: false,
1314
});
1415

1516
export function Hero() {
17+
const { theme } = useTheme();
1618
return (
1719
<section className="relative flex h-fit w-full items-center justify-center overflow-hidden py-36">
1820
<div className="z-20 flex w-screen max-w-full flex-col items-center justify-between gap-16 px-6 md:max-w-screen-md xl:max-w-[1440px] xl:flex-row">
@@ -62,7 +64,7 @@ export function Hero() {
6264
</FadeIn>
6365
<div className="relative z-20 h-full w-full overflow-scroll overscroll-contain rounded-lg">
6466
{/* TODO: Wait for editor & collab content to load before rendering. Show placeholder or delay loading?*/}
65-
<Demo />
67+
<Demo theme={theme === "dark" ? "dark" : "light"} />
6668
{/* <BackgroundIllustration className="absolute left-1/2 top-4 h-[1026px] w-[1026px] -translate-x-1/3 stroke-gray-300/70 [mask-image:linear-gradient(to_bottom,white_20%,transparent_75%)] sm:top-16 sm:-translate-x-1/2 lg:-top-16 lg:ml-12 xl:-top-14 xl:ml-0" />
6769
<div className="-mx-4 h-[448px] px-9 [mask-image:linear-gradient(to_bottom,white_60%,transparent)] sm:mx-0 lg:absolute lg:-inset-x-10 lg:-bottom-20 lg:-top-10 lg:h-auto lg:px-0 lg:pt-10 xl:-bottom-32">
6870
<PhoneFrame className="mx-auto max-w-[366px]" priority>

docs/next.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const nextConfig = withAnalyzer(
5454
cacheGroups: {
5555
vendor: {
5656
test: (module) => {
57-
console.log(module.resource);
57+
// console.log(module.resource);
5858
if (module.resource?.includes("blocknote") || module.resource?.includes("mantine")) {
5959

6060
return true;

docs/pages/docs/custom-schemas/custom-blocks.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import { Callout } from "nextra/components";
2+
import { Example } from "@/components/example";
13

24
## Custom Block Types
35

46
In addition to the default block types that BlockNote offers, you can also make your own custom blocks. Take a look at the demo below, in which we add a custom alert block to a BlockNote editor, as well as a custom [Slash Menu Item](/docs/slash-menu#custom-items) to insert it.
57

6-
<Example name="alert-block" />
8+
<Example name="custom-schema/alert-block" />
79

810
<Callout type={"info"}>While custom blocks open a lot of doors for what you can do with BlockNote, we're still working on the API and there are a few limitations for the kinds of blocks you can create. We'd love to hear your feedback on GitHub or in our Discord community!</Callout>
911

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
---
2-
title: Customizing the Editor
2+
title: Editor Setup
33
description: While you can get started with BlockNote in minutes, it's likely that you'll want to customize its features and functionality to better suit your app.
44
imageTitle: Customizing the Editor
55
path: /docs/editor
66
---
77

88
TODO:
9-
- review API
10-
- what needs to be part of useBlockNote vs the component?
11-
- expose / document hooks
12-
- controlled / uncontrolled
9+
[x] review API
10+
[x] what needs to be part of useBlockNote vs the component?
11+
[ ] document instantiation / useBlockNote
12+
[ ] expose / document hooks
13+
[ ] document events
14+
[ ] explain controlled / uncontrolled
1315

14-
# Customizing the Editor
16+
# Editor Setup
1517

1618
While you can get started with BlockNote in minutes, it's likely that you'll
1719
want to customize its features and functionality to better suit your app.
@@ -23,32 +25,41 @@ can use to customize the editor. You can find the full list of these below:
2325

2426
```typescript
2527
export type BlockNoteEditorOptions = Partial<{
26-
editable: boolean;
2728
initialContent: PartialBlock[];
28-
editorDOMAttributes: Record<string, string>;
29-
onEditorReady: (editor: BlockNoteEditor) => void;
30-
onEditorContentChange: (editor: BlockNoteEditor) => void;
31-
onTextCursorPositionChange: (editor: BlockNoteEditor) => void;
29+
domAttributes: Record<string, string>;
3230
slashMenuItems: ReactSlashMenuItem[];
3331
defaultStyles: boolean;
34-
uploadFile: (file: File) => Promise<string>
32+
uploadFile: (file: File) => Promise<string>;
33+
collaboration: CollaborationOptions;
34+
blockSpecs: BlockSpecs;
35+
inlineContentSpecs: InlineContentSpecs;
36+
styleSpecs: StyleSpecs;
3537
}>;
3638
```
3739

38-
`editable:` Locks the editor from being editable by the user if set to `false`. [Editor Functions](/docs/blocks#editor-functions) will still work.
39-
4040
`initialContent:` The content that should be in the editor when it's created, represented as an array of [partial block objects](/docs/manipulating-blocks#partial-blocks).
4141

4242
`domAttributes:` An object containing HTML attributes that should be added to various DOM elements in the editor. See [Adding DOM Attributes](/docs/theming#adding-dom-attributes) for more.
4343

44-
`onEditorReady:` A callback function that runs when the editor is ready to be used.
45-
46-
`onEditorContentChange:` A callback function that runs whenever the editor's contents change.
47-
48-
`onTextCursorPositionChange:` A callback function that runs whenever the text cursor position changes. Head to [Text Cursor](/docs/cursor-selections#text-cursor) to see how you can make use of this.
49-
5044
`slashMenuItems:` The commands that are listed in the editor's [Slash Menu](/docs/slash-menu). If this option isn't defined, a default list of commands is loaded.
5145

5246
`defaultStyles`: Whether to use the default font and reset the styles of `<p>`, `<li>`, `<h1>`, etc. elements that are used in BlockNote. Defaults to true if undefined.
5347

5448
`uploadFile`: A function which handles file uploads and eventually returns the URL to the uploaded file. Used by the [Image Toolbar](/docs/image-toolbar).
49+
50+
`collaboration`: Options for enabling real-time collaboration. See [Collaboration](/docs/collaboration) for more info.
51+
52+
`blockSpecs` (_advanced_): _advanced_ Specifications for Custom Blocks. See [Block Specs](/docs/block-specs) more info.
53+
54+
`inlineContentSpecs` (_advanced_): Specifications for Custom Inline Content. See [Inline Content Specs](/docs/inline-content-specs) for more info.
55+
56+
`styleSpecs` (_advanced_): Specifications for Custom Styles. See [Style Specs](/docs/style-specs) for more info.
57+
58+
59+
## `useBlockNote`
60+
61+
## `BlockNoteView`
62+
63+
- editable
64+
- events
65+

docs/pages/docs/ui-components/formatting-toolbar.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ If you want to change the buttons/dropdowns in the Formatting Toolbar, or replac
1919

2020
You can see how this is done in the example below, which has a custom Formatting Toolbar. It contains the same items as the default Formatting Toolbar, with and added blue text/background color and code style button.
2121

22-
<Example name="formatting-toolbar-buttons" />
22+
<Example name="ui-components/formatting-toolbar-buttons" />
2323

2424
`CustomFormattingToolbar` is the component we use to replace the default Formatting Toolbar. You can see it's made up of a bunch of other components that are exported by BlockNote. Read on to [Components](/docs/formatting-toolbar#components) to find out more about these.
2525

docs/pages/docs/ui-components/image-toolbar.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ type uploadFile = (file: File) => Promise<string>;
2727

2828
You can use the provided `uploadToTempFilesOrg` function to as a starting point, which uploads files to [tmpfiles.org](https://tmpfiles.org/). However, it's not recommended to use this in a production environment - you should use your own backend:
2929

30-
<Example name="basic" />
30+
<Example name="basic/minimal" />

docs/pages/docs/ui-components/side-menu.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ If you want to change the items in the Side Menu, or replace it altogether, you
2323

2424
You can see how this is done in the example below, which has a custom Side Menu with two items. The first one deletes the selected block, while the second one is a drag handle, which opens a menu on click.
2525

26-
<Example name="side-menu-buttons" />
26+
<Example name="ui-components/side-menu-buttons" />
2727

2828
`CustomDragHandleMenu` is the component we use to replace the default Side Menu. You can see it's made up of a bunch of other components that are exported by BlockNote. Read on to [Components](/docs/side-menu#components) to find out more about these.
2929

@@ -35,7 +35,7 @@ If you want to change the items in the Drag Handle Menu, or replace it altogethe
3535

3636
You can see how this is done in the example below, which has a custom Drag Handle Menu. It contains the default items, as well as a custom item which opens an alert.
3737

38-
<Example name="side-menu-drag-handle-items" />
38+
<Example name="ui-components/side-menu-drag-handle-items" />
3939

4040
`CustomDragHandleMenu` is the component we use to replace the default Drag Handle Menu. You can see it's made up of a bunch of other components that are exported by BlockNote. Read on to [Components](/docs/side-menu#components) to find out more about these.
4141

0 commit comments

Comments
 (0)