import { useState, forwardRef, useImperativeHandle } from 'react'; import { useEditor, EditorContent, Editor } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; import TextAlign from '@tiptap/extension-text-align'; import Image from '@tiptap/extension-image'; import Highlight from '@tiptap/extension-highlight'; import Blockquote from "@tiptap/extension-blockquote"; export interface ContentEditorRef { setContent: (content: string) => void; getEditor: () => Editor | null; } const ContentEditor = forwardRef((_, ref) => { const [selectedImage, setSelectedImage] = useState(null); const ResizableImage = Image.extend({ addAttributes() { return { ...this.parent?.(), src: { default: null, }, alt: { default: null, }, title: { default: null, }, class: { default: 'max-w-full h-auto', // Добавлено для адаптивности }, width: { default: 'auto', parseHTML: (element) => element.getAttribute('width') || 'auto', renderHTML: (attributes) => ({ width: attributes.width, }), }, height: { default: 'auto', parseHTML: (element) => element.getAttribute('height') || 'auto', renderHTML: (attributes) => ({ height: attributes.height, }), }, }; }, }); const editor = useEditor({ extensions: [ StarterKit.configure({ blockquote: false, // Отключаем дефолтный }), Blockquote.configure({ HTMLAttributes: { class: 'border-l-4 border-gray-300 pl-4 italic', }, }), TextAlign.configure({ types: ['heading', 'paragraph'], }), ResizableImage, Highlight, ], content: '', onUpdate: ({ editor }) => { const pos = editor.state.selection.$anchor.pos; const resolvedPos = editor.state.doc.resolve(pos); const parentNode = resolvedPos.parent; if (parentNode.type.name === 'image') { setSelectedImage(parentNode.attrs.src); // Сохраняем URL изображения } else { setSelectedImage(null); // Очищаем выбор, если это не изображение } }, editorProps: { attributes: { class: 'prose prose-lg focus:outline-none min-h-[300px] max-w-none', }, }, }); // Позволяем родительскому компоненту использовать методы редактора useImperativeHandle(ref, () => ({ setContent: (content: string) => { editor?.commands.setContent(content); }, getEditor: () => editor, })); // Функция изменения размера изображения const updateImageSize = (delta: number) => { if (selectedImage) { const attrs = editor?.getAttributes('image'); const newWidth = Math.max((parseInt(attrs?.width) || 100) + delta, 50); editor?.chain().focus().updateAttributes('image', { width: `${newWidth}px` }).run(); } }; return (
{selectedImage && (
)}
); }); ContentEditor.displayName = 'ContentEditor'; export default ContentEditor;