chain().setParagraph().run()}>
¶
chain().toggleHeading({ level: 2 }).run()}>
H2
chain().toggleHeading({ level: 3 }).run()}>
H3
chain().toggleHeading({ level: 4 }).run()}>
H4
chain().toggleBold().run()} className="font-bold">
B
chain().toggleItalic().run()} className="italic">
I
chain().toggleUnderline().run()} className="underline">
U
chain().toggleStrike().run()} className="line-through">
S
chain().toggleCode().run()} className="font-mono text-xs">
{">"}
🔗
chain().toggleBulletList().run()}>
••
chain().toggleOrderedList().run()}>
1.
chain().toggleBlockquote().run()}>
❝
chain().toggleCodeBlock().run()} className="font-mono text-xs">
{"{ }"}
chain().setHorizontalRule().run()}>
—
fileInputRef.current?.click()}>
🖼
{state?.image && (
Alt
)}
chain().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}
>
⊞
chain().undo().run()}>
↺
chain().redo().run()}>
↻
{state?.table && (
chain().addColumnAfter().run()}>
+Col
chain().deleteColumn().run()}>
−Col
chain().addRowAfter().run()}>
+Row
chain().deleteRow().run()}>
−Row
chain().toggleHeaderRow().run()}>
Header
chain().deleteTable().run()}>
✕ Table
)}
{
const files = Array.from(event.target.files ?? []);
event.target.value = "";
void uploadAndInsert(files);
}}
/>
{uploadState.kind === "uploading" && "Uploading image…"}
{uploadState.kind === "error" && (
{uploadState.message}
)}
{uploadState.kind === "idle" &&
"Drop or paste images to upload them. Pasted Markdown is converted automatically."}