88 lines
1.9 KiB
TypeScript
88 lines
1.9 KiB
TypeScript
"use client";
|
|
import "./styles/shared.css";
|
|
import {
|
|
EditorContent,
|
|
EditorInstance,
|
|
EditorRoot,
|
|
JSONContent,
|
|
Placeholder,
|
|
StarterKit,
|
|
TiptapUnderline,
|
|
} from "novel";
|
|
|
|
import { MenuBar } from "./menu/menu-bar";
|
|
|
|
const extentions = [
|
|
TiptapUnderline,
|
|
StarterKit.configure({
|
|
blockquote: false,
|
|
bulletList: false,
|
|
orderedList: false,
|
|
code: false,
|
|
codeBlock: false,
|
|
horizontalRule: false,
|
|
listItem: false,
|
|
|
|
heading: {
|
|
levels: [4, 5],
|
|
},
|
|
}),
|
|
Placeholder.configure({
|
|
placeholder: "Schreibe einen Kommentar …",
|
|
emptyNodeClass:
|
|
"first:before:absolute first:before:text-gray-400 first:before:float-left first:before:content-[attr(data-placeholder)] first:before:pointer-events-none",
|
|
}),
|
|
];
|
|
|
|
const CommentEditor = ({
|
|
children,
|
|
initialContent,
|
|
readOnly,
|
|
onContentChange,
|
|
setEditor,
|
|
}: {
|
|
initialContent?: JSONContent;
|
|
onContentChange?: (content: JSONContent) => void;
|
|
readOnly?: boolean;
|
|
children?: React.ReactNode;
|
|
setEditor?: (editor: EditorInstance) => void;
|
|
}) => {
|
|
const slotAfter = (
|
|
<div className="flex items-center justify-between gap-4">
|
|
{!readOnly && (
|
|
<MenuBar
|
|
className="w-full bg-muted p-0"
|
|
buttonProps={{
|
|
className: "size-max p-1 text-xs",
|
|
}}
|
|
onlyInline
|
|
/>
|
|
)}
|
|
{children}
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<EditorRoot>
|
|
<EditorContent
|
|
slotAfter={slotAfter}
|
|
extensions={extentions}
|
|
editorProps={{
|
|
attributes: {
|
|
class: !readOnly ? "min-h-12" : "",
|
|
},
|
|
}}
|
|
editable={!readOnly}
|
|
initialContent={initialContent}
|
|
onCreate={({ editor }) => {
|
|
setEditor?.(editor);
|
|
}}
|
|
onUpdate={({ editor }) => {
|
|
onContentChange?.(editor.getJSON());
|
|
}}
|
|
/>
|
|
</EditorRoot>
|
|
);
|
|
};
|
|
export default CommentEditor;
|