diff --git a/apps/admin/src/components/EditorShell.tsx b/apps/admin/src/components/EditorShell.tsx index 9513d9d..4de5238 100644 --- a/apps/admin/src/components/EditorShell.tsx +++ b/apps/admin/src/components/EditorShell.tsx @@ -1,6 +1,7 @@ import { Box, Button, Stack, TextField, Typography } from '@mui/material'; import AdminLayout from '../layout/AdminLayout'; import Recorder from '../features/recorder/Recorder'; +import RichEditor from './RichEditor'; import { useEffect, useState } from 'react'; export default function EditorShell({ onLogout }: { onLogout?: () => void }) { @@ -88,13 +89,7 @@ export default function EditorShell({ onLogout }: { onLogout?: () => void }) { Draft - setDraft(e.target.value)} - /> + setDraft(html)} placeholder="Write your post..." /> {draftId && ( diff --git a/apps/admin/src/components/RichEditor.tsx b/apps/admin/src/components/RichEditor.tsx new file mode 100644 index 0000000..90e56d2 --- /dev/null +++ b/apps/admin/src/components/RichEditor.tsx @@ -0,0 +1,46 @@ +import { useEffect } from 'react'; +import { EditorContent, useEditor } from '@tiptap/react'; +import StarterKit from '@tiptap/starter-kit'; +import Link from '@tiptap/extension-link'; +import Placeholder from '@tiptap/extension-placeholder'; + +export default function RichEditor({ + value, + onChange, + placeholder, +}: { + value: string; + onChange: (html: string) => void; + placeholder?: string; +}) { + const editor = useEditor({ + extensions: [ + StarterKit, + Link.configure({ openOnClick: true }), + Placeholder.configure({ placeholder: placeholder || 'Write something…' }), + ], + content: value || '', + onUpdate: ({ editor }) => { + const html = editor.getHTML(); + onChange(html); + }, + editorProps: { + attributes: { + class: 'tiptap-content', + }, + }, + }); + + // keep external value in sync if it changes (basic) + useEffect(() => { + if (editor && value !== editor.getHTML()) { + editor.commands.setContent(value || '', { emitUpdate: false }); + } + }, [value, editor]); + + return ( +
+ +
+ ); +}