"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"; interface EditorProps { content: string; onChange?: (content: string) => void; className?: string; setTitle?: React.Dispatch>; } export function LocalEditor({ content, onChange, className, setTitle, }: EditorProps) { const getTitle = (editor: Editor) => { const h1s: string[] = []; editor.state.doc.descendants((node, pos) => { if (node.type.name === "heading" && node.attrs.level === 1) { h1s.push(node.textContent); } }); return h1s.length > 0 ? h1s[0] : null; }; const editor = useEditor({ extensions: [ StarterKit, 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 }) => { localStorage.setItem("blog_draft", editor.getHTML()); // Set the first H1 if it exists const title = getTitle(editor); setTitle?.(title ?? ""); }, }); if (!editor) { return null; } return ( ); }