Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/cleanup mount system #567

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions docs/components/example/ExampleBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { AiFillGithub, AiFillCodeSandboxCircle } from "react-icons/ai";
import dynamic from "next/dynamic";
import { AiFillCodeSandboxCircle, AiFillGithub } from "react-icons/ai";

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


const baseGitHubURL =
"https://github.com/TypeCellOS/BlockNote/tree/main/examples/";
const baseCodeSandboxURL =
"https://githubbox.com/TypeCellOS/BlockNote/tree/main/examples/";

const ExampleWrapper = dynamic(() => import("./ExampleWrapper"), {
ssr: false,
});

export function ExampleBlock(props: {
name: keyof typeof examples;
children: any;
Expand All @@ -16,8 +22,7 @@ export function ExampleBlock(props: {
// if (!example) {
// throw new Error("invalid example");
// }
const example = examples[props.name];
const App = example.App;


return (
<div className="nx-bg-primary-700/5 dark:nx-bg-primary-300/10 mt-6 rounded-lg p-4">
Expand All @@ -40,7 +45,7 @@ export function ExampleBlock(props: {
</button>
</div>
<div className={"h-64 overflow-scroll rounded-lg"}>
<App />
<ExampleWrapper name={props.name} />
</div>
{props.children}
</div>
Expand Down
17 changes: 17 additions & 0 deletions docs/components/example/ThemedExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"use client";
import { BlockNoteContext } from "@blocknote/react";
import { useTheme } from "nextra-theme-docs";
import { examples } from "./generated/exampleComponents.gen";

export default function ThemedExample(props: { name: keyof typeof examples }) {
const example = examples[props.name];
const App = example.App;
const { theme } = useTheme();

return (
<BlockNoteContext.Provider
value={{ colorSchemePreference: theme === "dark" ? "dark" : "light" }}>
<App />
</BlockNoteContext.Provider>
);
}
62 changes: 23 additions & 39 deletions docs/components/pages/landing/hero/Demo.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
import { BlockNoteView, useBlockNote } from "@blocknote/react";
import "@blocknote/react/style.css";
import { useEffect, useMemo, useState } from "react";
import { useMemo } from "react";
import YPartyKitProvider from "y-partykit/provider";
import * as Y from "yjs";

import "./styles.css";

const html = document.getElementsByTagName("html")[0];
const getTheme = () => (html.className.includes("dark") ? "dark" : "light");

const colors = [
"#958DF1",
"#F98181",
Expand Down Expand Up @@ -56,8 +53,10 @@ function getUTCDateYYYYMMDD() {
return `${year}${formattedMonth}${formattedDay}`;
}

export function ReactBlockNote() {
const [theme, setTheme] = useState<"dark" | "light">(() => getTheme());
export function ReactBlockNote(props: {
theme: "light" | "dark";
}) {


const [doc, provider] = useMemo(() => {
console.log("create");
Expand Down Expand Up @@ -86,39 +85,24 @@ export function ReactBlockNote() {
[],
);

useEffect(() => {
let shownAlert = false;
const listener = () => {
if (!shownAlert) {
alert(
"Text you enter in this demo is displayed publicly on the internet to show multiplayer features. Be kind :)",
);
shownAlert = true;
}
};
editor?.domElement?.addEventListener("focus", listener);
return () => {
editor?.domElement?.removeEventListener("focus", listener);
};
}, [editor?.domElement]);

useEffect(() => {
const observer = new MutationObserver((mutationList) => {
mutationList.forEach(function (mutation) {
if (
mutation.type === "attributes" &&
mutation.attributeName === "class"
) {
setTheme(getTheme());
}
});
});
observer.observe(html, { attributes: true });

return () => observer.disconnect();
}, []);

return <BlockNoteView editor={editor} theme={theme} />;
// TODO
// useEffect(() => {
// let shownAlert = false;
// const listener = () => {
// if (!shownAlert) {
// alert(
// "Text you enter in this demo is displayed publicly on the internet to show multiplayer features. Be kind :)",
// );
// shownAlert = true;
// }
// };
// editor?.domElement?.addEventListener("focus", listener);
// return () => {
// editor?.domElement?.removeEventListener("focus", listener);
// };
// }, [editor?.domElement]);

return <BlockNoteView editor={editor} theme={props.theme} />;
}

export default ReactBlockNote;
10 changes: 6 additions & 4 deletions docs/components/pages/landing/hero/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
// import { PackLogo } from "../../logos/PackLogo";

import dynamic from "next/dynamic";
import { FadeIn } from "../shared/FadeIn";
import { HeroText, SectionSubtext } from "../../home-shared/Headings";
import Image from "next/image";
import { HeroText, SectionSubtext } from "../../home-shared/Headings";
import { FadeIn } from "../shared/FadeIn";

import tryHereImageLight from "../../../../public/img/assets/try.svg";
import { useTheme } from "nextra-theme-docs";
matthewlipski marked this conversation as resolved.
Show resolved Hide resolved
import tryHereImageDark from "../../../../public/img/assets/try.dark.svg";
import tryHereImageLight from "../../../../public/img/assets/try.svg";

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

export function Hero() {
const { theme } = useTheme();
return (
<section className="relative flex h-fit w-full items-center justify-center overflow-hidden py-36">
<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">
Expand Down Expand Up @@ -62,7 +64,7 @@ export function Hero() {
</FadeIn>
<div className="relative z-20 h-full w-full overflow-scroll overscroll-contain rounded-lg">
{/* TODO: Wait for editor & collab content to load before rendering. Show placeholder or delay loading?*/}
<Demo />
<Demo theme={theme === "dark" ? "dark" : "light"} />
{/* <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" />
<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">
<PhoneFrame className="mx-auto max-w-[366px]" priority>
Expand Down
2 changes: 1 addition & 1 deletion docs/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const nextConfig = withAnalyzer(
cacheGroups: {
vendor: {
test: (module) => {
console.log(module.resource);
// console.log(module.resource);
if (module.resource?.includes("blocknote") || module.resource?.includes("mantine")) {

return true;
Expand Down
4 changes: 3 additions & 1 deletion docs/pages/docs/custom-schemas/custom-blocks.mdx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Callout } from "nextra/components";
import { Example } from "@/components/example";

## Custom Block Types

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.

<Example name="alert-block" />
<Example name="custom-schema/alert-block" />

<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>

Expand Down
51 changes: 31 additions & 20 deletions docs/pages/docs/editor-api/editor.mdx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
---
title: Customizing the Editor
title: Editor Setup
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.
imageTitle: Customizing the Editor
path: /docs/editor
---

TODO:
- review API
- what needs to be part of useBlockNote vs the component?
- expose / document hooks
- controlled / uncontrolled
[x] review API
[x] what needs to be part of useBlockNote vs the component?
[ ] document instantiation / useBlockNote
[ ] expose / document hooks
[ ] document events
[ ] explain controlled / uncontrolled

# Customizing the Editor
# Editor Setup

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.
Expand All @@ -23,32 +25,41 @@ can use to customize the editor. You can find the full list of these below:

```typescript
export type BlockNoteEditorOptions = Partial<{
editable: boolean;
initialContent: PartialBlock[];
editorDOMAttributes: Record<string, string>;
onEditorReady: (editor: BlockNoteEditor) => void;
onEditorContentChange: (editor: BlockNoteEditor) => void;
onTextCursorPositionChange: (editor: BlockNoteEditor) => void;
domAttributes: Record<string, string>;
slashMenuItems: ReactSlashMenuItem[];
defaultStyles: boolean;
uploadFile: (file: File) => Promise<string>
uploadFile: (file: File) => Promise<string>;
collaboration: CollaborationOptions;
blockSpecs: BlockSpecs;
inlineContentSpecs: InlineContentSpecs;
styleSpecs: StyleSpecs;
}>;
```

`editable:` Locks the editor from being editable by the user if set to `false`. [Editor Functions](/docs/blocks#editor-functions) will still work.

`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).

`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.

`onEditorReady:` A callback function that runs when the editor is ready to be used.

`onEditorContentChange:` A callback function that runs whenever the editor's contents change.

`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.

`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.

`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.

`uploadFile`: A function which handles file uploads and eventually returns the URL to the uploaded file. Used by the [Image Toolbar](/docs/image-toolbar).

`collaboration`: Options for enabling real-time collaboration. See [Collaboration](/docs/collaboration) for more info.

`blockSpecs` (_advanced_): _advanced_ Specifications for Custom Blocks. See [Block Specs](/docs/block-specs) more info.

`inlineContentSpecs` (_advanced_): Specifications for Custom Inline Content. See [Inline Content Specs](/docs/inline-content-specs) for more info.

`styleSpecs` (_advanced_): Specifications for Custom Styles. See [Style Specs](/docs/style-specs) for more info.


## `useBlockNote`

## `BlockNoteView`

- editable
- events

2 changes: 1 addition & 1 deletion docs/pages/docs/ui-components/formatting-toolbar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ If you want to change the buttons/dropdowns in the Formatting Toolbar, or replac

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.

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

`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.

Expand Down
2 changes: 1 addition & 1 deletion docs/pages/docs/ui-components/image-toolbar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ type uploadFile = (file: File) => Promise<string>;

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:

<Example name="basic" />
<Example name="basic/minimal" />
4 changes: 2 additions & 2 deletions docs/pages/docs/ui-components/side-menu.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ If you want to change the items in the Side Menu, or replace it altogether, you

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.

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

`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.

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

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.

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

`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.

Expand Down
2 changes: 1 addition & 1 deletion docs/pages/docs/ui-components/slash-menu.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ If you want to change the items that appear in the Slash Menu, you can do that u

You can see how this is done in the example below, which has a custom Slash Menu item list. It includes all the default Slash Menu items, as well as a custom item, which inserts a new block below with "Hello World" in bold.

<Example name="slash-menu-items" />
<Example name="ui-components/slash-menu-items" />

To find out how to get the default Slash Menu items, as well as how to make custom items, read on to [Slash Menu Items](/docs/slash-menu#slash-menu-items)

Expand Down
4 changes: 2 additions & 2 deletions docs/pages/docs/ui-components/ui-elements.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ Explicitly adding `Positioner` components as children of `BlockNoteView` allows

In the following example, we remove the Side Menu from the editor. This is done by adding all `Positioner` components as children of `BlockNoteView`, for each UI element except the Side Menu:

<Example name="ui-elements-remove" />
<Example name="ui-components/ui-elements-remove" />

Each further `Positioner` component you remove will remove its corresponding UI element from the editor. If you only want to keep the editor itself, add only an empty fragment (`<></>`) to `BlockNoteView`'s children.

## Replacing UI Elements

In the following example, the Side Menu is replaced with a simple component which just displays the name of the element:

<Example name="ui-elements-replace" />
<Example name="ui-components/ui-elements-replace" />

As you can see, this is done by passing a React component to the `sideMenu` prop of `SideMenuPositioner`. Each `Positioner` element has a prop through which you can pass the component you want to render (`formattingToolbar` for the Formatting Toolbar, etc.). If nothing is passed, the `Positioner` will render the default UI element.

4 changes: 1 addition & 3 deletions examples/01-basic/01-minimal/.bnexample.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{
"playground": true,
"docs": false,
"group": "Basic Examples",
"order": 1
"docs": true
}
13 changes: 2 additions & 11 deletions examples/01-basic/01-minimal/App.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
import { uploadToTmpFilesDotOrg_DEV_ONLY } from "@blocknote/core";
import { BlockNoteView, useBlockNote } from "@blocknote/react";
import "@blocknote/react/style.css";

export default function App() {
// Creates a new editor instance.
const editor = useBlockNote({
domAttributes: {
editor: {
class: "editor",
"data-test": "editor",
},
},
uploadFile: uploadToTmpFilesDotOrg_DEV_ONLY,
});
const editor = useBlockNote({});

// Renders the editor instance using a React component.
return <BlockNoteView className="root" editor={editor} />;
return <BlockNoteView editor={editor} />;
}
2 changes: 2 additions & 0 deletions examples/01-basic/01-minimal/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# Basic Editor Setup

This example shows the minimal code required to setup your React rich text editor with BlockNote.
8 changes: 4 additions & 4 deletions examples/01-basic/01-minimal/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import App from "./App";

const root = createRoot(document.getElementById("root")!);
root.render(
// <React.StrictMode >
<App />
// </React.StrictMode>
);
<React.StrictMode>
<App />
</React.StrictMode>
);
4 changes: 4 additions & 0 deletions examples/01-basic/02-block-objects/.bnexample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"playground": true,
"docs": true
}
Loading
Loading