import type { RefObject } from 'react'; import { createRef, useCallback, useEffect, useRef } from 'react'; import { useEditorCommands } from '~/lib/hooks'; import type { DocumentProperties, Editor } from '~/types/editor'; import { EditorController } from './EditorController'; import { EditorRender } from './EditorRender'; import { PageRender, type PageRenderRef } from './PageRender'; export interface EditorComponentProps { documents?: Record; currentPage?: string; onReady?: (editor: Editor) => void; onLoad?: () => Promise; onContentChange?: (pageName: string, html: string) => void; onSave?: (pageName: string, html: string) => Promise | void; } export function EditorComponent(props: EditorComponentProps) { const { documents = {}, currentPage, onReady, onLoad, onContentChange, onSave } = props; const controllerRef = useRef(null); const lastContentRef = useRef>({}); const pageRefsRef = useRef>>({}); const currentPageRef = useRef(currentPage); useEditorCommands(controllerRef); useEffect(() => { Object.keys(documents).forEach((docName) => { if (!pageRefsRef.current[docName]) { pageRefsRef.current[docName] = createRef(); } }); }, [documents]); useEffect(() => { if (!controllerRef.current) { controllerRef.current = new EditorController({ getContentElement, getIframeElement, }); setTimeout(() => { if (controllerRef.current && onReady) { onReady(controllerRef.current); } }, 0); } }, [onReady]); useEffect(() => { currentPageRef.current = currentPage; }, [currentPage]); const getContentElement = useCallback((): HTMLElement | null => { const currentPageName = currentPageRef.current ?? 'index'; return pageRefsRef.current[currentPageName]?.current?.element ?? null; }, [pageRefsRef]); const getIframeElement = useCallback((): HTMLIFrameElement | null => { const currentPageName = currentPageRef.current ?? 'index'; return pageRefsRef.current[currentPageName]?.current?.iframe ?? null; }, [pageRefsRef]); /** * 执行保存 * @param html 要保存的 HTML 内容 */ const handleSave = useCallback( (pageName: string, html: string): void => { if (lastContentRef.current[pageName] === html) { return; } lastContentRef.current[pageName] = html; if (onSave) { onSave(pageName, html); } }, [onSave], ); const handleContentUpdate = useCallback( (pageName: string, html: string): void => { if (lastContentRef.current[pageName] === html) { return; } if (onContentChange) { onContentChange(pageName, html); } }, [onContentChange], ); const handleMount = useCallback(async (): Promise => { if (onLoad) { await onLoad(); } }, [onLoad]); return ( {Object.values(documents).map((document) => ( ))} ); }