'use client'; /** * @author: Kim Jino * @since: 2025.03.31 * @description: CKEditor component for Next.js using Script component for loading CKEditor script */ // @/app/(forum)/post/_component/Editor.tsx import '@/styles/editor.scss'; import Script from 'next/script'; import React, { useRef, useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import { CKEditor } from '@ckeditor/ckeditor5-react'; import type { Editor as CKEditorInstance } from '@ckeditor/ckeditor5-core'; import Loading from '@/app/component/Loading'; import BoardMeta from '@/types/forum/boardMeta'; import { PostConst } from '@/constants/forum'; export interface Handle { editorInstance: CKEditorInstance|null; getFileStore(): UploadedFile[]; getImageStore(): UploadedImage[]; getMediaStore(): UploadedMedia[]; } interface Props { key: string; data: string; onChange: (data: string) => void; boardMeta?: BoardMeta|null; } const Editor = forwardRef(({ key = '', data = '', onChange, boardMeta }: Props, ref) => { const [ready, setReady] = useState(false); // CKEditor가 준비되었는지 여부 const [instanceLoaded, setInstanceLoaded] = useState(false); const editorRef = useRef(null); // CKEditor 객체 const editorInstanceRef = useRef(null); useEffect(() => { if (typeof window !== 'undefined' && window.Editor) { editorRef.current = window.Editor; setReady(true); } }, [key]); // 게시판 주소가 바뀌면 다시 ready 확인 const handleScriptLoad = () => { if (typeof window !== 'undefined' && window.Editor) { editorRef.current = window.Editor; setReady(true); } else { console.error('CKEditor script not loaded properly.'); } }; // 외부에 접근 가능한 명령어 useImperativeHandle(ref, () => ({ editorInstance: editorInstanceRef.current, getFileStore: () => editorInstanceRef.current?._fileStore || [], getImageStore: () => editorInstanceRef.current?._imageStore || [], getMediaStore: () => editorInstanceRef.current?._mediaStore || [] }), [instanceLoaded]); return ( <>