Files

110 lines
2.6 KiB
TypeScript

"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
import { Card } from "@/components/ui/card";
import { Editor, EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Underline from "@tiptap/extension-underline";
import Link from "@tiptap/extension-link";
import TTImage from "@tiptap/extension-image";
import TextAlign from "@tiptap/extension-text-align";
import Youtube from "@tiptap/extension-youtube";
import Dropcursor from "@tiptap/extension-dropcursor";
import { EditorMenu } from "./editor-menu";
import { FontSize, TextColor } from "./extensions/marks";
interface EditorProps {
content: string;
onChange?: (content: string) => void;
className?: string;
onTitleChange?: (t: string) => void;
}
export function LocalEditor({
content,
onChange,
className,
onTitleChange: setTitle,
}: EditorProps) {
const getTitle = (editor: Editor) => {
const firstNode = editor.state.doc.firstChild;
if (!firstNode) {
editor.commands.setNode("heading", {
level: 1,
content: [{ type: "text", text: "Titre" }],
});
}
if (
firstNode &&
!(firstNode.type.name === "heading" && firstNode.attrs.level === 1)
) {
setFirstLineAsH1(editor);
}
return firstNode?.textContent;
};
const setFirstLineAsH1 = (editor: Editor) => {
const firstNode = editor.state.doc.firstChild;
// Check if the first node is a paragraph and make it h1
if (firstNode && firstNode.type.name === "paragraph") {
editor.commands.setNode("heading", { level: 1 });
}
};
const editor = useEditor({
extensions: [
StarterKit,
FontSize,
TextColor,
Underline,
Link,
Youtube,
Dropcursor,
TTImage.configure({
HTMLAttributes: {
class: "max-w-full w-auto h-auto resize overflow-auto",
},
}),
TextAlign.configure({
alignments: ["left", "center", "right", "justify"],
defaultAlignment: "justify",
types: ["heading", "paragraph"],
}),
],
content,
immediatelyRender: false,
editorProps: {
attributes: {
class: "prose prose-sm sm:prose-base lg:prose-lg xl:prose-2xl m-5 focus:outline-none dark:prose-invert",
},
},
onCreate: ({ editor }) => {
const title = getTitle(editor);
setTitle?.(title ?? "");
},
onUpdate: ({ editor }) => {
onChange?.(editor.getHTML());
const title = getTitle(editor);
setTitle?.(title ?? "");
},
});
if (!editor) {
return null;
}
return (
<Card className={cn("border rounded-lg overflow-hidden", className)}>
<EditorMenu editor={editor} />
<EditorContent editor={editor} />
</Card>
);
}