@buildingbite/blocks 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -0
- package/dist/index.d.mts +191 -0
- package/dist/index.d.ts +191 -0
- package/dist/index.js +2514 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2492 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/blocks.ts","../src/BlockMenu.tsx","../src/context/EditorContext.tsx","../src/blocks/TextBlockEditor.tsx","../src/blocks/ImageGalleryEditor.tsx","../src/blocks/LinkCardEditor.tsx","../src/blocks/LinkEmbedEditor.tsx","../src/blocks/DialogueEditor.tsx","../src/blocks/DividerEditor.tsx","../src/BlockEditor.tsx"],"names":["jsx","useRef","jsxs","useEffect","useState","X","Upload","Link2","Youtube","AlignLeft","AlignRight","Minus","ImageIcon","AlignCenter","useCallback","Plus","React"],"mappings":"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","file":"index.mjs","sourcesContent":["// 블록 타입 정의\nexport type BlockType =\n | 'paragraph' // 일반 텍스트\n | 'heading' // 제목 (H1, H2, H3)\n | 'image' // 단일 이미지\n | 'image-gallery' // 이미지 갤러리 (그리드, 가로스크롤)\n | 'link-card' // 링크 카드 (OG 미리보기)\n | 'link-embed' // 임베드 (YouTube 등)\n | 'dialogue' // 대사 (이름 + 대사)\n | 'divider' // 구분선/구분기호\n | 'quote' // 인용문\n | 'list'; // 목록\n\n// 텍스트 노드 (인라인 서식용)\nexport interface TextNode {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n link?: string;\n}\n\n// 기본 블록 인터페이스\ninterface BaseBlock {\n id: string;\n type: BlockType;\n}\n\n// 문단 블록\nexport interface ParagraphBlock extends BaseBlock {\n type: 'paragraph';\n content: TextNode[];\n}\n\n// 제목 블록\nexport interface HeadingBlock extends BaseBlock {\n type: 'heading';\n level: 1 | 2 | 3;\n content: TextNode[];\n}\n\n// 이미지 데이터\nexport interface ImageData {\n url: string;\n alt?: string;\n caption?: string;\n width?: number;\n height?: number;\n}\n\n// 단일 이미지 블록\nexport interface ImageBlock extends BaseBlock {\n type: 'image';\n image: ImageData;\n alignment: 'left' | 'center' | 'right' | 'full-width';\n}\n\n// 이미지 갤러리 블록\nexport interface ImageGalleryBlock extends BaseBlock {\n type: 'image-gallery';\n images: ImageData[];\n layout: 'grid' | 'horizontal-scroll' | 'masonry';\n columns?: 2 | 3 | 4;\n}\n\n// OG 데이터\nexport interface OGData {\n title?: string;\n description?: string;\n image?: string;\n siteName?: string;\n}\n\n// 링크 카드 블록\nexport interface LinkCardBlock extends BaseBlock {\n type: 'link-card';\n url: string;\n ogData?: OGData;\n}\n\n// 임베드 블록\nexport interface LinkEmbedBlock extends BaseBlock {\n type: 'link-embed';\n url: string;\n embedType: 'youtube' | 'twitter' | 'generic';\n videoId?: string;\n}\n\n// 대사 라인\nexport interface DialogueLine {\n speaker: string;\n content: TextNode[];\n speakerColor?: string; // 채팅 스타일: 말풍선 배경색\n profileImage?: string; // 채팅 스타일: 프로필 이미지 URL\n alignment?: 'left' | 'right'; // 채팅 스타일: 정렬 방향\n}\n\n// 대사 블록\nexport interface DialogueBlock extends BaseBlock {\n type: 'dialogue';\n lines: DialogueLine[];\n style?: 'chat' | 'play'; // chat: 카톡 스타일, play: 희극 스타일\n}\n\n// 구분선 블록\nexport interface DividerBlock extends BaseBlock {\n type: 'divider';\n variant: 'line' | 'short-line' | 'dots' | 'custom-image';\n customImage?: string;\n alignment?: 'left' | 'center' | 'right'; // line 제외한 나머지 타입에 적용\n}\n\n// 인용문 블록\nexport interface QuoteBlock extends BaseBlock {\n type: 'quote';\n content: TextNode[];\n citation?: string;\n}\n\n// 목록 블록 (단일 항목 - 각 항목이 개별 블록)\nexport interface ListBlock extends BaseBlock {\n type: 'list';\n listType: 'ordered' | 'unordered';\n content: TextNode[];\n}\n\n// 블록 유니온 타입\nexport type Block =\n | ParagraphBlock\n | HeadingBlock\n | ImageBlock\n | ImageGalleryBlock\n | LinkCardBlock\n | LinkEmbedBlock\n | DialogueBlock\n | DividerBlock\n | QuoteBlock\n | ListBlock;\n\n// 블록 콘텐츠 전체 구조\nexport interface BlockContent {\n version: 2;\n blocks: Block[];\n}\n\n// 캐릭터 (대사 블록용)\nexport interface Character {\n id: string;\n name: string;\n profileImage: string | null;\n defaultColor: string;\n description?: string | null;\n}\n\n// 헬퍼 함수: 빈 문단 블록 생성\nexport function createEmptyParagraphBlock(): ParagraphBlock {\n return {\n id: generateBlockId(),\n type: 'paragraph',\n content: [{ text: '' }],\n };\n}\n\n// 헬퍼 함수: 블록 ID 생성\nexport function generateBlockId(): string {\n return `block_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n}\n\n// 헬퍼 함수: TextNode 배열을 일반 텍스트로 변환\nexport function textNodesToPlainText(nodes: TextNode[]): string {\n return nodes.map(node => node.text).join('');\n}\n\n// 헬퍼 함수: 블록 배열에서 미리보기 텍스트 생성\nexport function generatePreviewFromBlocks(blocks: Block[], maxLength: number = 150): string {\n const textParts: string[] = [];\n\n for (const block of blocks) {\n if (textParts.join(' ').length >= maxLength) break;\n\n switch (block.type) {\n case 'paragraph':\n case 'heading':\n case 'quote':\n textParts.push(textNodesToPlainText(block.content));\n break;\n case 'dialogue':\n for (const line of block.lines) {\n textParts.push(`${line.speaker}: ${textNodesToPlainText(line.content)}`);\n }\n break;\n case 'list':\n textParts.push(textNodesToPlainText(block.content));\n break;\n }\n }\n\n const fullText = textParts.join(' ').replace(/\\s+/g, ' ').trim();\n return fullText.slice(0, maxLength);\n}\n\n// 헬퍼 함수: 블록 배열의 총 글자 수 계산\nexport function countBlocksCharacters(blocks: Block[]): number {\n let count = 0;\n\n for (const block of blocks) {\n switch (block.type) {\n case 'paragraph':\n case 'heading':\n case 'quote':\n count += textNodesToPlainText(block.content).length;\n break;\n case 'dialogue':\n for (const line of block.lines) {\n count += line.speaker.length + textNodesToPlainText(line.content).length;\n }\n break;\n case 'list':\n count += textNodesToPlainText(block.content).length;\n break;\n }\n }\n\n return count;\n}\n","import React, { useEffect, useRef } from 'react';\nimport { Block } from './types/blocks';\nimport {\n Type,\n Heading2,\n Quote,\n List,\n Image,\n Images,\n Link2,\n Youtube,\n MessageSquare,\n Minus,\n} from 'lucide-react';\n\ninterface BlockMenuProps {\n position: { x: number; y: number };\n onClose: () => void;\n onSelect: (type: Block['type']) => void;\n}\n\ninterface MenuItem {\n type: Block['type'] | 'heading1' | 'heading2' | 'heading3' | 'bullet-list' | 'ordered-list';\n icon: React.ReactNode;\n label: string;\n description: string;\n category: 'basic' | 'advanced';\n}\n\nconst menuItems: MenuItem[] = [\n {\n type: 'paragraph',\n icon: <Type size={20} />,\n label: '본문',\n description: '일반 텍스트',\n category: 'basic',\n },\n {\n type: 'heading',\n icon: <Heading2 size={20} />,\n label: '제목',\n description: '섹션 제목',\n category: 'basic',\n },\n {\n type: 'quote',\n icon: <Quote size={20} />,\n label: '인용문',\n description: '인용 텍스트',\n category: 'basic',\n },\n {\n type: 'list',\n icon: <List size={20} />,\n label: '목록',\n description: '글머리 목록',\n category: 'basic',\n },\n {\n type: 'divider',\n icon: <Minus size={20} />,\n label: '구분선',\n description: '섹션 구분',\n category: 'basic',\n },\n {\n type: 'image',\n icon: <Image size={20} />,\n label: '이미지',\n description: '단일 이미지',\n category: 'basic',\n },\n {\n type: 'image-gallery',\n icon: <Images size={20} />,\n label: '이미지 갤러리',\n description: '여러 이미지 그리드/슬라이드',\n category: 'advanced',\n },\n {\n type: 'link-card',\n icon: <Link2 size={20} />,\n label: '링크 카드',\n description: 'OG 미리보기 카드',\n category: 'advanced',\n },\n {\n type: 'link-embed',\n icon: <Youtube size={20} />,\n label: '임베드',\n description: 'YouTube, Twitter 등',\n category: 'advanced',\n },\n {\n type: 'dialogue',\n icon: <MessageSquare size={20} />,\n label: '대사',\n description: '캐릭터 대화',\n category: 'advanced',\n },\n];\n\nexport default function BlockMenu({ position, onClose, onSelect }: BlockMenuProps) {\n const menuRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n onClose();\n }\n };\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n document.addEventListener('keydown', handleKeyDown);\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [onClose]);\n\n const handleSelect = (item: MenuItem) => {\n onSelect(item.type as Block['type']);\n };\n\n // 화면 경계를 고려한 위치 계산\n const adjustedPosition = {\n x: Math.min(position.x, typeof window !== 'undefined' ? window.innerWidth - 280 : position.x),\n y: Math.min(position.y, typeof window !== 'undefined' ? window.innerHeight - 400 : position.y),\n };\n\n const basicItems = menuItems.filter(item => item.category === 'basic');\n const advancedItems = menuItems.filter(item => item.category === 'advanced');\n\n return (\n <div\n ref={menuRef}\n className=\"fixed z-50 bg-white rounded-xl shadow-xl border border-gray-200 py-2 w-64 max-h-96 overflow-y-auto\"\n style={{\n left: adjustedPosition.x,\n top: adjustedPosition.y,\n }}\n >\n <div className=\"px-3 py-2\">\n <p className=\"text-xs font-medium text-gray-400 uppercase\">블록 추가</p>\n </div>\n\n <div className=\"divide-y divide-gray-100\">\n {/* 기본 블록 */}\n <div className=\"py-1\">\n <p className=\"px-3 py-1 text-xs text-gray-400\">기본</p>\n {basicItems.map((item) => (\n <button\n key={item.type}\n onClick={() => handleSelect(item)}\n className=\"w-full px-3 py-2 flex items-center gap-3 hover:bg-gray-50 transition-colors\"\n >\n <div className=\"text-gray-500\">{item.icon}</div>\n <div className=\"text-left\">\n <p className=\"text-sm font-medium text-gray-900\">{item.label}</p>\n <p className=\"text-xs text-gray-500\">{item.description}</p>\n </div>\n </button>\n ))}\n </div>\n\n {/* 고급 블록 */}\n <div className=\"py-1\">\n <p className=\"px-3 py-1 text-xs text-gray-400\">고급</p>\n {advancedItems.map((item) => (\n <button\n key={item.type}\n onClick={() => handleSelect(item)}\n className=\"w-full px-3 py-2 flex items-center gap-3 hover:bg-gray-50 transition-colors\"\n >\n <div className=\"text-gray-500\">{item.icon}</div>\n <div className=\"text-left\">\n <p className=\"text-sm font-medium text-gray-900\">{item.label}</p>\n <p className=\"text-xs text-gray-500\">{item.description}</p>\n </div>\n </button>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import React, { createContext, useContext, ReactNode } from 'react';\nimport { OGData, Character } from '../types/blocks';\n\n// 이미지 컴포넌트 Props\nexport interface ImageComponentProps {\n src: string;\n alt: string;\n fill?: boolean;\n width?: number;\n height?: number;\n className?: string;\n style?: React.CSSProperties;\n}\n\n// 에디터 서비스 인터페이스\nexport interface EditorServices {\n // 이미지 업로드 (Firebase Storage 등 대체)\n uploadImage: (file: File, category: string) => Promise<string>;\n\n // OG 데이터 조회 (/api/og 대체)\n fetchOGData: (url: string) => Promise<OGData>;\n\n // 캐릭터 라이브러리 (선택적, Firestore 대체)\n getCharacters?: () => Promise<Character[]>;\n\n // 이미지 컴포넌트 (next/image 대체)\n ImageComponent?: React.ComponentType<ImageComponentProps>;\n}\n\n// Context 생성\nconst EditorContext = createContext<EditorServices | null>(null);\n\n// Provider Props\ninterface EditorProviderProps {\n services: EditorServices;\n children: ReactNode;\n}\n\n// Provider 컴포넌트\nexport function EditorProvider({ services, children }: EditorProviderProps) {\n return (\n <EditorContext.Provider value={services}>\n {children}\n </EditorContext.Provider>\n );\n}\n\n// Hook: EditorServices 사용\nexport function useEditorServices(): EditorServices {\n const context = useContext(EditorContext);\n if (!context) {\n throw new Error('useEditorServices must be used within an EditorProvider');\n }\n return context;\n}\n\n// Hook: 선택적 EditorServices 사용 (Provider 없이도 동작)\nexport function useOptionalEditorServices(): EditorServices | null {\n return useContext(EditorContext);\n}\n\n// 기본 이미지 컴포넌트 (next/image가 없을 때 사용)\nexport function DefaultImage({\n src,\n alt,\n fill,\n width,\n height,\n className,\n style,\n}: ImageComponentProps) {\n if (fill) {\n return (\n <img\n src={src}\n alt={alt}\n className={className}\n style={{\n ...style,\n position: 'absolute',\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n }}\n />\n );\n }\n\n return (\n <img\n src={src}\n alt={alt}\n width={width}\n height={height}\n className={className}\n style={style}\n />\n );\n}\n","import React, { useRef, useEffect, useCallback, useState } from 'react';\nimport {\n Block,\n ParagraphBlock,\n HeadingBlock,\n QuoteBlock,\n ListBlock,\n ImageBlock,\n TextNode,\n} from '../types/blocks';\nimport { useEditorServices, DefaultImage } from '../context/EditorContext';\nimport { Upload, X, AlignLeft, AlignCenter, AlignRight, Maximize } from 'lucide-react';\n\ninterface TextBlockEditorProps {\n block: ParagraphBlock | HeadingBlock | QuoteBlock | ListBlock | ImageBlock;\n onUpdate: (updates: Partial<Block>) => void;\n onMergeWithPrevious?: () => void;\n onSplitBlock?: (beforeText: TextNode[], afterText: TextNode[]) => void;\n onPasteBlocks?: (beforeText: TextNode[], pastedLines: string[], afterText: TextNode[]) => void;\n onDeleteEmptyBlock?: () => void;\n onFocusPrevious?: () => void;\n onFocusNext?: () => void;\n isOnlyBlock?: boolean;\n}\n\n// TextNode 배열을 HTML로 변환\nfunction textNodesToHtml(nodes: TextNode[]): string {\n return nodes.map(node => {\n let html = node.text;\n\n // 특수 문자 이스케이프\n html = html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n\n if (node.bold) html = `<strong>${html}</strong>`;\n if (node.italic) html = `<em>${html}</em>`;\n if (node.underline) html = `<u>${html}</u>`;\n if (node.strikethrough) html = `<s>${html}</s>`;\n if (node.link) html = `<a href=\"${node.link}\" class=\"text-blue-600 underline\">${html}</a>`;\n\n return html;\n }).join('');\n}\n\n// HTML을 TextNode 배열로 변환 (단순 버전)\nfunction htmlToTextNodes(html: string): TextNode[] {\n // 단순히 텍스트만 추출 (서식 정보는 나중에 개선)\n const div = document.createElement('div');\n div.innerHTML = html;\n const text = div.textContent || '';\n return [{ text }];\n}\n\nexport default function TextBlockEditor({ block, onUpdate, onMergeWithPrevious, onSplitBlock, onPasteBlocks, onDeleteEmptyBlock, onFocusPrevious, onFocusNext, isOnlyBlock }: TextBlockEditorProps) {\n const editorRef = useRef<HTMLDivElement>(null);\n const [uploading, setUploading] = useState(false);\n const isComposingRef = useRef(false);\n const lastContentRef = useRef<string>(''); // 마지막으로 설정한 content 추적\n\n const services = useEditorServices();\n const ImageComponent = services.ImageComponent || DefaultImage;\n\n // 커서가 맨 앞에 있는지 확인\n const isCursorAtStart = useCallback(() => {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return false;\n const range = selection.getRangeAt(0);\n if (!range.collapsed) return false;\n\n const editor = editorRef.current;\n if (!editor) return false;\n\n // 첫 번째 노드의 처음에 커서가 있는지 확인\n if (range.startOffset === 0) {\n const startNode = range.startContainer;\n if (startNode === editor || startNode === editor.firstChild) {\n return true;\n }\n // 첫 번째 텍스트 노드인지 확인\n if (startNode.nodeType === Node.TEXT_NODE) {\n let node = startNode;\n while (node.previousSibling === null && node.parentNode && node.parentNode !== editor) {\n node = node.parentNode as unknown as ChildNode;\n }\n if (node.previousSibling === null) return true;\n }\n }\n return false;\n }, []);\n\n // 커서가 맨 끝에 있는지 확인\n const isCursorAtEnd = useCallback(() => {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return false;\n const range = selection.getRangeAt(0);\n if (!range.collapsed) return false;\n\n const editor = editorRef.current;\n if (!editor) return false;\n\n const endNode = range.endContainer;\n const endOffset = range.endOffset;\n\n // 텍스트 노드의 끝에 있는지 확인\n if (endNode.nodeType === Node.TEXT_NODE) {\n if (endOffset !== endNode.textContent?.length) return false;\n // 마지막 노드인지 확인\n let node = endNode;\n while (node.nextSibling === null && node.parentNode && node.parentNode !== editor) {\n node = node.parentNode as unknown as ChildNode;\n }\n if (node.nextSibling === null) return true;\n } else if (endNode === editor) {\n return endOffset === editor.childNodes.length;\n }\n return false;\n }, []);\n\n // 이미지 블록 처리\n if (block.type === 'image') {\n const imageBlock = block as ImageBlock;\n\n const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n try {\n setUploading(true);\n const url = await services.uploadImage(file, 'editor');\n onUpdate({\n image: { ...imageBlock.image, url },\n });\n } catch (error) {\n console.error('Image upload error:', error);\n alert('이미지 업로드에 실패했습니다.');\n } finally {\n setUploading(false);\n }\n };\n\n const handleRemove = () => {\n onUpdate({ image: { url: '', alt: '', caption: '' } });\n };\n\n const handleAlignmentChange = (alignment: ImageBlock['alignment']) => {\n onUpdate({ alignment });\n };\n\n if (!imageBlock.image.url) {\n return (\n <label className=\"flex flex-col items-center justify-center w-full h-40 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:border-gray-400 hover:bg-gray-50 transition-colors\">\n <input\n type=\"file\"\n accept=\"image/*\"\n onChange={handleUpload}\n className=\"hidden\"\n disabled={uploading}\n />\n {uploading ? (\n <div className=\"text-center\">\n <div className=\"w-6 h-6 border-2 border-gray-400 border-t-transparent rounded-full animate-spin mx-auto mb-2\"></div>\n <span className=\"text-sm text-gray-500\">업로드 중...</span>\n </div>\n ) : (\n <div className=\"text-center\">\n <Upload size={24} className=\"mx-auto mb-2 text-gray-400\" />\n <span className=\"text-sm text-gray-500\">이미지 업로드</span>\n </div>\n )}\n </label>\n );\n }\n\n return (\n <div className=\"space-y-2\">\n <div className=\"relative\">\n <div\n className={`relative ${\n imageBlock.alignment === 'full-width' ? 'w-full' : 'max-w-md'\n } ${\n imageBlock.alignment === 'left' ? 'mr-auto' :\n imageBlock.alignment === 'right' ? 'ml-auto' : 'mx-auto'\n }`}\n >\n <div className=\"relative aspect-video\">\n <ImageComponent\n src={imageBlock.image.url}\n alt={imageBlock.image.alt || ''}\n fill\n className=\"object-contain rounded-lg\"\n />\n </div>\n <button\n onClick={handleRemove}\n className=\"absolute top-2 right-2 p-1 bg-red-500 text-white rounded-full hover:bg-red-600\"\n >\n <X size={14} />\n </button>\n </div>\n </div>\n <div className=\"flex items-center justify-center gap-1\">\n <button\n onClick={() => handleAlignmentChange('left')}\n className={`p-1.5 rounded ${imageBlock.alignment === 'left' ? 'bg-gray-200' : 'hover:bg-gray-100'}`}\n >\n <AlignLeft size={14} />\n </button>\n <button\n onClick={() => handleAlignmentChange('center')}\n className={`p-1.5 rounded ${imageBlock.alignment === 'center' ? 'bg-gray-200' : 'hover:bg-gray-100'}`}\n >\n <AlignCenter size={14} />\n </button>\n <button\n onClick={() => handleAlignmentChange('right')}\n className={`p-1.5 rounded ${imageBlock.alignment === 'right' ? 'bg-gray-200' : 'hover:bg-gray-100'}`}\n >\n <AlignRight size={14} />\n </button>\n <button\n onClick={() => handleAlignmentChange('full-width')}\n className={`p-1.5 rounded ${imageBlock.alignment === 'full-width' ? 'bg-gray-200' : 'hover:bg-gray-100'}`}\n >\n <Maximize size={14} />\n </button>\n </div>\n <input\n type=\"text\"\n value={imageBlock.image.caption || ''}\n onChange={(e) => onUpdate({ image: { ...imageBlock.image, caption: e.target.value } })}\n placeholder=\"캡션 (선택)\"\n className=\"w-full text-center text-sm text-gray-500 border-none outline-none\"\n />\n </div>\n );\n }\n\n // 목록 블록인지 확인\n const isListBlock = block.type === 'list';\n\n // 텍스트 블록 (paragraph, heading, quote, list)\n const textBlock = block as ParagraphBlock | HeadingBlock | QuoteBlock | ListBlock;\n const content = textBlock.content;\n\n // HTML 설정 및 외부 변경 동기화\n useEffect(() => {\n if (editorRef.current && !isComposingRef.current) {\n const html = textNodesToHtml(content);\n const currentHtml = editorRef.current.innerHTML;\n\n // 내용이 실제로 다른 경우에만 업데이트 (입력 중 커서 이동 방지)\n // lastContentRef와 비교하여 외부에서 변경된 경우에만 DOM 업데이트\n if (html !== lastContentRef.current && currentHtml !== html) {\n editorRef.current.innerHTML = html || '';\n lastContentRef.current = html;\n }\n }\n }, [content]);\n\n // 붙여넣기 이벤트 처리 - 줄바꿈마다 새 블록 생성\n const handlePaste = useCallback((e: React.ClipboardEvent) => {\n const text = e.clipboardData.getData('text/plain');\n const lines = text.split('\\n');\n\n // 줄바꿈이 없으면 기본 동작 (단일 블록 내 붙여넣기)\n if (lines.length <= 1 || !onPasteBlocks) return;\n\n e.preventDefault();\n\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n const range = selection.getRangeAt(0);\n const editor = editorRef.current;\n if (!editor) return;\n\n // 선택 영역이 있으면 먼저 삭제\n if (!range.collapsed) {\n range.deleteContents();\n }\n\n // 커서 기준으로 앞/뒤 텍스트 분리\n const beforeRange = document.createRange();\n beforeRange.setStart(editor, 0);\n beforeRange.setEnd(range.startContainer, range.startOffset);\n const beforeText = beforeRange.toString();\n\n const afterRange = document.createRange();\n afterRange.setStart(range.endContainer, range.endOffset);\n afterRange.setEnd(editor, editor.childNodes.length);\n const afterText = afterRange.toString();\n\n // 현재 블록 DOM을 첫 번째 줄로 업데이트\n const firstLineText = beforeText + lines[0];\n const firstLineHtml = textNodesToHtml([{ text: firstLineText }]);\n editor.innerHTML = firstLineHtml;\n lastContentRef.current = firstLineHtml;\n\n onPasteBlocks(\n [{ text: firstLineText }],\n lines.slice(1, -1),\n [{ text: lines[lines.length - 1] + afterText }]\n );\n }, [onPasteBlocks]);\n\n // 키보드 이벤트 처리\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n // 크로스 블록 선택 가드: 선택이 현재 블록 밖으로 나가면 처리하지 않고 버블링\n if (e.key === 'Delete' || e.key === 'Backspace') {\n const sel = window.getSelection();\n if (sel && !sel.isCollapsed && sel.rangeCount > 0) {\n const range = sel.getRangeAt(0);\n const editor = editorRef.current;\n if (editor && (!editor.contains(range.startContainer) || !editor.contains(range.endContainer))) {\n return; // 부모(BlockEditor)의 전역 핸들러가 처리\n }\n }\n }\n\n // Ctrl/Cmd + B for bold\n if ((e.ctrlKey || e.metaKey) && e.key === 'b') {\n e.preventDefault();\n document.execCommand('bold');\n return;\n }\n // Ctrl/Cmd + I for italic\n if ((e.ctrlKey || e.metaKey) && e.key === 'i') {\n e.preventDefault();\n document.execCommand('italic');\n return;\n }\n // Ctrl/Cmd + U for underline\n if ((e.ctrlKey || e.metaKey) && e.key === 'u') {\n e.preventDefault();\n document.execCommand('underline');\n return;\n }\n\n // Arrow up at start - move to previous block\n if (e.key === 'ArrowUp' && onFocusPrevious && isCursorAtStart()) {\n e.preventDefault();\n onFocusPrevious();\n return;\n }\n\n // Arrow down at end - move to next block\n if (e.key === 'ArrowDown' && onFocusNext && isCursorAtEnd()) {\n e.preventDefault();\n onFocusNext();\n return;\n }\n\n if (e.key === 'Enter' && !e.shiftKey && onSplitBlock) {\n // IME 조합 중이면 무시\n if (isComposingRef.current) return;\n\n e.preventDefault();\n\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n const range = selection.getRangeAt(0);\n const editor = editorRef.current;\n if (!editor) return;\n\n // 선택 영역이 있으면 먼저 삭제\n if (!range.collapsed) {\n range.deleteContents();\n }\n\n // 커서 위치 기준으로 텍스트 분할\n const beforeRange = document.createRange();\n beforeRange.setStart(editor, 0);\n beforeRange.setEnd(range.startContainer, range.startOffset);\n\n const afterRange = document.createRange();\n afterRange.setStart(range.endContainer, range.endOffset);\n afterRange.setEnd(editor, editor.childNodes.length);\n\n const beforeText = beforeRange.toString();\n const afterText = afterRange.toString();\n\n // 현재 블록의 DOM을 직접 업데이트 (beforeText만 남김)\n const beforeHtml = textNodesToHtml([{ text: beforeText }]);\n editor.innerHTML = beforeHtml;\n lastContentRef.current = beforeHtml;\n\n onSplitBlock(\n [{ text: beforeText }],\n [{ text: afterText }]\n );\n } else if (e.key === 'Backspace' && onMergeWithPrevious) {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n const range = selection.getRangeAt(0);\n\n // 커서가 맨 앞에 있고 선택 영역이 없을 때\n if (range.collapsed && range.startOffset === 0) {\n const editor = editorRef.current;\n if (editor && (range.startContainer === editor.firstChild || range.startContainer === editor)) {\n e.preventDefault();\n onMergeWithPrevious();\n }\n }\n } else if (e.key === 'Delete' && onDeleteEmptyBlock) {\n // 빈 블록에서 Delete 키 → 블록 삭제 후 이전 블록으로 포커스\n const editor = editorRef.current;\n const text = editor?.textContent || '';\n if (text.length === 0) {\n e.preventDefault();\n onDeleteEmptyBlock();\n }\n }\n }, [onSplitBlock, onMergeWithPrevious, onDeleteEmptyBlock, onFocusPrevious, onFocusNext, isCursorAtStart, isCursorAtEnd]);\n\n // 입력 이벤트 처리\n const handleInput = useCallback(() => {\n if (editorRef.current) {\n const html = editorRef.current.innerHTML;\n const nodes = htmlToTextNodes(html);\n // lastContentRef에 모델 기준 HTML 저장 (useEffect의 textNodesToHtml과 일치시킴)\n // DOM innerHTML은 를 사용하지만 모델은 \\u00A0을 사용하므로 불일치 방지\n lastContentRef.current = textNodesToHtml(nodes);\n onUpdate({ content: nodes });\n }\n }, [onUpdate]);\n\n // IME 조합 이벤트 처리\n const handleCompositionStart = useCallback(() => {\n isComposingRef.current = true;\n }, []);\n\n const handleCompositionEnd = useCallback(() => {\n isComposingRef.current = false;\n }, []);\n\n // 블록 타입에 따른 스타일\n const getBlockStyle = () => {\n switch (block.type) {\n case 'heading':\n const headingBlock = block as HeadingBlock;\n switch (headingBlock.level) {\n case 1:\n return 'text-3xl font-bold';\n case 2:\n return 'text-2xl font-semibold';\n case 3:\n return 'text-xl font-semibold';\n default:\n return 'text-2xl font-semibold';\n }\n case 'quote':\n return 'border-l-4 border-gray-300 pl-4 text-gray-600 italic';\n default:\n return 'text-base';\n }\n };\n\n // 플레이스홀더 - paragraph는 블록이 하나뿐일 때만 표시\n const getPlaceholder = () => {\n switch (block.type) {\n case 'heading':\n return '제목을 입력하세요...';\n case 'quote':\n return '인용문을 입력하세요...';\n case 'list':\n return '목록 항목...';\n default:\n return isOnlyBlock ? '내용을 입력하세요...' : '';\n }\n };\n\n // 목록 블록은 마커와 함께 렌더링\n if (isListBlock) {\n const listBlock = block as ListBlock;\n return (\n <div className=\"flex items-start gap-2\">\n <span className=\"flex-shrink-0 select-none text-gray-500 mt-0.5\">\n {listBlock.listType === 'ordered' ? '1.' : '•'}\n </span>\n <div\n ref={editorRef}\n contentEditable\n suppressContentEditableWarning\n onInput={handleInput}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n data-placeholder={getPlaceholder()}\n className=\"flex-1 outline-none min-h-[1.5em] empty:before:content-[attr(data-placeholder)] empty:before:text-gray-300\"\n />\n </div>\n );\n }\n\n return (\n <div\n ref={editorRef}\n contentEditable\n suppressContentEditableWarning\n onInput={handleInput}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n data-placeholder={getPlaceholder()}\n className={`outline-none min-h-[1.5em] ${getBlockStyle()} empty:before:content-[attr(data-placeholder)] empty:before:text-gray-300`}\n />\n );\n}\n","import React, { useState } from 'react';\nimport { ImageGalleryBlock, ImageData } from '../types/blocks';\nimport { useEditorServices, DefaultImage } from '../context/EditorContext';\nimport { Upload, X, Grid, MoveHorizontal, LayoutGrid } from 'lucide-react';\n\ninterface ImageGalleryEditorProps {\n block: ImageGalleryBlock;\n onUpdate: (updates: Partial<ImageGalleryBlock>) => void;\n}\n\nexport default function ImageGalleryEditor({ block, onUpdate }: ImageGalleryEditorProps) {\n const [uploading, setUploading] = useState(false);\n const services = useEditorServices();\n const ImageComponent = services.ImageComponent || DefaultImage;\n\n const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (!files || files.length === 0) return;\n\n try {\n setUploading(true);\n const uploadedImages: ImageData[] = [];\n\n for (const file of Array.from(files)) {\n const url = await services.uploadImage(file, 'gallery');\n uploadedImages.push({\n url,\n alt: '',\n caption: '',\n });\n }\n\n onUpdate({\n images: [...block.images, ...uploadedImages],\n });\n } catch (error) {\n console.error('Image upload error:', error);\n alert('이미지 업로드에 실패했습니다.');\n } finally {\n setUploading(false);\n }\n };\n\n const handleRemoveImage = (index: number) => {\n const newImages = block.images.filter((_, i) => i !== index);\n onUpdate({ images: newImages });\n };\n\n const handleLayoutChange = (layout: ImageGalleryBlock['layout']) => {\n onUpdate({ layout });\n };\n\n const handleColumnsChange = (columns: 2 | 3 | 4) => {\n onUpdate({ columns });\n };\n\n const handleImageCaptionChange = (index: number, caption: string) => {\n const newImages = [...block.images];\n newImages[index] = { ...newImages[index], caption };\n onUpdate({ images: newImages });\n };\n\n return (\n <div className=\"space-y-4\">\n {/* 레이아웃 선택 */}\n <div className=\"flex items-center gap-4\">\n <div className=\"flex items-center gap-1 bg-gray-100 rounded-lg p-1\">\n <button\n onClick={() => handleLayoutChange('grid')}\n className={`p-2 rounded flex items-center gap-1 text-sm ${\n block.layout === 'grid' ? 'bg-white shadow' : 'hover:bg-gray-200'\n }`}\n title=\"그리드\"\n >\n <Grid size={16} />\n <span>그리드</span>\n </button>\n <button\n onClick={() => handleLayoutChange('horizontal-scroll')}\n className={`p-2 rounded flex items-center gap-1 text-sm ${\n block.layout === 'horizontal-scroll' ? 'bg-white shadow' : 'hover:bg-gray-200'\n }`}\n title=\"가로 스크롤\"\n >\n <MoveHorizontal size={16} />\n <span>가로 스크롤</span>\n </button>\n <button\n onClick={() => handleLayoutChange('masonry')}\n className={`p-2 rounded flex items-center gap-1 text-sm ${\n block.layout === 'masonry' ? 'bg-white shadow' : 'hover:bg-gray-200'\n }`}\n title=\"매소니\"\n >\n <LayoutGrid size={16} />\n <span>매소니</span>\n </button>\n </div>\n\n {/* 열 수 (그리드/매소니에서만) */}\n {(block.layout === 'grid' || block.layout === 'masonry') && (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-gray-500\">열:</span>\n <select\n value={block.columns || 2}\n onChange={(e) => handleColumnsChange(parseInt(e.target.value) as 2 | 3 | 4)}\n className=\"px-2 py-1 border border-gray-200 rounded text-sm\"\n >\n <option value={2}>2열</option>\n <option value={3}>3열</option>\n <option value={4}>4열</option>\n </select>\n </div>\n )}\n </div>\n\n {/* 이미지 그리드 */}\n {block.images.length > 0 && (\n <div\n className={`grid gap-2 ${\n block.layout === 'horizontal-scroll'\n ? 'grid-flow-col auto-cols-[200px] overflow-x-auto pb-2'\n : block.columns === 2\n ? 'grid-cols-2'\n : block.columns === 3\n ? 'grid-cols-3'\n : 'grid-cols-4'\n }`}\n >\n {block.images.map((image, index) => (\n <div key={index} className=\"relative group\">\n <div className=\"relative aspect-square\">\n <ImageComponent\n src={image.url}\n alt={image.alt || ''}\n fill\n className=\"object-cover rounded-lg\"\n />\n <button\n onClick={() => handleRemoveImage(index)}\n className=\"absolute top-1 right-1 p-1 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition-opacity\"\n >\n <X size={12} />\n </button>\n </div>\n <input\n type=\"text\"\n value={image.caption || ''}\n onChange={(e) => handleImageCaptionChange(index, e.target.value)}\n placeholder=\"캡션\"\n className=\"w-full mt-1 px-2 py-1 text-xs border border-gray-200 rounded\"\n />\n </div>\n ))}\n </div>\n )}\n\n {/* 이미지 추가 버튼 */}\n <label className=\"flex flex-col items-center justify-center w-full h-32 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:border-gray-400 hover:bg-gray-50 transition-colors\">\n <input\n type=\"file\"\n accept=\"image/*\"\n multiple\n onChange={handleUpload}\n className=\"hidden\"\n disabled={uploading}\n />\n {uploading ? (\n <div className=\"text-center\">\n <div className=\"w-6 h-6 border-2 border-gray-400 border-t-transparent rounded-full animate-spin mx-auto mb-2\"></div>\n <span className=\"text-sm text-gray-500\">업로드 중...</span>\n </div>\n ) : (\n <div className=\"text-center\">\n <Upload size={24} className=\"mx-auto mb-2 text-gray-400\" />\n <span className=\"text-sm text-gray-500\">이미지 추가 (여러 개 선택 가능)</span>\n </div>\n )}\n </label>\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport { LinkCardBlock, OGData } from '../types/blocks';\nimport { useEditorServices, DefaultImage } from '../context/EditorContext';\nimport { Link2, RefreshCw, ExternalLink } from 'lucide-react';\n\ninterface LinkCardEditorProps {\n block: LinkCardBlock;\n onUpdate: (updates: Partial<LinkCardBlock>) => void;\n}\n\nexport default function LinkCardEditor({ block, onUpdate }: LinkCardEditorProps) {\n const [urlInput, setUrlInput] = useState(block.url || '');\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const services = useEditorServices();\n const ImageComponent = services.ImageComponent || DefaultImage;\n\n const fetchOGData = async (url: string) => {\n try {\n setLoading(true);\n setError(null);\n\n const ogData = await services.fetchOGData(url);\n onUpdate({ url, ogData });\n } catch (err) {\n console.error('OG fetch error:', err);\n setError('링크 정보를 가져올 수 없습니다.');\n // URL만 저장\n onUpdate({ url, ogData: undefined });\n } finally {\n setLoading(false);\n }\n };\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (urlInput.trim()) {\n fetchOGData(urlInput.trim());\n }\n };\n\n const handleRefresh = () => {\n if (block.url) {\n fetchOGData(block.url);\n }\n };\n\n // URL이 없거나 OG 데이터가 없는 경우 입력 폼 표시\n if (!block.url || (!block.ogData && !loading)) {\n return (\n <form onSubmit={handleSubmit} className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex-1 relative\">\n <Link2 size={18} className=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400\" />\n <input\n type=\"url\"\n value={urlInput}\n onChange={(e) => setUrlInput(e.target.value)}\n placeholder=\"https://example.com\"\n className=\"w-full pl-10 pr-4 py-2.5 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-200\"\n disabled={loading}\n />\n </div>\n <button\n type=\"submit\"\n disabled={loading || !urlInput.trim()}\n className=\"px-4 py-2.5 bg-gray-900 text-white rounded-lg hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {loading ? (\n <RefreshCw size={18} className=\"animate-spin\" />\n ) : (\n '확인'\n )}\n </button>\n </div>\n {error && (\n <p className=\"text-sm text-red-500\">{error}</p>\n )}\n </form>\n );\n }\n\n // OG 데이터가 있는 경우 카드 미리보기 표시\n return (\n <div className=\"space-y-2\">\n <a\n href={block.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"block border border-gray-200 rounded-lg overflow-hidden hover:border-gray-300 transition-colors\"\n >\n <div className=\"flex\">\n {/* 이미지 */}\n {block.ogData?.image && (\n <div className=\"relative w-40 flex-shrink-0\">\n <div className=\"absolute inset-0\">\n <ImageComponent\n src={block.ogData.image}\n alt=\"\"\n fill\n className=\"object-cover\"\n />\n </div>\n </div>\n )}\n\n {/* 텍스트 정보 */}\n <div className=\"flex-1 p-4\">\n {block.ogData?.siteName && (\n <p className=\"text-xs text-gray-500 mb-1\">{block.ogData.siteName}</p>\n )}\n <h4 className=\"font-medium text-gray-900 line-clamp-2 mb-1\">\n {block.ogData?.title || block.url}\n </h4>\n {block.ogData?.description && (\n <p className=\"text-sm text-gray-500 line-clamp-2\">\n {block.ogData.description}\n </p>\n )}\n <div className=\"flex items-center gap-1 mt-2 text-xs text-gray-400\">\n <ExternalLink size={12} />\n <span className=\"truncate\">{new URL(block.url).hostname}</span>\n </div>\n </div>\n </div>\n </a>\n\n {/* 새로고침 버튼 */}\n <div className=\"flex justify-end gap-2\">\n <button\n onClick={handleRefresh}\n disabled={loading}\n className=\"flex items-center gap-1 text-sm text-gray-500 hover:text-gray-700\"\n >\n <RefreshCw size={14} className={loading ? 'animate-spin' : ''} />\n 새로고침\n </button>\n <button\n onClick={() => {\n setUrlInput('');\n onUpdate({ url: '', ogData: undefined });\n }}\n className=\"text-sm text-red-500 hover:text-red-600\"\n >\n 변경\n </button>\n </div>\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport { LinkEmbedBlock } from '../types/blocks';\nimport { Link2, Youtube, Twitter } from 'lucide-react';\n\ninterface LinkEmbedEditorProps {\n block: LinkEmbedBlock;\n onUpdate: (updates: Partial<LinkEmbedBlock>) => void;\n}\n\n// YouTube URL에서 비디오 ID 추출\nfunction extractYouTubeId(url: string): string | null {\n const patterns = [\n /(?:youtube\\.com\\/watch\\?v=|youtu\\.be\\/|youtube\\.com\\/embed\\/)([^&\\n?#]+)/,\n /youtube\\.com\\/shorts\\/([^&\\n?#]+)/,\n ];\n\n for (const pattern of patterns) {\n const match = url.match(pattern);\n if (match) return match[1];\n }\n\n return null;\n}\n\n// URL에서 임베드 타입 감지\nfunction detectEmbedType(url: string): LinkEmbedBlock['embedType'] {\n if (url.includes('youtube.com') || url.includes('youtu.be')) {\n return 'youtube';\n }\n if (url.includes('twitter.com') || url.includes('x.com')) {\n return 'twitter';\n }\n return 'generic';\n}\n\nexport default function LinkEmbedEditor({ block, onUpdate }: LinkEmbedEditorProps) {\n const [urlInput, setUrlInput] = useState(block.url || '');\n const [error, setError] = useState<string | null>(null);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n const url = urlInput.trim();\n\n if (!url) return;\n\n const embedType = detectEmbedType(url);\n setError(null);\n\n if (embedType === 'youtube') {\n const videoId = extractYouTubeId(url);\n if (videoId) {\n onUpdate({ url, embedType, videoId });\n } else {\n setError('올바른 YouTube URL이 아닙니다.');\n }\n } else if (embedType === 'twitter') {\n onUpdate({ url, embedType });\n } else {\n onUpdate({ url, embedType: 'generic' });\n }\n };\n\n // 임베드 미리보기 렌더링\n const renderEmbed = () => {\n switch (block.embedType) {\n case 'youtube':\n if (block.videoId) {\n return (\n <div className=\"relative w-full aspect-video rounded-lg overflow-hidden\">\n <iframe\n src={`https://www.youtube.com/embed/${block.videoId}`}\n title=\"YouTube video\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n className=\"absolute inset-0 w-full h-full\"\n />\n </div>\n );\n }\n break;\n\n case 'twitter':\n return (\n <div className=\"border border-gray-200 rounded-lg p-4 bg-gray-50\">\n <div className=\"flex items-center gap-2 text-gray-500\">\n <Twitter size={20} />\n <span className=\"text-sm\">Twitter 임베드</span>\n </div>\n <p className=\"mt-2 text-sm text-gray-600 truncate\">{block.url}</p>\n </div>\n );\n\n case 'generic':\n return (\n <div className=\"border border-gray-200 rounded-lg p-4 bg-gray-50\">\n <div className=\"flex items-center gap-2 text-gray-500\">\n <Link2 size={20} />\n <span className=\"text-sm\">외부 링크</span>\n </div>\n <p className=\"mt-2 text-sm text-gray-600 truncate\">{block.url}</p>\n </div>\n );\n }\n\n return null;\n };\n\n // URL이 설정되지 않은 경우 입력 폼 표시\n if (!block.url) {\n return (\n <form onSubmit={handleSubmit} className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex-1 relative\">\n <Youtube size={18} className=\"absolute left-3 top-1/2 -translate-y-1/2 text-gray-400\" />\n <input\n type=\"url\"\n value={urlInput}\n onChange={(e) => setUrlInput(e.target.value)}\n placeholder=\"YouTube, Twitter URL을 입력하세요\"\n className=\"w-full pl-10 pr-4 py-2.5 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-200\"\n />\n </div>\n <button\n type=\"submit\"\n disabled={!urlInput.trim()}\n className=\"px-4 py-2.5 bg-gray-900 text-white rounded-lg hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n 확인\n </button>\n </div>\n {error && (\n <p className=\"text-sm text-red-500\">{error}</p>\n )}\n <div className=\"flex items-center gap-4 text-xs text-gray-400\">\n <span className=\"flex items-center gap-1\">\n <Youtube size={14} /> YouTube\n </span>\n <span className=\"flex items-center gap-1\">\n <Twitter size={14} /> Twitter/X\n </span>\n </div>\n </form>\n );\n }\n\n // 임베드 미리보기\n return (\n <div className=\"space-y-2\">\n {renderEmbed()}\n <div className=\"flex justify-end\">\n <button\n onClick={() => {\n setUrlInput('');\n onUpdate({ url: '', videoId: undefined });\n }}\n className=\"text-sm text-red-500 hover:text-red-600\"\n >\n 변경\n </button>\n </div>\n </div>\n );\n}\n","import React, { useRef, useState, useEffect } from 'react';\nimport { DialogueBlock, DialogueLine, TextNode, Character } from '../types/blocks';\nimport { useEditorServices, DefaultImage } from '../context/EditorContext';\nimport { Plus, X, MessageCircle, Theater, User, Loader2, AlignLeft, AlignRight } from 'lucide-react';\n\ninterface DialogueEditorProps {\n block: DialogueBlock;\n onUpdate: (updates: Partial<DialogueBlock>) => void;\n}\n\n// 기본 말풍선 색상 팔레트\nconst BUBBLE_COLORS = [\n '#FEE500', // 카카오 노란색\n '#A8D8EA', // 하늘색\n '#FFB7B2', // 연분홍\n '#BAFFC9', // 연두색\n '#E2D1F9', // 연보라\n '#FFFFFF', // 흰색\n];\n\nexport default function DialogueEditor({ block, onUpdate }: DialogueEditorProps) {\n const fileInputRefs = useRef<(HTMLInputElement | null)[]>([]);\n const [uploadingIndices, setUploadingIndices] = useState<Set<number>>(new Set());\n const [characters, setCharacters] = useState<Character[]>([]);\n const [showProfileMenu, setShowProfileMenu] = useState<number | null>(null);\n\n const services = useEditorServices();\n const ImageComponent = services.ImageComponent || DefaultImage;\n\n // 캐릭터 라이브러리 로드\n useEffect(() => {\n if (services.getCharacters) {\n services.getCharacters().then(setCharacters).catch(console.error);\n }\n }, [services]);\n\n // 메뉴 바깥 클릭시 닫기\n useEffect(() => {\n if (showProfileMenu === null) return;\n\n const handleClickOutside = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n if (!target.closest('.profile-menu-container')) {\n setShowProfileMenu(null);\n }\n };\n\n document.addEventListener('click', handleClickOutside);\n return () => document.removeEventListener('click', handleClickOutside);\n }, [showProfileMenu]);\n\n // 캐릭터 선택 핸들러\n const handleSelectCharacter = (index: number, character: Character) => {\n handleUpdateLine(index, {\n speaker: character.name,\n profileImage: character.profileImage || undefined,\n speakerColor: character.defaultColor,\n });\n setShowProfileMenu(null);\n };\n\n const handleAddLine = () => {\n const newLine: DialogueLine = {\n speaker: '',\n content: [{ text: '' }],\n speakerColor: block.style === 'chat' ? '#FEE500' : undefined,\n alignment: 'left',\n };\n onUpdate({\n lines: [...block.lines, newLine],\n });\n };\n\n const handleRemoveLine = (index: number) => {\n if (block.lines.length <= 1) return;\n const newLines = block.lines.filter((_, i) => i !== index);\n onUpdate({ lines: newLines });\n };\n\n const handleUpdateLine = (index: number, updates: Partial<DialogueLine>) => {\n const newLines = block.lines.map((line, i) =>\n i === index ? { ...line, ...updates } : line\n );\n onUpdate({ lines: newLines });\n };\n\n const handleSpeakerChange = (index: number, speaker: string) => {\n // 같은 화자가 이미 있는지 확인하여 프로필과 색상 자동 복사\n const existingLine = block.lines.find(\n (line, i) => i !== index && line.speaker.trim().toLowerCase() === speaker.trim().toLowerCase() && line.speaker.trim() !== ''\n );\n\n if (existingLine && speaker.trim() !== '') {\n // 같은 화자가 있으면 프로필 이미지와 색상 복사\n handleUpdateLine(index, {\n speaker,\n profileImage: existingLine.profileImage,\n speakerColor: existingLine.speakerColor,\n });\n } else {\n handleUpdateLine(index, { speaker });\n }\n };\n\n const handleContentChange = (index: number, text: string) => {\n handleUpdateLine(index, { content: [{ text }] });\n };\n\n const handleColorChange = (index: number, color: string) => {\n handleUpdateLine(index, { speakerColor: color || undefined });\n };\n\n const handleAlignmentChange = (index: number, alignment: 'left' | 'right') => {\n handleUpdateLine(index, { alignment });\n };\n\n const handleProfileImageUpload = async (index: number, file: File) => {\n setUploadingIndices(prev => new Set(prev).add(index));\n\n try {\n const url = await services.uploadImage(file, 'profile');\n handleUpdateLine(index, { profileImage: url });\n } catch (error) {\n console.error('Profile image upload error:', error);\n alert('이미지 업로드에 실패했습니다.');\n } finally {\n setUploadingIndices(prev => {\n const next = new Set(prev);\n next.delete(index);\n return next;\n });\n }\n };\n\n const handleRemoveProfileImage = (index: number) => {\n handleUpdateLine(index, { profileImage: undefined });\n };\n\n const handleStyleChange = (style: DialogueBlock['style']) => {\n const updatedLines = block.lines.map(line => ({\n ...line,\n speakerColor: style === 'chat' ? (line.speakerColor || '#FEE500') : undefined,\n alignment: style === 'chat' ? (line.alignment || 'left') : undefined,\n }));\n onUpdate({ style, lines: updatedLines });\n };\n\n const getLineText = (nodes: TextNode[]): string => {\n return nodes.map(node => node.text).join('');\n };\n\n // 채팅 스타일 에디터\n const renderChatEditor = (line: DialogueLine, index: number) => {\n const isUploading = uploadingIndices.has(index);\n const isRight = line.alignment === 'right';\n\n return (\n <div key={index} className=\"p-3 bg-gray-50 rounded-lg space-y-2\">\n {/* 상단: 정렬 버튼 + 화자 이름 + 색상 */}\n <div className=\"flex items-center gap-2\">\n {/* 정렬 버튼 */}\n <div className=\"flex items-center gap-0.5 bg-gray-200 rounded p-0.5\">\n <button\n onClick={() => handleAlignmentChange(index, 'left')}\n className={`p-1 rounded ${!isRight ? 'bg-white shadow' : 'hover:bg-gray-300'}`}\n title=\"왼쪽 정렬\"\n >\n <AlignLeft size={14} />\n </button>\n <button\n onClick={() => handleAlignmentChange(index, 'right')}\n className={`p-1 rounded ${isRight ? 'bg-white shadow' : 'hover:bg-gray-300'}`}\n title=\"오른쪽 정렬\"\n >\n <AlignRight size={14} />\n </button>\n </div>\n\n {/* 화자 이름 */}\n <input\n type=\"text\"\n value={line.speaker}\n onChange={(e) => handleSpeakerChange(index, e.target.value)}\n placeholder=\"화자 이름\"\n className=\"flex-1 px-2 py-1 text-sm font-medium border border-gray-200 rounded focus:outline-none focus:ring-2 focus:ring-gray-200\"\n />\n\n {/* 말풍선 색상 선택 */}\n <div className=\"flex items-center gap-1\">\n {BUBBLE_COLORS.map((color) => (\n <button\n key={color}\n onClick={() => handleColorChange(index, color)}\n className={`w-5 h-5 rounded-full border-2 transition-transform ${\n line.speakerColor === color ? 'border-gray-600 scale-110' : 'border-gray-300'\n }`}\n style={{ backgroundColor: color }}\n title={color}\n />\n ))}\n </div>\n\n {/* 삭제 버튼 */}\n <button\n onClick={() => handleRemoveLine(index)}\n disabled={block.lines.length <= 1}\n className=\"p-1 text-gray-400 hover:text-red-500 disabled:opacity-30 disabled:cursor-not-allowed\"\n title=\"대사 삭제\"\n >\n <X size={16} />\n </button>\n </div>\n\n {/* 하단: 프로필 + 말풍선 (정렬에 따라) */}\n <div className={`flex items-start gap-2 ${isRight ? 'flex-row-reverse' : ''}`}>\n {/* 프로필 이미지 */}\n <div className=\"flex-shrink-0 relative profile-menu-container\">\n <input\n type=\"file\"\n accept=\"image/*\"\n ref={el => { fileInputRefs.current[index] = el; }}\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) handleProfileImageUpload(index, file);\n e.target.value = '';\n setShowProfileMenu(null);\n }}\n className=\"hidden\"\n />\n\n {isUploading ? (\n <div className=\"w-10 h-10 flex items-center justify-center bg-gray-200 rounded-full\">\n <Loader2 size={16} className=\"text-gray-400 animate-spin\" />\n </div>\n ) : line.profileImage ? (\n <div className=\"relative w-10 h-10\">\n <ImageComponent\n src={line.profileImage}\n alt={line.speaker || '프로필'}\n fill\n className=\"rounded-full object-cover cursor-pointer\"\n />\n <button\n onClick={() => handleRemoveProfileImage(index)}\n className=\"absolute -top-1 -right-1 p-0.5 bg-red-500 text-white rounded-full hover:bg-red-600 z-10\"\n >\n <X size={10} />\n </button>\n </div>\n ) : (\n <button\n onClick={() => setShowProfileMenu(showProfileMenu === index ? null : index)}\n className=\"w-10 h-10 flex items-center justify-center bg-gray-200 rounded-full hover:bg-gray-300 transition-colors\"\n >\n <User size={16} className=\"text-gray-400\" />\n </button>\n )}\n\n {/* 프로필 메뉴 */}\n {showProfileMenu === index && (\n <div className=\"absolute top-full mt-1 left-0 z-50 bg-white border border-gray-200 rounded-lg shadow-lg py-1 min-w-[160px]\">\n {/* 이미지 업로드 옵션 */}\n <button\n onClick={() => {\n fileInputRefs.current[index]?.click();\n }}\n className=\"w-full flex items-center gap-2 px-3 py-2 hover:bg-gray-100 text-left text-sm\"\n >\n <User size={16} className=\"text-gray-500\" />\n <span>프로필 사진 설정</span>\n </button>\n\n {/* 캐릭터 선택 (캐릭터가 있을 때만) */}\n {characters.length > 0 && (\n <>\n <div className=\"border-t border-gray-100 my-1\" />\n <div className=\"px-3 py-1 text-xs text-gray-500\">캐릭터 선택</div>\n <div className=\"max-h-40 overflow-y-auto\">\n {characters.map((char) => (\n <button\n key={char.id}\n onClick={() => handleSelectCharacter(index, char)}\n className=\"w-full flex items-center gap-2 px-3 py-1.5 hover:bg-gray-100 text-left\"\n >\n {char.profileImage ? (\n <ImageComponent\n src={char.profileImage}\n alt={char.name}\n width={20}\n height={20}\n className=\"rounded-full object-cover\"\n />\n ) : (\n <div\n className=\"w-5 h-5 rounded-full flex items-center justify-center text-xs font-bold\"\n style={{ backgroundColor: char.defaultColor }}\n >\n {char.name.charAt(0).toUpperCase()}\n </div>\n )}\n <span className=\"text-sm truncate flex-1\">{char.name}</span>\n <div\n className=\"w-3 h-3 rounded-full border border-gray-300 flex-shrink-0\"\n style={{ backgroundColor: char.defaultColor }}\n />\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )}\n </div>\n\n {/* 말풍선 */}\n <div\n className={`flex-1 px-3 py-2 rounded-lg ${isRight ? 'ml-8' : 'mr-8'}`}\n style={{ backgroundColor: line.speakerColor || '#FEE500' }}\n >\n <textarea\n value={getLineText(line.content)}\n onChange={(e) => handleContentChange(index, e.target.value)}\n placeholder=\"대사를 입력하세요...\"\n rows={2}\n className=\"w-full bg-transparent text-sm resize-none focus:outline-none\"\n style={{ color: isLightColor(line.speakerColor || '#FEE500') ? '#000' : '#fff' }}\n />\n </div>\n </div>\n </div>\n );\n };\n\n // 희극 스타일 에디터 (심플)\n const renderSimpleEditor = (line: DialogueLine, index: number) => (\n <div key={index} className=\"flex items-start gap-3\">\n <input\n type=\"text\"\n value={line.speaker}\n onChange={(e) => handleSpeakerChange(index, e.target.value)}\n placeholder=\"화자\"\n className=\"w-24 px-2 py-1.5 text-sm font-bold border border-gray-200 rounded focus:outline-none focus:ring-2 focus:ring-gray-200\"\n />\n <textarea\n value={getLineText(line.content)}\n onChange={(e) => handleContentChange(index, e.target.value)}\n placeholder=\"대사를 입력하세요...\"\n rows={1}\n className=\"flex-1 px-2 py-1.5 text-sm border border-gray-200 rounded focus:outline-none focus:ring-2 focus:ring-gray-200 resize-none\"\n />\n <button\n onClick={() => handleRemoveLine(index)}\n disabled={block.lines.length <= 1}\n className=\"p-1 text-gray-400 hover:text-red-500 disabled:opacity-30 disabled:cursor-not-allowed\"\n title=\"대사 삭제\"\n >\n <X size={16} />\n </button>\n </div>\n );\n\n return (\n <div className=\"space-y-4\">\n {/* 스타일 선택 */}\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-gray-500\">스타일:</span>\n <div className=\"flex items-center gap-1 bg-gray-100 rounded-lg p-1\">\n <button\n onClick={() => handleStyleChange('chat')}\n className={`p-1.5 rounded flex items-center gap-1 text-sm ${\n block.style === 'chat' ? 'bg-white shadow' : 'hover:bg-gray-200'\n }`}\n title=\"채팅 스타일\"\n >\n <MessageCircle size={14} />\n <span>채팅</span>\n </button>\n <button\n onClick={() => handleStyleChange('play')}\n className={`p-1.5 rounded flex items-center gap-1 text-sm ${\n block.style === 'play' ? 'bg-white shadow' : 'hover:bg-gray-200'\n }`}\n title=\"희극 스타일\"\n >\n <Theater size={14} />\n <span>희극</span>\n </button>\n </div>\n </div>\n\n {/* 대사 라인 목록 */}\n <div className=\"space-y-3\">\n {block.lines.map((line, index) =>\n block.style === 'chat'\n ? renderChatEditor(line, index)\n : renderSimpleEditor(line, index)\n )}\n </div>\n\n {/* 대사 추가 버튼 */}\n <button\n onClick={handleAddLine}\n className=\"w-full py-2 border-2 border-dashed border-gray-300 rounded-lg text-gray-400 hover:border-gray-400 hover:text-gray-500 transition-colors flex items-center justify-center gap-1\"\n >\n <Plus size={16} />\n <span className=\"text-sm\">대사 추가</span>\n </button>\n </div>\n );\n}\n\nfunction isLightColor(hexColor: string): boolean {\n const hex = hexColor.replace('#', '');\n const r = parseInt(hex.substr(0, 2), 16);\n const g = parseInt(hex.substr(2, 2), 16);\n const b = parseInt(hex.substr(4, 2), 16);\n const brightness = (r * 299 + g * 587 + b * 114) / 1000;\n return brightness > 128;\n}\n","import React, { useState } from 'react';\nimport { DividerBlock } from '../types/blocks';\nimport { useEditorServices, DefaultImage } from '../context/EditorContext';\nimport { Minus, MoreHorizontal, Image as ImageIcon, X, AlignLeft, AlignCenter, AlignRight } from 'lucide-react';\n\ninterface DividerEditorProps {\n block: DividerBlock;\n onUpdate: (updates: Partial<DividerBlock>) => void;\n}\n\nexport default function DividerEditor({ block, onUpdate }: DividerEditorProps) {\n const [uploading, setUploading] = useState(false);\n const services = useEditorServices();\n const ImageComponent = services.ImageComponent || DefaultImage;\n\n const handleVariantChange = (variant: DividerBlock['variant']) => {\n const alignment = variant === 'line' ? undefined : (block.alignment || 'center');\n onUpdate({ variant, customImage: variant === 'custom-image' ? block.customImage : undefined, alignment });\n };\n\n const handleAlignmentChange = (alignment: DividerBlock['alignment']) => {\n onUpdate({ alignment });\n };\n\n const handleImageUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n try {\n setUploading(true);\n const url = await services.uploadImage(file, 'divider');\n onUpdate({ variant: 'custom-image', customImage: url, alignment: block.alignment || 'center' });\n } catch (error) {\n console.error('Image upload error:', error);\n alert('이미지 업로드에 실패했습니다.');\n } finally {\n setUploading(false);\n }\n };\n\n const handleRemoveImage = () => {\n onUpdate({ variant: 'line', customImage: undefined, alignment: undefined });\n };\n\n // 구분선 미리보기 렌더링\n const renderDivider = () => {\n const alignClass = block.alignment === 'left' ? 'justify-start' :\n block.alignment === 'right' ? 'justify-end' : 'justify-center';\n\n switch (block.variant) {\n case 'line':\n return <hr className=\"border-t border-black\" />;\n\n case 'short-line':\n return (\n <div className={`flex ${alignClass}`}>\n <hr className=\"border-t border-black w-1/5\" />\n </div>\n );\n\n case 'dots':\n return (\n <div className={`flex items-center ${alignClass} gap-2`}>\n <span className=\"w-1 h-1 bg-black rounded-full\"></span>\n <span className=\"w-1 h-1 bg-black rounded-full\"></span>\n <span className=\"w-1 h-1 bg-black rounded-full\"></span>\n </div>\n );\n\n case 'custom-image':\n if (block.customImage) {\n return (\n <div className={`flex ${alignClass}`}>\n <div className=\"relative w-12 h-12\">\n <ImageComponent\n src={block.customImage}\n alt=\"구분선\"\n fill\n className=\"object-contain\"\n />\n </div>\n </div>\n );\n }\n return <hr className=\"border-t border-black\" />;\n\n default:\n return <hr className=\"border-t border-black\" />;\n }\n };\n\n const showAlignment = block.variant !== 'line';\n\n return (\n <div className=\"space-y-3\">\n {/* 스타일 선택 - 작은 슬라이드 바 형태 */}\n <div className=\"flex items-center justify-center gap-1\">\n <div className=\"flex items-center bg-gray-100 rounded-lg p-0.5\">\n <button\n onClick={() => handleVariantChange('line')}\n className={`px-2 py-1 rounded text-xs transition-colors ${\n block.variant === 'line'\n ? 'bg-white shadow text-gray-900'\n : 'text-gray-500 hover:text-gray-700'\n }`}\n title=\"직선\"\n >\n <Minus size={14} />\n </button>\n <button\n onClick={() => handleVariantChange('short-line')}\n className={`px-2 py-1 rounded text-xs transition-colors ${\n block.variant === 'short-line'\n ? 'bg-white shadow text-gray-900'\n : 'text-gray-500 hover:text-gray-700'\n }`}\n title=\"짧은 선\"\n >\n <span className=\"inline-block w-3 border-t border-current\"></span>\n </button>\n <button\n onClick={() => handleVariantChange('dots')}\n className={`px-2 py-1 rounded text-xs transition-colors ${\n block.variant === 'dots'\n ? 'bg-white shadow text-gray-900'\n : 'text-gray-500 hover:text-gray-700'\n }`}\n title=\"점\"\n >\n <MoreHorizontal size={14} />\n </button>\n <label\n className={`px-2 py-1 rounded text-xs transition-colors cursor-pointer ${\n block.variant === 'custom-image'\n ? 'bg-white shadow text-gray-900'\n : 'text-gray-500 hover:text-gray-700'\n }`}\n title=\"커스텀 이미지\"\n >\n <input\n type=\"file\"\n accept=\"image/*\"\n onChange={handleImageUpload}\n className=\"hidden\"\n disabled={uploading}\n />\n {uploading ? (\n <div className=\"w-3.5 h-3.5 border border-gray-400 border-t-transparent rounded-full animate-spin\"></div>\n ) : (\n <ImageIcon size={14} />\n )}\n </label>\n </div>\n\n {/* 정렬 옵션 (line 제외) */}\n {showAlignment && (\n <div className=\"flex items-center bg-gray-100 rounded-lg p-0.5 ml-2\">\n <button\n onClick={() => handleAlignmentChange('left')}\n className={`px-1.5 py-1 rounded text-xs transition-colors ${\n block.alignment === 'left'\n ? 'bg-white shadow text-gray-900'\n : 'text-gray-500 hover:text-gray-700'\n }`}\n title=\"왼쪽\"\n >\n <AlignLeft size={12} />\n </button>\n <button\n onClick={() => handleAlignmentChange('center')}\n className={`px-1.5 py-1 rounded text-xs transition-colors ${\n (!block.alignment || block.alignment === 'center')\n ? 'bg-white shadow text-gray-900'\n : 'text-gray-500 hover:text-gray-700'\n }`}\n title=\"가운데\"\n >\n <AlignCenter size={12} />\n </button>\n <button\n onClick={() => handleAlignmentChange('right')}\n className={`px-1.5 py-1 rounded text-xs transition-colors ${\n block.alignment === 'right'\n ? 'bg-white shadow text-gray-900'\n : 'text-gray-500 hover:text-gray-700'\n }`}\n title=\"오른쪽\"\n >\n <AlignRight size={12} />\n </button>\n </div>\n )}\n </div>\n\n {/* 커스텀 이미지 삭제 버튼 */}\n {block.variant === 'custom-image' && block.customImage && (\n <div className=\"flex items-center justify-center\">\n <button\n onClick={handleRemoveImage}\n className=\"text-xs text-gray-400 hover:text-red-500 flex items-center gap-1\"\n title=\"이미지 삭제\"\n >\n <X size={12} />\n <span>이미지 제거</span>\n </button>\n </div>\n )}\n\n {/* 미리보기 */}\n <div className=\"py-4\">\n {renderDivider()}\n </div>\n </div>\n );\n}\n","import React, { useEffect, useState, useCallback, useRef } from 'react';\nimport {\n Block,\n ParagraphBlock,\n HeadingBlock,\n ImageBlock,\n ImageGalleryBlock,\n LinkCardBlock,\n LinkEmbedBlock,\n DialogueBlock,\n DividerBlock,\n QuoteBlock,\n ListBlock,\n TextNode,\n generateBlockId,\n countBlocksCharacters,\n createEmptyParagraphBlock,\n} from './types/blocks';\nimport BlockMenu from './BlockMenu';\nimport TextBlockEditor from './blocks/TextBlockEditor';\nimport ImageGalleryEditor from './blocks/ImageGalleryEditor';\nimport LinkCardEditor from './blocks/LinkCardEditor';\nimport LinkEmbedEditor from './blocks/LinkEmbedEditor';\nimport DialogueEditor from './blocks/DialogueEditor';\nimport DividerEditor from './blocks/DividerEditor';\nimport { GripVertical, Trash2, Plus } from 'lucide-react';\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n DragEndEvent,\n} from '@dnd-kit/core';\nimport {\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n useSortable,\n} from '@dnd-kit/sortable';\nimport { CSS } from '@dnd-kit/utilities';\n\ninterface BlockEditorProps {\n initialBlocks?: Block[];\n onChange: (blocks: Block[]) => void;\n onCharCountChange?: (count: number) => void;\n}\n\n// 블록 래퍼 컴포넌트 - 모든 블록에 컨트롤 추가\ninterface BlockItemProps {\n block: Block;\n blockIndex: number;\n onUpdate: (updates: Partial<Block>) => void;\n onDelete: () => void;\n onAddBlock: () => void;\n onMergeWithPrevious?: () => void;\n onSplitBlock?: (beforeText: TextNode[], afterText: TextNode[]) => void;\n onPasteBlocks?: (beforeText: TextNode[], pastedLines: string[], afterText: TextNode[]) => void;\n onDeleteEmptyBlock?: () => void;\n onFocusPrevious?: () => void;\n onFocusNext?: () => void;\n isOnlyBlock?: boolean;\n isSelected?: boolean;\n onSelect?: (e: React.MouseEvent) => void;\n}\n\nfunction BlockItem({\n block,\n blockIndex,\n onUpdate,\n onDelete,\n onAddBlock,\n onMergeWithPrevious,\n onSplitBlock,\n onPasteBlocks,\n onDeleteEmptyBlock,\n onFocusPrevious,\n onFocusNext,\n isOnlyBlock,\n isSelected,\n onSelect,\n}: BlockItemProps) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: block.id });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n };\n\n const renderBlockContent = () => {\n switch (block.type) {\n case 'paragraph':\n case 'heading':\n case 'quote':\n return (\n <TextBlockEditor\n block={block as ParagraphBlock | HeadingBlock | QuoteBlock}\n onUpdate={onUpdate}\n onMergeWithPrevious={onMergeWithPrevious}\n onSplitBlock={onSplitBlock}\n onPasteBlocks={onPasteBlocks}\n onDeleteEmptyBlock={onDeleteEmptyBlock}\n onFocusPrevious={onFocusPrevious}\n onFocusNext={onFocusNext}\n isOnlyBlock={isOnlyBlock}\n />\n );\n\n case 'list':\n return (\n <TextBlockEditor\n block={block as ListBlock}\n onUpdate={onUpdate}\n onMergeWithPrevious={onMergeWithPrevious}\n onSplitBlock={onSplitBlock}\n onPasteBlocks={onPasteBlocks}\n onDeleteEmptyBlock={onDeleteEmptyBlock}\n onFocusPrevious={onFocusPrevious}\n onFocusNext={onFocusNext}\n isOnlyBlock={isOnlyBlock}\n />\n );\n\n case 'image':\n return (\n <TextBlockEditor block={block as ImageBlock} onUpdate={onUpdate} />\n );\n\n case 'image-gallery':\n return (\n <ImageGalleryEditor\n block={block as ImageGalleryBlock}\n onUpdate={onUpdate}\n />\n );\n\n case 'link-card':\n return (\n <LinkCardEditor block={block as LinkCardBlock} onUpdate={onUpdate} />\n );\n\n case 'link-embed':\n return (\n <LinkEmbedEditor\n block={block as LinkEmbedBlock}\n onUpdate={onUpdate}\n />\n );\n\n case 'dialogue':\n return (\n <DialogueEditor block={block as DialogueBlock} onUpdate={onUpdate} />\n );\n\n case 'divider':\n return (\n <DividerEditor block={block as DividerBlock} onUpdate={onUpdate} />\n );\n\n default:\n return <div className=\"text-gray-400\">Unknown block type</div>;\n }\n };\n\n // 블록 ref 등록 콜백\n const setBlockRef = useCallback((el: HTMLDivElement | null) => {\n setNodeRef(el);\n }, [setNodeRef]);\n\n return (\n <div\n ref={setBlockRef}\n style={style}\n className={`group relative flex items-start gap-2 ${isSelected ? 'bg-blue-50 rounded' : ''}`}\n data-block-id={block.id}\n onClick={onSelect}\n >\n {/* 왼쪽: + 버튼 */}\n <div className=\"absolute -left-10 top-1 opacity-0 group-hover:opacity-100 transition-opacity\">\n <button\n onClick={onAddBlock}\n className=\"rounded hover:bg-gray-100 text-gray-400 hover:text-gray-600\"\n title=\"블록 추가\"\n >\n <Plus size={18} />\n </button>\n </div>\n\n {/* 블록 콘텐츠 */}\n <div className=\"flex-1 min-w-0\">{renderBlockContent()}</div>\n\n {/* 오른쪽: 삭제 및 드래그 버튼 */}\n <div className=\"absolute -right-16 top-1 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity\">\n <button\n onClick={onDelete}\n className=\"p-1 rounded hover:bg-red-50 text-gray-300 hover:text-red-500\"\n title=\"블록 삭제\"\n >\n <Trash2 size={16} />\n </button>\n <button\n {...attributes}\n {...listeners}\n className=\"p-1 rounded hover:bg-gray-100 text-gray-300 hover:text-gray-500 cursor-grab active:cursor-grabbing\"\n title=\"드래그하여 이동\"\n >\n <GripVertical size={16} />\n </button>\n </div>\n </div>\n );\n}\n\n// --- 크로스 블록 선택 유틸리티 ---\n\n/** DOM 노드에서 [data-block-id] 조상 탐색 */\nfunction findBlockElement(node: Node, container: HTMLElement): HTMLElement | null {\n let current: Node | null = node;\n while (current && current !== container) {\n if (current instanceof HTMLElement && current.hasAttribute('data-block-id')) {\n return current;\n }\n current = current.parentNode;\n }\n return null;\n}\n\n/** TreeWalker로 contentEditable 내 문자 오프셋 계산 */\nfunction getCharacterOffsetWithin(rootEl: HTMLElement, targetNode: Node, targetOffset: number): number {\n const walker = document.createTreeWalker(rootEl, NodeFilter.SHOW_TEXT, null);\n let offset = 0;\n let node: Node | null;\n while ((node = walker.nextNode())) {\n if (node === targetNode) {\n return offset + targetOffset;\n }\n offset += (node.textContent?.length || 0);\n }\n // targetNode이 rootEl 자체인 경우 (빈 요소 등)\n return offset;\n}\n\ninterface CrossBlockSelection {\n startBlockId: string;\n startBlockIndex: number;\n startOffset: number;\n endBlockId: string;\n endBlockIndex: number;\n endOffset: number;\n}\n\n/** window.getSelection()에서 크로스 블록 선택 정보 추출. 단일 블록이면 null */\nfunction getCrossBlockSelection(blocks: Block[], containerEl: HTMLElement): CrossBlockSelection | null {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return null;\n\n const range = sel.getRangeAt(0);\n const startBlockEl = findBlockElement(range.startContainer, containerEl);\n const endBlockEl = findBlockElement(range.endContainer, containerEl);\n\n if (!startBlockEl || !endBlockEl) return null;\n\n const startBlockId = startBlockEl.getAttribute('data-block-id');\n const endBlockId = endBlockEl.getAttribute('data-block-id');\n if (!startBlockId || !endBlockId) return null;\n\n // 같은 블록이면 단일 블록 선택 → null\n if (startBlockId === endBlockId) return null;\n\n const startBlockIndex = blocks.findIndex(b => b.id === startBlockId);\n const endBlockIndex = blocks.findIndex(b => b.id === endBlockId);\n if (startBlockIndex === -1 || endBlockIndex === -1) return null;\n\n // contentEditable 요소 찾기\n const startEditable = startBlockEl.querySelector('[contenteditable=\"true\"]') as HTMLElement | null;\n const endEditable = endBlockEl.querySelector('[contenteditable=\"true\"]') as HTMLElement | null;\n\n const startOffset = startEditable\n ? getCharacterOffsetWithin(startEditable, range.startContainer, range.startOffset)\n : 0;\n const endOffset = endEditable\n ? getCharacterOffsetWithin(endEditable, range.endContainer, range.endOffset)\n : 0;\n\n return {\n startBlockId,\n startBlockIndex,\n startOffset,\n endBlockId,\n endBlockIndex,\n endOffset,\n };\n}\n\nexport default function BlockEditor({\n initialBlocks = [],\n onChange,\n onCharCountChange,\n}: BlockEditorProps) {\n const [blocks, setBlocks] = useState<Block[]>(\n initialBlocks.length > 0 ? initialBlocks : [createEmptyParagraphBlock()],\n );\n const [showBlockMenu, setShowBlockMenu] = useState(false);\n const [blockMenuPosition, setBlockMenuPosition] = useState({ x: 0, y: 0 });\n const [insertIndex, setInsertIndex] = useState<number>(0);\n const [selectedBlocks, setSelectedBlocks] = useState<Set<string>>(new Set()); // 선택된 블록 ID들\n const [lastSelectedIndex, setLastSelectedIndex] = useState<number | null>(null); // Shift 선택용\n const blockRefs = React.useRef<Map<string, HTMLDivElement>>(new Map());\n const editorContainerRef = useRef<HTMLDivElement>(null);\n const pendingFocusRef = useRef<{ blockId: string; position: 'start' | 'end' } | null>(null);\n\n // 크로스 블록 드래그 선택 추적용\n const selStartRef = useRef<{ blockId: string; node: Node; offset: number } | null>(null);\n\n // 블록 ID로 포커스 이동 (상태에 의존하지 않음)\n const focusBlockById = useCallback((blockId: string, position: 'start' | 'end' = 'start') => {\n // 약간의 지연 후 포커스 (DOM 업데이트 대기)\n setTimeout(() => {\n const blockEl = blockRefs.current.get(blockId);\n if (!blockEl) return;\n\n // contentEditable 요소 찾기\n const editable = blockEl.querySelector('[contenteditable=\"true\"]') as HTMLElement;\n if (editable) {\n editable.focus();\n\n // 커서 위치 설정\n const range = document.createRange();\n const selection = window.getSelection();\n\n if (position === 'end' && editable.lastChild) {\n const lastChild = editable.lastChild;\n if (lastChild.nodeType === Node.TEXT_NODE) {\n range.setStart(lastChild, lastChild.textContent?.length || 0);\n } else {\n range.setStartAfter(lastChild);\n }\n } else {\n range.setStart(editable, 0);\n }\n\n range.collapse(true);\n selection?.removeAllRanges();\n selection?.addRange(range);\n } else {\n // input이나 textarea 찾기 (file input 제외)\n const input = blockEl.querySelector('input:not([type=\"file\"]), textarea') as HTMLInputElement | HTMLTextAreaElement;\n if (input) {\n input.focus();\n try {\n if (position === 'end') {\n input.selectionStart = input.selectionEnd = input.value.length;\n } else {\n input.selectionStart = input.selectionEnd = 0;\n }\n } catch (e) {\n // selection이 지원되지 않는 input 타입 무시\n }\n }\n }\n }, 0);\n }, []);\n\n // 블록 포커스 이동 (인덱스 기반 - blocks 상태 사용)\n const focusBlock = useCallback((index: number, position: 'start' | 'end' = 'start') => {\n const targetBlock = blocks[index];\n if (!targetBlock) return;\n\n // 약간의 지연 후 포커스 (DOM 업데이트 대기)\n setTimeout(() => {\n const blockEl = blockRefs.current.get(targetBlock.id);\n if (!blockEl) return;\n\n // contentEditable 요소 찾기\n const editable = blockEl.querySelector('[contenteditable=\"true\"]') as HTMLElement;\n if (editable) {\n editable.focus();\n\n // 커서 위치 설정\n const range = document.createRange();\n const selection = window.getSelection();\n\n if (position === 'end' && editable.lastChild) {\n const lastChild = editable.lastChild;\n if (lastChild.nodeType === Node.TEXT_NODE) {\n range.setStart(lastChild, lastChild.textContent?.length || 0);\n } else {\n range.setStartAfter(lastChild);\n }\n } else {\n range.setStart(editable, 0);\n }\n\n range.collapse(true);\n selection?.removeAllRanges();\n selection?.addRange(range);\n } else {\n // input이나 textarea 찾기 (file input 제외)\n const input = blockEl.querySelector('input:not([type=\"file\"]), textarea') as HTMLInputElement | HTMLTextAreaElement;\n if (input) {\n input.focus();\n try {\n if (position === 'end') {\n input.selectionStart = input.selectionEnd = input.value.length;\n } else {\n input.selectionStart = input.selectionEnd = 0;\n }\n } catch (e) {\n // selection이 지원되지 않는 input 타입 무시\n }\n }\n }\n }, 0);\n }, [blocks]);\n\n // 블록 변경 후 포커스 적용 (React 재렌더링 이후 실행 보장)\n useEffect(() => {\n if (pendingFocusRef.current) {\n const { blockId, position } = pendingFocusRef.current;\n pendingFocusRef.current = null;\n focusBlockById(blockId, position);\n }\n }, [blocks, focusBlockById]);\n\n // 드래그 앤 드롭 센서\n const sensors = useSensors(\n useSensor(PointerSensor, {\n activationConstraint: {\n distance: 8,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n // 블록 변경시 콜백 호출\n useEffect(() => {\n onChange(blocks);\n if (onCharCountChange) {\n onCharCountChange(countBlocksCharacters(blocks));\n }\n }, [blocks]);\n\n // 블록 업데이트\n const handleUpdateBlock = useCallback(\n (id: string, updates: Partial<Block>) => {\n setBlocks((prev) =>\n prev.map((block) =>\n block.id === id ? ({ ...block, ...updates } as Block) : block,\n ),\n );\n },\n [],\n );\n\n // 블록 삭제\n const handleDeleteBlock = useCallback((id: string) => {\n setBlocks((prev) => {\n const filtered = prev.filter((block) => block.id !== id);\n // 최소 하나의 블록은 유지\n if (filtered.length === 0) {\n return [createEmptyParagraphBlock()];\n }\n return filtered;\n });\n }, []);\n\n // 블록 추가 메뉴 열기\n const handleShowBlockMenu = useCallback(\n (e: React.MouseEvent, index: number) => {\n e.preventDefault();\n e.stopPropagation();\n\n const rect = (e.target as HTMLElement).getBoundingClientRect();\n setBlockMenuPosition({ x: rect.left, y: rect.bottom + 5 });\n setInsertIndex(index);\n setShowBlockMenu(true);\n },\n [],\n );\n\n // 블록 추가\n const handleAddBlock = useCallback(\n (type: Block['type']) => {\n let newBlock: Block;\n const id = generateBlockId();\n\n switch (type) {\n case 'paragraph':\n newBlock = {\n id,\n type: 'paragraph',\n content: [{ text: '' }],\n } as ParagraphBlock;\n break;\n case 'heading':\n newBlock = {\n id,\n type: 'heading',\n level: 2,\n content: [{ text: '' }],\n } as HeadingBlock;\n break;\n case 'quote':\n newBlock = {\n id,\n type: 'quote',\n content: [{ text: '' }],\n } as QuoteBlock;\n break;\n case 'list':\n newBlock = {\n id,\n type: 'list',\n listType: 'unordered',\n content: [{ text: '' }],\n } as ListBlock;\n break;\n case 'divider':\n newBlock = { id, type: 'divider', variant: 'line' } as DividerBlock;\n break;\n case 'image':\n newBlock = {\n id,\n type: 'image',\n image: { url: '' },\n alignment: 'center',\n } as ImageBlock;\n break;\n case 'image-gallery':\n newBlock = {\n id,\n type: 'image-gallery',\n images: [],\n layout: 'grid',\n columns: 2,\n } as ImageGalleryBlock;\n break;\n case 'link-card':\n newBlock = { id, type: 'link-card', url: '' } as LinkCardBlock;\n break;\n case 'link-embed':\n newBlock = {\n id,\n type: 'link-embed',\n url: '',\n embedType: 'youtube',\n } as LinkEmbedBlock;\n break;\n case 'dialogue':\n newBlock = {\n id,\n type: 'dialogue',\n lines: [{ speaker: '', content: [{ text: '' }] }],\n style: 'chat',\n } as DialogueBlock;\n break;\n default:\n return;\n }\n\n setBlocks((prev) => {\n const newBlocks = [...prev];\n newBlocks.splice(insertIndex + 1, 0, newBlock);\n return newBlocks;\n });\n setShowBlockMenu(false);\n },\n [insertIndex],\n );\n\n // 이전 블록과 병합 (Backspace 처리)\n const handleMergeWithPrevious = useCallback((index: number) => {\n if (index <= 0) return;\n\n const currentBlock = blocks[index];\n const previousBlock = blocks[index - 1];\n if (!currentBlock || !previousBlock) return;\n\n // 둘 다 텍스트 블록인 경우에만 병합\n const isTextType = (t: string) =>\n t === 'paragraph' || t === 'heading' || t === 'quote' || t === 'list';\n if (!isTextType(currentBlock.type) || !isTextType(previousBlock.type)) return;\n\n const prevBlockId = previousBlock.id;\n\n setBlocks((prev) => {\n const merged = [...prev];\n const prevContent = (prev[index - 1] as ParagraphBlock).content;\n const currContent = (prev[index] as ParagraphBlock).content;\n\n merged[index - 1] = {\n ...prev[index - 1],\n content: [...prevContent, ...currContent],\n } as Block;\n\n merged.splice(index, 1);\n return merged;\n });\n\n // 병합 후 이전 블록의 끝에 포커스\n pendingFocusRef.current = { blockId: prevBlockId, position: 'end' };\n }, [blocks]);\n\n // 빈 블록 삭제 후 이전 블록으로 포커스 (Delete 키 처리)\n const handleDeleteEmptyBlock = useCallback((index: number) => {\n if (index <= 0) return;\n\n const prevBlockId = blocks[index - 1]?.id;\n if (!prevBlockId) return;\n\n setBlocks((prev) => {\n if (prev.length <= 1) return prev;\n const newBlocks = [...prev];\n newBlocks.splice(index, 1);\n return newBlocks;\n });\n\n // 블록 제거 후 이전 블록 끝에 포커스\n pendingFocusRef.current = { blockId: prevBlockId, position: 'end' };\n }, [blocks]);\n\n // 블록 분할 (Enter 처리)\n const handleSplitBlock = useCallback(\n (index: number, beforeText: TextNode[], afterText: TextNode[]) => {\n // 새 블록 ID를 미리 생성 (포커스에 사용)\n const newBlockId = generateBlockId();\n\n setBlocks((prev) => {\n const newBlocks = [...prev];\n const currentBlock = newBlocks[index];\n\n // 현재 블록 업데이트\n newBlocks[index] = {\n ...currentBlock,\n content: beforeText,\n } as Block;\n\n // 새 블록 생성 - 목록 블록인 경우 같은 타입 유지\n let newBlock: Block;\n if (currentBlock.type === 'list') {\n newBlock = {\n id: newBlockId,\n type: 'list',\n listType: (currentBlock as ListBlock).listType,\n content: afterText.length > 0 ? afterText : [{ text: '' }],\n } as ListBlock;\n } else {\n newBlock = {\n id: newBlockId,\n type: 'paragraph',\n content: afterText.length > 0 ? afterText : [{ text: '' }],\n } as ParagraphBlock;\n }\n\n newBlocks.splice(index + 1, 0, newBlock);\n return newBlocks;\n });\n\n // 새 블록으로 포커스 이동 (ID 기반으로 상태 의존 없이)\n setTimeout(() => {\n focusBlockById(newBlockId, 'start');\n }, 10);\n },\n [focusBlockById],\n );\n\n // 여러 줄 붙여넣기 처리 (줄바꿈마다 새 블록 생성)\n const handlePasteBlocks = useCallback(\n (index: number, beforeText: TextNode[], pastedLines: string[], afterText: TextNode[]) => {\n // 마지막 블록 ID (포커스 이동용)\n const lastBlockId = generateBlockId();\n\n setBlocks((prev) => {\n const newBlocks = [...prev];\n const currentBlock = newBlocks[index];\n\n // 현재 블록을 beforeText (첫 번째 줄 포함)로 업데이트\n newBlocks[index] = {\n ...currentBlock,\n content: beforeText,\n } as Block;\n\n // 중간 줄들을 새 paragraph 블록으로 생성\n const middleBlocks: Block[] = pastedLines.map((line) => ({\n id: generateBlockId(),\n type: 'paragraph' as const,\n content: [{ text: line }],\n }));\n\n // 마지막 블록 (마지막 붙여넣기 줄 + afterText)\n const lastBlock: ParagraphBlock = {\n id: lastBlockId,\n type: 'paragraph',\n content: afterText,\n };\n\n // 현재 블록 뒤에 삽입\n newBlocks.splice(index + 1, 0, ...middleBlocks, lastBlock);\n return newBlocks;\n });\n\n // 마지막 블록으로 포커스 이동\n setTimeout(() => {\n focusBlockById(lastBlockId, 'end');\n }, 10);\n },\n [focusBlockById],\n );\n\n // 드래그 앤 드롭 핸들러\n const handleDragEnd = useCallback((event: DragEndEvent) => {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n setBlocks((prev) => {\n const oldIndex = prev.findIndex((block) => block.id === active.id);\n const newIndex = prev.findIndex((block) => block.id === over.id);\n\n if (oldIndex !== -1 && newIndex !== -1) {\n const newBlocks = [...prev];\n const [removed] = newBlocks.splice(oldIndex, 1);\n newBlocks.splice(newIndex, 0, removed);\n return newBlocks;\n }\n\n return prev;\n });\n }\n }, []);\n\n // 블록 선택 핸들러\n const handleBlockSelect = useCallback((index: number, e: React.MouseEvent) => {\n // 블록 내부의 contentEditable 클릭 시에는 선택 무시\n const target = e.target as HTMLElement;\n if (target.closest('[contenteditable=\"true\"]') || target.closest('input') || target.closest('textarea')) {\n // 선택 해제\n if (selectedBlocks.size > 0) {\n setSelectedBlocks(new Set());\n }\n setLastSelectedIndex(index);\n return;\n }\n\n if (e.shiftKey && lastSelectedIndex !== null) {\n // Shift+클릭: 범위 선택\n const start = Math.min(lastSelectedIndex, index);\n const end = Math.max(lastSelectedIndex, index);\n const newSelected = new Set<string>();\n for (let i = start; i <= end; i++) {\n newSelected.add(blocks[i].id);\n }\n setSelectedBlocks(newSelected);\n } else if (e.metaKey || e.ctrlKey) {\n // Cmd/Ctrl+클릭: 토글 선택\n const newSelected = new Set(selectedBlocks);\n if (newSelected.has(blocks[index].id)) {\n newSelected.delete(blocks[index].id);\n } else {\n newSelected.add(blocks[index].id);\n }\n setSelectedBlocks(newSelected);\n setLastSelectedIndex(index);\n } else {\n // 일반 클릭: 단일 선택 해제\n setSelectedBlocks(new Set());\n setLastSelectedIndex(index);\n }\n }, [blocks, selectedBlocks, lastSelectedIndex]);\n\n // 선택된 블록 삭제\n const handleDeleteSelected = useCallback(() => {\n if (selectedBlocks.size === 0) return;\n\n setBlocks((prev) => {\n const filtered = prev.filter((block) => !selectedBlocks.has(block.id));\n if (filtered.length === 0) {\n return [createEmptyParagraphBlock()];\n }\n return filtered;\n });\n setSelectedBlocks(new Set());\n }, [selectedBlocks]);\n\n // 크로스 블록 선택 삭제 처리\n const handleCrossBlockDelete = useCallback((crossSel: CrossBlockSelection, insertChar?: string) => {\n const { startBlockIndex, endBlockIndex, startOffset, endOffset } = crossSel;\n\n setBlocks((prev) => {\n const startBlock = prev[startBlockIndex];\n const endBlock = prev[endBlockIndex];\n\n // 시작 블록의 선택 이전 텍스트\n let beforeText = '';\n if (startBlock.type === 'paragraph' || startBlock.type === 'heading' || startBlock.type === 'quote' || startBlock.type === 'list') {\n const fullText = (startBlock as ParagraphBlock).content.map(n => n.text).join('');\n beforeText = fullText.slice(0, startOffset);\n }\n\n // 끝 블록의 선택 이후 텍스트\n let afterText = '';\n if (endBlock.type === 'paragraph' || endBlock.type === 'heading' || endBlock.type === 'quote' || endBlock.type === 'list') {\n const fullText = (endBlock as ParagraphBlock).content.map(n => n.text).join('');\n afterText = fullText.slice(endOffset);\n }\n\n // 병합된 텍스트\n const mergedText = beforeText + (insertChar || '') + afterText;\n\n // 시작 블록을 병합된 텍스트로 업데이트\n const mergedBlock = {\n ...startBlock,\n content: [{ text: mergedText }],\n } as Block;\n\n // 새 블록 배열: 시작 블록 이전 + 병합 블록 + 끝 블록 이후\n const newBlocks = [\n ...prev.slice(0, startBlockIndex),\n mergedBlock,\n ...prev.slice(endBlockIndex + 1),\n ];\n\n if (newBlocks.length === 0) {\n return [createEmptyParagraphBlock()];\n }\n\n return newBlocks;\n });\n\n // 병합 지점에 커서 배치\n const cursorPos = startOffset + (insertChar?.length || 0);\n setTimeout(() => {\n const blockEl = blockRefs.current.get(crossSel.startBlockId);\n if (!blockEl) return;\n const editable = blockEl.querySelector('[contenteditable=\"true\"]') as HTMLElement;\n if (!editable) return;\n editable.focus();\n\n // DOM 업데이트 후 커서 배치\n requestAnimationFrame(() => {\n const walker = document.createTreeWalker(editable, NodeFilter.SHOW_TEXT, null);\n let offset = 0;\n let targetNode: Node | null = null;\n let targetOffset = 0;\n let node: Node | null;\n while ((node = walker.nextNode())) {\n const len = node.textContent?.length || 0;\n if (offset + len >= cursorPos) {\n targetNode = node;\n targetOffset = cursorPos - offset;\n break;\n }\n offset += len;\n }\n if (targetNode) {\n const range = document.createRange();\n range.setStart(targetNode, targetOffset);\n range.collapse(true);\n const sel = window.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n }\n });\n }, 0);\n }, []);\n\n // 전역 키보드 이벤트 (선택된 블록 삭제 + 크로스 블록 선택 삭제)\n useEffect(() => {\n const container = editorContainerRef.current;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // 기존: 블록 단위 선택 삭제\n if (selectedBlocks.size > 0 && (e.key === 'Delete' || e.key === 'Backspace')) {\n const activeEl = document.activeElement;\n if (!activeEl?.closest('[contenteditable=\"true\"]') &&\n !(activeEl instanceof HTMLInputElement) &&\n !(activeEl instanceof HTMLTextAreaElement)) {\n e.preventDefault();\n handleDeleteSelected();\n return;\n }\n }\n\n // 크로스 블록 텍스트 선택 삭제\n if ((e.key === 'Delete' || e.key === 'Backspace') && !e.isComposing && container) {\n const crossSel = getCrossBlockSelection(blocks, container);\n if (crossSel) {\n e.preventDefault();\n handleCrossBlockDelete(crossSel);\n return;\n }\n }\n\n // Escape로 선택 해제\n if (e.key === 'Escape' && selectedBlocks.size > 0) {\n setSelectedBlocks(new Set());\n }\n };\n\n // beforeinput: 크로스 블록 선택 상태에서 입력 가로채기 + 컨테이너 직접 편집 방지\n const handleBeforeInput = (e: InputEvent) => {\n if (!container) return;\n\n const crossSel = getCrossBlockSelection(blocks, container);\n if (crossSel) {\n // 크로스 블록 선택 상태: 모든 입력을 커스텀 처리\n if ((e.inputType === 'insertText' || e.inputType === 'insertCompositionText') && !e.isComposing && e.data) {\n e.preventDefault();\n handleCrossBlockDelete(crossSel, e.data);\n } else if (e.inputType.startsWith('delete')) {\n e.preventDefault();\n handleCrossBlockDelete(crossSel);\n } else {\n e.preventDefault(); // 크로스 블록 선택 중 다른 입력 유형 차단\n }\n return;\n }\n\n // 크로스 블록 선택이 아닌데 컨테이너가 직접 타겟인 경우 차단\n if (e.target === container) {\n e.preventDefault();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n if (container) {\n container.addEventListener('beforeinput', handleBeforeInput);\n }\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n if (container) {\n container.removeEventListener('beforeinput', handleBeforeInput);\n }\n };\n }, [selectedBlocks, handleDeleteSelected, blocks, handleCrossBlockDelete]);\n\n // 크로스 블록 드래그 선택: 마우스로 블록 경계를 넘어가면 프로그래밍으로 Selection 생성\n useEffect(() => {\n const container = editorContainerRef.current;\n if (!container) return;\n\n let docMoveHandler: ((e: MouseEvent) => void) | null = null;\n let docUpHandler: (() => void) | null = null;\n\n const handleMouseDown = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n const editable = target.closest('[contenteditable=\"true\"]');\n // 컨테이너 자체나 contentEditable 밖이면 무시\n if (!editable || editable === container) return;\n\n // Shift+Click: 기존 시작점에서 크로스 블록 선택 확장\n if (e.shiftKey && selStartRef.current) {\n const caretRange = document.caretRangeFromPoint(e.clientX, e.clientY);\n if (!caretRange) return;\n\n const caretBlockEl = findBlockElement(caretRange.startContainer, container);\n if (!caretBlockEl) return;\n const caretBlockId = caretBlockEl.getAttribute('data-block-id');\n\n if (caretBlockId && caretBlockId !== selStartRef.current.blockId) {\n e.preventDefault();\n const sel = window.getSelection();\n if (sel) {\n try {\n sel.setBaseAndExtent(\n selStartRef.current.node,\n selStartRef.current.offset,\n caretRange.startContainer,\n caretRange.startOffset,\n );\n } catch (_) {}\n }\n }\n return;\n }\n\n // 일반 클릭: 시작점 기록 (브라우저가 커서를 배치한 후)\n requestAnimationFrame(() => {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n\n const blockEl = findBlockElement(range.startContainer, container);\n if (!blockEl) return;\n\n selStartRef.current = {\n blockId: blockEl.getAttribute('data-block-id')!,\n node: range.startContainer,\n offset: range.startOffset,\n };\n });\n\n // 드래그 추적 시작\n docMoveHandler = (moveE: MouseEvent) => {\n if (!selStartRef.current) return;\n\n const caretRange = document.caretRangeFromPoint(moveE.clientX, moveE.clientY);\n if (!caretRange) return;\n\n const caretBlockEl = findBlockElement(caretRange.startContainer, container);\n if (!caretBlockEl) return;\n\n const caretBlockId = caretBlockEl.getAttribute('data-block-id');\n if (!caretBlockId || caretBlockId === selStartRef.current.blockId) return;\n\n // 블록 경계를 넘었으면 프로그래밍으로 Selection 생성\n requestAnimationFrame(() => {\n if (!selStartRef.current) return;\n const sel = window.getSelection();\n if (!sel) return;\n try {\n sel.setBaseAndExtent(\n selStartRef.current.node,\n selStartRef.current.offset,\n caretRange.startContainer,\n caretRange.startOffset,\n );\n } catch (_) {}\n });\n };\n\n docUpHandler = () => {\n if (docMoveHandler) document.removeEventListener('mousemove', docMoveHandler);\n if (docUpHandler) document.removeEventListener('mouseup', docUpHandler);\n docMoveHandler = null;\n docUpHandler = null;\n };\n\n document.addEventListener('mousemove', docMoveHandler);\n document.addEventListener('mouseup', docUpHandler);\n };\n\n container.addEventListener('mousedown', handleMouseDown);\n return () => {\n container.removeEventListener('mousedown', handleMouseDown);\n if (docMoveHandler) document.removeEventListener('mousemove', docMoveHandler);\n if (docUpHandler) document.removeEventListener('mouseup', docUpHandler);\n };\n }, []);\n\n // 크로스 블록 선택 시 빈 블록에 선택 표시 (selectionchange 추적)\n useEffect(() => {\n const container = editorContainerRef.current;\n if (!container) return;\n\n const handleSelectionChange = () => {\n // 이전 표시 제거\n container.querySelectorAll('[data-cross-selected]').forEach(el => {\n el.removeAttribute('data-cross-selected');\n });\n\n const crossSel = getCrossBlockSelection(blocks, container);\n if (!crossSel) return;\n\n const minIdx = Math.min(crossSel.startBlockIndex, crossSel.endBlockIndex);\n const maxIdx = Math.max(crossSel.startBlockIndex, crossSel.endBlockIndex);\n\n for (let i = minIdx; i <= maxIdx; i++) {\n const wrapper = blockRefs.current.get(blocks[i].id);\n if (wrapper) {\n wrapper.setAttribute('data-cross-selected', 'true');\n }\n }\n };\n\n document.addEventListener('selectionchange', handleSelectionChange);\n return () => document.removeEventListener('selectionchange', handleSelectionChange);\n }, [blocks]);\n\n return (\n <div className=\"block-editor relative select-text\">\n {/* 빈 블록 크로스 선택 표시 스타일 */}\n <style>{`\n [data-cross-selected] [contenteditable]:empty::after {\n content: '\\\\00a0';\n background-color: rgb(191 219 254);\n border-radius: 1px;\n }\n `}</style>\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext\n items={blocks.map((b) => b.id)}\n strategy={verticalListSortingStrategy}\n >\n <div\n ref={editorContainerRef}\n contentEditable\n suppressContentEditableWarning\n className=\"space-y-1 selection:bg-blue-200 outline-none\"\n >\n {blocks.map((block, index) => (\n <div\n key={block.id}\n contentEditable={false}\n ref={(el) => {\n if (el) blockRefs.current.set(block.id, el);\n else blockRefs.current.delete(block.id);\n }}\n >\n <BlockItem\n block={block}\n blockIndex={index}\n onUpdate={(updates) => handleUpdateBlock(block.id, updates)}\n onDelete={() => handleDeleteBlock(block.id)}\n onAddBlock={(e?: React.MouseEvent) => {\n if (e) {\n handleShowBlockMenu(e, index);\n } else {\n setInsertIndex(index);\n setShowBlockMenu(true);\n setBlockMenuPosition({ x: 100, y: 100 });\n }\n }}\n onMergeWithPrevious={\n index > 0 ? () => handleMergeWithPrevious(index) : undefined\n }\n onSplitBlock={(before, after) =>\n handleSplitBlock(index, before, after)\n }\n onPasteBlocks={(before, lines, after) =>\n handlePasteBlocks(index, before, lines, after)\n }\n onDeleteEmptyBlock={\n index > 0 ? () => handleDeleteEmptyBlock(index) : undefined\n }\n onFocusPrevious={\n index > 0 ? () => focusBlock(index - 1, 'end') : undefined\n }\n onFocusNext={\n index < blocks.length - 1 ? () => focusBlock(index + 1, 'start') : undefined\n }\n isOnlyBlock={blocks.length === 1}\n isSelected={selectedBlocks.has(block.id)}\n onSelect={(e) => handleBlockSelect(index, e)}\n />\n </div>\n ))}\n </div>\n </SortableContext>\n </DndContext>\n\n {/* 블록 메뉴 */}\n {showBlockMenu && (\n <BlockMenu\n position={blockMenuPosition}\n onClose={() => setShowBlockMenu(false)}\n onSelect={handleAddBlock}\n />\n )}\n\n </div>\n );\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@buildingbite/blocks",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Block-based rich text editor for blogs",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"typecheck": "tsc --noEmit"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"react": "^18.0.0",
|
|
25
|
+
"react-dom": "^18.0.0"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@dnd-kit/core": "^6.3.1",
|
|
29
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
30
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
31
|
+
"lucide-react": "^0.468.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/react": "^18.0.0",
|
|
35
|
+
"@types/react-dom": "^18.0.0",
|
|
36
|
+
"react": "^18.0.0",
|
|
37
|
+
"react-dom": "^18.0.0",
|
|
38
|
+
"tsup": "^8.0.0",
|
|
39
|
+
"typescript": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"block-editor",
|
|
43
|
+
"rich-text",
|
|
44
|
+
"react",
|
|
45
|
+
"editor"
|
|
46
|
+
],
|
|
47
|
+
"license": "MIT"
|
|
48
|
+
}
|