diff --git a/docs/api/og.tsx b/docs/api/og.tsx.bak similarity index 99% rename from docs/api/og.tsx rename to docs/api/og.tsx.bak index b7794f6e1b..dd02f0b647 100644 --- a/docs/api/og.tsx +++ b/docs/api/og.tsx.bak @@ -1,12 +1,11 @@ import { ImageResponse } from "@vercel/og"; -import React from "react"; export const config = { runtime: "edge", }; const font = fetch( - new URL("../docs/public/fonts/Gilroy-Regular.ttf", import.meta.url) + new URL("../../assets/fonts/Gilroy-Regular.ttf", import.meta.url), ).then((res) => res.arrayBuffer()); export default async function handler(request: { url: string }) { diff --git a/docs/public/fonts/Gilroy-Bold.ttf b/docs/assets/fonts/Gilroy-Bold.ttf similarity index 100% rename from docs/public/fonts/Gilroy-Bold.ttf rename to docs/assets/fonts/Gilroy-Bold.ttf diff --git a/docs/public/fonts/Gilroy-ExtraBold.ttf b/docs/assets/fonts/Gilroy-ExtraBold.ttf similarity index 100% rename from docs/public/fonts/Gilroy-ExtraBold.ttf rename to docs/assets/fonts/Gilroy-ExtraBold.ttf diff --git a/docs/public/fonts/Gilroy-Medium.ttf b/docs/assets/fonts/Gilroy-Medium.ttf similarity index 100% rename from docs/public/fonts/Gilroy-Medium.ttf rename to docs/assets/fonts/Gilroy-Medium.ttf diff --git a/docs/public/fonts/Gilroy-Regular.ttf b/docs/assets/fonts/Gilroy-Regular.ttf similarity index 100% rename from docs/public/fonts/Gilroy-Regular.ttf rename to docs/assets/fonts/Gilroy-Regular.ttf diff --git a/docs/public/fonts/Gilroy-SemiBold.ttf b/docs/assets/fonts/Gilroy-SemiBold.ttf similarity index 100% rename from docs/public/fonts/Gilroy-SemiBold.ttf rename to docs/assets/fonts/Gilroy-SemiBold.ttf diff --git a/docs/public/fonts/gilroy-bold.woff2 b/docs/assets/fonts/gilroy-bold.woff2 similarity index 100% rename from docs/public/fonts/gilroy-bold.woff2 rename to docs/assets/fonts/gilroy-bold.woff2 diff --git a/docs/public/fonts/gilroy-extrabold.woff2 b/docs/assets/fonts/gilroy-extrabold.woff2 similarity index 100% rename from docs/public/fonts/gilroy-extrabold.woff2 rename to docs/assets/fonts/gilroy-extrabold.woff2 diff --git a/docs/public/fonts/gilroy-medium.woff2 b/docs/assets/fonts/gilroy-medium.woff2 similarity index 100% rename from docs/public/fonts/gilroy-medium.woff2 rename to docs/assets/fonts/gilroy-medium.woff2 diff --git a/docs/public/fonts/gilroy-regular.woff2 b/docs/assets/fonts/gilroy-regular.woff2 similarity index 100% rename from docs/public/fonts/gilroy-regular.woff2 rename to docs/assets/fonts/gilroy-regular.woff2 diff --git a/docs/public/fonts/gilroy-semibold.woff2 b/docs/assets/fonts/gilroy-semibold.woff2 similarity index 100% rename from docs/public/fonts/gilroy-semibold.woff2 rename to docs/assets/fonts/gilroy-semibold.woff2 diff --git a/docs/package.json b/docs/package.json index 3b1d5147ac..8ec05f7036 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "dev": "next dev", - "build": "next build", + "docs:build": "next build", "start": "next start", "lint": "next lint" }, diff --git a/docs/pages/docs/_meta.json b/docs/pages/docs/_meta.json index bfd05ce72a..9d5049f9ce 100644 --- a/docs/pages/docs/_meta.json +++ b/docs/pages/docs/_meta.json @@ -1,7 +1,7 @@ { - "index": "Introduction", "quickstart": "Quickstart", + "editor-basics": "Editor Basics", "editor-api": "Editor API", "styling-theming": "Styling & Theming", "ui-components": "UI Components", diff --git a/docs/pages/docs/advanced/vanilla-js.mdx b/docs/pages/docs/advanced/vanilla-js.mdx index 518ed18903..0921d07b11 100644 --- a/docs/pages/docs/advanced/vanilla-js.mdx +++ b/docs/pages/docs/advanced/vanilla-js.mdx @@ -12,7 +12,10 @@ import { Callout } from "nextra/components"; BlockNote is mainly designed as a quick and easy drop-in block-based editor for React apps, but can also be used in vanilla JavaScript apps. However, this does involve writing your own UI elements. - We recommend using BlockNote with React so you can use the built-in UI components. This document will explain how you can use BlockNote without React, and write your own components, but this is not recommended as you'll lose the great out-of-the-box experience that BlockNote offers. + We recommend using BlockNote with React so you can use the built-in UI + components. This document will explain how you can use BlockNote without + React, and write your own components, but this is not recommended as you'll + lose the great out-of-the-box experience that BlockNote offers. ## Installing with NPM @@ -25,19 +28,14 @@ npm install @blocknote/core ## Creating an editor -TODO: AFAIK there is actually just no way of doing this anymore - This is how to create a new BlockNote editor: -``` typescript +```typescript import { BlockNoteEditor } from "@blocknote/core"; -const editor = BlockNoteEditor.create({ - element: document.getElementById("root")!, // element to append the editor to - onEditorContentChange: ({) => { - console.log(editor.getJSON()); - } -}); +const editor = BlockNoteEditor.create(); + +editor.mount(document.getElementById("root")); // element to append the editor to ``` Now, you'll have a plain BlockNote instance on your page. However, it's missing some menus and other UI elements. @@ -70,60 +68,58 @@ Let's look at how you could add the [Side Menu]() to your editor: import { BlockNoteEditor } from "@blocknote/core"; const editor = BlockNoteEditor.create({ - element: document.getElementById("root")! + element: document.getElementById("root")!, }); export function createButton(text: string, onClick?: () => void) { - const element = document.createElement("a"); - element.href = "#"; - element.text = text; - element.style.margin = "10px"; - - if (onClick) { - element.addEventListener("click", (e) => { - onClick(); - e.preventDefault(); - }); - } - - return element; + const element = document.createElement("a"); + element.href = "#"; + element.text = text; + element.style.margin = "10px"; + + if (onClick) { + element.addEventListener("click", (e) => { + onClick(); + e.preventDefault(); + }); + } + + return element; } let element: HTMLElement; editor.sideMenu.onUpdate((sideMenuState) => { - if (!element) { - element = document.createElement("div"); - element.style.background = "gray"; - element.style.position = "absolute"; - element.style.padding = "10px"; - element.style.opacity = "0.8"; - const addBtn = createButton("+", () => { - editor.sideMenu.addBlock(); - }); - element.appendChild(addBtn); - - const dragBtn = createButton("::", () => {}); - - dragBtn.addEventListener("dragstart", editor.sideMenu.blockDragStart); - dragBtn.addEventListener("dragend", editor.sideMenu.blockDragEnd); - dragBtn.draggable = true; - element.style.display = "none"; - element.appendChild(dragBtn); - - document.getElementById("root")!.appendChild(element); - } - - if (sideMenuState.show) { - element.style.display = "block"; - - element.style.top = sideMenuState.referencePos.top + "px"; - element.style.left = - sideMenuState.referencePos.x - element.offsetWidth + "px"; - } else { - element.style.display = "none"; - } + if (!element) { + element = document.createElement("div"); + element.style.background = "gray"; + element.style.position = "absolute"; + element.style.padding = "10px"; + element.style.opacity = "0.8"; + const addBtn = createButton("+", () => { + editor.sideMenu.addBlock(); + }); + element.appendChild(addBtn); + + const dragBtn = createButton("::", () => {}); + + dragBtn.addEventListener("dragstart", editor.sideMenu.blockDragStart); + dragBtn.addEventListener("dragend", editor.sideMenu.blockDragEnd); + dragBtn.draggable = true; + element.style.display = "none"; + element.appendChild(dragBtn); + + document.getElementById("root")!.appendChild(element); + } + + if (sideMenuState.show) { + element.style.display = "block"; + + element.style.top = sideMenuState.referencePos.top + "px"; + element.style.left = + sideMenuState.referencePos.x - element.offsetWidth + "px"; + } else { + element.style.display = "none"; + } }); ``` - -TODO: Bring back vanilla example? diff --git a/docs/pages/docs/custom-schemas.mdx b/docs/pages/docs/custom-schemas.mdx index 700a40cdda..b83c34a1a6 100644 --- a/docs/pages/docs/custom-schemas.mdx +++ b/docs/pages/docs/custom-schemas.mdx @@ -5,7 +5,7 @@ description: Learn how to create custom schemas for your BlockNote editor # Custom Schemas (advanced) -By default, BlockNote documents support different kind of blocks, inline content and text styles. See xxxx. +By default, BlockNote documents support different kind of blocks, inline content and text styles (see [default schema](/docs/editor-basics/default-schema)). However, you can extend BlockNote and create custom schemas to support your own blocks, inline content and text styles. ## Custom Blocks diff --git a/docs/pages/docs/custom-schemas/custom-styles.mdx b/docs/pages/docs/custom-schemas/custom-styles.mdx index 7a2e79d55c..729d6415ce 100644 --- a/docs/pages/docs/custom-schemas/custom-styles.mdx +++ b/docs/pages/docs/custom-schemas/custom-styles.mdx @@ -20,19 +20,14 @@ function createReactStyleSpec( Let's look at our custom font style from the demo, and go over each field to explain how it works: ```typescript -const Mention = createReactStyleSpec( +export const Font = createReactStyleSpec( { - type: "mention", - propSchema: { - user: { - default: "Unknown", - }, - }, - content: "none", - } as const, + type: "font", + propSchema: "string", + }, { render: (props) => ( - ... + ), } ); @@ -57,7 +52,7 @@ Defines the identifier of the custom style. The `PropSchema` specifies whether the style can only be toggled (`"boolean"`), or whether it can take a string value (`"string"`). Having a string value is useful for e.g. setting a color on the style. -_In the font style demo, we set this to `"string"` so we can store the font name._ +_In the font style demo, we set this to `"string"` so we can store the font family._ #### Style Implementation (`ReactCustomStyleImplementation`) @@ -78,9 +73,9 @@ This is your React component which defines how your custom style should be rende `value:` The string value of the style, this is only available if your style config contains `propSchema: "string"`. -`contentRef:` A React `ref` you can use to mark which element in your style is editable. +`contentRef:` A React `ref` to mark the editable element. -_Note that since styles are applied to text, you must set `contentRef` somewhere in you component, and should also return an HTML inline element._ +_Note that in contrast to Custom Blocks and Inline Content, the `render` function of Custom Styles cannot access React Context or other state. They should be plain React functions analogous to the example._ ### Adding Custom Style to the Editor diff --git a/docs/pages/docs/editor-api.mdx b/docs/pages/docs/editor-api.mdx index b6fc4c620b..45cd273b96 100644 --- a/docs/pages/docs/editor-api.mdx +++ b/docs/pages/docs/editor-api.mdx @@ -1 +1,9 @@ -hello \ No newline at end of file +# Editor API + +BlockNote exposes an API to interact with the editor and its contents from code. +These methods are directly available on the `BlockNoteEditor` object you created when instantiating your editor. + +- [Manipulating Blocks](/docs/editor-api/manipulating-blocks.md) explains how to read / update Blocks in the document. +- [Manipulating Inline Content](/docs/editor-api/manipulating-inline-content.md) explains how to update / read data from selected text. +- [Cursors & Selections](/docs/editor-api/cursor-selections) explains methods related to cursor positions and selections. +- [Markdown & HTML](/docs/converting-blocks) explains how to convert the document to and from Markdown and HTML. diff --git a/docs/pages/docs/editor-api/_meta.json b/docs/pages/docs/editor-api/_meta.json index 325393d7bb..7d69575259 100644 --- a/docs/pages/docs/editor-api/_meta.json +++ b/docs/pages/docs/editor-api/_meta.json @@ -1,9 +1,6 @@ { - "editor":"", - "blocks": "", - "default-blocks":"", "manipulating-blocks":"", - "block-content":"", + "manipulating-inline-content":"", "cursor-selections":"", "converting-blocks":"" } diff --git a/docs/pages/docs/editor-api/block-content.mdx b/docs/pages/docs/editor-api/block-content.mdx deleted file mode 100644 index 45fa95ade0..0000000000 --- a/docs/pages/docs/editor-api/block-content.mdx +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: Block Content -description: TODO -imageTitle: Block Content -path: /docs/block-content ---- - -TODO: where should this page be? and / or do we need API changes? (matthew has some thoughts on this) - -# Block Content - -The `content` field of a `Block` describes the content of the block. For all blocks except tables, this field is an array of `InlineContent` objects and describes the rich text content typed inside the block. - -In the example below, you can see how a sentence like "Hello __there__, [BlockNote](https://www.blocknotejs.org)" is represented as an array of `InlineContent` objects: - -TODO: DEMO - - -## `InlineContent` Types - -`InlineContent` can be styled text (rich text), a link, or a mention: - -### Styled Text - -`StyledText` is a type of `InlineContent` used to display pieces of text with styles: - -```typescript -type StyledText = { - type: "text"; - text: string; - styles: Styles; -}; -``` - -`text:` The displayed text. - -`styles:` The styles that are applied to the text. - -**Styles Object** - -`StyledText` supports a variety of styles, including bold, underline, and text color, which are represented using a `Styles` object: - -```typescript -type Styles = Partial<{ - bold: true; - italic: true; - underline: true; - strikethrough: true; - textColor: string; - backgroundColor: string; -}>; -``` - -### Links - -`Link` objects represent links to a URL: - -```typescript -type Link = { - type: "link"; - content: StyledText[]; - href: string; -}; -``` - -`content:` The styled text used to display the link. - -`href:` The URL that opens when clicking the link. - -### Mentions - -TODO - -### Custom `InlineContent` and `Styles` - -You can create your own types of `InlineContent` and `Styles` using React. Skip to the Advanced "custom schemas" section to learn more about extending the editor. (TODO: link) - -## TableContent - -Most blocks use an array of `InlineContent` objects to describe their content, but tables are slightly different. Table blocks have `TableContent` as their content, in which each row contains an array of cells, that - - -```typescript -type TableContent = { - type: "tableContent"; - rows: { - cells: InlineContent[][]; - }[]; -}; -``` - -## Editor Functions - -TODO: where should this be? - -While `InlineContent` objects are used to describe a block's content, they can be cumbersome to work with directly. Therefore, BlockNote exposes functions which make it easier to edit block contents. - -### Accessing Styles - -You can get the styles at the current [Text Cursor Position](/docs/cursor-selections#text-cursor) using the following function: - -```typescript -getActiveStyles(): Styles; - -// Usage -const styles = editor.getActiveStyles(); -``` - -If a [Selection](/docs/cursor-selections#selections) is active, this function returns the active styles at the end of the selection. - -### Adding Styles - -You can add styles to the currently selected text using the following function: - -```typescript -addStyles(styles: Styles): void; - -// Usage -editor.addStyles({ textColor: "red" }); -``` - -### Removing Styles - -You can remove styles from the currently selected text using the following function: - -```typescript -removeStyles(styles: Styles): void; - -// Usage -editor.removeStyles({ bold: true }); -``` - -### Toggling Styles - -You can toggle styles on the currently selected text using the following function: - -```typescript -toggleStyles(styles: Styles): void; - -// Usage -editor.toggleStyles({ bold: true, italic: true }); -``` - -### Accessing Selected Text - -You can get the currently selected text using the following function: - -```typescript -getSelectedText(): string; - -// Usage -const text = editor.getSelectedText(); -``` - -### Accessing Selected Link - -You can get the URL of the link in the current selection the following function: - -```typescript -getSelectedLink(): string | undefined; - -// Usage -const linkUrl = editor.getSelectedLink(); -``` - -If there are multiple links in the selection, this function only returns the last one's URL. If there are no links, returns `undefined`. - -### Creating a Link - -You can create a new link using the following function: - -```typescript -createLink(url: string, text?: string): void; - -// Usage -editor.createLink("https://www.blocknotejs.org/", "BlockNote"); -``` - -If a [Selection](/docs/cursor-selections#selections) is active, the new link will replace the currently selected content. diff --git a/docs/pages/docs/editor-api/blocks.mdx b/docs/pages/docs/editor-api/blocks.mdx deleted file mode 100644 index 133e435af3..0000000000 --- a/docs/pages/docs/editor-api/blocks.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Introduction to Blocks -description: So, you've set up a BlockNote editor and your users can start writing content, organized in blocks. What are blocks exactly, and how do we access the blocks from code? -imageTitle: Introduction to Blocks ---- - -import { Example } from "@/components/example"; - -[ ] Maybe move outside of "Editor API" or create separate "Editor basics" page? - -# Introduction to Blocks - -So, you've set up a BlockNote editor and your users can start writing content, organized in blocks. What are blocks exactly, and how do we access the blocks from code? - -## Editor Functions - -The `editor` returned from `useCreateBlockNote` exposes functions to access and update blocks. -We'll go through the full API later, but let's start with a simple example that shows the document (a list of blocks) in JSON. -Play around with the editor to see how blocks are represented in JSON. - - - -## Block Objects - -So, BlockNote is centered around the idea of blocks. A block - like a heading, paragraph, or list item - contains a piece of content and optionally nested blocks: - -image - -In code, the `Block` type is used to describe any given block in the editor: - -```typescript -type Block = { - id: string; - type: string; // the block type, e.g. 'paragraph', 'heading' - props: Record; // exact props depends on the Block type - content: InlineContent[] | TableContent; - children: Block[]; -}; -``` - -`id:` The block's ID. Multiple blocks cannot share a single ID, and a block will keep the same ID from when it's created until it's removed. - -`type:` The block's type, such as a paragraph, heading, or list item. For an overview of built-in block types, see [Built-In Block Types](/docs/block-types#built-in-block-types). - -`props:` The block's properties, which are stored in a set of key/value pairs and specify how the block looks and behaves. Different block types have different props - see [Block Types & Properties](/docs/block-types) for more. - -`content:` The block's rich text content, represented as an array of `InlineContent` objects. This does not include content from any nested blocks. [Table](/docs/block-types#table) blocks are slightly different, as they contain `TableContent`, where each table cell is represented as an array of `InlineContent` objects. For more information on `InlineContent` and `TableContent` objects, visit [Inline Content](/docs/inline-content). - -`children:` Any blocks nested inside the block. The nested blocks are also represented using `Block` objects. diff --git a/docs/pages/docs/editor-api/converting-blocks.mdx b/docs/pages/docs/editor-api/converting-blocks.mdx index ce4fea298c..26f4b9fc95 100644 --- a/docs/pages/docs/editor-api/converting-blocks.mdx +++ b/docs/pages/docs/editor-api/converting-blocks.mdx @@ -10,15 +10,13 @@ import { Callout } from "nextra/components"; # Markdown & HTML -TODO: use hooks in examples -TODO: use examples with content - It's possible to export or import Blocks to and from Markdown and HTML. The functions to import/export to and from Markdown/HTML are considered "lossy"; some information might be dropped when you export Blocks to those formats. - To serialize Blocks to a non-lossy format (for example, to store the contents of the editor in your backend), simply export the built-in Block format using `JSON.stringify(editor.topLevelBlocks)`. + To serialize Blocks to a non-lossy format (for example, to store the contents of the editor in your backend), simply export the built-in Block format using `JSON.stringify(editor.document)`. + ## Markdown diff --git a/docs/pages/docs/editor-api/cursor-selections.mdx b/docs/pages/docs/editor-api/cursor-selections.mdx index 571a9b6e74..83f3429308 100644 --- a/docs/pages/docs/editor-api/cursor-selections.mdx +++ b/docs/pages/docs/editor-api/cursor-selections.mdx @@ -5,6 +5,7 @@ imageTitle: Cursor & Selections path: /docs/cursor-selections --- + import { Example } from "@/components/example"; # Cursor & Selections @@ -59,7 +60,7 @@ setTextCursorPosition( editor.setTextCursorPosition(targetBlock, placement); ``` -`targetBlock:` The [identifier](/docs/manipulating-blocks#block-identifiers) of an existing block that the text cursor should be moved to. +`targetBlock:` The [identifier](/docs/editor-api/manipulating-blocks#block-identifiers) of an existing block that the text cursor should be moved to. `placement:` Whether the text cursor should be placed at the start or end of the block. diff --git a/docs/pages/docs/editor-api/default-blocks.mdx b/docs/pages/docs/editor-api/default-blocks.mdx deleted file mode 100644 index 024f858bca..0000000000 --- a/docs/pages/docs/editor-api/default-blocks.mdx +++ /dev/null @@ -1,163 +0,0 @@ ---- -title: Default Blocks -description: Overview of all default block types and their properties in BlockNote. -imageTitle: Default Blocks ---- - -import { Example } from "@/components/example"; - -# Default blocks - -TBD: move to a separate "reference" section? - -BlockNote includes a number of built-in block types. The demo editor below displays all of them: - -TODO: demo - -## Reference - -Here's an overview of all default blocks and the properties they support: - -### Paragraph - -**Appearance** - -image - -**Type & Props** - -```typescript -type ParagraphBlock = { - id: string; - type: "paragraph"; - props: DefaultProps; - content: InlineContent[]; - children: Block[]; -}; -``` - -### Heading - -**Appearance** - -image - -**Type & Props** - -```typescript -type HeadingBlock = { - id: string; - type: "heading"; - props: { - level: 1 | 2 | 3 = 1; - } & DefaultProps; - content: InlineContent[]; - children: Block[]; -}; -``` - -`level:` The heading level, representing a title (`level: 1`), heading (`level: 2`), and subheading (`level: 3`). - -### Bullet List Item - -**Appearance** - -image - -**Type & Props** - -```typescript -type BulletListItemBlock = { - id: string; - type: "bulletListItem"; - props: DefaultProps; - content: InlineContent[]; - children: Block[]; -}; -``` - -### Numbered List Item - -**Appearance** - -image - -**Type & Props** - -```typescript -type NumberedListItemBlock = { - id: string; - type: "numberedListItem"; - props: DefaultProps; - content: InlineContent[]; - children: Block[]; -}; -``` - -### Image - -**Appearance** - -image - -**Type & Props** - -```typescript -type ImageBlock = { - id: string; - type: "image"; - props: { - url: string = ""; - caption: string = ""; - width: number = 512; - } & Omit; - content: InlineContent[]; - children: Block[]; -}; -``` - -`url:` The image URL. - -`caption:` The image caption. - -`width:` The image width in pixels. - -### Table - -**Appearance** - -image - -**Type & Props** - -```typescript -type TableBlock = { - id: string; - type: "table"; - props: DefaultProps; - content: TableContent[]; - children: Block[]; -}; -``` - -## Default Block Properties - -While each type of block can have its own set of properties, there are some properties that all built-in block types have by default, which you can find in the definition for `DefaultProps`: - -```typescript -type DefaultProps = { - backgroundColor: string = "default"; - textColor: string = "default"; - textAlignment: "left" | "center" | "right" | "justify" = "left"; -}; -``` - -`backgroundColor:` The background color of the block, which also applies to nested blocks. - -`textColor:` The text color of the block, which also applies to nested blocks. - -`textAlignment:` The text alignment of the block. - -## Creating your own blocks - -You can create your own custom blocks using React. Skip to the Advanced "custom schemas" section to learn more about extending the editor. (TODO: link) \ No newline at end of file diff --git a/docs/pages/docs/editor-api/editor.mdx b/docs/pages/docs/editor-api/editor.mdx deleted file mode 100644 index 5429872d54..0000000000 --- a/docs/pages/docs/editor-api/editor.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -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 ---- - -import { Example } from "@/components/example"; - -TODO: -[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 -[ ] Maybe move outside of "Editor API"? - -# 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. - -## Editor Options - -There are a number of options that you can pass to `useCreateBlockNote()`, which you -can use to customize the editor. You can find the full list of these below: - -```typescript -export type BlockNoteEditorOptions = Partial<{ - initialContent: PartialBlock[]; - domAttributes: Record; - slashMenuItems: ReactSlashMenuItem[]; - defaultStyles: boolean; - uploadFile: (file: File) => Promise; - collaboration: CollaborationOptions; - blockSpecs: BlockSpecs; - inlineContentSpecs: InlineContentSpecs; - styleSpecs: StyleSpecs; -}>; -``` - -`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. - -`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 `

`, `

  • `, `

    `, 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. - -## `useCreateBlockNote` - -## `BlockNoteView` - -- editable -- events - -### Removing UI Elements - -TODO: probably just explain the props of BlockNoteView - -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: - - - -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. diff --git a/docs/pages/docs/editor-api/manipulating-blocks.mdx b/docs/pages/docs/editor-api/manipulating-blocks.mdx index 3b72676d1b..24b0dd63fa 100644 --- a/docs/pages/docs/editor-api/manipulating-blocks.mdx +++ b/docs/pages/docs/editor-api/manipulating-blocks.mdx @@ -9,18 +9,17 @@ path: /docs/manipulating-blocks Below, we explain the methods on `editor` you can use to read Blocks from the editor, and how to create / remove / update Blocks: -- topLevelBlocks -- getBlock -- forEachBlock -- insertBlocks -- updateBlock -- removeBlocks -- replaceBlocks -- canNestBlock -- nestBlock -- canUnnestBlock - -(TODO: link) +- [`get document`](/docs/editor-api/manipulating-blocks#getting-the-document) +- [`getBlock`](/docs/editor-api/manipulating-blocks#getting-a-specific-block) +- [`forEachBlock`](/docs/editor-api/manipulating-blocks#traversing-all-blocks) +- [`insertBlocks`](/docs/editor-api/manipulating-blocks#inserting-new-blocks) +- [`updateBlock`](/docs/editor-api/manipulating-blocks#updating-blocks) +- [`removeBlocks`](/docs/editor-api/manipulating-blocks#removing-blocks) +- [`replaceBlocks`](/docs/editor-api/manipulating-blocks#replacing-blocks) +- [`canNestBlock`](/docs/editor-api/manipulating-blocks#nesting-blocks) +- [`nestBlock`](/docs/editor-api/manipulating-blocks#nesting-blocks) +- [`canUnnestBlock`](/docs/editor-api/manipulating-blocks#un-nesting-blocks) +- [`unnestBlock`](/docs/editor-api/manipulating-blocks#un-nesting-blocks) ## Common types @@ -28,7 +27,7 @@ Before we dive into the methods, let's discuss some common types used in paramet ### Block Identifiers -The methods to access, insert, update, remove, or replace blocks, can require a `BlockIdentifier` as reference to an existing block in the document. +The methods to access, insert, update, remove, or replace blocks, can require a `BlockIdentifier` as reference to an existing block in the document. This is either a `string` representing the block ID, or a `Block` object from which the ID is taken: ```typescript @@ -37,7 +36,7 @@ type BlockIdentifier = string | Block; ### Partial Blocks -When retrieving blocks from the editor, you always receive complete `Block` objects. +When retrieving blocks from the editor, you always receive complete `Block` objects. For updating or creating blocks, you don't need to pass all properties and you can use a `PartialBlock` type instead: ```typescript @@ -52,25 +51,24 @@ type PartialBlock = { `PartialBlock` objects are almost the same as regular `Block` objects, but with all members optional and partial `props`. This makes updating or creating simpler blocks much easier. We'll see this below. - ## Accessing Blocks There are a few different ways to retrieve Blocks from the editor: -### Getting All Top-Level Blocks +### Getting the Document -Retrieve a snapshot of all top-level (non-nested) blocks in the editor using the following call: +Retrieve a snapshot of the document (all top-level, non-nested blocks) in the editor using the following call: ```typescript -topLevelBlocks: Block[]; +document: Block[]; // Usage -const blocks = editor.topLevelBlocks; +const blocks = editor.document; ``` `returns:` The document; a snapshot of all top-level (non-nested) blocks in the editor. -We already used this for the demo in [Getting Familiar with Block Objects](/docs/blocks#demo-getting-familiar-with-block-objects), to show the JSON representation of blocks below the editor. +We already used this for the [Editor Content in JSON](/docs/editor-basics/content-structure#editor-content-in-json) demo. ### Getting a Specific Block @@ -83,7 +81,7 @@ getBlock(blockIdentifier: BlockIdentifier): Block | undefined; const block = editor.getBlock(blockIdentifier); ``` -`blockIdentifier:` The [identifier](#block-identifiers) of an existing block that should be retrieved. +`blockIdentifier:` The [identifier](/docs/editor-api/manipulating-blocks#block-identifiers) of an existing block that should be retrieved. `returns:` The block that matches the identifier, or `undefined` if no matching block was found. @@ -107,7 +105,7 @@ editor.forEachBlock((block) => {...}); ### Getting the hovered / selected Block -See [Cursor & Selections](/docs/cursor-selections) to learn how to retrieve the block a user is interacting with. +See [Cursor & Selections](/docs/editor-api/cursor-selections) to learn how to retrieve the block a user is interacting with. ## Inserting New Blocks @@ -124,13 +122,13 @@ insertBlocks( editor.insertBlocks([{type: "paragraph", text: "Hello World"}], referenceBlock, placement) ``` -`blocksToInsert:` An array of [partial blocks](#partial-blocks) that should be inserted. +`blocksToInsert:` An array of [partial blocks](/docs/editor-api/manipulating-blocks#partial-blocks) that should be inserted. -`referenceBlock:` An [identifier](#block-identifiers) for an existing block, at which the new blocks should be inserted. +`referenceBlock:` An [identifier](/docs/editor-api/manipulating-blocks#block-identifiers) for an existing block, at which the new blocks should be inserted. `placement:` Whether the blocks should be inserted just before, just after, or nested inside the `referenceBlock`. Inserts the blocks at the start of the existing block's children if `"nested"` is used. -If a block's `id` is undefined, BlockNote generates one automatically. +If a block's `id` is undefined, BlockNote generates one automatically. The method throws an error if the reference block could not be found. @@ -148,11 +146,11 @@ updateBlock( editor.updateBlock(blockToUpdate, { type: "paragraph" }); ``` -`blockToUpdate:` The [identifier](#block-identifiers) of an existing block that should be updated. +`blockToUpdate:` The [identifier](/docs/editor-api/manipulating-blocks#block-identifiers) of an existing block that should be updated. -`update:` A [partial block](#partial-blocks) which defines how the existing block should be changed. +`update:` A [partial blocks](/docs/editor-api/manipulating-blocks#partial-blocks) which defines how the existing block should be changed. -Since `blockToUpdate` is a `PartialBlock` object, some fields might not be defined. These undefined fields are kept as-is from the existing block. +Since `blockToUpdate` is a `PartialBlock` object, some fields might not be defined. These undefined fields are kept as-is from the existing block. Throws an error if the block to update could not be found. @@ -169,7 +167,7 @@ removeBlocks( editor.removeBlocks(blocksToRemove) ``` -`blocksToRemove:` An array of [identifiers](#block-identifiers) for existing blocks that should be removed. +`blocksToRemove:` An array of [identifier](/docs/editor-api/manipulating-blocks#block-identifiers) for existing blocks that should be removed. Throws an error if any of the blocks could not be found. @@ -187,23 +185,23 @@ replaceBlocks( editor.replaceBlocks(blocksToRemove, blocksToInsert) ``` -`blocksToRemove:` An array of [identifiers](#block-identifiers) for existing blocks that should be replaced. +`blocksToRemove:` An array of [identifier](/docs/editor-api/manipulating-blocks#block-identifiers) for existing blocks that should be replaced. -`blocksToInsert:` An array of [partial blocks](#partial-blocks) that the existing ones should be replaced with. +`blocksToInsert:` An array of [partial blocks](/docs/editor-api/manipulating-blocks#partial-blocks) that the existing ones should be replaced with. -If the blocks that should be removed are not adjacent or are at different nesting levels, `blocksToInsert` will be inserted at the position of the first block in `blocksToRemove`. +If the blocks that should be removed are not adjacent or are at different nesting levels, `blocksToInsert` will be inserted at the position of the first block in `blocksToRemove`. Throws an error if any of the blocks to remove could not be found. ## Nesting & Un-nesting Blocks -BlockNote also provides functions to nest & un-nest the block containing the [Text Cursor](/docs/cursor-selections#text-cursor). +BlockNote also provides functions to nest & un-nest the block containing the [Text Cursor](/docs/editor-api/cursor-selections#text-cursor). ### Nesting Blocks -TODO: this API seems different as it doesn't require a block id. should we make it possible to pass an identifier? +{/* TODO: this API seems different as it doesn't require a block id. should we make it possible to pass an identifier? */} -Use `canNestBlock` to check whether the block containing the [Text Cursor](/docs/cursor-selections#text-cursor) can be nested (i.e. if there is a block above it at the same nesting level): +Use `canNestBlock` to check whether the block containing the [Text Cursor](/docs/editor-api/cursor-selections#text-cursor) can be nested (i.e. if there is a block above it at the same nesting level): ```typescript canNestBlock(): boolean; @@ -223,7 +221,7 @@ editor.nestBlock(); ### Un-nesting Blocks -Use `canUnnestBlock` to check whether the block containing the [Text Cursor](/docs/cursor-selections#text-cursor) can be un-nested (i.e. if it's nested in another block): +Use `canUnnestBlock` to check whether the block containing the [Text Cursor](/docs/editor-api/cursor-selections#text-cursor) can be un-nested (i.e. if it's nested in another block): ```typescript canUnnestBlock(): boolean; @@ -239,4 +237,4 @@ unnestBlock(): void; // Usage editor.unnestBlock(); -``` \ No newline at end of file +``` diff --git a/docs/pages/docs/editor-api/manipulating-inline-content.mdx b/docs/pages/docs/editor-api/manipulating-inline-content.mdx new file mode 100644 index 0000000000..0f90561e11 --- /dev/null +++ b/docs/pages/docs/editor-api/manipulating-inline-content.mdx @@ -0,0 +1,93 @@ +--- +title: Manipulating Inline Content +description: TODO +imageTitle: Manipulating Inline Content +path: /docs/block-content +--- + +# Manipulating Inline Content + +`BlockNoteEditor` exposes a number of functions to interact with the currently selected content. + +## Accessing Styles + +You can get the styles at the current [Text Cursor Position](/docs/editor-api/cursor-selections#text-cursor) using the following function: + +```typescript +getActiveStyles(): Styles; + +// Usage +const styles = editor.getActiveStyles(); +``` + +If a [Selection](/docs/editor-api/cursor-selections#selections) is active, this function returns the active styles at the end of the selection. + +## Adding Styles + +You can add styles to the currently selected text using the following function: + +```typescript +addStyles(styles: Styles): void; + +// Usage +editor.addStyles({ textColor: "red" }); +``` + +## Removing Styles + +You can remove styles from the currently selected text using the following function: + +```typescript +removeStyles(styles: Styles): void; + +// Usage +editor.removeStyles({ bold: true }); +``` + +## Toggling Styles + +You can toggle styles on the currently selected text using the following function: + +```typescript +toggleStyles(styles: Styles): void; + +// Usage +editor.toggleStyles({ bold: true, italic: true }); +``` + +## Accessing Selected Text + +You can get the currently selected text using the following function: + +```typescript +getSelectedText(): string; + +// Usage +const text = editor.getSelectedText(); +``` + +## Accessing Selected Link + +You can get the URL of the link in the current selection the following function: + +```typescript +getSelectedLink(): string | undefined; + +// Usage +const linkUrl = editor.getSelectedLink(); +``` + +If there are multiple links in the selection, this function only returns the last one's URL. If there are no links, returns `undefined`. + +## Creating a Link + +You can create a new link using the following function: + +```typescript +createLink(url: string, text?: string): void; + +// Usage +editor.createLink("https://www.blocknotejs.org/", "BlockNote"); +``` + +If a [Selection](/docs/editor-api/cursor-selections#selections) is active, the new link will replace the currently selected content. diff --git a/docs/pages/docs/editor-basics.mdx b/docs/pages/docs/editor-basics.mdx new file mode 100644 index 0000000000..08889d9421 --- /dev/null +++ b/docs/pages/docs/editor-basics.mdx @@ -0,0 +1,5 @@ +# Editor basics + +In this section, we first explore the [methods to setup your editor](/docs/editor-basics/setup). +Then, we'll dive into the structure of documents, Blocks and rich text content in BlockNote ([document structure](/docs/editor-basics/document-structure)). +We'll also go over the blocks and content types that are part of BlockNote's [default built-in schema](/docs/editor-basics/default-schema). diff --git a/docs/pages/docs/editor-basics/_meta.json b/docs/pages/docs/editor-basics/_meta.json new file mode 100644 index 0000000000..56345dccb5 --- /dev/null +++ b/docs/pages/docs/editor-basics/_meta.json @@ -0,0 +1,5 @@ +{ + "setup": "Editor Setup", + "document-structure": "Document Structure", + "default-schema": "Default Schema" +} diff --git a/docs/pages/docs/editor-basics/default-schema.mdx b/docs/pages/docs/editor-basics/default-schema.mdx new file mode 100644 index 0000000000..4f2cebf656 --- /dev/null +++ b/docs/pages/docs/editor-basics/default-schema.mdx @@ -0,0 +1,191 @@ +--- +title: Default Content Types +description: BlockNote supports a variety on built-in block and inline content types that are included in the editor by default. +imageTitle: Default Content Types +--- + +import { Example } from "@/components/example"; + +# Default Content Types + +BlockNote supports a number of built-in blocks, inline content types, and styles that are included in the editor by default. This is called the Default Schema. To create your own content types, see [Custom Schemas](/docs/custom-schemas). + +## Default Blocks + +Quickly explore the default blocks in this demo: + + + +### Reference + +Let's look more in-depth at the default blocks and the properties they support: + +#### Paragraph + +**Type & Props** + +```typescript +type ParagraphBlock = { + id: string; + type: "paragraph"; + props: DefaultProps; + content: InlineContent[]; + children: Block[]; +}; +``` + +#### Heading + +**Type & Props** + +```typescript +type HeadingBlock = { + id: string; + type: "heading"; + props: { + level: 1 | 2 | 3 = 1; + } & DefaultProps; + content: InlineContent[]; + children: Block[]; +}; +``` + +`level:` The heading level, representing a title (`level: 1`), heading (`level: 2`), and subheading (`level: 3`). + +#### Bullet List Item + +**Type & Props** + +```typescript +type BulletListItemBlock = { + id: string; + type: "bulletListItem"; + props: DefaultProps; + content: InlineContent[]; + children: Block[]; +}; +``` + +#### Numbered List Item + +**Type & Props** + +```typescript +type NumberedListItemBlock = { + id: string; + type: "numberedListItem"; + props: DefaultProps; + content: InlineContent[]; + children: Block[]; +}; +``` + +#### Image + +**Type & Props** + +```typescript +type ImageBlock = { + id: string; + type: "image"; + props: { + url: string = ""; + caption: string = ""; + width: number = 512; + } & DefaultProps; + content: undefined; + children: Block[]; +}; +``` + +`url:` The image URL. + +`caption:` The image caption. + +`width:` The image width in pixels. + +#### Table + +**Type & Props** + +```typescript +type TableBlock = { + id: string; + type: "table"; + props: DefaultProps; + content: TableContent[]; + children: Block[]; +}; +``` + +### Default Block Properties + +There are some default block props that BlockNote uses for the built-in blocks: + +```typescript +type DefaultProps = { + backgroundColor: string = "default"; + textColor: string = "default"; + textAlignment: "left" | "center" | "right" | "justify" = "left"; +}; +``` + +`backgroundColor:` The background color of the block, which also applies to nested blocks. + +`textColor:` The text color of the block, which also applies to nested blocks. + +`textAlignment:` The text alignment of the block. + +## Default Inline Content + +By default, `InlineContent` (the content of text blocks like paragraphs) in BlockNote can either be a `StyledText` or a `Link` object. Inspect them in the editor below: + + + +### Reference + +Here's an overview of all default inline content and the properties they support: + +#### Styled Text + +`StyledText` is a type of `InlineContent` used to display pieces of text with styles: + +```typescript +type StyledText = { + type: "text"; + text: string; + styles: Styles; +}; +``` + +#### Link + +`Link` objects represent links to a URL: + +```typescript +type Link = { + type: "link"; + content: StyledText[]; + href: string; +}; +``` + +## Default Styles + +The default text formatting options in BlockNote are represented by the `Styles` in the default schema: + +```typescript +type Styles = { + bold: boolean; + italic: boolean; + underline: boolean; + strikethrough: boolean; + textColor: string; + backgroundColor: string; +}; +``` + +## Creating New Block or Inline Content Types + +You can also extend your editor and create your own Blocks, Inline Content or Styles using React. +Skip to [Custom Schemas (advanced)](/docs/custom-schemas) to learn how to do this. diff --git a/docs/pages/docs/editor-basics/document-structure.mdx b/docs/pages/docs/editor-basics/document-structure.mdx new file mode 100644 index 0000000000..1cc95a1682 --- /dev/null +++ b/docs/pages/docs/editor-basics/document-structure.mdx @@ -0,0 +1,103 @@ +--- +description: Learn how documents (the content of the rich text editor) are structured to make the most out of BlockNote. +--- + +import { Example } from "@/components/example"; + +# Document Structure + +Learn how documents (the content of the rich text editor) are structured to make the most out of BlockNote. + +## Blocks + +Each BlockNote document is made up of a list of blocks. +A block is a piece of content like a paragraph, heading, list item or image. Blocks can be dragged around by users in the editor. A block contains a piece of content and optionally nested (child) blocks: + +image + +### Block Objects + +The `Block` type is used to describe any given block in the editor: + +```typescript +type Block = { + id: string; + type: string; + props: Record; + content: InlineContent[] | TableContent | undefined; + children: Block[]; +}; +``` + +`id:` The block's ID. Multiple blocks cannot share a single ID, and a block will keep the same ID from when it's created until it's removed. + +`type:` The block's type, such as a paragraph, heading, or list item. For an overview of built-in block types, see [Default Blocks](/docs/editor-basics/default-content-types#default-blocks). + +`props:` The block's properties, which is a set of key/value pairs that further specify how the block looks and behaves. Different block types have different props - see [Default Blocks](/docs/editor-basics/default-content-types#default-blocks) for more. + +`content:` The block's rich text content, usually represented as an array of `InlineContent` objects. This does not include content from any nested blocks. Read on to [Inline Content](/docs/editor-basics/content-structure#inline-content) for more on this. + +`children:` Any blocks nested inside the block. The nested blocks are also represented using `Block` objects. + +### Editor Content in JSON + +The demo below shows the editor contents (document) in JSON. It's basically an array of `Block` objects that updates as you type in the editor: + + + +## Inline Content + +The `content` field of a block contains the rich-text content of a block. This is defined as an array of `InlineContent` objects. Inline content can either be styled text or a link (or a custom inline content type if you customize the editor schema). + +### Inline Content Objects + +The `InlineContent` type is used to describe a piece of inline content: + +```typescript +type Link = { + type: "link"; + content: StyledText[]; + href: string; +}; + +type StyledText = { + type: "text"; + text: string; + styles: Styles; +}; + +type InlineContent = Link | StyledText; +``` + +The `styles` property is explained below. + +### Other types of Block Content + +While most blocks use an array of `InlineContent` objects to describe their content (e.g.: paragraphs, headings, list items). Some blocks, like [images](/docs/editor-basics/default-content-types#image), don't contain any rich text content, so their `content` fields will be `undefined`. + +[Tables](/docs/editor-basics/default-content-types#table) are also different, as they contain `TableContent`. Here, each table cell is represented as an array of `InlineContent` objects: + +```typescript +type TableContent = { + type: "tableContent"; + rows: { + cells: InlineContent[][]; + }[]; +}; +``` + +## Styles and rich text + +The `styles` property of `StyledText` objects is used to describe the rich text styles (e.g.: bold, italic, color) or other attributes of a piece of text. It's a set of key / value pairs that specify the styles applied to the text. + +See the [Default Schema](/docs/editor-basics/default-schema) to learn which styles are included in BlockNote by default. + +## Demo: Block Content + +In the demo below, you can explore how the block content and styles are represented in JSON by outputting only the `content` field of each top level block. + + diff --git a/docs/pages/docs/editor-basics/setup.mdx b/docs/pages/docs/editor-basics/setup.mdx new file mode 100644 index 0000000000..05a926253d --- /dev/null +++ b/docs/pages/docs/editor-basics/setup.mdx @@ -0,0 +1,135 @@ +--- +description: Learn how to setup your BlockNote editor using the `useCreateBlockNote` hook and the ``BlockNoteView` component. +--- + +import { Example } from "@/components/example"; +import { Callout } from "nextra/components"; + +# Editor Setup + +You can customize your editor when you instantiate it. Let's take a closer looks at the basic methods and components to set up your BlockNote editor. + +## `useCreateBlockNote` hook + +Create a new `BlockNoteEditor` by calling the `useCreateBlockNote` hook. This instantiates a new editor and its required state. You can later interact with the editor using the Editor API and pass it to the `BlockNoteView` component. + +```ts +function useCreateBlockNote( + options?: BlockNoteEditorOptions, + deps?: React.DependencyList = [], +): BlockNoteEditor; + +type BlockNoteEditorOptions = { + initialContent?: PartialBlock[]; + domAttributes?: Record; + defaultStyles?: boolean; + uploadFile?: (file: File) => Promise; + collaboration?: CollaborationOptions; + schema?: BlockNoteSchema; +}; +``` + +The hook takes two optional parameters: + +**options:** An object containing options for the editor: + +`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. + +`defaultStyles`: Whether to use the default font and reset the styles of `

    `, `

  • `, `

    `, 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). TODO + +`collaboration`: Options for enabling real-time collaboration. See [Collaboration](/docs/collaboration) for more info. + +`schema` (_advanced_): The editor schema if you want to extend your editor with custom blocks, styles, or inline content [Custom Schemas](/docs/custom-schemas). + +**deps:** Dependency array that's internally passed to `useMemo`. A new editor will only be created when this array changes. + + + Manually creating the editor (`BlockNoteEditor.create`) +

    + The `useCreateBlockNote` hook is actually a simple `useMemo` wrapper around + the `BlockNoteEditor.create` method. You can use this method directly if you + want to control the editor lifecycle manually. For example, we do this in + the [Saving & Loading example](/examples/basic/saving-loading) to delay the + editor creation until some content has been fetched from an external data + source. +

    +
    + +## Rendering the Editor with `` + +Use the `` component to render the `BlockNoteEditor` instance you just created: + +```tsx +const editor = useCreateBlockNote(); + +return ; +``` + +### Props + +There are a number of additional props you can pass to `BlockNoteView`. You can find the full list of these below: + +```typescript +export type BlockNoteViewProps = { + editor: BlockNoteEditor; + editable?: boolean; + onSelectionChange?: () => void; + onChange?: () => void; + theme?: + | "light" + | "dark" + | Theme + | { + light: Theme; + dark: Theme; + }; + formattingToolbar?: boolean; + hyperlinkToolbar?: boolean; + sideMenu?: boolean; + slashMenu?: boolean; + imageToolbar?: boolean; + tableHandles?: boolean; + children?: +} & HTMLAttributes; +``` + +`editor`: The `BlockNoteEditor` instance to render. + +`editable`: Whether the editor should be editable. + +`onSelectionChange`: Callback for when the editor selection changes. + +`onChange`: Callback for when the editor selection or content changes. + +`theme`: The editor's theme, see [Themes](/docs/styling-theming/themes) for more about this. + +`formattingToolbar`: Whether the [Formatting Toolbar](/docs/ui-components/formatting-toolbar) should be enabled. + +`hyperlinkToolbar`: Whether the Hyperlink Toolbar should be enabled. + +`sideMenu`: Whether the [Block Side Menu](/docs/ui-components/side-menu) should be enabled. + +`slashMenu`: Whether the [Slash Menu](/docs/ui-components/suggestion-menus#slash-menu) should be enabled. + +`imageToolbar`: Whether the Image Toolbar should be enabled. + +`tableHandles`: Whether the Table Handles should be enabled. + +`children`: Pass child elements to the `BlockNoteView` to create or customize toolbars, menus, or other UI components. See [UI Components](/docs/ui-components) for more. + +Additional props passed are forwarded to the HTML `div` element BlockNote renders internally. + + + Uncontrolled component +

    + Note that the `BlockNoteView` component is an [uncontrolled component](https://react.dev/learn/sharing-state-between-components#controlled-and-uncontrolled-components). + This means you don't pass in the editor content directly as a prop. You can use the `initialContent` option in the `useCreateBlockNote` hook to set the initial content of the editor (similar to the `defaultValue` prop in a regular React `