return (
<div className="space-y-4 border rounded-md p-6">
<Slate editor={editor} initialValue={initialValue} onChange={handleEditorChange}>
<Editable
className="slate-editor h-40 overflow-auto border-b border-b-gray-300 mb-5 focus-visible:outline-none"
renderElement={renderElement}
renderLeaf={renderLeaf}
placeholder="Enter description here (250 words max.)"
spellCheck
autoFocus
onKeyDown={event => {
for (const hotkey in HOTKEYS) {
if (isHotkey(hotkey, event as any)) {
event.preventDefault();
const mark = HOTKEYS[hotkey];
toggleMark(editor, mark);
}
}
}}
/>
<Toolbar>
<UndoButton />
<RedoButton />
<BlockButton format="left" icon={AlignLeft} />
<BlockButton format="center" icon={AlignCenter} />
<BlockButton format="right" icon={AlignRight} />
<BlockButton format="justify" icon={AlignJustify} />
<MarkButton format="bold" icon={Bold} />
<MarkButton format="italic" icon={Italic} />
<MarkButton format="underline" icon={Underline} />
{
}
<BlockButton format="numbered-list" icon={ListOrdered} />
<BlockButton format="bulleted-list" icon={List} />
<BlockButton format="block-quote" icon={Quote} />
</Toolbar>
<div className="slate-editor" dangerouslySetInnerHTML={{ __html: sanitizedHtml }} />
</Slate>
</div>
);
};
const toggleBlock = (editor, format) => {
const isActive = isBlockActive(
editor,
format,
TEXT_ALIGN_TYPES.includes(format) ? 'align' : 'type'
);
const isList = LIST_TYPES.includes(format);
Transforms.unwrapNodes(editor, {
match: n =>
!Editor.isEditor(n) &&
SlateElement.isElement(n) &&
LIST_TYPES.includes(n.type) &&
!TEXT_ALIGN_TYPES.includes(format),
split: true,
});
let newProperties: Partial<SlateElement>;
if (TEXT_ALIGN_TYPES.includes(format)) {
newProperties = {
align: isActive ? undefined : format,
};
} else {
newProperties = {
type: isActive ? 'paragraph' : isList ? 'list-item' : format,
};
}
Transforms.setNodes<SlateElement>(editor, newProperties);
if (!isActive && isList) {
const block = { type: format, children: [] };
Transforms.wrapNodes(editor, block);
}
};
const toggleMark = (editor, format) => {
const isActive = isMarkActive(editor, format);
if (isActive) {
Editor.removeMark(editor, format);
} else {
Editor.addMark(editor, format, true);
}
};
const isBlockActive = (editor, format, blockType = 'type') => {
const { selection } = editor;
if (!selection) return false;
const [match] = Array.from(
Editor.nodes(editor, {
at: Editor.unhangRange(editor, selection),
match: n => !Editor.isEditor(n) && SlateElement.isElement(n) && n[blockType] === format,
})
);
return !!match;
};