mediahub-fe/components/editor/custom-editor.js

114 lines
3.8 KiB
JavaScript
Raw Normal View History

import React, { useRef, useEffect, useState, useCallback } from "react";
import { Editor } from "@tinymce/tinymce-react";
function CustomEditor(props) {
const editorRef = useRef(null);
const [isEditorReady, setIsEditorReady] = useState(false);
const [currentContent, setCurrentContent] = useState(props.initialData || "");
2025-07-20 09:07:22 +00:00
const isUserTypingRef = useRef(false);
// Handle editor initialization
const handleInit = useCallback((evt, editor) => {
editorRef.current = editor;
setIsEditorReady(true);
// Set initial content immediately when editor is ready
2025-07-20 09:07:22 +00:00
if (props.initialData) {
editor.setContent(props.initialData);
setCurrentContent(props.initialData);
}
// Simple onChange handler
editor.on('change', () => {
2025-07-20 09:07:22 +00:00
isUserTypingRef.current = true; // Mark that user is typing
const content = editor.getContent();
setCurrentContent(content);
if (props.onChange) {
props.onChange(content);
}
2025-07-20 09:07:22 +00:00
// Reset typing flag after a short delay
setTimeout(() => {
isUserTypingRef.current = false;
}, 100);
});
2025-07-20 09:07:22 +00:00
}, [props.initialData, props.onChange]);
2025-07-20 09:07:22 +00:00
// Watch for changes in initialData prop (from external sources like setValue)
useEffect(() => {
2025-07-20 09:07:22 +00:00
if (props.initialData !== currentContent && !isUserTypingRef.current) {
setCurrentContent(props.initialData || "");
// Update editor content if editor is ready
if (editorRef.current && isEditorReady) {
editorRef.current.setContent(props.initialData || "");
}
}
2025-07-20 09:07:22 +00:00
}, [props.initialData, isEditorReady]); // Removed currentContent from dependency
2025-07-20 09:07:22 +00:00
// Handle initial data when editor becomes ready (only for initialization)
useEffect(() => {
2025-07-20 09:07:22 +00:00
if (isEditorReady && props.initialData && editorRef.current && !isUserTypingRef.current) {
editorRef.current.setContent(props.initialData);
setCurrentContent(props.initialData);
}
2025-07-20 09:07:22 +00:00
}, [isEditorReady]); // Only depend on isEditorReady, not currentContent
return (
<Editor
onInit={handleInit}
apiKey={process.env.NEXT_PUBLIC_TINYMCE_API_KEY}
init={{
height: 400,
menubar: false,
plugins: [
'advlist', 'autolink', 'lists', 'link', 'image', 'charmap', 'preview',
'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
'insertdatetime', 'media', 'table', 'code', 'help', 'wordcount'
],
toolbar: 'undo redo | blocks | ' +
'bold italic forecolor | alignleft aligncenter ' +
'alignright alignjustify | bullist numlist outdent indent | ' +
'removeformat | table | code | help',
content_style: `
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 14px;
line-height: 1.6;
color: #333;
}
.mce-content-body {
padding: 16px;
min-height: 368px;
}
`,
placeholder: 'Start typing...',
branding: false,
elementpath: false,
resize: false,
statusbar: false,
auto_focus: false,
forced_root_block: 'p',
entity_encoding: 'raw',
verify_html: false,
cleanup: false,
cleanup_on_startup: false,
auto_resize: false,
paste_as_text: false,
paste_enable_default_filters: true,
paste_word_valid_elements: 'b,strong,i,em,h1,h2,h3,h4,h5,h6',
paste_retain_style_properties: 'color background-color font-size font-weight',
mobile: {
theme: 'silver',
plugins: ['lists', 'autolink', 'link', 'image', 'table'],
toolbar: 'bold italic | bullist numlist | link image'
}
}}
/>
);
}
export default CustomEditor;