'use client';
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import Link from '@tiptap/extension-link';
import Placeholder from '@tiptap/extension-placeholder';
import { useEffect } from 'react';
import { Button } from '@/components/ui/button';
import {
Bold,
Italic,
Strikethrough,
Code,
List,
ListOrdered,
Quote,
Undo,
Redo,
} from 'lucide-react';
import { cn } from '@/lib/utils';
interface NoteEditorProps {
content: string;
onChange: (content: string) => void;
onBlur?: () => void;
}
export function NoteEditor({ content, onChange, onBlur }: NoteEditorProps) {
const editor = useEditor({
extensions: [
StarterKit,
Link.configure({
openOnClick: false,
}),
Placeholder.configure({
placeholder: 'Start writing... Use [[Note Title]] to link to other notes',
}),
],
content,
onUpdate: ({ editor: e }) => {
onChange(e.getHTML());
},
onBlur: () => {
onBlur?.();
},
});
useEffect(() => {
if (editor && content !== editor.getHTML()) {
editor.commands.setContent(content);
}
}, [content, editor]);
if (!editor) {
return null;
}
return (
{/* Toolbar */}
editor.chain().focus().toggleBold().run()}
active={editor.isActive('bold')}
label="Bold"
>
editor.chain().focus().toggleItalic().run()}
active={editor.isActive('italic')}
label="Italic"
>
editor.chain().focus().toggleStrike().run()}
active={editor.isActive('strike')}
label="Strikethrough"
>
editor.chain().focus().toggleCode().run()}
active={editor.isActive('code')}
label="Code"
>
editor.chain().focus().toggleBulletList().run()}
active={editor.isActive('bulletList')}
label="Bullet list"
>
editor.chain().focus().toggleOrderedList().run()}
active={editor.isActive('orderedList')}
label="Ordered list"
>
editor.chain().focus().toggleBlockquote().run()}
active={editor.isActive('blockquote')}
label="Blockquote"
>
editor.chain().focus().undo().run()}
disabled={!editor.can().undo()}
label="Undo"
>
editor.chain().focus().redo().run()}
disabled={!editor.can().redo()}
label="Redo"
>
{/* Editor content */}
);
}
function ToolbarButton({
onClick,
active,
disabled,
label,
children,
}: {
onClick: () => void;
active?: boolean;
disabled?: boolean;
label: string;
children: React.ReactNode;
}) {
return (
);
}