Block Editor

Writes and saves documents.

@paneui/theme@paneui/icons@paneui/button@paneui/input@paneui/menu@paneui/popover@paneui/tooltip@paneui/toolbar@paneui/menu-list@paneui/swatch-picker@tiptap/core@tiptap/pm@tiptap/react@tiptap/starter-kit@tiptap/extensions@tiptap/extension-text-style@tiptap/extension-highlight@tiptap/suggestion@floating-ui/dom@tiptap/extension-list@tiptap/extension-table@tiptap/extension-image@tiptap/extension-code-block-lowlight@tiptap/extension-detailslowlightunifiedremark-parseremark-mdxremark-gfmremark-stringifymdast-util-mdx@base-ui/react

Installation

pnpm dlx shadcn@latest add @paneui/notion-editor

Usage

Composition

Examples

Controlled MDX

Use when the document lives in your own state as an MDX string.

Read Only

Use to show a finished document that no one should edit.

Custom Slash Items

Blocks and shortcuts

Text, headings 1–3 (4–6 kept from MDX), bulleted, numbered and to-do lists, toggle, quote, callout, divider, code block (with syntax highlighting), image and table. Markdown input rules cover #, -, 1., [ ], >, three backticks, ---, **bold**, _italic_, backtick code, ~~strike~~. ⌘B ⌘I ⌘U ⌘⇧S ⌘E for marks, ⌘K for a link, ⌘⇧H highlight, ⌘⌥1–3 headings, ⌘⇧7/8/9 lists, ⌘⇧↑ / ⌘⇧↓ move the block.

Moving blocks

Drag the grip with a mouse, pen or finger; a line marks where the block lands, the scroll area follows the pointer near its edges and Escape cancels. On touch the gutter sits on the block that holds the caret. The grip menu also has Move up and Move down. Every move is one undo step.

MDX round trip

fromMDX parses MDX with GitHub-flavoured Markdown and toMDX prints it back. <Callout type icon> maps to the callout block, <details><summary> to the toggle, <u>, <mark> and <span style={{ color }}> to underline, highlight and colour. Anything else (unknown JSX, import / export, {expressions}, footnotes) becomes an editable raw MDX block, so toMDX(fromMDX(source)) equals formatMDX(source).

Images

The image block, paste and drop go through uploadImage(file) => Promise<url>; the default inlines a data URL, so pass your own uploader for real documents.

API Reference

NotionEditor

Also takes every useNotionEditor option.

defaultValue
string | JSONContent
Initial document: an MDX string or editor JSON (JSONContent).
value
string | JSONContent
Controlled document. Pair with onChange; setting it from outside replaces the document.
onChange
(mdx: string, editor: Editor) => void
Called with the document as MDX on every change.
onUpdate
(editor: Editor) => void
Called on every change; read editor.getJSON() for JSON.
readOnly= false
boolean
Hide the gutter, bubble and slash menu.
toolbar= false
boolean
Show the top bar with undo / redo and Import / Export MDX.
fileName= "document.mdx"
string
Download name for Export.
placeholder
string
Empty-block placeholder.
placeholders
Partial<Record<string, string>>
Placeholder per node type (heading, paragraph, detailsSummary…).
slashItems= defaultSlashItems
SlashItem[]
The / menu. Each item has a command({ editor, range }).
uploadImage
(file: File) => Promise<string>
Uploader for picked, pasted and dropped images.
extensions
AnyExtension[]
Extra editor extensions.
onReady
(editor: Editor) => void
Receive the editor instance.
contentClassName
string
Classes for the scrolling document area (padding).
PropTypeDefaultDescription
defaultValuestring | JSONContent—Initial document: an MDX string or editor JSON (JSONContent).
valuestring | JSONContent—Controlled document. Pair with onChange; setting it from outside replaces the document.
onChange(mdx: string, editor: Editor) => void—Called with the document as MDX on every change.
onUpdate(editor: Editor) => void—Called on every change; read editor.getJSON() for JSON.
readOnlybooleanfalseHide the gutter, bubble and slash menu.
toolbarbooleanfalseShow the top bar with undo / redo and Import / Export MDX.
fileNamestring"document.mdx"Download name for Export.
placeholderstring—Empty-block placeholder.
placeholdersPartial<Record<string, string>>—Placeholder per node type (heading, paragraph, detailsSummary…).
slashItemsSlashItem[]defaultSlashItemsThe / menu. Each item has a command({ editor, range }).
uploadImage(file: File) => Promise<string>—Uploader for picked, pasted and dropped images.
extensionsAnyExtension[]—Extra editor extensions.
onReady(editor: Editor) => void—Receive the editor instance.
contentClassNamestring—Classes for the scrolling document area (padding).

toMDX

toMDX(editor | json): string. Unknown nodes keep their children.

fromMDX

fromMDX(source): JSONContent, ready for editor.commands.setContent.

NotionEditorToolbar

editor*
Editor | null
The editor to drive.
fileName= "document.mdx"
string
Download name.
PropTypeDefaultDescription
editor*Editor | null—The editor to drive.
fileNamestring"document.mdx"Download name.

EditorBubbleMenu

Shared with the email editor.

editor*
Editor
The editor.
blockTypes
BlockType[] | false
"Turn into" targets; false hides the dropdown.
colors= true
boolean
Show the colour popover.
textColors / highlightColors
Swatch[]
Palettes (theme tokens by default).
PropTypeDefaultDescription
editor*Editor—The editor.
blockTypesBlockType[] | false—"Turn into" targets; false hides the dropdown.
colorsbooleantrueShow the colour popover.
textColors / highlightColorsSwatch[]—Palettes (theme tokens by default).

moveBlock

moveBlock(editor, from, to): boolean moves the top-level block at from to the gap at to.

EditorBlockHandle

Render inside the same relative container as EditorContent.

editor*
Editor
The editor.
blockTypes
BlockType[] | false
"Turn into" targets in the grip menu.
PropTypeDefaultDescription
editor*Editor—The editor.
blockTypesBlockType[] | false—"Turn into" targets in the grip menu.