@noseberry/nbd-editor 1.0.1 → 1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"nbd-editor.esm.js","sources":["../src/utils/EventEmitter.js","../src/utils/dom.js","../src/utils/icons.js","../src/core/BlockManager.js","../src/core/MediaUploader.js","../src/core/DragDrop.js","../src/blocks/registry.js","../src/blocks/BlockRenderer.js","../src/ui/Header.js","../src/ui/Toolbar.js","../src/ui/InserterPanel.js","../src/ui/SettingsPanel.js","../src/ui/SlashMenu.js","../src/ui/StatusBar.js","../src/NBDEditor.js","../src/react/ReactNBDEditor.js"],"sourcesContent":["/**\n * Lightweight event emitter for editor internals.\n */\nexport class EventEmitter {\n constructor() {\n this._listeners = {};\n }\n\n on(event, fn) {\n (this._listeners[event] ||= []).push(fn);\n return () => this.off(event, fn);\n }\n\n off(event, fn) {\n const list = this._listeners[event];\n if (!list) return;\n this._listeners[event] = list.filter((f) => f !== fn);\n }\n\n emit(event, ...args) {\n (this._listeners[event] || []).forEach((fn) => fn(...args));\n }\n\n once(event, fn) {\n const wrapper = (...args) => {\n this.off(event, wrapper);\n fn(...args);\n };\n this.on(event, wrapper);\n }\n}\n","/**\n * DOM helper utilities.\n */\n\nexport function el(tag, attrs = {}, children = []) {\n const node = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) {\n if (k === 'className') node.className = v;\n else if (k === 'style' && typeof v === 'object') Object.assign(node.style, v);\n else if (k === 'dataset' && typeof v === 'object') {\n for (const [dk, dv] of Object.entries(v)) node.dataset[dk] = dv;\n } else if (k.startsWith('on') && typeof v === 'function') {\n node.addEventListener(k.slice(2).toLowerCase(), v);\n } else if (k === 'contentEditable') {\n node.contentEditable = v;\n } else if (k === 'innerHTML') {\n node.innerHTML = v;\n } else {\n node.setAttribute(k, v);\n }\n }\n for (const child of (Array.isArray(children) ? children : [children])) {\n if (typeof child === 'string') node.appendChild(document.createTextNode(child));\n else if (child instanceof Node) node.appendChild(child);\n }\n return node;\n}\n\nexport function qs(sel, root = document) {\n return root.querySelector(sel);\n}\n\nexport function qsa(sel, root = document) {\n return [...root.querySelectorAll(sel)];\n}\n\nexport function generateId() {\n return 'blk_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);\n}\n\nexport function stripHTML(html) {\n const tmp = document.createElement('div');\n tmp.innerHTML = html;\n return tmp.textContent || '';\n}\n\nexport function getCaretRect() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n return range.getBoundingClientRect();\n}\n\nexport function placeCaretAtEnd(element) {\n element.focus();\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\nexport function placeCaretAtStart(element) {\n element.focus();\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n}\n","/**\n * SVG icons used throughout the editor.\n */\n\nconst svg = (inner, vb = '0 0 24 24') =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"${vb}\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${inner}</svg>`;\n\nconst filled = (inner, vb = '0 0 24 24') =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"${vb}\" fill=\"currentColor\">${inner}</svg>`;\n\nexport const icons = {\n plus: svg('<line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/>'),\n undo: svg('<path d=\"M3 10h13a4 4 0 010 8H7\"/><path d=\"M3 10l4-4M3 10l4 4\"/>'),\n redo: svg('<path d=\"M21 10H8a4 4 0 000 8h9\"/><path d=\"M21 10l-4-4M21 10l-4 4\"/>'),\n listView: svg('<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"/><line x1=\"3\" y1=\"6\" x2=\"3.01\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"3.01\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"3.01\" y2=\"18\"/>'),\n settings: svg('<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z\"/>'),\n moreVert: filled('<circle cx=\"12\" cy=\"5\" r=\"1.5\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\"/><circle cx=\"12\" cy=\"19\" r=\"1.5\"/>'),\n bold: '<b>B</b>',\n italic: '<i>I</i>',\n underline: '<u>U</u>',\n strikethrough: '<s>S</s>',\n link: svg('<path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\"/>'),\n code: svg('<polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/>'),\n alignLeft: svg('<line x1=\"17\" y1=\"10\" x2=\"3\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\"/>'),\n alignCenter: svg('<line x1=\"18\" y1=\"10\" x2=\"6\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"18\" y1=\"18\" x2=\"6\" y2=\"18\"/>'),\n alignRight: svg('<line x1=\"21\" y1=\"10\" x2=\"7\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"21\" y1=\"18\" x2=\"7\" y2=\"18\"/>'),\n image: svg('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>'),\n heading: '<b>H</b>',\n paragraph: '<span style=\"font-size:16px\">¶</span>',\n quote: '<span style=\"font-size:18px\">&#10077;</span>',\n list: svg('<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"/><circle cx=\"4\" cy=\"6\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"4\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"4\" cy=\"18\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/>'),\n orderedList: svg('<line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"/><text x=\"3\" y=\"8\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">1</text><text x=\"3\" y=\"14\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">2</text><text x=\"3\" y=\"20\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">3</text>'),\n separator: svg('<line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/>'),\n table: svg('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/>'),\n button: svg('<rect x=\"3\" y=\"7\" width=\"18\" height=\"10\" rx=\"3\"/>'),\n columns: svg('<rect x=\"3\" y=\"3\" width=\"7\" height=\"18\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"18\" rx=\"1\"/>'),\n spacer: svg('<path d=\"M12 5v14M5 12h14\"/>', '0 0 24 24'),\n embed: svg('<path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\"/>'),\n gallery: svg('<rect x=\"2\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"14\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"2\" y=\"14\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"8\" height=\"8\" rx=\"1\"/>'),\n video: svg('<polygon points=\"5 3 19 12 5 21 5 3\"/>'),\n audio: svg('<path d=\"M9 18V5l12-2v13\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><circle cx=\"18\" cy=\"16\" r=\"3\"/>'),\n file: svg('<path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/>'),\n dragHandle: filled('<circle cx=\"9\" cy=\"5\" r=\"1.2\"/><circle cx=\"15\" cy=\"5\" r=\"1.2\"/><circle cx=\"9\" cy=\"10\" r=\"1.2\"/><circle cx=\"15\" cy=\"10\" r=\"1.2\"/><circle cx=\"9\" cy=\"15\" r=\"1.2\"/><circle cx=\"15\" cy=\"15\" r=\"1.2\"/><circle cx=\"9\" cy=\"20\" r=\"1.2\"/><circle cx=\"15\" cy=\"20\" r=\"1.2\"/>'),\n arrowUp: svg('<polyline points=\"18 15 12 9 6 15\"/>'),\n arrowDown: svg('<polyline points=\"6 9 12 15 18 9\"/>'),\n trash: svg('<polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/>'),\n close: svg('<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>'),\n check: svg('<polyline points=\"20 6 9 17 4 12\"/>'),\n inlineCode: '<span style=\"font-family:monospace;font-size:13px\">&lt;/&gt;</span>',\n upload: svg('<path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\"/><polyline points=\"17 8 12 3 7 8\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"/>'),\n externalLink: svg('<path d=\"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6\"/><polyline points=\"15 3 21 3 21 9\"/><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"/>'),\n html: '<span style=\"font-family:monospace;font-size:11px\">&lt;HTML&gt;</span>',\n pullquote: svg('<path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z\"/><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"/>'),\n};\n","import { generateId } from '../utils/dom.js';\nimport { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Manages the block data model: add, remove, move, update, and undo/redo.\n */\nexport class BlockManager extends EventEmitter {\n constructor() {\n super();\n this.blocks = [];\n this._undoStack = [];\n this._redoStack = [];\n this._maxHistory = 100;\n this._undoStack.push(JSON.stringify(this.blocks));\n }\n\n /* ---- CRUD ---- */\n\n addBlock(type, data = {}, afterId = null) {\n const block = {\n id: generateId(),\n type,\n content: '',\n attrs: {},\n ...data,\n };\n\n if (afterId) {\n const idx = this.blocks.findIndex((b) => b.id === afterId);\n this.blocks.splice(idx + 1, 0, block);\n } else {\n this.blocks.push(block);\n }\n\n this._pushUndo();\n this.emit('block:added', block);\n this.emit('change', this.blocks);\n return block;\n }\n\n removeBlock(id) {\n const idx = this.blocks.findIndex((b) => b.id === id);\n if (idx === -1) return;\n if (this.blocks.length <= 1) return; // keep at least one block\n const [removed] = this.blocks.splice(idx, 1);\n this._pushUndo();\n this.emit('block:removed', removed, idx);\n this.emit('change', this.blocks);\n return removed;\n }\n\n updateBlock(id, patch) {\n const block = this.getBlock(id);\n if (!block) return;\n Object.assign(block, patch);\n this.emit('block:updated', block);\n this.emit('change', this.blocks);\n }\n\n changeBlockType(id, newType) {\n const block = this.getBlock(id);\n if (!block) return;\n block.type = newType;\n this._pushUndo();\n this.emit('block:typeChanged', block);\n this.emit('change', this.blocks);\n }\n\n moveBlock(id, direction) {\n const idx = this.blocks.findIndex((b) => b.id === id);\n const newIdx = idx + direction;\n if (newIdx < 0 || newIdx >= this.blocks.length) return;\n [this.blocks[idx], this.blocks[newIdx]] = [this.blocks[newIdx], this.blocks[idx]];\n this._pushUndo();\n this.emit('block:moved', this.blocks[newIdx], direction);\n this.emit('change', this.blocks);\n }\n\n duplicateBlock(id) {\n const block = this.getBlock(id);\n if (!block) return;\n const clone = { ...block, id: generateId(), content: block.content, attrs: { ...block.attrs } };\n const idx = this.blocks.findIndex((b) => b.id === id);\n this.blocks.splice(idx + 1, 0, clone);\n this._pushUndo();\n this.emit('block:added', clone);\n this.emit('change', this.blocks);\n return clone;\n }\n\n /* ---- Queries ---- */\n\n getBlock(id) {\n return this.blocks.find((b) => b.id === id) || null;\n }\n\n getIndex(id) {\n return this.blocks.findIndex((b) => b.id === id);\n }\n\n getPrevBlock(id) {\n const idx = this.getIndex(id);\n return idx > 0 ? this.blocks[idx - 1] : null;\n }\n\n getNextBlock(id) {\n const idx = this.getIndex(id);\n return idx < this.blocks.length - 1 ? this.blocks[idx + 1] : null;\n }\n\n /* ---- Serialization ---- */\n\n toJSON() {\n return this.blocks.map((b) => ({ ...b }));\n }\n\n fromJSON(data) {\n this.blocks = data.map((b) => ({ ...b }));\n this._undoStack = [JSON.stringify(this.blocks)];\n this._redoStack = [];\n this.emit('change', this.blocks);\n }\n\n toHTML() {\n return this.blocks.map((b) => this.blockToHTML(b)).join('\\n');\n }\n\n toHTMLBlocks() {\n return this.blocks.map((b) => ({\n ...b,\n html: this.blockToHTML(b),\n }));\n }\n\n blockToHTML(block) {\n return blockToHTML(block);\n }\n\n /* ---- Undo / Redo ---- */\n\n _pushUndo() {\n const next = JSON.stringify(this.blocks);\n const last = this._undoStack[this._undoStack.length - 1];\n if (next === last) return;\n this._undoStack.push(next);\n if (this._undoStack.length > this._maxHistory) this._undoStack.shift();\n this._redoStack = [];\n }\n\n saveSnapshot() {\n this._pushUndo();\n }\n\n undo() {\n if (this._undoStack.length < 2) return false;\n this._redoStack.push(this._undoStack.pop());\n this.blocks = JSON.parse(this._undoStack[this._undoStack.length - 1]);\n this.emit('change', this.blocks);\n return true;\n }\n\n redo() {\n if (this._redoStack.length === 0) return false;\n const state = this._redoStack.pop();\n this._undoStack.push(state);\n this.blocks = JSON.parse(state);\n this.emit('change', this.blocks);\n return true;\n }\n\n /* ---- Stats ---- */\n\n getWordCount() {\n let text = '';\n for (const b of this.blocks) {\n if (b.content) {\n const tmp = document.createElement('div');\n tmp.innerHTML = b.content;\n text += tmp.textContent + ' ';\n }\n }\n const words = text.trim().split(/\\s+/).filter((w) => w.length > 0);\n return words.length;\n }\n\n getCharCount() {\n let text = '';\n for (const b of this.blocks) {\n if (b.content) {\n const tmp = document.createElement('div');\n tmp.innerHTML = b.content;\n text += tmp.textContent;\n }\n }\n return text.replace(/\\s/g, '').length;\n }\n}\n\n/* ---- Helpers ---- */\n\n/**\n * Escape a string for safe use inside an HTML attribute value.\n * Prevents XSS via attribute injection (e.g. `\" onload=\"alert(1)`).\n */\nfunction _escAttr(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Escape a string for safe use as HTML text content.\n */\nfunction _escText(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\nfunction blockToHTML(block) {\n const c = block.content || '';\n switch (block.type) {\n case 'paragraph':\n return _containsBlockMarkup(c) ? c : `<p>${c}</p>`;\n case 'heading':\n return `<h2>${c}</h2>`;\n case 'heading-3':\n return `<h3>${c}</h3>`;\n case 'heading-4':\n return `<h4>${c}</h4>`;\n case 'quote':\n return `<blockquote>${c}</blockquote>`;\n case 'code':\n return `<pre><code>${_escText(c)}</code></pre>`;\n case 'list':\n return `<ul>${c}</ul>`;\n case 'ordered-list':\n return `<ol>${c}</ol>`;\n case 'image': {\n if (!c) return '';\n const width = Number(block.attrs?.width);\n const style = Number.isFinite(width) ? ` style=\"width:${Math.max(10, Math.min(100, Math.round(width)))}%\"` : '';\n return `<figure><img src=\"${_escAttr(c)}\" alt=\"${_escAttr(block.attrs?.alt || '')}\"${style}/>${block.attrs?.caption ? `<figcaption>${block.attrs.caption}</figcaption>` : ''}</figure>`;\n }\n case 'separator':\n return '<hr/>';\n case 'spacer':\n return `<div style=\"height:${Number(block.attrs?.height) || 48}px\"></div>`;\n case 'table':\n return c || '<table></table>';\n case 'button':\n return `<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"${_escAttr(block.attrs?.url || '#')}\">${c || 'Button'}</a></div>`;\n case 'columns':\n return `<div class=\"wp-block-columns\">${c}</div>`;\n case 'embed':\n return `<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">${c}</div></figure>`;\n case 'gallery':\n return `<figure class=\"wp-block-gallery\">${c}</figure>`;\n case 'video':\n return c ? `<figure class=\"wp-block-video\"><video controls src=\"${_escAttr(c)}\"></video></figure>` : '';\n case 'audio':\n return c ? `<figure class=\"wp-block-audio\"><audio controls src=\"${_escAttr(c)}\"></audio></figure>` : '';\n case 'file':\n return c ? `<div class=\"wp-block-file\"><a href=\"${_escAttr(c)}\">${_escText(block.attrs?.filename || 'Download')}</a></div>` : '';\n case 'html':\n return c;\n case 'pullquote':\n return `<figure class=\"wp-block-pullquote\"><blockquote>${c}</blockquote></figure>`;\n default:\n return `<p>${c}</p>`;\n }\n}\n\nfunction _containsBlockMarkup(html) {\n if (!html || typeof html !== 'string') return false;\n return /<(h[1-6]|p|div|section|article|blockquote|ul|ol|li|table|thead|tbody|tr|td|th|figure|figcaption|img|pre|hr)\\b/i.test(html);\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Handles media uploads: images, video, audio, files.\n * Supports custom upload handlers, drag-and-drop, clipboard paste, and local preview.\n */\nexport class MediaUploader extends EventEmitter {\n constructor(options = {}) {\n super();\n this.uploadHandler = options.uploadHandler || null; // async (file) => { url, id }\n this.maxFileSize = options.maxFileSize || 10 * 1024 * 1024; // 10MB\n this.allowedImageTypes = options.allowedImageTypes || ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'];\n this.allowedVideoTypes = options.allowedVideoTypes || ['video/mp4', 'video/webm', 'video/ogg'];\n this.allowedAudioTypes = options.allowedAudioTypes || ['audio/mpeg', 'audio/ogg', 'audio/wav', 'audio/webm'];\n this._fileInput = null;\n }\n\n /**\n * Create a hidden file input and trigger it.\n */\n openFilePicker(accept = 'image/*', multiple = false) {\n return new Promise((resolve) => {\n if (this._fileInput) this._fileInput.remove();\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = accept;\n input.multiple = multiple;\n input.style.display = 'none';\n document.body.appendChild(input);\n this._fileInput = input;\n\n input.addEventListener('change', () => {\n const files = [...input.files];\n input.remove();\n this._fileInput = null;\n resolve(files);\n });\n\n input.addEventListener('cancel', () => {\n input.remove();\n this._fileInput = null;\n resolve([]);\n });\n\n input.click();\n });\n }\n\n /**\n * Process a file: validate, generate local preview, then optionally upload.\n * Returns { localUrl, remoteUrl?, file, error? }\n */\n async processFile(file) {\n // Validate size\n if (file.size > this.maxFileSize) {\n const err = `File \"${file.name}\" exceeds the ${(this.maxFileSize / 1024 / 1024).toFixed(0)}MB limit.`;\n this.emit('error', err);\n return { error: err, file };\n }\n\n // Generate local preview\n const localUrl = await this._readAsDataURL(file);\n this.emit('preview', { file, localUrl });\n\n // If a custom upload handler is provided, use it\n if (this.uploadHandler) {\n try {\n this.emit('upload:start', { file });\n const result = await this.uploadHandler(file);\n this.emit('upload:complete', { file, ...result });\n return { localUrl, remoteUrl: result.url, file, id: result.id };\n } catch (err) {\n this.emit('upload:error', { file, error: err });\n return { localUrl, file, error: err.message || 'Upload failed' };\n }\n }\n\n // No remote handler — just use local data URL\n return { localUrl, file };\n }\n\n /**\n * Process multiple files.\n */\n async processFiles(files) {\n return Promise.all(files.map((f) => this.processFile(f)));\n }\n\n /**\n * Handle a paste event for images.\n */\n async handlePaste(clipboardData) {\n const items = [...(clipboardData.items || [])];\n const imageItems = items.filter((item) => item.type.startsWith('image/'));\n if (imageItems.length === 0) return null;\n\n const files = imageItems.map((item) => item.getAsFile()).filter(Boolean);\n if (files.length === 0) return null;\n\n return this.processFiles(files);\n }\n\n /**\n * Handle drag-and-drop of files.\n */\n async handleDrop(dataTransfer) {\n const files = [...(dataTransfer.files || [])];\n if (files.length === 0) return null;\n return this.processFiles(files);\n }\n\n /**\n * Determine media type from file.\n */\n getMediaType(file) {\n if (file.type.startsWith('image/')) return 'image';\n if (file.type.startsWith('video/')) return 'video';\n if (file.type.startsWith('audio/')) return 'audio';\n return 'file';\n }\n\n /**\n * Read file as data URL.\n */\n _readAsDataURL(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n }\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Drag-and-drop reordering for blocks.\n */\nexport class DragDrop extends EventEmitter {\n constructor(container) {\n super();\n this.container = container;\n this._dragging = null;\n this._placeholder = null;\n this._offsetY = 0;\n this._bound = {};\n this._enabled = true;\n }\n\n enable() {\n this._enabled = true;\n }\n\n disable() {\n this._enabled = false;\n }\n\n /**\n * Initialise drag on a handle element within a block wrapper.\n */\n initDrag(handleEl, wrapperEl, blockId) {\n handleEl.setAttribute('draggable', 'true');\n handleEl.style.cursor = 'grab';\n\n handleEl.addEventListener('dragstart', (e) => {\n if (!this._enabled) return e.preventDefault();\n this._dragging = { el: wrapperEl, id: blockId };\n wrapperEl.style.opacity = '0.4';\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', blockId);\n this.emit('drag:start', blockId);\n });\n\n handleEl.addEventListener('dragend', () => {\n if (this._dragging) {\n this._dragging.el.style.opacity = '';\n this._dragging = null;\n }\n this._removePlaceholder();\n this.emit('drag:end');\n });\n\n wrapperEl.addEventListener('dragover', (e) => {\n if (!this._dragging || this._dragging.id === blockId) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n\n const rect = wrapperEl.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position = e.clientY < midY ? 'before' : 'after';\n\n this._showPlaceholder(wrapperEl, position);\n });\n\n wrapperEl.addEventListener('drop', (e) => {\n e.preventDefault();\n if (!this._dragging) return;\n const fromId = this._dragging.id;\n const toId = blockId;\n\n const rect = wrapperEl.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position = e.clientY < midY ? 'before' : 'after';\n\n this._removePlaceholder();\n this._dragging.el.style.opacity = '';\n this._dragging = null;\n\n this.emit('drop', { fromId, toId, position });\n });\n }\n\n _showPlaceholder(referenceEl, position) {\n if (!this._placeholder) {\n this._placeholder = document.createElement('div');\n this._placeholder.className = 'fe-drag-placeholder';\n this._placeholder.style.cssText =\n 'height:4px;background:#2271b1;border-radius:2px;margin:4px 0;transition:all 0.15s;';\n }\n if (position === 'before') {\n referenceEl.parentNode.insertBefore(this._placeholder, referenceEl);\n } else {\n referenceEl.parentNode.insertBefore(this._placeholder, referenceEl.nextSibling);\n }\n }\n\n _removePlaceholder() {\n if (this._placeholder && this._placeholder.parentNode) {\n this._placeholder.parentNode.removeChild(this._placeholder);\n }\n }\n}\n","import { icons } from '../utils/icons.js';\n\n/**\n * Block type registry. Each entry describes a block type and how to render it.\n */\nexport const BLOCK_TYPES = {\n paragraph: {\n label: 'Paragraph',\n description: 'Start with the building block of all narrative.',\n icon: icons.paragraph,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Type / to choose a block',\n className: '',\n },\n heading: {\n label: 'Heading 2',\n description: 'Introduce new sections and organize content.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h2',\n placeholder: 'Heading 2',\n className: 'fe-heading-2',\n },\n 'heading-3': {\n label: 'Heading 3',\n description: 'A smaller heading for subsections.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h3',\n placeholder: 'Heading 3',\n className: 'fe-heading-3',\n },\n 'heading-4': {\n label: 'Heading 4',\n description: 'A small heading for nested subsections.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h4',\n placeholder: 'Heading 4',\n className: 'fe-heading-4',\n },\n list: {\n label: 'List',\n description: 'Create a bulleted list.',\n icon: icons.list,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'List',\n className: 'fe-list-block',\n },\n 'ordered-list': {\n label: 'Ordered List',\n description: 'Create a numbered list.',\n icon: icons.orderedList,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'List',\n className: 'fe-ordered-list-block',\n },\n quote: {\n label: 'Quote',\n description: 'Give quoted text visual emphasis.',\n icon: icons.quote,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write quote...',\n className: 'fe-quote',\n },\n pullquote: {\n label: 'Pullquote',\n description: 'Highlight a key quote from your content.',\n icon: icons.pullquote,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write pullquote...',\n className: 'fe-pullquote',\n },\n code: {\n label: 'Code',\n description: 'Display code snippets that respect your spacing.',\n icon: icons.code,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write code...',\n className: 'fe-code-block',\n },\n html: {\n label: 'Custom HTML',\n description: 'Add custom HTML code.',\n icon: icons.html,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write HTML...',\n className: 'fe-html-block',\n },\n image: {\n label: 'Image',\n description: 'Insert an image to make a visual statement.',\n icon: icons.image,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n gallery: {\n label: 'Gallery',\n description: 'Display multiple images in a gallery.',\n icon: icons.gallery,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n video: {\n label: 'Video',\n description: 'Embed a video from your media library or URL.',\n icon: icons.video,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n audio: {\n label: 'Audio',\n description: 'Embed an audio file.',\n icon: icons.audio,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n file: {\n label: 'File',\n description: 'Add a link to a downloadable file.',\n icon: icons.file,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n separator: {\n label: 'Separator',\n description: 'Create a break between ideas or sections.',\n icon: icons.separator,\n category: 'design',\n hasContent: false,\n },\n spacer: {\n label: 'Spacer',\n description: 'Add white space between blocks.',\n icon: icons.spacer,\n category: 'design',\n hasContent: false,\n },\n columns: {\n label: 'Columns',\n description: 'Display content in multiple columns.',\n icon: icons.columns,\n category: 'design',\n hasContent: false,\n },\n table: {\n label: 'Table',\n description: 'Insert a table for sharing data.',\n icon: icons.table,\n category: 'design',\n hasContent: false,\n },\n button: {\n label: 'Button',\n description: 'Prompt visitors to take action with a button.',\n icon: icons.button,\n category: 'design',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Add text...',\n className: 'fe-button-block',\n },\n embed: {\n label: 'Embed',\n description: 'Embed content from YouTube, Twitter, etc.',\n icon: icons.embed,\n category: 'media',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Enter URL to embed...',\n className: 'fe-embed-block',\n },\n};\n\nexport const CATEGORIES = [\n { id: 'text', label: 'Text' },\n { id: 'media', label: 'Media' },\n { id: 'design', label: 'Design' },\n];\n\n/**\n * Get blocks for a category.\n */\nexport function getBlocksByCategory(catId) {\n return Object.entries(BLOCK_TYPES)\n .filter(([, def]) => def.category === catId)\n .map(([type, def]) => ({ type, ...def }));\n}\n\n/**\n * Search blocks by query.\n */\nexport function searchBlocks(query) {\n const q = query.toLowerCase();\n return Object.entries(BLOCK_TYPES)\n .filter(([type, def]) => type.includes(q) || def.label.toLowerCase().includes(q) || def.description.toLowerCase().includes(q))\n .map(([type, def]) => ({ type, ...def }));\n}\n","import { el, placeCaretAtEnd } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\nimport { BLOCK_TYPES } from './registry.js';\n\n/**\n * Creates the DOM for a single block based on its type and data.\n */\nexport class BlockRenderer {\n constructor(editor) {\n this.editor = editor;\n }\n\n render(block) {\n const def = BLOCK_TYPES[block.type];\n if (!def) return this._renderParagraph(block);\n\n if (def.isMedia) return this._renderMediaBlock(block, def);\n if (def.hasContent) return this._renderContentBlock(block, def);\n\n // Non-content blocks\n switch (block.type) {\n case 'separator': return this._renderSeparator(block);\n case 'spacer': return this._renderSpacer(block);\n case 'columns': return this._renderColumns(block);\n case 'table': return this._renderTable(block);\n default: return this._renderParagraph(block);\n }\n }\n\n /* ---- Content Blocks (editable) ---- */\n\n _renderContentBlock(block, def) {\n const isRawTextBlock = block.type === 'code' || block.type === 'html';\n const isEmpty = !block.content || block.content.trim() === '';\n const node = el(def.contentTag || 'div', {\n className: `fe-block-content ${def.className || ''}`.trim(),\n contentEditable: 'true',\n dataset: { \n placeholder: def.placeholder || '',\n empty: isEmpty ? 'true' : 'false'\n },\n innerHTML: isRawTextBlock ? '' : (block.content || '<br>'),\n });\n if (isRawTextBlock && block.content) {\n node.textContent = block.content;\n }\n\n this._bindContentEvents(node, block);\n return node;\n }\n\n _renderParagraph(block) {\n const isEmpty = !block.content || block.content.trim() === '';\n const node = el('div', {\n className: 'fe-block-content',\n contentEditable: 'true',\n dataset: { \n placeholder: 'Type / to choose a block',\n empty: isEmpty ? 'true' : 'false'\n },\n innerHTML: block.content || '<br>',\n });\n this._bindContentEvents(node, block);\n return node;\n }\n\n /* ---- Media Blocks ---- */\n\n _renderMediaBlock(block, def) {\n const container = el('div', { className: `fe-block-media fe-block-${block.type}` });\n\n switch (block.type) {\n case 'image':\n return this._renderImageBlock(block, container);\n case 'gallery':\n return this._renderGalleryBlock(block, container);\n case 'video':\n return this._renderVideoBlock(block, container);\n case 'audio':\n return this._renderAudioBlock(block, container);\n case 'file':\n return this._renderFileBlock(block, container);\n default:\n return this._renderMediaPlaceholder(block, container, def);\n }\n }\n\n _renderImageBlock(block, container) {\n if (block.content) {\n const width = _normalizeImageWidth(block.attrs?.width);\n const fig = el('figure', { className: 'fe-image-figure' });\n const img = el('img', { src: block.content, alt: block.attrs?.alt || '' });\n img.style.width = `${width}%`;\n img.style.maxWidth = '100%';\n img.style.borderRadius = '4px';\n img.style.display = 'block';\n fig.appendChild(img);\n\n // Caption\n const caption = el('figcaption', {\n className: 'fe-image-caption',\n contentEditable: 'true',\n dataset: { placeholder: 'Add caption...' },\n innerHTML: block.attrs?.caption || '',\n });\n caption.addEventListener('input', () => {\n block.attrs = block.attrs || {};\n block.attrs.caption = caption.innerHTML;\n });\n fig.appendChild(caption);\n\n // Toolbar overlay\n const overlay = el('div', { className: 'fe-image-overlay' });\n const replaceBtn = el('button', {\n className: 'fe-img-overlay-btn',\n innerHTML: 'Replace',\n onClick: () => this._triggerImageUpload(block),\n });\n const removeBtn = el('button', {\n className: 'fe-img-overlay-btn fe-img-overlay-btn-danger',\n innerHTML: 'Remove',\n onClick: () => {\n block.content = '';\n block.attrs = {};\n this.editor.render();\n },\n });\n overlay.appendChild(replaceBtn);\n overlay.appendChild(removeBtn);\n fig.appendChild(overlay);\n\n const resizeHandle = el('button', {\n type: 'button',\n className: 'fe-image-resize-handle',\n title: 'Drag to resize image',\n });\n resizeHandle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.editor.selectBlock(block.id);\n\n const startX = e.clientX;\n const startWidth = img.getBoundingClientRect().width;\n const parentWidth = container.getBoundingClientRect().width || startWidth || 1;\n\n const onMove = (ev) => {\n const delta = ev.clientX - startX;\n const nextWidthPx = Math.max(80, Math.min(parentWidth, startWidth + delta));\n const nextPercent = _normalizeImageWidth((nextWidthPx / parentWidth) * 100);\n block.attrs = block.attrs || {};\n block.attrs.width = nextPercent;\n img.style.width = `${nextPercent}%`;\n };\n\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this.editor.statusBar.update();\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n fig.appendChild(resizeHandle);\n\n container.appendChild(fig);\n\n const sizeControls = el('div', { className: 'fe-image-size-controls' });\n [25, 50, 75, 100].forEach((pct) => {\n const btn = el('button', {\n type: 'button',\n className: `fe-img-size-btn ${width === pct ? 'is-active' : ''}`.trim(),\n innerHTML: `${pct}%`,\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.width = pct;\n this.editor.render();\n },\n });\n sizeControls.appendChild(btn);\n });\n container.appendChild(sizeControls);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.image);\n }\n\n return container;\n }\n\n _renderGalleryBlock(block, container) {\n const images = block.attrs?.images || [];\n if (images.length > 0) {\n const grid = el('div', { className: 'fe-gallery-grid' });\n images.forEach((src, i) => {\n const item = el('div', { className: 'fe-gallery-item' });\n item.appendChild(el('img', { src, alt: '' }));\n const removeBtn = el('button', {\n className: 'fe-gallery-remove',\n innerHTML: '&times;',\n onClick: () => {\n images.splice(i, 1);\n this.editor.render();\n },\n });\n item.appendChild(removeBtn);\n grid.appendChild(item);\n });\n container.appendChild(grid);\n\n const addMore = el('button', {\n className: 'fe-gallery-add',\n innerHTML: '+ Add Images',\n onClick: () => this._triggerGalleryUpload(block),\n });\n container.appendChild(addMore);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.gallery);\n }\n return container;\n }\n\n _renderVideoBlock(block, container) {\n if (block.content) {\n const video = el('video', { src: block.content });\n video.controls = true;\n video.style.maxWidth = '100%';\n video.style.borderRadius = '4px';\n container.appendChild(video);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.video);\n }\n return container;\n }\n\n _renderAudioBlock(block, container) {\n if (block.content) {\n const audio = el('audio', { src: block.content });\n audio.controls = true;\n audio.style.width = '100%';\n container.appendChild(audio);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.audio);\n }\n return container;\n }\n\n _renderFileBlock(block, container) {\n if (block.content) {\n const wrapper = el('div', { className: 'fe-file-wrapper' });\n\n const infoDiv = el('div', { className: 'fe-file-info' });\n infoDiv.appendChild(el('span', { className: 'fe-file-icon', innerHTML: icons.file }));\n infoDiv.appendChild(el('span', { className: 'fe-file-name' }, [block.attrs?.filename || 'File']));\n infoDiv.appendChild(el('span', { className: 'fe-file-size' }, [block.attrs?.filesize || '']));\n wrapper.appendChild(infoDiv);\n\n const downloadLink = el('a', { className: 'fe-file-download', href: block.content, download: '' }, ['Download']);\n wrapper.appendChild(downloadLink);\n\n container.appendChild(wrapper);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.file);\n }\n return container;\n }\n\n _renderMediaPlaceholder(block, container, def) {\n const placeholder = el('div', { className: 'fe-media-placeholder' });\n\n const iconEl = el('div', { className: 'fe-media-placeholder-icon', innerHTML: def.icon });\n const label = el('p', { className: 'fe-media-placeholder-label' }, [def.label]);\n const desc = el('p', { className: 'fe-media-placeholder-desc' }, ['Upload a file or pick one from your media library.']);\n\n const btnRow = el('div', { className: 'fe-media-placeholder-actions' });\n\n const uploadBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n innerHTML: `${icons.upload} Upload`,\n onClick: () => this._handleMediaUpload(block),\n });\n btnRow.appendChild(uploadBtn);\n\n // URL input for embeds, video, audio\n if (['embed', 'video', 'audio'].includes(block.type)) {\n const urlInput = el('input', {\n type: 'text',\n className: 'fe-media-url-input',\n placeholder: 'Or paste a URL...',\n });\n urlInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n block.content = urlInput.value;\n this.editor.render();\n }\n });\n btnRow.appendChild(urlInput);\n }\n\n placeholder.appendChild(iconEl);\n placeholder.appendChild(label);\n placeholder.appendChild(desc);\n placeholder.appendChild(btnRow);\n container.appendChild(placeholder);\n\n // Drop zone\n this._setupDropZone(placeholder, block);\n\n return container;\n }\n\n /* ---- Non-content Blocks ---- */\n\n _renderSeparator(block) {\n const node = el('div', { className: 'fe-block-separator' });\n node.appendChild(el('hr'));\n return node;\n }\n\n _renderSpacer(block) {\n const height = block.attrs?.height || 48;\n const node = el('div', {\n className: 'fe-block-spacer',\n style: { height: height + 'px' },\n });\n\n // Resize handle\n const handle = el('div', { className: 'fe-spacer-handle' });\n let startY, startH;\n handle.addEventListener('mousedown', (e) => {\n startY = e.clientY;\n startH = height;\n const onMove = (ev) => {\n const newH = Math.max(16, startH + ev.clientY - startY);\n node.style.height = newH + 'px';\n block.attrs = block.attrs || {};\n block.attrs.height = newH;\n };\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n node.appendChild(handle);\n return node;\n }\n\n _renderColumns(block) {\n const numCols = block.attrs?.columns || 2;\n const node = el('div', { className: 'fe-block-columns' });\n for (let i = 0; i < numCols; i++) {\n const col = el('div', {\n className: 'fe-column',\n contentEditable: 'true',\n dataset: { placeholder: `Column ${i + 1}` },\n innerHTML: block.attrs?.[`col${i}`] || '',\n });\n col.addEventListener('input', () => {\n block.attrs = block.attrs || {};\n block.attrs[`col${i}`] = col.innerHTML;\n });\n node.appendChild(col);\n }\n\n const controls = el('div', { className: 'fe-columns-controls' });\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n type: 'button',\n innerHTML: '+ Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.columns = Math.max(1, Number(block.attrs.columns || numCols) + 1);\n this.editor.render();\n },\n })\n );\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n type: 'button',\n innerHTML: '- Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n const current = Math.max(1, Number(block.attrs.columns || numCols));\n if (current <= 1) return;\n delete block.attrs[`col${current - 1}`];\n block.attrs.columns = current - 1;\n this.editor.render();\n },\n })\n );\n node.appendChild(controls);\n return node;\n }\n\n _renderTable(block) {\n const rows = block.attrs?.rows || 3;\n const cols = block.attrs?.cols || 3;\n const node = el('div', { className: 'fe-block-table' });\n const table = el('table');\n const data = block.attrs?.data || [];\n\n for (let r = 0; r < rows; r++) {\n const tr = el('tr');\n for (let c = 0; c < cols; c++) {\n const cellTag = r === 0 ? 'th' : 'td';\n const cell = el(cellTag, {\n contentEditable: 'true',\n innerHTML: data[r]?.[c] || '',\n });\n cell.addEventListener('input', () => {\n if (!block.attrs) block.attrs = {};\n if (!block.attrs.data) block.attrs.data = [];\n if (!block.attrs.data[r]) block.attrs.data[r] = [];\n block.attrs.data[r][c] = cell.innerHTML;\n });\n tr.appendChild(cell);\n }\n table.appendChild(tr);\n }\n\n node.appendChild(table);\n\n // Add row/column buttons\n const controls = el('div', { className: 'fe-table-controls' });\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: '+ Row',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.rows = (block.attrs.rows || 3) + 1;\n this.editor.render();\n },\n })\n );\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: '+ Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.cols = (block.attrs.cols || 3) + 1;\n this.editor.render();\n },\n })\n );\n node.appendChild(controls);\n return node;\n }\n\n /* ---- Upload Helpers ---- */\n\n async _handleMediaUpload(block) {\n let accept = '*/*';\n if (block.type === 'image' || block.type === 'gallery') accept = 'image/*';\n else if (block.type === 'video') accept = 'video/*';\n else if (block.type === 'audio') accept = 'audio/*';\n\n const multiple = block.type === 'gallery';\n const files = await this.editor.mediaUploader.openFilePicker(accept, multiple);\n if (files.length === 0) return;\n\n if (block.type === 'gallery') {\n const results = await this.editor.mediaUploader.processFiles(files);\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n } else {\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) {\n block.content = result.remoteUrl || result.localUrl;\n if (block.type === 'file') {\n block.attrs = block.attrs || {};\n block.attrs.filename = files[0].name;\n block.attrs.filesize = _formatSize(files[0].size);\n }\n }\n }\n this.editor.render();\n }\n\n async _triggerImageUpload(block) {\n const files = await this.editor.mediaUploader.openFilePicker('image/*');\n if (files.length === 0) return;\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) block.content = result.remoteUrl || result.localUrl;\n this.editor.render();\n }\n\n async _triggerGalleryUpload(block) {\n const files = await this.editor.mediaUploader.openFilePicker('image/*', true);\n if (files.length === 0) return;\n const results = await this.editor.mediaUploader.processFiles(files);\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n this.editor.render();\n }\n\n _setupDropZone(element, block) {\n element.addEventListener('dragover', (e) => {\n e.preventDefault();\n element.classList.add('fe-drop-active');\n });\n element.addEventListener('dragleave', () => {\n element.classList.remove('fe-drop-active');\n });\n element.addEventListener('drop', async (e) => {\n e.preventDefault();\n element.classList.remove('fe-drop-active');\n const results = await this.editor.mediaUploader.handleDrop(e.dataTransfer);\n if (results && results.length > 0) {\n if (block.type === 'gallery') {\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n } else {\n const res = results[0];\n if (!res.error) block.content = res.remoteUrl || res.localUrl;\n }\n this.editor.render();\n }\n });\n }\n\n /* ---- Content Events ---- */\n\n _bindContentEvents(node, block) {\n const isRawTextBlock = block.type === 'code' || block.type === 'html';\n\n // Helper to update empty state\n const updateEmptyState = () => {\n const text = node.textContent || '';\n const isEmpty = isRawTextBlock\n ? text.trim() === ''\n : text.trim() === '' && (node.innerHTML.trim() === '<br>' || node.innerHTML.trim() === '');\n node.dataset.empty = isEmpty ? 'true' : 'false';\n };\n\n // Update empty state initially\n updateEmptyState();\n\n // Ensure contenteditable gets focus when clicked\n node.addEventListener('mousedown', (e) => {\n // Let wrapper click handle first-time block selection to avoid losing focus on re-render\n if (this.editor._selectedBlockId !== block.id) return;\n // Stop propagation so wrapper click does not override caret placement on selected blocks\n e.stopPropagation();\n // Immediately focus on mousedown for better responsiveness\n if (document.activeElement !== node) {\n node.focus();\n // If empty (only has <br>), place caret correctly\n const text = node.textContent || '';\n if (text.trim() === '' && (node.innerHTML.trim() === '<br>' || node.innerHTML.trim() === '')) {\n // Ensure there's a <br> for cursor visibility\n if (node.innerHTML.trim() === '') {\n node.innerHTML = '<br>';\n }\n // Place caret after the <br>\n setTimeout(() => {\n const range = document.createRange();\n const sel = window.getSelection();\n range.selectNodeContents(node);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n }, 0);\n }\n }\n });\n\n node.addEventListener('input', () => {\n if (isRawTextBlock) {\n block.content = node.textContent || '';\n updateEmptyState();\n this.editor._onBlockInput(block, node);\n return;\n }\n\n // Clean up: if content is just <br> or empty, store as empty string\n let content = node.innerHTML.trim();\n if (content === '<br>' || content === '<br/>' || content === '') {\n content = '';\n // Keep the <br> in the DOM for cursor visibility, but don't save it\n if (!node.querySelector('br')) {\n node.innerHTML = '<br>';\n }\n }\n block.content = content;\n updateEmptyState();\n this.editor._onBlockInput(block, node);\n });\n\n node.addEventListener('keydown', (e) => {\n this.editor._onBlockKeydown(e, block, node);\n });\n\n node.addEventListener('focus', () => {\n this.editor.selectBlock(block.id);\n });\n\n node.addEventListener('paste', (e) => {\n // Code blocks: plain text only\n if (block.type === 'code' || block.type === 'html') {\n e.preventDefault();\n const text = e.clipboardData.getData('text/plain');\n document.execCommand('insertText', false, text);\n return;\n }\n\n // Image paste\n if (e.clipboardData.items) {\n const imageItems = [...e.clipboardData.items].filter((i) => i.type.startsWith('image/'));\n if (imageItems.length > 0) {\n e.preventDefault();\n this.editor.mediaUploader.handlePaste(e.clipboardData).then((results) => {\n if (results && results.length > 0) {\n const src = results[0].remoteUrl || results[0].localUrl;\n if (src) {\n document.execCommand('insertHTML', false, `<img src=\"${src}\" alt=\"\" />`);\n }\n }\n });\n return;\n }\n }\n });\n }\n}\n\nfunction _formatSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n}\n\nfunction _normalizeImageWidth(value) {\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) return 100;\n return Math.max(10, Math.min(100, Math.round(numeric)));\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\n\n/**\n * Top editor header bar: inserter button, undo/redo, status, save/publish, settings toggle.\n */\nexport class Header {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-header' });\n\n // Left\n const left = el('div', { className: 'fe-header-left' });\n\n // Block inserter toggle\n const inserterBtn = el('button', {\n className: 'fe-inserter-toggle',\n innerHTML: icons.plus,\n title: 'Toggle block inserter',\n onClick: (e) => this.editor.inserterPanel.toggle(e.currentTarget),\n });\n left.appendChild(inserterBtn);\n left.appendChild(el('span', { className: 'fe-sep' }));\n\n // Undo / Redo\n left.appendChild(this._iconBtn(icons.undo, 'Undo (Ctrl+Z)', () => {\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.editor.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.editor.rootEl.contains(window.getSelection().anchorNode));\n this.editor.undo({ preferNative: inEditable });\n }));\n left.appendChild(this._iconBtn(icons.redo, 'Redo (Ctrl+Y)', () => {\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.editor.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.editor.rootEl.contains(window.getSelection().anchorNode));\n this.editor.redo({ preferNative: inEditable });\n }));\n left.appendChild(el('span', { className: 'fe-sep' }));\n\n // List view\n left.appendChild(this._iconBtn(icons.listView, 'Document overview', () => {\n this.editor.emit('listView:toggle');\n }));\n\n this.el.appendChild(left);\n\n // Center spacer\n const center = el('div', { className: 'fe-header-center' });\n this.el.appendChild(center);\n\n // Right\n const right = el('div', { className: 'fe-header-right' });\n\n if (this.editor.options.showHeaderActions) {\n const draftBtn = el('button', {\n className: 'fe-btn fe-btn-outline',\n innerHTML: 'Save draft',\n onClick: () => this.editor.save(),\n });\n right.appendChild(draftBtn);\n\n const publishBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n innerHTML: 'Publish',\n onClick: () => this.editor.publish(),\n });\n right.appendChild(publishBtn);\n }\n\n if (this.editor.options.showSettingsPanel) {\n if (right.childNodes.length > 0) {\n right.appendChild(el('span', { className: 'fe-sep' }));\n }\n right.appendChild(this._iconBtn(icons.settings, 'Settings', () => {\n this.editor.settingsPanel.toggle();\n this.editor._updateCanvasMargin();\n }));\n }\n\n this.el.appendChild(right);\n return this.el;\n }\n\n setStatus(text, color) {\n // no-op: status text removed from header UI\n }\n\n _iconBtn(iconHTML, title, onClick) {\n return el('button', {\n className: 'fe-icon-btn',\n innerHTML: iconHTML,\n title,\n onClick,\n });\n }\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\n\n/**\n * Floating block toolbar for formatting and block controls.\n */\nexport class Toolbar {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._linkPopover = null;\n this._fontSizeSelect = null;\n this._onSelectionChange = null;\n this._statefulButtons = [];\n this._savedLinkRange = null;\n this._tableToolsSep = null;\n this._tableRowBtn = null;\n this._tableColBtn = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-block-toolbar' });\n this._linkPopover = this._createLinkPopover();\n this._fontSizeSelect = null;\n this._onSelectionChange = null;\n return this.el;\n }\n\n show(blockId) {\n const block = this.editor.blockManager.getBlock(blockId);\n if (!block) return this.hide();\n const getActiveBlockId = () => this.editor._selectedBlockId || blockId;\n\n this.el.innerHTML = '';\n this.el.classList.add('fe-visible');\n this._statefulButtons = [];\n\n // Drag handle\n this._addBtn(icons.dragHandle, 'Drag', null, 'fe-tb-drag');\n\n this._addSep();\n\n // Move buttons\n this._addBtn(icons.arrowUp, 'Move up', () => this.editor.blockManager.moveBlock(blockId, -1));\n this._addBtn(icons.arrowDown, 'Move down', () => this.editor.blockManager.moveBlock(blockId, 1));\n\n this._addSep();\n\n // Type-specific tools\n const type = block.type;\n const textTypes = ['paragraph', 'heading', 'heading-3', 'heading-4', 'quote', 'pullquote', 'list', 'ordered-list'];\n const htmlEditableTypes = [...textTypes, 'code', 'html'];\n\n if (textTypes.includes(type)) {\n // Block type selector\n const select = el('select', { className: 'fe-tb-select' });\n const options = [\n { value: 'paragraph', label: 'Paragraph' },\n { value: 'heading', label: 'Heading 2' },\n { value: 'heading-3', label: 'Heading 3' },\n { value: 'heading-4', label: 'Heading 4' },\n { value: 'quote', label: 'Quote' },\n { value: 'list', label: 'Bullet List' },\n { value: 'ordered-list', label: 'Numbered List' },\n { value: 'code', label: 'Code' },\n ];\n options.forEach((opt) => {\n const o = el('option', { value: opt.value }, [opt.label]);\n if (opt.value === type) o.selected = true;\n select.appendChild(o);\n });\n select.addEventListener('change', () => {\n const value = select.value;\n const blockNow = this.editor.blockManager.getBlock(blockId);\n if (!blockNow) return;\n\n const ensureParagraphContext = () => {\n if (blockNow.type !== 'paragraph') {\n this.editor.blockManager.changeBlockType(blockId, 'paragraph');\n this.editor.render();\n }\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.focus();\n return contentEl;\n };\n\n if (value === 'paragraph' || value === 'heading' || value === 'heading-3' || value === 'heading-4' || value === 'quote') {\n const contentEl = ensureParagraphContext();\n if (!contentEl) return;\n const tag = value === 'paragraph'\n ? 'P'\n : value === 'heading'\n ? 'H2'\n : value === 'heading-3'\n ? 'H3'\n : value === 'heading-4'\n ? 'H4'\n : 'BLOCKQUOTE';\n document.execCommand('formatBlock', false, tag);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (value === 'list' || value === 'ordered-list') {\n const contentEl = ensureParagraphContext();\n if (!contentEl) return;\n document.execCommand(value === 'list' ? 'insertUnorderedList' : 'insertOrderedList', false, null);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n this.editor.blockManager.changeBlockType(blockId, value);\n this.editor.render();\n this.editor.focusBlock(blockId);\n });\n this.el.appendChild(select);\n\n this._addSep();\n\n // Font size\n const fontSizeSelect = el('select', { className: 'fe-tb-select', title: 'Font size' });\n [\n { value: '', label: 'Size' },\n { value: '13', label: '13px' },\n { value: '16', label: '16px' },\n { value: '20', label: '20px' },\n { value: '28', label: '28px' },\n { value: '36', label: '36px' },\n ].forEach((opt) => {\n const o = el('option', { value: opt.value }, [opt.label]);\n fontSizeSelect.appendChild(o);\n });\n fontSizeSelect.addEventListener('change', () => {\n if (!fontSizeSelect.value) return;\n this._applyFontSize(fontSizeSelect.value);\n this._syncFontSizeSelect();\n });\n this.el.appendChild(fontSizeSelect);\n this._fontSizeSelect = fontSizeSelect;\n this._bindFontSizeTracking();\n this._syncFontSizeSelect();\n\n this._addSep();\n\n // Formatting\n this._addStatefulBtn('bold', icons.bold, 'Bold (Ctrl+B)', () => this._exec('bold'));\n this._addStatefulBtn('italic', icons.italic, 'Italic (Ctrl+I)', () => this._exec('italic'));\n this._addStatefulBtn('underline', icons.underline, 'Underline (Ctrl+U)', () => this._exec('underline'));\n this._addStatefulBtn('strikeThrough', icons.strikethrough, 'Strikethrough', () => this._exec('strikeThrough'));\n this._addBtn(icons.inlineCode, 'Inline Code', () => this._wrapInlineCode());\n this._addStatefulBtn('link', icons.link, 'Link (Ctrl+K)', () => this._showLinkPopover());\n\n this._addSep();\n\n // Alignment\n this._addBtn(icons.alignLeft, 'Align Left', () => this._exec('justifyLeft'));\n this._addBtn(icons.alignCenter, 'Align Center', () => this._exec('justifyCenter'));\n this._addBtn(icons.alignRight, 'Align Right', () => this._exec('justifyRight'));\n\n this._tableToolsSep = this._addSep();\n this._tableRowBtn = this._addTextBtn('+Row', 'Add table row', () => this._addTableRow());\n this._tableColBtn = this._addTextBtn('+Col', 'Add table column', () => this._addTableColumn());\n }\n\n if (htmlEditableTypes.includes(type)) {\n this._addSep();\n this._addBtn(\n icons.html,\n type === 'html' ? 'Switch to normal text mode' : 'Switch to HTML mode',\n () => this.editor.toggleBlockHtmlMode(getActiveBlockId()),\n type === 'html' ? 'active' : ''\n );\n }\n\n this._syncStatefulButtons();\n\n this._addSep();\n\n // Duplicate & Delete\n this._addBtn(icons.file, 'Duplicate', () => {\n const clone = this.editor.blockManager.duplicateBlock(getActiveBlockId());\n if (clone) this.editor.render();\n });\n this._addBtn(icons.trash, 'Delete', () => {\n const activeId = getActiveBlockId();\n const removed = this.editor.blockManager.removeBlock(activeId);\n if (removed) {\n this.editor.render();\n return;\n }\n\n // If only one block remains, make delete behave like \"clear block\".\n const blockToClear = this.editor.blockManager.getBlock(activeId);\n if (!blockToClear) return;\n blockToClear.type = 'paragraph';\n blockToClear.content = '';\n blockToClear.attrs = {};\n this.editor.render();\n this.editor.focusBlock(activeId);\n }, 'fe-tb-btn-danger');\n }\n\n hide() {\n if (this.el) this.el.classList.remove('fe-visible');\n this._hideLinkPopover();\n this._unbindFontSizeTracking();\n }\n\n /* ---- Private ---- */\n\n _addBtn(iconHTML, title, onClick, extraClass = '') {\n const btn = el('button', {\n className: `fe-tb-btn ${extraClass}`.trim(),\n type: 'button',\n innerHTML: iconHTML,\n title,\n });\n btn.addEventListener('mousedown', (e) => {\n // Preserve current editor selection for rich-text commands/popovers.\n e.preventDefault();\n e.stopPropagation();\n });\n if (onClick) btn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); onClick(); });\n this.el.appendChild(btn);\n return btn;\n }\n\n _addStatefulBtn(command, iconHTML, title, onClick) {\n const btn = this._addBtn(iconHTML, title, onClick);\n this._statefulButtons.push({ command, btn });\n return btn;\n }\n\n _addSep() {\n const sep = el('span', { className: 'fe-tb-sep' });\n this.el.appendChild(sep);\n return sep;\n }\n\n _addTextBtn(label, title, onClick) {\n const btn = el('button', {\n className: 'fe-tb-text-btn',\n type: 'button',\n title,\n innerHTML: label,\n });\n btn.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick();\n });\n this.el.appendChild(btn);\n return btn;\n }\n\n _exec(cmd) {\n document.execCommand(cmd, false, null);\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n }\n\n _wrapInlineCode() {\n const sel = window.getSelection();\n if (!sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n const code = document.createElement('code');\n code.className = 'fe-inline-code';\n range.surroundContents(code);\n this.editor._syncCurrentBlockContent();\n }\n\n _applyFontSize(px) {\n const size = Number(px);\n if (!Number.isFinite(size)) return;\n\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n\n if (range.collapsed) {\n // Apply style for text typed from the current caret onward only.\n const marker = document.createElement('span');\n marker.style.fontSize = `${size}px`;\n marker.appendChild(document.createTextNode('\\u200B'));\n range.insertNode(marker);\n\n const nextRange = document.createRange();\n nextRange.setStart(marker.firstChild, 1);\n nextRange.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nextRange);\n\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n const span = document.createElement('span');\n span.style.fontSize = `${size}px`;\n span.appendChild(range.extractContents());\n range.insertNode(span);\n\n const nextRange = document.createRange();\n nextRange.selectNodeContents(span);\n sel.removeAllRanges();\n sel.addRange(nextRange);\n this.editor._syncCurrentBlockContent();\n }\n\n _bindFontSizeTracking() {\n if (!this._fontSizeSelect || this._onSelectionChange) return;\n this._onSelectionChange = () => {\n this._syncFontSizeSelect();\n this._syncStatefulButtons();\n };\n document.addEventListener('selectionchange', this._onSelectionChange);\n }\n\n _unbindFontSizeTracking() {\n if (!this._onSelectionChange) return;\n document.removeEventListener('selectionchange', this._onSelectionChange);\n this._onSelectionChange = null;\n }\n\n _syncFontSizeSelect() {\n if (!this._fontSizeSelect) return;\n const px = this._currentSelectionFontSizePx();\n if (!px) {\n this._fontSizeSelect.value = '';\n return;\n }\n const snapped = _closestFontSize(px, [13, 16, 20, 28, 36]);\n this._fontSizeSelect.value = String(snapped);\n }\n\n _currentSelectionFontSizePx() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const node = sel.focusNode;\n if (!node) return null;\n const elNode = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n if (!elNode) return null;\n const wrapper = this.editor._getSelectedBlockEl();\n if (!wrapper || !wrapper.contains(elNode)) return null;\n const raw = window.getComputedStyle(elNode).fontSize;\n const px = Number.parseFloat(raw || '');\n return Number.isFinite(px) ? px : null;\n }\n\n _createLinkPopover() {\n const pop = el('div', { className: 'fe-link-popover' });\n const input = el('input', { type: 'text', placeholder: 'Paste URL or search...', className: 'fe-link-input' });\n const applyBtn = el('button', {\n className: 'fe-btn fe-btn-primary fe-btn-sm',\n innerHTML: 'Apply',\n });\n const removeBtn = el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: 'Remove',\n });\n\n applyBtn.addEventListener('click', () => {\n this._restoreSavedLinkRange();\n if (input.value) {\n document.execCommand('createLink', false, input.value);\n // Style links\n const wrapper = this.editor._getSelectedBlockEl();\n if (wrapper) {\n wrapper.querySelectorAll('a').forEach((a) => {\n a.classList.add('fe-link');\n a.target = '_blank';\n a.rel = 'noopener';\n });\n }\n }\n this._hideLinkPopover();\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n });\n\n removeBtn.addEventListener('click', () => {\n this._restoreSavedLinkRange();\n document.execCommand('unlink', false, null);\n this._hideLinkPopover();\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') { e.preventDefault(); applyBtn.click(); }\n if (e.key === 'Escape') this._hideLinkPopover();\n });\n\n pop.appendChild(input);\n pop.appendChild(applyBtn);\n pop.appendChild(removeBtn);\n return pop;\n }\n\n _showLinkPopover() {\n const sel = window.getSelection();\n if (!sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n this._savedLinkRange = range.cloneRange();\n const rect = range.getBoundingClientRect();\n const wrapper = this.el.parentElement;\n if (!wrapper) return;\n\n if (!this._linkPopover.parentElement) {\n wrapper.appendChild(this._linkPopover);\n }\n\n this._linkPopover.style.top = (rect.bottom - wrapper.getBoundingClientRect().top + 6) + 'px';\n this._linkPopover.style.left = '0px';\n this._linkPopover.classList.add('fe-open');\n\n // Pre-fill if there's an existing link\n const anchor = sel.anchorNode?.parentElement?.closest('a');\n const input = this._linkPopover.querySelector('input');\n input.value = anchor ? anchor.href : '';\n setTimeout(() => input.focus(), 10);\n }\n\n _hideLinkPopover() {\n if (this._linkPopover) this._linkPopover.classList.remove('fe-open');\n }\n\n _getCurrentTableContext() {\n const wrapper = this.editor._getSelectedBlockEl();\n if (!wrapper) return null;\n const contentEl = wrapper.querySelector('.fe-block-content');\n if (!contentEl) return null;\n\n const sel = window.getSelection();\n let cell = null;\n if (sel && sel.rangeCount > 0) {\n let node = sel.anchorNode;\n if (node && node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (node && typeof node.closest === 'function') {\n const maybeCell = node.closest('td,th');\n if (maybeCell && contentEl.contains(maybeCell)) cell = maybeCell;\n }\n }\n\n const table = cell ? cell.closest('table') : contentEl.querySelector('table');\n if (!table) return null;\n if (!cell) cell = table.querySelector('td,th');\n if (!cell) return null;\n return { table, cell };\n }\n\n _addTableRow() {\n const ctx = this._getCurrentTableContext();\n if (!ctx) return;\n const { table, cell } = ctx;\n const currentRow = cell.closest('tr');\n if (!currentRow) return;\n\n const rowCells = Array.from(currentRow.querySelectorAll('th,td'));\n const colCount = Math.max(1, rowCells.length);\n const newRow = document.createElement('tr');\n for (let i = 0; i < colCount; i++) {\n const td = document.createElement('td');\n td.innerHTML = '<br>';\n newRow.appendChild(td);\n }\n\n if (currentRow.nextSibling) currentRow.parentNode.insertBefore(newRow, currentRow.nextSibling);\n else currentRow.parentNode.appendChild(newRow);\n\n const range = document.createRange();\n range.selectNodeContents(newRow.querySelector('td'));\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n this.editor._syncCurrentBlockContent();\n }\n\n _addTableColumn() {\n const ctx = this._getCurrentTableContext();\n if (!ctx) return;\n const { table, cell } = ctx;\n const currentRow = cell.closest('tr');\n if (!currentRow) return;\n\n const idx = Array.from(currentRow.querySelectorAll('th,td')).indexOf(cell);\n if (idx < 0) return;\n\n const rows = Array.from(table.querySelectorAll('tr'));\n rows.forEach((row) => {\n const cells = Array.from(row.querySelectorAll('th,td'));\n const ref = cells[Math.min(idx, cells.length - 1)];\n const newCell = document.createElement(ref && ref.tagName.toLowerCase() === 'th' ? 'th' : 'td');\n newCell.innerHTML = '<br>';\n if (ref && ref.nextSibling) row.insertBefore(newCell, ref.nextSibling);\n else row.appendChild(newCell);\n });\n\n const targetRowCells = Array.from(currentRow.querySelectorAll('th,td'));\n const focusCell = targetRowCells[Math.min(idx + 1, targetRowCells.length - 1)];\n if (focusCell) {\n const range = document.createRange();\n range.selectNodeContents(focusCell);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n this.editor._syncCurrentBlockContent();\n }\n\n _restoreSavedLinkRange() {\n if (!this._savedLinkRange) return;\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedLinkRange);\n }\n\n _syncStatefulButtons() {\n const wrapper = this.editor._getSelectedBlockEl();\n const sel = window.getSelection();\n const anchor = sel?.anchorNode?.parentElement?.closest('a');\n const hasSelectionInEditor =\n wrapper &&\n sel &&\n sel.rangeCount > 0 &&\n wrapper.contains(sel.anchorNode);\n\n this._statefulButtons.forEach(({ command, btn }) => {\n let active = false;\n if (hasSelectionInEditor) {\n if (command === 'link') {\n active = Boolean(anchor && wrapper.contains(anchor));\n } else {\n try {\n active = document.queryCommandState(command);\n } catch {\n active = false;\n }\n }\n }\n btn.classList.toggle('active', Boolean(active));\n });\n\n const inTable = this._isSelectionInTable(wrapper);\n const tableDisplay = inTable ? '' : 'none';\n if (this._tableToolsSep) this._tableToolsSep.style.display = tableDisplay;\n if (this._tableRowBtn) this._tableRowBtn.style.display = tableDisplay;\n if (this._tableColBtn) this._tableColBtn.style.display = tableDisplay;\n }\n\n _isSelectionInTable(wrapper) {\n if (!wrapper) return false;\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let node = sel.anchorNode;\n if (!node) return false;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || typeof node.closest !== 'function') return false;\n const table = node.closest('table');\n return Boolean(table && wrapper.contains(table));\n }\n}\n\nfunction _closestFontSize(value, sizes) {\n let best = sizes[0];\n let bestDelta = Math.abs(value - best);\n for (let i = 1; i < sizes.length; i++) {\n const delta = Math.abs(value - sizes[i]);\n if (delta < bestDelta) {\n best = sizes[i];\n bestDelta = delta;\n }\n }\n return best;\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\nimport { CATEGORIES, getBlocksByCategory, searchBlocks } from '../blocks/registry.js';\n\n/**\n * Side panel for browsing and inserting block types.\n */\nexport class InserterPanel {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._searchInput = null;\n this._listEl = null;\n this._anchorEl = null;\n this._onDocMouseDown = null;\n this._onDocKeyDown = null;\n this._savedRange = null;\n this._mediaModal = null;\n this._mediaModalCard = null;\n this._mediaModalTitle = null;\n this._mediaModalBody = null;\n this._mediaModalResolver = null;\n this._forceNewBlock = false;\n }\n\n create() {\n this.el = el('div', { className: 'fe-inserter-panel' });\n\n // Header\n const header = el('div', { className: 'fe-inserter-header' });\n header.appendChild(el('h3', {}, ['Blocks']));\n const closeBtn = el('button', {\n className: 'fe-icon-btn fe-icon-btn-sm',\n innerHTML: icons.close,\n onClick: () => this.close(),\n });\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n // Search\n this._searchInput = el('input', {\n type: 'text',\n className: 'fe-inserter-search',\n placeholder: 'Search blocks...',\n });\n this._searchInput.addEventListener('input', () => this._renderList());\n this.el.appendChild(this._searchInput);\n\n // List\n this._listEl = el('div', { className: 'fe-inserter-list' });\n this.el.appendChild(this._listEl);\n\n this._renderList();\n this._createMediaModal();\n return this.el;\n }\n\n open(anchorEl = null, options = {}) {\n this._anchorEl = anchorEl || this._anchorEl;\n this._forceNewBlock = Boolean(options.forceNewBlock);\n this._savedRange = this._captureSelectionRange();\n this._positionNearAnchor();\n this.el.classList.add('fe-open');\n this._searchInput.value = '';\n this._renderList();\n this._bindGlobalCloseHandlers();\n setTimeout(() => this._searchInput.focus(), 20);\n }\n\n close() {\n this.el.classList.remove('fe-open');\n this._forceNewBlock = false;\n this._unbindGlobalCloseHandlers();\n }\n\n toggle(anchorEl = null, options = {}) {\n if (anchorEl) this._anchorEl = anchorEl;\n this.el.classList.contains('fe-open') ? this.close() : this.open(anchorEl, options);\n }\n\n isOpen() {\n return this.el.classList.contains('fe-open');\n }\n\n _renderList() {\n this._listEl.innerHTML = '';\n const query = this._searchInput?.value?.trim() || '';\n\n if (query) {\n const results = searchBlocks(query);\n if (results.length === 0) {\n this._listEl.appendChild(el('p', { className: 'fe-inserter-empty' }, ['No blocks found.']));\n return;\n }\n results.forEach((block) => this._listEl.appendChild(this._createBlockItem(block)));\n } else {\n for (const cat of CATEGORIES) {\n const blocks = getBlocksByCategory(cat.id);\n if (blocks.length === 0) continue;\n this._listEl.appendChild(el('div', { className: 'fe-inserter-category' }, [cat.label]));\n blocks.forEach((block) => this._listEl.appendChild(this._createBlockItem(block)));\n }\n }\n }\n\n _createBlockItem(blockDef) {\n const item = el('div', { className: 'fe-inserter-item' });\n item.appendChild(el('div', { className: 'fe-inserter-item-icon', innerHTML: blockDef.icon }));\n const info = el('div', { className: 'fe-inserter-item-info' });\n info.appendChild(el('h4', {}, [blockDef.label]));\n info.appendChild(el('p', {}, [blockDef.description]));\n item.appendChild(info);\n\n item.addEventListener('click', () => {\n this._insertFromPopover(blockDef.type);\n this.close();\n });\n\n return item;\n }\n\n _positionNearAnchor() {\n if (!this.el || !this._anchorEl) return;\n const rect = this._anchorEl.getBoundingClientRect();\n const gap = 8;\n const desiredLeft = Math.max(8, Math.min(window.innerWidth - 368, rect.left));\n const desiredTop = Math.max(8, Math.min(window.innerHeight - 520, rect.bottom + gap));\n this.el.style.left = `${desiredLeft}px`;\n this.el.style.top = `${desiredTop}px`;\n }\n\n _bindGlobalCloseHandlers() {\n this._onDocMouseDown = (e) => {\n if (!this.el?.classList.contains('fe-open')) return;\n if (this.el.contains(e.target)) return;\n if (this._anchorEl && this._anchorEl.contains(e.target)) return;\n this.close();\n };\n this._onDocKeyDown = (e) => {\n if (e.key === 'Escape') this.close();\n };\n document.addEventListener('mousedown', this._onDocMouseDown);\n document.addEventListener('keydown', this._onDocKeyDown);\n window.addEventListener('resize', () => this._positionNearAnchor(), { once: true });\n }\n\n _unbindGlobalCloseHandlers() {\n if (this._onDocMouseDown) {\n document.removeEventListener('mousedown', this._onDocMouseDown);\n this._onDocMouseDown = null;\n }\n if (this._onDocKeyDown) {\n document.removeEventListener('keydown', this._onDocKeyDown);\n this._onDocKeyDown = null;\n }\n }\n\n _captureSelectionRange() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n const container = range.commonAncestorContainer;\n if (!this.editor.rootEl.contains(container)) return null;\n return range.cloneRange();\n }\n\n _restoreSelectionRange() {\n if (!this._savedRange) return false;\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange);\n return true;\n }\n\n async _insertFromPopover(type) {\n if (this._forceNewBlock) {\n const selectedId = this.editor._selectedBlockId;\n const block = this.editor.blockManager.addBlock(type, {}, selectedId || null);\n this.editor.render();\n this.editor.focusBlock(block.id);\n return;\n }\n\n const selectedId = this.editor._selectedBlockId;\n const selectedBlock = selectedId ? this.editor.blockManager.getBlock(selectedId) : null;\n const canInline =\n selectedBlock &&\n selectedBlock.type !== 'code' &&\n selectedBlock.type !== 'html' &&\n selectedBlock.type !== 'image' &&\n selectedBlock.type !== 'gallery' &&\n selectedBlock.type !== 'video' &&\n selectedBlock.type !== 'audio' &&\n selectedBlock.type !== 'file';\n\n if (!canInline) {\n if (!this.editor.insertSingleBlockType(type)) {\n this.editor.insertBlockAtSelection(type);\n }\n return;\n }\n\n this._restoreSelectionRange();\n const contentEl = this.editor._getBlockContentEl(selectedId);\n if (contentEl) contentEl.focus();\n\n if (type === 'paragraph' || type === 'heading' || type === 'heading-3' || type === 'heading-4' || type === 'quote') {\n const tag = type === 'paragraph'\n ? 'P'\n : type === 'heading'\n ? 'H2'\n : type === 'heading-3'\n ? 'H3'\n : type === 'heading-4'\n ? 'H4'\n : 'BLOCKQUOTE';\n document.execCommand('formatBlock', false, tag);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'list' || type === 'ordered-list') {\n document.execCommand(type === 'list' ? 'insertUnorderedList' : 'insertOrderedList', false, null);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'image') {\n const files = await this.editor.mediaUploader.openFilePicker('image/*');\n if (!files.length) return;\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) {\n const src = result.remoteUrl || result.localUrl;\n document.execCommand('insertHTML', false, `<img src=\"${src}\" alt=\"\" />`);\n this.editor._syncCurrentBlockContent();\n }\n return;\n }\n\n if (type === 'video' || type === 'audio') {\n const source = await this._chooseMediaSource(type);\n if (!source) return;\n\n if (source === 'url') {\n const url = await this._promptForMediaUrl(type);\n if (!url) return;\n const trimmed = url.trim();\n if (!trimmed) return;\n if (type === 'video') {\n document.execCommand('insertHTML', false, `<video controls style=\"width:100%;max-width:100%;\" src=\"${trimmed}\"></video><p><br></p>`);\n } else {\n document.execCommand('insertHTML', false, `<audio controls style=\"width:100%;\" src=\"${trimmed}\"></audio><p><br></p>`);\n }\n this.editor._syncCurrentBlockContent();\n return;\n }\n }\n\n if (type === 'video' || type === 'audio' || type === 'file') {\n const accept = type === 'video' ? 'video/*' : type === 'audio' ? 'audio/*' : '*/*';\n const files = await this.editor.mediaUploader.openFilePicker(accept);\n if (!files.length) return;\n const file = files[0];\n const result = await this.editor.mediaUploader.processFile(file);\n if (result.error) {\n if (typeof this.editor._showToast === 'function') this.editor._showToast(result.error);\n return;\n }\n const src = result.remoteUrl || result.localUrl;\n if (!src) return;\n\n if (type === 'video') {\n document.execCommand('insertHTML', false, `<video controls style=\"width:100%;max-width:100%;\" src=\"${src}\"></video><p><br></p>`);\n } else if (type === 'audio') {\n document.execCommand('insertHTML', false, `<audio controls style=\"width:100%;\" src=\"${src}\"></audio><p><br></p>`);\n } else {\n document.execCommand('insertHTML', false, `<p><a href=\"${src}\" target=\"_blank\" rel=\"noopener\">${file.name || 'Download file'}</a></p><p><br></p>`);\n }\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'embed') {\n const url = window.prompt('Paste embed URL');\n if (!url) return;\n const trimmed = url.trim();\n if (!trimmed) return;\n document.execCommand('insertHTML', false, `<p><a href=\"${trimmed}\" target=\"_blank\" rel=\"noopener\">${trimmed}</a></p><p><br></p>`);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (!this.editor.insertSingleBlockType(type)) {\n this.editor.insertBlockAtSelection(type);\n }\n }\n\n async _chooseMediaSource(type) {\n if (typeof this.editor.options.onChooseMediaSource === 'function') {\n const selected = await this.editor.options.onChooseMediaSource(type);\n if (selected === 'url' || selected === 'upload') return selected;\n }\n return this._openMediaSourceModal(type);\n }\n\n _createMediaModal() {\n const overlay = el('div', { className: 'fe-media-modal-overlay' });\n const card = el('div', { className: 'fe-media-modal-card' });\n const title = el('h3', { className: 'fe-media-modal-title' }, ['Insert media']);\n const body = el('div', { className: 'fe-media-modal-body' });\n\n card.appendChild(title);\n card.appendChild(body);\n overlay.appendChild(card);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this._closeMediaModal(null);\n });\n\n this.editor.rootEl.appendChild(overlay);\n this._mediaModal = overlay;\n this._mediaModalCard = card;\n this._mediaModalTitle = title;\n this._mediaModalBody = body;\n }\n\n _openMediaSourceModal(type) {\n return new Promise((resolve) => {\n this._mediaModalResolver = resolve;\n this._mediaModalTitle.textContent = `Insert ${type}`;\n this._mediaModalBody.innerHTML = '';\n\n const desc = el('p', { className: 'fe-media-modal-desc' }, ['Choose how you want to add media']);\n const actions = el('div', { className: 'fe-media-modal-actions' });\n const uploadBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n type: 'button',\n innerHTML: 'Upload File',\n onClick: () => this._closeMediaModal('upload'),\n });\n const urlBtn = el('button', {\n className: 'fe-btn fe-btn-outline',\n type: 'button',\n innerHTML: 'Use URL',\n onClick: () => this._closeMediaModal('url'),\n });\n const cancelBtn = el('button', {\n className: 'fe-btn',\n type: 'button',\n innerHTML: 'Cancel',\n onClick: () => this._closeMediaModal(null),\n });\n actions.appendChild(uploadBtn);\n actions.appendChild(urlBtn);\n actions.appendChild(cancelBtn);\n this._mediaModalBody.appendChild(desc);\n this._mediaModalBody.appendChild(actions);\n\n this._mediaModal.classList.add('fe-open');\n });\n }\n\n _promptForMediaUrl(type) {\n return new Promise((resolve) => {\n this._mediaModalResolver = resolve;\n this._mediaModalTitle.textContent = `${type} URL`;\n this._mediaModalBody.innerHTML = '';\n\n const desc = el('p', { className: 'fe-media-modal-desc' }, ['Paste a direct media URL']);\n const input = el('input', {\n type: 'url',\n className: 'fe-media-modal-input',\n placeholder: `https://example.com/${type}.mp4`,\n });\n const actions = el('div', { className: 'fe-media-modal-actions' });\n const applyBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n type: 'button',\n innerHTML: 'Insert',\n onClick: () => this._closeMediaModal(input.value || null),\n });\n const cancelBtn = el('button', {\n className: 'fe-btn',\n type: 'button',\n innerHTML: 'Cancel',\n onClick: () => this._closeMediaModal(null),\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this._closeMediaModal(input.value || null);\n }\n if (e.key === 'Escape') this._closeMediaModal(null);\n });\n\n actions.appendChild(applyBtn);\n actions.appendChild(cancelBtn);\n this._mediaModalBody.appendChild(desc);\n this._mediaModalBody.appendChild(input);\n this._mediaModalBody.appendChild(actions);\n this._mediaModal.classList.add('fe-open');\n setTimeout(() => input.focus(), 0);\n });\n }\n\n _closeMediaModal(value) {\n if (!this._mediaModal) return;\n this._mediaModal.classList.remove('fe-open');\n const resolver = this._mediaModalResolver;\n this._mediaModalResolver = null;\n if (resolver) resolver(value);\n }\n}\n","import { el } from '../utils/dom.js';\n\n/**\n * Right-hand settings panel with Post and Block tabs.\n */\nexport class SettingsPanel {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._activeTab = 'post';\n this._postTab = null;\n this._blockTab = null;\n this._tagInput = null;\n this._tags = [];\n this._categories = ['Uncategorized', 'Technology', 'Design', 'Business', 'Lifestyle'];\n this._featuredImage = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-settings-panel' });\n\n // Tabs\n const tabs = el('div', { className: 'fe-panel-tabs' });\n this._postTabBtn = el('button', { className: 'fe-panel-tab fe-active' }, ['Post']);\n this._blockTabBtn = el('button', { className: 'fe-panel-tab' }, ['Block']);\n this._postTabBtn.addEventListener('click', () => this._switchTab('post'));\n this._blockTabBtn.addEventListener('click', () => this._switchTab('block'));\n tabs.appendChild(this._postTabBtn);\n tabs.appendChild(this._blockTabBtn);\n this.el.appendChild(tabs);\n\n // Post tab content\n this._postTab = el('div', { className: 'fe-tab-content' });\n this._buildPostTab();\n this.el.appendChild(this._postTab);\n\n // Block tab content\n this._blockTab = el('div', { className: 'fe-tab-content', style: { display: 'none' } });\n this._buildBlockTab();\n this.el.appendChild(this._blockTab);\n\n return this.el;\n }\n\n open() { this.el.classList.add('fe-open'); }\n close() { this.el.classList.remove('fe-open'); }\n toggle() { this.el.classList.contains('fe-open') ? this.close() : this.open(); }\n isOpen() { return this.el.classList.contains('fe-open'); }\n\n updateBlockSettings(blockId) {\n this._blockSettingsContent.innerHTML = '';\n const block = this.editor.blockManager.getBlock(blockId);\n if (!block) {\n this._blockSettingsContent.innerHTML = '<p class=\"fe-muted fe-text-center\">Select a block to see its settings.</p>';\n return;\n }\n\n // Typography\n const section = el('div', { className: 'fe-panel-section' });\n section.appendChild(el('h3', { className: 'fe-section-title' }, ['Typography']));\n\n // Font size\n section.appendChild(el('label', {}, ['Font size']));\n const fontSelect = el('select', { className: 'fe-input' });\n [{ v: '', l: 'Default' }, { v: '13px', l: 'Small' }, { v: '16px', l: 'Medium' }, { v: '20px', l: 'Large' }, { v: '28px', l: 'Extra Large' }, { v: '36px', l: 'Huge' }]\n .forEach(({ v, l }) => fontSelect.appendChild(el('option', { value: v }, [l])));\n fontSelect.addEventListener('change', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.fontSize = fontSelect.value;\n });\n section.appendChild(fontSelect);\n\n // Line height\n section.appendChild(el('label', {}, ['Line height']));\n const lhInput = el('input', { type: 'text', className: 'fe-input', placeholder: '1.7' });\n lhInput.addEventListener('change', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl && lhInput.value) contentEl.style.lineHeight = lhInput.value;\n });\n section.appendChild(lhInput);\n\n this._blockSettingsContent.appendChild(section);\n\n // Color\n const colorSection = el('div', { className: 'fe-panel-section' });\n colorSection.appendChild(el('h3', { className: 'fe-section-title' }, ['Color']));\n\n // Text colors\n colorSection.appendChild(el('label', {}, ['Text color']));\n const textColors = el('div', { className: 'fe-color-grid' });\n ['#1e1e1e', '#cf2e2e', '#ff6900', '#fcb900', '#7bdcb5', '#00d084', '#0693e3', '#9b51e0'].forEach((c) => {\n const swatch = el('div', { className: 'fe-color-swatch', style: { background: c } });\n swatch.addEventListener('click', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.color = c;\n });\n textColors.appendChild(swatch);\n });\n colorSection.appendChild(textColors);\n\n // BG colors\n colorSection.appendChild(el('label', {}, ['Background color']));\n const bgColors = el('div', { className: 'fe-color-grid' });\n ['transparent', '#fcf0f0', '#fef8ee', '#fefce8', '#edf7f2', '#eef6fc', '#f3eafa', '#f0f0f1'].forEach((c) => {\n const swatch = el('div', { className: 'fe-color-swatch', style: { background: c === 'transparent' ? '#fff' : c, border: c === 'transparent' ? '2px solid #ddd' : 'none' } });\n swatch.addEventListener('click', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.background = c;\n });\n bgColors.appendChild(swatch);\n });\n colorSection.appendChild(bgColors);\n\n this._blockSettingsContent.appendChild(colorSection);\n }\n\n _switchTab(tab) {\n this._activeTab = tab;\n this._postTabBtn.classList.toggle('fe-active', tab === 'post');\n this._blockTabBtn.classList.toggle('fe-active', tab === 'block');\n this._postTab.style.display = tab === 'post' ? 'block' : 'none';\n this._blockTab.style.display = tab === 'block' ? 'block' : 'none';\n }\n\n _buildPostTab() {\n // Summary\n const summary = this._section('Summary');\n summary.appendChild(this._field('Visibility', 'select', ['Public', 'Private', 'Password Protected']));\n summary.appendChild(this._field('Publish', 'select', ['Immediately', 'Schedule']));\n summary.appendChild(this._field('URL Slug', 'text', null, 'fe-url-slug'));\n summary.appendChild(this._field('Author', 'select', ['Admin', 'Editor', 'Author']));\n this._postTab.appendChild(summary);\n\n // Categories\n const cats = this._section('Categories');\n const catList = el('div', { className: 'fe-category-list' });\n this._categories.forEach((cat) => {\n const label = el('label', { className: 'fe-checkbox-label' });\n label.appendChild(el('input', { type: 'checkbox' }));\n label.appendChild(document.createTextNode(' ' + cat));\n catList.appendChild(label);\n });\n cats.appendChild(catList);\n const addCat = el('a', { href: '#', className: 'fe-add-link' }, ['+ Add New Category']);\n addCat.addEventListener('click', (e) => {\n e.preventDefault();\n const name = prompt('Category name:');\n if (name) {\n this._categories.push(name);\n const label = el('label', { className: 'fe-checkbox-label' });\n label.appendChild(el('input', { type: 'checkbox', checked: true }));\n label.appendChild(document.createTextNode(' ' + name));\n catList.appendChild(label);\n }\n });\n cats.appendChild(addCat);\n this._postTab.appendChild(cats);\n\n // Tags\n const tags = this._section('Tags');\n const tagWrapper = el('div', { className: 'fe-tag-input-wrapper' });\n const tagInput = el('input', { type: 'text', placeholder: 'Add tag...' });\n tagInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ',') {\n e.preventDefault();\n const val = tagInput.value.replace(',', '').trim();\n if (!val) return;\n this._tags.push(val);\n const tag = el('span', { className: 'fe-tag' });\n tag.appendChild(document.createTextNode(val + ' '));\n const remove = el('span', { className: 'fe-tag-remove', innerHTML: '&times;' });\n remove.addEventListener('click', () => {\n this._tags = this._tags.filter((t) => t !== val);\n tag.remove();\n });\n tag.appendChild(remove);\n tagWrapper.insertBefore(tag, tagInput);\n tagInput.value = '';\n }\n });\n tagWrapper.appendChild(tagInput);\n tagWrapper.addEventListener('click', () => tagInput.focus());\n tags.appendChild(tagWrapper);\n tags.appendChild(el('p', { className: 'fe-hint' }, ['Separate with commas or Enter key']));\n this._postTab.appendChild(tags);\n\n // Featured Image\n const fi = this._section('Featured Image');\n const fiArea = el('div', { className: 'fe-featured-image-area' });\n fiArea.appendChild(el('p', {}, ['Set featured image']));\n const fiInput = el('input', { type: 'file', accept: 'image/*', style: { display: 'none' } });\n fiInput.addEventListener('change', (e) => {\n const file = e.target.files[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (ev) => {\n fiArea.innerHTML = '';\n const img = el('img', { src: ev.target.result });\n img.style.maxWidth = '100%';\n img.style.borderRadius = '4px';\n fiArea.appendChild(img);\n this._featuredImage = ev.target.result;\n this.editor.emit('featuredImage:change', this._featuredImage);\n };\n reader.readAsDataURL(file);\n });\n fiArea.addEventListener('click', () => fiInput.click());\n fi.appendChild(fiArea);\n fi.appendChild(fiInput);\n this._postTab.appendChild(fi);\n\n // Excerpt\n const exc = this._section('Excerpt');\n exc.appendChild(el('textarea', { className: 'fe-input fe-textarea', placeholder: 'Write an excerpt (optional)' }));\n this._postTab.appendChild(exc);\n\n // Discussion\n const disc = this._section('Discussion');\n disc.appendChild(this._toggle('Allow comments', true));\n disc.appendChild(this._toggle('Allow pingbacks', false));\n this._postTab.appendChild(disc);\n }\n\n _buildBlockTab() {\n const section = el('div', { className: 'fe-panel-section' });\n section.appendChild(el('h3', { className: 'fe-section-title' }, ['Block Settings']));\n this._blockSettingsContent = el('div');\n this._blockSettingsContent.innerHTML = '<p class=\"fe-muted fe-text-center\">Select a block to see its settings.</p>';\n section.appendChild(this._blockSettingsContent);\n this._blockTab.appendChild(section);\n }\n\n _section(title) {\n const s = el('div', { className: 'fe-panel-section' });\n s.appendChild(el('h3', { className: 'fe-section-title' }, [title]));\n return s;\n }\n\n _field(label, type, options, id) {\n const frag = document.createDocumentFragment();\n frag.appendChild(el('label', {}, [label]));\n if (type === 'select') {\n const select = el('select', { className: 'fe-input' });\n if (id) select.id = id;\n (options || []).forEach((o) => select.appendChild(el('option', {}, [o])));\n frag.appendChild(select);\n } else {\n const input = el('input', { type, className: 'fe-input', placeholder: label.toLowerCase() });\n if (id) input.id = id;\n frag.appendChild(input);\n }\n return frag;\n }\n\n _toggle(label, defaultOn) {\n const row = el('div', { className: 'fe-toggle-row' });\n row.appendChild(el('label', {}, [label]));\n const btn = el('button', { className: `fe-toggle-switch ${defaultOn ? 'fe-on' : ''}` });\n btn.addEventListener('click', () => btn.classList.toggle('fe-on'));\n row.appendChild(btn);\n return row;\n }\n}\n","import { el } from '../utils/dom.js';\nimport { searchBlocks, BLOCK_TYPES } from '../blocks/registry.js';\n\n/**\n * Inline slash-command menu that appears when user types \"/\".\n */\nexport class SlashMenu {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._visible = false;\n this._highlightIndex = 0;\n this._items = [];\n this._targetBlock = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-slash-menu' });\n this._boundDocClick = (e) => {\n if (!e.target.closest('.fe-slash-menu')) this.close();\n };\n document.addEventListener('click', this._boundDocClick);\n return this.el;\n }\n\n /** Remove global listeners. Called by editor.destroy(). */\n destroy() {\n if (this._boundDocClick) {\n document.removeEventListener('click', this._boundDocClick);\n this._boundDocClick = null;\n }\n }\n\n open(block, rect) {\n this._targetBlock = block;\n this._visible = true;\n this._highlightIndex = 0;\n this.el.classList.add('fe-open');\n\n // Position near the caret\n const editorRect = this.editor.el.getBoundingClientRect();\n this.el.style.top = (rect.bottom - editorRect.top + 4) + 'px';\n this.el.style.left = (rect.left - editorRect.left) + 'px';\n\n this._filter('');\n }\n\n close() {\n this._visible = false;\n this._targetBlock = null;\n this.el.classList.remove('fe-open');\n }\n\n isOpen() {\n return this._visible;\n }\n\n filter(query) {\n this._filter(query);\n }\n\n handleKeydown(e) {\n if (!this._visible) return false;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._navigate(1);\n return true;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n this._navigate(-1);\n return true;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n const visible = this._items.filter((i) => i.el.style.display !== 'none');\n if (visible[this._highlightIndex]) {\n this._selectItem(visible[this._highlightIndex].type);\n }\n return true;\n }\n if (e.key === 'Escape') {\n this.close();\n return true;\n }\n return false;\n }\n\n _filter(query) {\n this.el.innerHTML = '';\n this._items = [];\n\n const allBlocks = query ? searchBlocks(query) : Object.entries(BLOCK_TYPES).map(([type, def]) => ({ type, ...def }));\n\n allBlocks.forEach((blockDef, i) => {\n const item = el('div', { className: `fe-slash-item ${i === 0 ? 'fe-highlighted' : ''}` });\n item.appendChild(el('div', { className: 'fe-slash-icon', innerHTML: blockDef.icon }));\n const info = el('div', { className: 'fe-slash-info' });\n info.appendChild(el('div', { className: 'fe-slash-label' }, [blockDef.label]));\n info.appendChild(el('div', { className: 'fe-slash-desc' }, [blockDef.description]));\n item.appendChild(info);\n\n item.addEventListener('click', () => this._selectItem(blockDef.type));\n item.addEventListener('mouseenter', () => {\n this.el.querySelectorAll('.fe-slash-item').forEach((el) => el.classList.remove('fe-highlighted'));\n item.classList.add('fe-highlighted');\n });\n\n this.el.appendChild(item);\n this._items.push({ el: item, type: blockDef.type });\n });\n\n if (this._items.length === 0) {\n this.el.appendChild(el('div', { className: 'fe-slash-empty' }, ['No blocks found']));\n }\n\n this._highlightIndex = 0;\n }\n\n _navigate(dir) {\n const visible = this._items.filter((i) => i.el.style.display !== 'none');\n visible.forEach((i) => i.el.classList.remove('fe-highlighted'));\n this._highlightIndex = Math.max(0, Math.min(visible.length - 1, this._highlightIndex + dir));\n if (visible[this._highlightIndex]) {\n visible[this._highlightIndex].el.classList.add('fe-highlighted');\n visible[this._highlightIndex].el.scrollIntoView({ block: 'nearest' });\n }\n }\n\n _selectItem(type) {\n if (!this._targetBlock) return;\n const block = this._targetBlock;\n const inserted = this.editor.insertSingleBlockType(type);\n if (inserted) {\n this.close();\n this.editor.render();\n this.editor.focusBlock(block.id);\n return;\n }\n\n // Change the block type and clear content\n this.editor.blockManager.changeBlockType(block.id, type);\n block.content = '';\n this.close();\n this.editor.render();\n this.editor.focusBlock(block.id);\n }\n}\n","import { el } from '../utils/dom.js';\n\n/**\n * Bottom status bar showing word count, character count, block count.\n */\nexport class StatusBar {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._wordEl = null;\n this._charEl = null;\n this._blockEl = null;\n this._savedEl = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-status-bar' });\n this._wordEl = el('span', {}, ['Words: 0']);\n this._charEl = el('span', {}, ['Characters: 0']);\n this._blockEl = el('span', {}, ['Blocks: 0']);\n this._savedEl = el('span', { className: 'fe-status-right' });\n\n this.el.appendChild(this._wordEl);\n this.el.appendChild(this._charEl);\n this.el.appendChild(this._blockEl);\n this.el.appendChild(this._savedEl);\n\n return this.el;\n }\n\n update() {\n const bm = this.editor.blockManager;\n const titleText = this.editor._titleEl ? this.editor._titleEl.value : '';\n const titleWords = titleText.trim().split(/\\s+/).filter((w) => w.length).length;\n const words = bm.getWordCount() + titleWords;\n const chars = bm.getCharCount() + titleText.replace(/\\s/g, '').length;\n\n this._wordEl.textContent = `Words: ${words}`;\n this._charEl.textContent = `Characters: ${chars}`;\n this._blockEl.textContent = `Blocks: ${bm.blocks.length}`;\n }\n\n setSaved(text) {\n this._savedEl.textContent = text;\n }\n}\n","import { EventEmitter } from './utils/EventEmitter.js';\nimport { el, placeCaretAtEnd, placeCaretAtStart, getCaretRect } from './utils/dom.js';\nimport { icons } from './utils/icons.js';\nimport { BlockManager } from './core/BlockManager.js';\nimport { MediaUploader } from './core/MediaUploader.js';\nimport { DragDrop } from './core/DragDrop.js';\nimport { BlockRenderer } from './blocks/BlockRenderer.js';\nimport { Header } from './ui/Header.js';\nimport { Toolbar } from './ui/Toolbar.js';\nimport { InserterPanel } from './ui/InserterPanel.js';\nimport { SettingsPanel } from './ui/SettingsPanel.js';\nimport { SlashMenu } from './ui/SlashMenu.js';\nimport { StatusBar } from './ui/StatusBar.js';\n\n/**\n * NBDEditor — Gutenberg-style block editor.\n *\n * Usage:\n * const editor = new NBDEditor('#app', { ... });\n */\nexport class NBDEditor extends EventEmitter {\n constructor(selector, options = {}) {\n super();\n\n this.options = {\n siteName: 'My Site',\n authorName: 'Admin',\n showStatusBar: true,\n showSettingsPanel: false,\n showHeaderActions: false,\n placeholder: 'Start writing...',\n autoSaveInterval: 30000,\n uploadHandler: null, // async (file) => { url, id }\n maxFileSize: 10 * 1024 * 1024,\n onChooseMediaSource: null, // async/sync (type: 'video'|'audio') => 'url' | 'upload'\n content: null, // initial HTML content\n onChange: null,\n onSave: null,\n onPublish: null,\n ...options,\n };\n\n // Root element\n this.rootEl = typeof selector === 'string' ? document.querySelector(selector) : selector;\n if (!this.rootEl) throw new Error(`NBDEditor: element \"${selector}\" not found.`);\n\n // Core modules\n this.blockManager = new BlockManager();\n this.mediaUploader = new MediaUploader({\n uploadHandler: this.options.uploadHandler,\n maxFileSize: this.options.maxFileSize,\n });\n\n // UI modules\n this.blockRenderer = new BlockRenderer(this);\n this.header = new Header(this);\n this.toolbar = new Toolbar(this);\n this.inserterPanel = new InserterPanel(this);\n this.settingsPanel = new SettingsPanel(this);\n this.slashMenu = new SlashMenu(this);\n this.statusBar = new StatusBar(this);\n\n // State\n this._selectedBlockId = null;\n this._titleEl = null;\n this._blocksContainer = null;\n this._autoSaveTimer = null;\n this.el = null;\n this._htmlEditorModal = null;\n this._htmlEditorTextarea = null;\n this._htmlEditorTitle = null;\n this._htmlEditorBlockId = null;\n\n // Bound handlers for cleanup\n this._boundGlobalKeydown = (e) => this._handleGlobalKeydown(e);\n\n this._init();\n }\n\n /* ===== Initialization ===== */\n\n _init() {\n this.rootEl.innerHTML = '';\n this.rootEl.className = 'fe-root';\n\n // Header\n this.rootEl.appendChild(this.header.create());\n\n // Inserter panel\n this.rootEl.appendChild(this.inserterPanel.create());\n\n // Main wrapper\n this.el = el('div', { className: 'fe-editor-main' });\n\n // Canvas\n const canvas = el('div', { className: 'fe-editor-canvas', id: 'fe-canvas' });\n const content = el('div', { className: 'fe-editor-content' });\n\n // Blocks container\n this._blocksContainer = el('div', { className: 'fe-blocks-container' });\n content.appendChild(this._blocksContainer);\n\n canvas.appendChild(content);\n this.el.appendChild(canvas);\n\n // Settings panel\n if (this.options.showSettingsPanel) {\n this.el.appendChild(this.settingsPanel.create());\n }\n\n this.rootEl.appendChild(this.el);\n\n // Slash menu (appended to editor main for positioning)\n this.el.appendChild(this.slashMenu.create());\n\n // Status bar\n if (this.options.showStatusBar) {\n this.rootEl.appendChild(this.statusBar.create());\n }\n\n // Toast element\n this._toast = el('div', { className: 'fe-toast' });\n this.rootEl.appendChild(this._toast);\n this._createHtmlEditorModal();\n\n // Load initial content or create first block\n if (typeof this.options.content === 'string') {\n this.blockManager.fromJSON([{\n id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\n type: 'paragraph',\n content: this.options.content,\n attrs: {},\n }]);\n } else if (this.options.content) {\n this.blockManager.fromJSON(this.options.content);\n } else {\n this.blockManager.addBlock('paragraph');\n }\n this._ensureAtLeastOneBlock();\n\n this.render();\n\n // Open settings panel by default\n if (this.options.showSettingsPanel) {\n this.settingsPanel.open();\n this._updateCanvasMargin();\n }\n\n // Keyboard shortcuts\n document.addEventListener('keydown', this._boundGlobalKeydown);\n\n // Auto-save\n if (this.options.autoSaveInterval > 0) {\n this._autoSaveTimer = setInterval(() => {\n this._syncAllBlockContent();\n this.statusBar.setSaved('Auto-saved: ' + new Date().toLocaleTimeString());\n this.emit('autosave', this.getData());\n }, this.options.autoSaveInterval);\n }\n\n // Listen for structural block changes (add, remove, move, type-change)\n this.blockManager.on('change', () => {\n const data = this.getData();\n if (this.options.onChange) this.options.onChange(data);\n this.emit('change', data);\n });\n\n // Drag & drop files onto the editor\n this._blocksContainer.addEventListener('dragover', (e) => e.preventDefault());\n this._blocksContainer.addEventListener('drop', async (e) => {\n if (e.dataTransfer.files.length > 0) {\n e.preventDefault();\n const results = await this.mediaUploader.handleDrop(e.dataTransfer);\n if (results) {\n const target =\n (this._selectedBlockId && this.blockManager.getBlock(this._selectedBlockId)) ||\n this.blockManager.blocks[0] ||\n this.blockManager.addBlock('paragraph');\n if (!target) return;\n const chunks = [];\n for (const res of results) {\n if (res.error) continue;\n const type = this.mediaUploader.getMediaType(res.file);\n const src = res.remoteUrl || res.localUrl;\n if (!src) continue;\n if (type === 'image') chunks.push(`<img src=\"${src}\" alt=\"\">`);\n else if (type === 'video') chunks.push(`<video controls src=\"${src}\"></video>`);\n else if (type === 'audio') chunks.push(`<audio controls src=\"${src}\"></audio>`);\n else if (type === 'file') chunks.push(`<a href=\"${src}\" target=\"_blank\" rel=\"noopener\">${res.file.name || 'Download file'}</a>`);\n }\n const toAppend = chunks.join('\\n');\n if (toAppend) target.content = `${target.content || ''}${target.content ? '\\n' : ''}${toAppend}`;\n this.render();\n this.focusBlock(target.id);\n }\n }\n });\n }\n\n /* ===== Rendering ===== */\n\n render() {\n this._ensureAtLeastOneBlock();\n this._blocksContainer.innerHTML = '';\n\n this.blockManager.blocks.forEach((block) => {\n const wrapper = el('section', {\n className: `fe-block-wrapper ${this._selectedBlockId === block.id ? 'fe-selected' : ''}`,\n dataset: { blockId: block.id },\n });\n\n // Toolbar (per-block, shown on selection)\n const tbContainer = el('div', { className: 'fe-block-toolbar-container' });\n if (this._selectedBlockId === block.id) {\n const tb = this.toolbar.create();\n this.toolbar.show(block.id);\n tb.scrollLeft = 0;\n tbContainer.appendChild(tb);\n requestAnimationFrame(() => this._positionBlockToolbar(tb, wrapper));\n }\n wrapper.appendChild(tbContainer);\n\n // Block content\n const rendered = this.blockRenderer.render(block);\n wrapper.appendChild(rendered);\n\n // Click to select\n wrapper.addEventListener('click', (e) => {\n const clickedContent = e.target.closest('.fe-block-content');\n const clickedEditable = e.target.closest('[contenteditable]');\n const clickedCell = e.target.closest('td,th');\n let clickedEditableIndex = -1;\n if (clickedEditable && wrapper.contains(clickedEditable)) {\n const editables = Array.from(wrapper.querySelectorAll('[contenteditable]'));\n clickedEditableIndex = editables.indexOf(clickedEditable);\n }\n let clickedCellPos = null;\n if (clickedCell) {\n const row = clickedCell.closest('tr');\n const table = clickedCell.closest('table');\n if (row && table) {\n const rows = Array.from(table.querySelectorAll('tr'));\n const rowIndex = rows.indexOf(row);\n const cols = Array.from(row.querySelectorAll('th,td'));\n const colIndex = cols.indexOf(clickedCell);\n if (rowIndex >= 0 && colIndex >= 0) clickedCellPos = { rowIndex, colIndex };\n }\n }\n if (!e.target.closest('.fe-block-toolbar') && !e.target.closest('.fe-link-popover')) {\n if (this._selectedBlockId === block.id && (clickedContent || clickedEditable || clickedCell)) {\n return;\n }\n const blockId = block.id;\n this.selectBlock(blockId);\n // selectBlock calls render() which destroys DOM; focus the NEW contenteditable\n setTimeout(() => {\n const contentEl = this._getBlockContentEl(blockId);\n if (contentEl) {\n contentEl.focus();\n if (clickedCellPos) {\n const rows = Array.from(contentEl.querySelectorAll('tr'));\n const row = rows[clickedCellPos.rowIndex];\n const cols = row ? Array.from(row.querySelectorAll('th,td')) : [];\n const nextCell = cols[clickedCellPos.colIndex] || cols[cols.length - 1] || null;\n if (nextCell) {\n const range = document.createRange();\n range.selectNodeContents(nextCell);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n }\n }\n if (clickedEditableIndex >= 0) {\n const newWrapper = this._blocksContainer.querySelector(`[data-block-id=\"${blockId}\"]`);\n const editables = newWrapper ? Array.from(newWrapper.querySelectorAll('[contenteditable]')) : [];\n const targetEditable = editables[clickedEditableIndex] || editables[0] || null;\n if (targetEditable) {\n targetEditable.focus();\n placeCaretAtEnd(targetEditable);\n return;\n }\n }\n if (!clickedContent) placeCaretAtEnd(contentEl);\n }\n }, 0);\n }\n });\n\n // Drag handle setup\n const dragHandle = wrapper.querySelector('.fe-tb-drag');\n if (dragHandle) {\n const dd = new DragDrop(this._blocksContainer);\n dd.initDrag(dragHandle, wrapper, block.id);\n dd.on('drop', ({ fromId, toId, position }) => {\n const fromIdx = this.blockManager.getIndex(fromId);\n let toIdx = this.blockManager.getIndex(toId);\n if (position === 'after') toIdx++;\n if (fromIdx < toIdx) toIdx--;\n const [moved] = this.blockManager.blocks.splice(fromIdx, 1);\n this.blockManager.blocks.splice(toIdx, 0, moved);\n this.blockManager.saveSnapshot();\n this.render();\n });\n }\n\n this._blocksContainer.appendChild(wrapper);\n });\n\n // Single global appender (outside blocks) to match WP-like flow.\n const appender = el('button', {\n type: 'button',\n className: 'fe-block-appender',\n 'aria-label': 'Add block',\n });\n const plusIcon = el('span', { className: 'fe-plus-icon', innerHTML: icons.plus });\n const label = el('span', {}, ['Add block']);\n appender.appendChild(plusIcon);\n appender.appendChild(label);\n appender.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const targetId = this._selectedBlockId || this.blockManager.blocks[this.blockManager.blocks.length - 1]?.id;\n if (targetId) this.selectBlock(targetId);\n this.inserterPanel.open(appender, { forceNewBlock: true });\n });\n this._blocksContainer.appendChild(appender);\n\n this.statusBar.update();\n }\n\n /* ===== Block Operations ===== */\n\n selectBlock(id) {\n if (this._selectedBlockId === id) {\n if (this.options.showSettingsPanel) {\n this.settingsPanel.updateBlockSettings(id);\n }\n return;\n }\n this._selectedBlockId = id;\n this.render();\n if (this.options.showSettingsPanel) {\n this.settingsPanel.updateBlockSettings(id);\n }\n this.emit('block:select', id);\n }\n\n focusBlock(id) {\n this.selectBlock(id);\n setTimeout(() => {\n const contentEl = this._getBlockContentEl(id);\n if (contentEl) {\n contentEl.focus();\n placeCaretAtEnd(contentEl);\n }\n }, 0);\n }\n\n insertBlockAtSelection(type, data = {}) {\n if (this.insertSingleBlockType(type, data)) {\n const block = this._getInsertionTargetBlock();\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n const selectedId = this._selectedBlockId;\n const block = this.blockManager.addBlock(type, data, selectedId || null);\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n\n insertBlockAtEnd(type, data = {}) {\n if (this.insertSingleBlockType(type, data)) {\n const block = this._getInsertionTargetBlock();\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n const block = this.blockManager.addBlock(type, data);\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n\n /* ===== Block Input Handling ===== */\n\n _onBlockInput(block, node) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (node.textContent || '')\n : node.innerHTML;\n this.statusBar.update();\n\n // Slash command detection\n const text = node.textContent;\n if (text === '/') {\n const rect = getCaretRect() || node.getBoundingClientRect();\n this.slashMenu.open(block, rect);\n } else if (text.startsWith('/') && text.length > 1) {\n if (this.slashMenu.isOpen()) {\n this.slashMenu.filter(text.slice(1).toLowerCase());\n }\n } else {\n if (this.slashMenu.isOpen()) this.slashMenu.close();\n }\n\n const data = this.getData();\n if (this.options.onChange) this.options.onChange(data);\n this.emit('change', data);\n this.emit('input', block);\n }\n\n _onBlockKeydown(e, block, node) {\n // Slash menu takes priority\n if (this.slashMenu.isOpen() && this.slashMenu.handleKeydown(e)) return;\n // Keep Enter behavior inside the same block.\n // New blocks are created explicitly via inserter/add controls.\n\n // Table navigation + row creation with Tab\n if (e.key === 'Tab') {\n const cell = this._getSelectionTableCell();\n if (cell) {\n e.preventDefault();\n this._handleTableTab(cell, e.shiftKey);\n this._syncCurrentBlockContent();\n return;\n }\n }\n\n // Arrow Up at start: focus previous block\n if (e.key === 'ArrowUp') {\n const sel = window.getSelection();\n if (sel.rangeCount) {\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n const nodeRect = node.getBoundingClientRect();\n if (rect.top <= nodeRect.top + 2) {\n const prev = this.blockManager.getPrevBlock(block.id);\n if (prev) {\n e.preventDefault();\n this.focusBlock(prev.id);\n }\n }\n }\n }\n\n // Arrow Down at end: focus next block\n if (e.key === 'ArrowDown') {\n const sel = window.getSelection();\n if (sel.rangeCount) {\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n const nodeRect = node.getBoundingClientRect();\n if (rect.bottom >= nodeRect.bottom - 2) {\n const next = this.blockManager.getNextBlock(block.id);\n if (next) {\n e.preventDefault();\n const contentEl = this._getBlockContentEl(next.id);\n if (contentEl) {\n contentEl.focus();\n placeCaretAtStart(contentEl);\n this.selectBlock(next.id);\n }\n }\n }\n }\n }\n\n // Tab in code block\n if (e.key === 'Tab' && (block.type === 'code' || block.type === 'html')) {\n e.preventDefault();\n document.execCommand('insertText', false, ' ');\n }\n }\n\n /* ===== Helpers ===== */\n\n _getBlockContentEl(blockId) {\n const wrapper = this._blocksContainer.querySelector(`[data-block-id=\"${blockId}\"]`);\n return wrapper?.querySelector('.fe-block-content') || wrapper?.querySelector('[contenteditable]');\n }\n\n _getSelectedBlockEl() {\n if (!this._selectedBlockId) return null;\n return this._blocksContainer.querySelector(`[data-block-id=\"${this._selectedBlockId}\"]`);\n }\n\n _syncCurrentBlockContent() {\n if (!this._selectedBlockId) return;\n const block = this.blockManager.getBlock(this._selectedBlockId);\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (block && contentEl) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (contentEl.textContent || '')\n : contentEl.innerHTML;\n }\n }\n\n _syncAllBlockContent() {\n this.blockManager.blocks.forEach((block) => {\n const contentEl = this._getBlockContentEl(block.id);\n if (contentEl) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (contentEl.textContent || '')\n : contentEl.innerHTML;\n }\n });\n }\n\n _generateSlug() {\n const slug = (this._titleEl?.value || '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n const slugEl = document.getElementById('fe-url-slug');\n if (slugEl) slugEl.value = slug;\n }\n\n _updateCanvasMargin() {\n if (!this.options.showSettingsPanel) return;\n const canvas = this.el.querySelector('.fe-editor-canvas');\n if (canvas) {\n canvas.classList.toggle('fe-panel-open', this.settingsPanel.isOpen());\n }\n }\n\n _createHtmlEditorModal() {\n const overlay = el('div', { className: 'fe-html-modal-overlay' });\n const modal = el('div', { className: 'fe-html-modal' });\n const header = el('div', { className: 'fe-html-modal-header' });\n const title = el('h3', { className: 'fe-html-modal-title' }, ['Edit as HTML']);\n const closeBtn = el('button', {\n type: 'button',\n className: 'fe-icon-btn fe-icon-btn-sm',\n innerHTML: icons.close,\n onClick: () => this._closeBlockHtmlEditor(),\n });\n header.appendChild(title);\n header.appendChild(closeBtn);\n\n const textarea = el('textarea', {\n className: 'fe-html-modal-textarea',\n spellcheck: 'false',\n placeholder: 'Edit block HTML...',\n });\n\n const actions = el('div', { className: 'fe-html-modal-actions' });\n const cancelBtn = el('button', {\n type: 'button',\n className: 'fe-btn fe-btn-outline',\n innerHTML: 'Cancel',\n onClick: () => this._closeBlockHtmlEditor(),\n });\n const applyBtn = el('button', {\n type: 'button',\n className: 'fe-btn fe-btn-primary',\n innerHTML: 'Apply HTML',\n onClick: () => this._applyBlockHtmlEditor(),\n });\n actions.appendChild(cancelBtn);\n actions.appendChild(applyBtn);\n\n modal.appendChild(header);\n modal.appendChild(textarea);\n modal.appendChild(actions);\n overlay.appendChild(modal);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this._closeBlockHtmlEditor();\n });\n textarea.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') this._closeBlockHtmlEditor();\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') this._applyBlockHtmlEditor();\n });\n\n this.rootEl.appendChild(overlay);\n this._htmlEditorModal = overlay;\n this._htmlEditorTextarea = textarea;\n this._htmlEditorTitle = title;\n }\n\n _parseBlockFromHTML(html, fallbackType = 'paragraph') {\n const raw = (html || '').trim();\n if (!raw) return { type: fallbackType, content: '', attrs: {} };\n if (typeof document === 'undefined') return { type: 'html', content: raw, attrs: {} };\n\n const wrap = document.createElement('div');\n wrap.innerHTML = raw;\n const first = wrap.firstElementChild;\n const onlyOneElement =\n wrap.childElementCount === 1 &&\n Array.from(wrap.childNodes).every((n) => n.nodeType === Node.ELEMENT_NODE || n.textContent.trim() === '');\n\n if (!first || !onlyOneElement) {\n return { type: 'html', content: raw, attrs: {} };\n }\n\n const tag = first.tagName.toLowerCase();\n if (tag === 'p') return { type: 'paragraph', content: first.innerHTML, attrs: {} };\n if (tag === 'h2') return { type: 'heading', content: first.innerHTML, attrs: {} };\n if (tag === 'h3') return { type: 'heading-3', content: first.innerHTML, attrs: {} };\n if (tag === 'h4') return { type: 'heading-4', content: first.innerHTML, attrs: {} };\n if (tag === 'blockquote') return { type: 'quote', content: first.innerHTML, attrs: {} };\n if (tag === 'ul') return { type: 'list', content: first.innerHTML, attrs: {} };\n if (tag === 'ol') return { type: 'ordered-list', content: first.innerHTML, attrs: {} };\n if (tag === 'hr') return { type: 'separator', content: '', attrs: {} };\n if (tag === 'img') {\n const styleWidth = _readPercentWidth(first.getAttribute('style') || '');\n return {\n type: 'image',\n content: first.getAttribute('src') || '',\n attrs: {\n alt: first.getAttribute('alt') || '',\n ...(styleWidth ? { width: styleWidth } : {}),\n },\n };\n }\n if (tag === 'figure') {\n const img = first.querySelector('img');\n if (img) {\n const caption = first.querySelector('figcaption');\n const styleWidth = _readPercentWidth(img.getAttribute('style') || '');\n return {\n type: 'image',\n content: img.getAttribute('src') || '',\n attrs: {\n alt: img.getAttribute('alt') || '',\n caption: caption ? caption.innerHTML : '',\n ...(styleWidth ? { width: styleWidth } : {}),\n },\n };\n }\n }\n if (tag === 'pre') {\n const code = first.querySelector('code');\n return {\n type: 'code',\n content: code ? (code.textContent || '') : (first.textContent || ''),\n attrs: {},\n };\n }\n\n return { type: 'html', content: raw, attrs: {} };\n }\n\n /* ===== Global Keyboard Shortcuts ===== */\n\n _handleGlobalKeydown(e) {\n const mod = e.ctrlKey || e.metaKey;\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.rootEl.contains(window.getSelection().anchorNode));\n\n if (mod && e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n this.undo({ preferNative: inEditable });\n }\n if (mod && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {\n e.preventDefault();\n this.redo({ preferNative: inEditable });\n }\n if (mod && e.key === 's') {\n e.preventDefault();\n this.save();\n }\n if (mod && e.key === 'b') {\n e.preventDefault();\n document.execCommand('bold', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'i') {\n e.preventDefault();\n document.execCommand('italic', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'u') {\n e.preventDefault();\n document.execCommand('underline', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'k') {\n e.preventDefault();\n this.toolbar._showLinkPopover();\n }\n if (mod && e.key === 'a') {\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (contentEl && this.rootEl.contains(document.activeElement)) {\n e.preventDefault();\n const range = document.createRange();\n range.selectNodeContents(contentEl);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n }\n\n /* ===== Public API ===== */\n\n /** Get all editor data as a JSON object. */\n getData() {\n this._syncAllBlockContent();\n const mergedHtml = this.blockManager.toHTML();\n return { content: mergedHtml };\n }\n\n /** Set editor content from a content string or { content } object. */\n setData(data) {\n const content = typeof data === 'string'\n ? data\n : (typeof data?.content === 'string' ? data.content : '');\n\n this.blockManager.fromJSON([\n {\n id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\n type: 'paragraph',\n content,\n attrs: {},\n },\n ]);\n this.render();\n }\n\n /** Export blocks as HTML string. */\n toHTML() {\n this._syncAllBlockContent();\n return this.blockManager.toHTML();\n }\n\n toggleBlockHtmlMode(blockId = this._selectedBlockId) {\n if (!blockId) return;\n this._syncCurrentBlockContent();\n const block = this.blockManager.getBlock(blockId);\n if (!block) return;\n\n if (block.type === 'html') {\n const fallbackType = block.attrs?.__sourceType || 'paragraph';\n const parsed = this._parseBlockFromHTML(block.content || '', fallbackType);\n block.type = parsed.type === 'html' ? fallbackType : parsed.type;\n block.content = parsed.content;\n block.attrs = parsed.attrs || {};\n this.render();\n this.focusBlock(blockId);\n return;\n }\n\n const html = this.blockManager.blockToHTML(block);\n block.attrs = { ...(block.attrs || {}), __sourceType: block.type };\n block.type = 'html';\n block.content = html;\n this.render();\n this.focusBlock(blockId);\n }\n\n openBlockHtmlEditor(blockId = this._selectedBlockId) {\n if (!blockId || !this._htmlEditorModal || !this._htmlEditorTextarea) return;\n this._syncCurrentBlockContent();\n const block = this.blockManager.getBlock(blockId);\n if (!block) return;\n\n this._htmlEditorBlockId = blockId;\n this._htmlEditorTitle.textContent = `Edit as HTML: ${block.type}`;\n this._htmlEditorTextarea.value = this.blockManager.blockToHTML(block);\n this._htmlEditorModal.classList.add('fe-open');\n setTimeout(() => {\n this._htmlEditorTextarea.focus();\n this._htmlEditorTextarea.select();\n }, 0);\n }\n\n _closeBlockHtmlEditor() {\n if (!this._htmlEditorModal) return;\n this._htmlEditorModal.classList.remove('fe-open');\n this._htmlEditorBlockId = null;\n }\n\n _applyBlockHtmlEditor() {\n if (!this._htmlEditorBlockId || !this._htmlEditorTextarea) return;\n const block = this.blockManager.getBlock(this._htmlEditorBlockId);\n if (!block) return this._closeBlockHtmlEditor();\n\n const parsed = this._parseBlockFromHTML(this._htmlEditorTextarea.value, block.type);\n block.type = parsed.type;\n block.content = parsed.content;\n block.attrs = parsed.attrs || {};\n this._closeBlockHtmlEditor();\n this.render();\n this.focusBlock(block.id);\n }\n\n /** Save draft (emits save event). */\n save() {\n const data = this.getData();\n this.header.setStatus('Draft saved');\n this.statusBar.setSaved('Last saved: ' + new Date().toLocaleTimeString());\n this._showToast('Draft saved');\n if (this.options.onSave) this.options.onSave(data);\n this.emit('save', data);\n }\n\n /** Publish (emits publish event). */\n publish() {\n const data = this.getData();\n this.header.setStatus('Published', '#00a32a');\n this._showToast('Post published!');\n if (this.options.onPublish) this.options.onPublish(data);\n this.emit('publish', data);\n }\n\n /** Get / set the title. */\n getTitle() { return this._titleEl?.value || ''; }\n setTitle(title) { if (this._titleEl) this._titleEl.value = title; }\n\n undo({ preferNative = false } = {}) {\n if (preferNative) {\n const didNative = document.execCommand('undo', false, null);\n if (didNative) {\n this._syncCurrentBlockContent();\n return true;\n }\n }\n\n const didBlockUndo = this.blockManager.undo();\n if (didBlockUndo) this.render();\n return didBlockUndo;\n }\n\n redo({ preferNative = false } = {}) {\n if (preferNative) {\n const didNative = document.execCommand('redo', false, null);\n if (didNative) {\n this._syncCurrentBlockContent();\n return true;\n }\n }\n\n const didBlockRedo = this.blockManager.redo();\n if (didBlockRedo) this.render();\n return didBlockRedo;\n }\n\n /** Destroy editor instance. */\n destroy() {\n if (this._autoSaveTimer) clearInterval(this._autoSaveTimer);\n document.removeEventListener('keydown', this._boundGlobalKeydown);\n this.slashMenu.destroy();\n this.toolbar.hide();\n this.rootEl.innerHTML = '';\n this._listeners = {};\n }\n\n _showToast(msg) {\n this._toast.textContent = msg;\n this._toast.classList.add('fe-show');\n setTimeout(() => this._toast.classList.remove('fe-show'), 2500);\n }\n\n _positionBlockToolbar(toolbarEl, wrapperEl) {\n if (!toolbarEl || !wrapperEl) return;\n const viewportPadding = 8;\n\n toolbarEl.classList.remove('fe-toolbar-below');\n toolbarEl.style.top = '-44px';\n toolbarEl.style.left = '0px';\n\n const toolbarRect = toolbarEl.getBoundingClientRect();\n const wrapperRect = wrapperEl.getBoundingClientRect();\n\n let shiftX = 0;\n if (toolbarRect.right > window.innerWidth - viewportPadding) {\n shiftX -= toolbarRect.right - (window.innerWidth - viewportPadding);\n }\n if (toolbarRect.left + shiftX < viewportPadding) {\n shiftX += viewportPadding - (toolbarRect.left + shiftX);\n }\n toolbarEl.style.left = `${Math.round(shiftX)}px`;\n\n const topIfAbove = wrapperRect.top - toolbarRect.height - 6;\n const shouldPlaceBelow = topIfAbove < viewportPadding;\n if (shouldPlaceBelow) {\n toolbarEl.classList.add('fe-toolbar-below');\n toolbarEl.style.top = '6px';\n }\n wrapperEl.classList.toggle('fe-toolbar-inset', shouldPlaceBelow);\n }\n\n _getSelectionTableCell() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n let node = sel.anchorNode;\n if (!node) return null;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || typeof node.closest !== 'function') return null;\n const cell = node.closest('td,th');\n if (!cell) return null;\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (!contentEl || !contentEl.contains(cell)) return null;\n return cell;\n }\n\n _handleTableTab(currentCell, reverse = false) {\n const row = currentCell.closest('tr');\n const table = currentCell.closest('table');\n if (!row || !table) return;\n\n const rowCells = Array.from(row.querySelectorAll('th,td'));\n const cellIndex = rowCells.indexOf(currentCell);\n const rows = Array.from(table.querySelectorAll('tr'));\n const rowIndex = rows.indexOf(row);\n\n if (reverse) {\n if (cellIndex > 0) {\n this._placeCaretInCell(rowCells[cellIndex - 1]);\n return;\n }\n if (rowIndex > 0) {\n const prevRowCells = Array.from(rows[rowIndex - 1].querySelectorAll('th,td'));\n this._placeCaretInCell(prevRowCells[prevRowCells.length - 1]);\n }\n return;\n }\n\n if (cellIndex < rowCells.length - 1) {\n this._placeCaretInCell(rowCells[cellIndex + 1]);\n return;\n }\n\n if (rowIndex < rows.length - 1) {\n const nextRowCells = Array.from(rows[rowIndex + 1].querySelectorAll('th,td'));\n this._placeCaretInCell(nextRowCells[0]);\n return;\n }\n\n const colCount = Math.max(1, rowCells.length);\n const newRow = document.createElement('tr');\n for (let i = 0; i < colCount; i++) {\n const td = document.createElement('td');\n td.innerHTML = '<br>';\n newRow.appendChild(td);\n }\n\n const tbody = table.querySelector('tbody');\n if (tbody) tbody.appendChild(newRow);\n else table.appendChild(newRow);\n this._placeCaretInCell(newRow.querySelector('td'));\n }\n\n _placeCaretInCell(cell) {\n if (!cell) return;\n if ((cell.innerHTML || '').trim() === '') cell.innerHTML = '<br>';\n const range = document.createRange();\n range.selectNodeContents(cell);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n insertSingleBlockType(type, data = {}) {\n const block = this._getInsertionTargetBlock();\n if (!block) return false;\n\n const snippet = this._snippetForType(type, data);\n if (!snippet) return false;\n\n if (typeof document.execCommand === 'function') {\n const contentEl = this._getBlockContentEl(block.id);\n if (contentEl) {\n contentEl.focus();\n const ok = document.execCommand('insertHTML', false, snippet);\n if (ok) {\n this._focusEditableTail(contentEl);\n this._syncCurrentBlockContent();\n return true;\n }\n }\n }\n\n block.content = `${block.content || ''}${block.content ? '\\n' : ''}${snippet}`;\n return true;\n }\n\n _snippetForType(type, data = {}) {\n if (type === 'separator') return '<hr><p><br></p>';\n if (type === 'spacer') return `<div style=\"height:${Number(data?.height) || 48}px\"></div><p><br></p>`;\n if (type === 'table') {\n return [\n '<table border=\"1\" style=\"width:100%;border-collapse:collapse;\">',\n '<tbody>',\n '<tr><td>Cell 1</td><td>Cell 2</td></tr>',\n '<tr><td>Cell 3</td><td>Cell 4</td></tr>',\n '</tbody>',\n '</table>',\n '<p><br></p>',\n ].join('');\n }\n if (type === 'columns') {\n return [\n '<div class=\"fe-inline-columns\">',\n '<div class=\"fe-inline-column\"><p>Column 1</p></div>',\n '<div class=\"fe-inline-column\"><p>Column 2</p></div>',\n '</div>',\n '<p><br></p>',\n ].join('');\n }\n\n if (type === 'button') {\n return '<p><a href=\"#\" style=\"display:inline-block;background:#2271b1;color:#fff;padding:10px 24px;border-radius:4px;text-decoration:none;\" contenteditable=\"false\">Button</a></p><p><br></p>';\n }\n if (type === 'video') {\n const src = String(data?.url || '').trim();\n return src\n ? `<video controls style=\"width:100%;max-width:100%;\" src=\"${src}\"></video><p><br></p>`\n : '<video controls style=\"width:100%;max-width:100%;\"></video><p><br></p>';\n }\n if (type === 'audio') {\n const src = String(data?.url || '').trim();\n return src\n ? `<audio controls style=\"width:100%;\" src=\"${src}\"></audio><p><br></p>`\n : '<audio controls style=\"width:100%;\"></audio><p><br></p>';\n }\n if (type === 'file') {\n const url = String(data?.url || '').trim();\n const name = String(data?.name || 'Download file').trim();\n return url ? `<p><a href=\"${url}\" target=\"_blank\" rel=\"noopener\">${name}</a></p><p><br></p>` : null;\n }\n if (type === 'embed') {\n const url = String(data?.url || '').trim();\n return url\n ? `<p><a href=\"${url}\" target=\"_blank\" rel=\"noopener\">${url}</a></p><p><br></p>`\n : '<p>Paste embed URL here</p><p><br></p>';\n }\n return null;\n }\n\n _focusEditableTail(contentEl) {\n if (!contentEl) return;\n let tail = contentEl.lastElementChild;\n const needsTail = !tail || tail.tagName !== 'P';\n if (needsTail) {\n tail = document.createElement('p');\n tail.innerHTML = '<br>';\n contentEl.appendChild(tail);\n } else if ((tail.innerHTML || '').trim() === '') {\n tail.innerHTML = '<br>';\n }\n\n const range = document.createRange();\n range.selectNodeContents(tail);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n _ensureAtLeastOneBlock() {\n if (!Array.isArray(this.blockManager.blocks) || this.blockManager.blocks.length === 0) {\n return this.blockManager.addBlock('paragraph');\n }\n return this.blockManager.blocks[0];\n }\n\n _getInsertionTargetBlock() {\n const selected =\n this._selectedBlockId\n ? this.blockManager.getBlock(this._selectedBlockId)\n : null;\n if (selected) return selected;\n\n const last = this.blockManager.blocks[this.blockManager.blocks.length - 1];\n if (last) return last;\n\n return this.blockManager.addBlock('paragraph');\n }\n}\n\nfunction _readPercentWidth(style) {\n const match = /width\\s*:\\s*([0-9.]+)%/i.exec(style || '');\n if (!match) return null;\n const value = Number(match[1]);\n if (!Number.isFinite(value)) return null;\n return Math.max(10, Math.min(100, Math.round(value)));\n}\n","/**\n * React wrapper for NBDEditor.\n *\n * Guarded so the module can be safely imported in environments where React\n * is not available (e.g. vanilla-JS UMD usage). When React is missing,\n * `ReactNBDEditor` will be `null`.\n */\nimport * as React from 'react';\nimport { NBDEditor } from '../NBDEditor.js';\n\n// Guard: React may be undefined in vanilla-JS / UMD without React loaded.\nconst _hasReact = typeof React !== 'undefined' && React !== null && typeof React.forwardRef === 'function';\n\nfunction ReactNBDEditorComponent(props, ref) {\n const {\n className,\n style,\n content,\n onChange,\n onReady,\n ...editorOptions\n } = props || {};\n\n const hostRef = React.useRef(null);\n const editorRef = React.useRef(null);\n const lastContentRef = React.useRef(undefined);\n\n React.useEffect(() => {\n if (!hostRef.current) return undefined;\n\n const initialOptions = {\n ...editorOptions,\n onChange: (data) => {\n const nextContent = typeof data?.content === 'string' ? data.content : '';\n lastContentRef.current = nextContent;\n if (typeof onChange === 'function') onChange(data);\n },\n ...(typeof content === 'string' ? { content } : {}),\n };\n\n const editor = new NBDEditor(hostRef.current, initialOptions);\n editorRef.current = editor;\n lastContentRef.current = typeof content === 'string' ? content : undefined;\n if (typeof onReady === 'function') onReady(editor);\n\n return () => {\n if (editorRef.current) {\n editorRef.current.destroy();\n editorRef.current = null;\n }\n };\n // Intentionally one-time init; options should be stable at mount.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n React.useEffect(() => {\n if (!editorRef.current) return;\n if (typeof content !== 'string') return;\n if (content === lastContentRef.current) return;\n if (content === editorRef.current.toHTML()) {\n lastContentRef.current = content;\n return;\n }\n editorRef.current.setData({ content });\n lastContentRef.current = content;\n }, [content]);\n\n React.useImperativeHandle(ref, () => ({\n getInstance: () => editorRef.current,\n getData: () => editorRef.current?.getData(),\n setData: (data) => editorRef.current?.setData(data),\n toHTML: () => editorRef.current?.toHTML(),\n save: () => editorRef.current?.save(),\n publish: () => editorRef.current?.publish(),\n undo: (opts) => editorRef.current?.undo(opts),\n redo: (opts) => editorRef.current?.redo(opts),\n destroy: () => editorRef.current?.destroy(),\n }), []);\n\n return React.createElement('div', {\n ref: hostRef,\n className,\n style,\n });\n}\n\nexport const ReactNBDEditor = _hasReact ? React.forwardRef(ReactNBDEditorComponent) : null;\n"],"names":["EventEmitter","constructor","this","_listeners","on","event","fn","push","off","list","filter","f","emit","args","forEach","once","wrapper","el","tag","attrs","children","node","document","createElement","k","v","Object","entries","className","assign","style","dk","dv","dataset","startsWith","addEventListener","slice","toLowerCase","contentEditable","innerHTML","setAttribute","child","Array","isArray","appendChild","createTextNode","Node","generateId","Date","now","toString","Math","random","placeCaretAtEnd","element","focus","range","createRange","selectNodeContents","collapse","sel","window","getSelection","removeAllRanges","addRange","svg","inner","vb","icons","plus","undo","redo","listView","settings","bold","italic","underline","strikethrough","link","code","alignLeft","alignCenter","alignRight","image","heading","paragraph","quote","orderedList","separator","table","button","columns","spacer","embed","gallery","video","audio","file","dragHandle","filled","arrowUp","arrowDown","trash","close","inlineCode","upload","html","pullquote","BlockManager","super","blocks","_undoStack","_redoStack","_maxHistory","JSON","stringify","addBlock","type","data","afterId","block","id","content","idx","findIndex","b","splice","_pushUndo","removeBlock","length","removed","updateBlock","patch","getBlock","changeBlockType","newType","moveBlock","direction","newIdx","duplicateBlock","clone","find","getIndex","getPrevBlock","getNextBlock","toJSON","map","fromJSON","toHTML","blockToHTML","join","toHTMLBlocks","c","test","_escText","width","Number","isFinite","max","min","round","_escAttr","alt","caption","height","url","filename","next","shift","saveSnapshot","pop","parse","state","getWordCount","text","tmp","textContent","trim","split","w","getCharCount","replace","str","String","MediaUploader","options","uploadHandler","maxFileSize","allowedImageTypes","allowedVideoTypes","allowedAudioTypes","_fileInput","openFilePicker","accept","multiple","Promise","resolve","remove","input","display","body","files","click","processFile","size","err","name","toFixed","error","localUrl","_readAsDataURL","result","remoteUrl","message","processFiles","all","handlePaste","clipboardData","imageItems","items","item","getAsFile","Boolean","handleDrop","dataTransfer","getMediaType","reject","reader","FileReader","onload","onerror","readAsDataURL","DragDrop","container","_dragging","_placeholder","_offsetY","_bound","_enabled","enable","disable","initDrag","handleEl","wrapperEl","blockId","cursor","e","preventDefault","opacity","effectAllowed","setData","_removePlaceholder","dropEffect","rect","getBoundingClientRect","midY","top","position","clientY","_showPlaceholder","fromId","toId","referenceEl","cssText","parentNode","insertBefore","nextSibling","removeChild","BLOCK_TYPES","label","description","icon","category","hasContent","contentTag","placeholder","isMedia","CATEGORIES","getBlocksByCategory","catId","def","searchBlocks","query","q","includes","BlockRenderer","editor","render","_renderParagraph","_renderMediaBlock","_renderContentBlock","_renderSeparator","_renderSpacer","_renderColumns","_renderTable","isRawTextBlock","isEmpty","empty","_bindContentEvents","_renderImageBlock","_renderGalleryBlock","_renderVideoBlock","_renderAudioBlock","_renderFileBlock","_renderMediaPlaceholder","_normalizeImageWidth","fig","img","src","maxWidth","borderRadius","overlay","replaceBtn","onClick","_triggerImageUpload","removeBtn","resizeHandle","title","stopPropagation","selectBlock","startX","clientX","startWidth","parentWidth","onMove","ev","delta","nextPercent","onUp","removeEventListener","statusBar","update","sizeControls","pct","btn","images","grid","i","addMore","_triggerGalleryUpload","controls","infoDiv","filesize","downloadLink","href","download","iconEl","desc","btnRow","uploadBtn","_handleMediaUpload","urlInput","key","value","_setupDropZone","handle","startY","startH","newH","numCols","col","current","rows","cols","r","tr","cell","mediaUploader","results","res","bytes","classList","add","async","updateEmptyState","_selectedBlockId","activeElement","setTimeout","_onBlockInput","querySelector","_onBlockKeydown","getData","execCommand","then","numeric","Header","create","left","inserterBtn","inserterPanel","toggle","currentTarget","_iconBtn","activeEl","inEditable","isContentEditable","rootEl","contains","anchorNode","preferNative","center","right","showHeaderActions","draftBtn","save","publishBtn","publish","showSettingsPanel","childNodes","settingsPanel","_updateCanvasMargin","setStatus","color","iconHTML","Toolbar","_linkPopover","_fontSizeSelect","_onSelectionChange","_statefulButtons","_savedLinkRange","_tableToolsSep","_tableRowBtn","_tableColBtn","_createLinkPopover","show","blockManager","hide","getActiveBlockId","_addBtn","_addSep","textTypes","htmlEditableTypes","select","opt","o","selected","blockNow","ensureParagraphContext","contentEl","_getBlockContentEl","_syncCurrentBlockContent","focusBlock","fontSizeSelect","_applyFontSize","_syncFontSizeSelect","_bindFontSizeTracking","_addStatefulBtn","_exec","_wrapInlineCode","_showLinkPopover","_addTextBtn","_addTableRow","_addTableColumn","toggleBlockHtmlMode","_syncStatefulButtons","activeId","blockToClear","_hideLinkPopover","_unbindFontSizeTracking","extraClass","command","sep","cmd","rangeCount","getRangeAt","surroundContents","px","collapsed","marker","fontSize","insertNode","nextRange","setStart","firstChild","span","extractContents","_currentSelectionFontSizePx","snapped","sizes","best","bestDelta","abs","_closestFontSize","focusNode","elNode","nodeType","ELEMENT_NODE","parentElement","_getSelectedBlockEl","raw","getComputedStyle","parseFloat","applyBtn","_restoreSavedLinkRange","querySelectorAll","a","target","rel","cloneRange","bottom","anchor","closest","_getCurrentTableContext","TEXT_NODE","maybeCell","ctx","currentRow","rowCells","from","colCount","newRow","td","indexOf","row","cells","ref","newCell","tagName","targetRowCells","focusCell","hasSelectionInEditor","active","queryCommandState","tableDisplay","_isSelectionInTable","InserterPanel","_searchInput","_listEl","_anchorEl","_onDocMouseDown","_onDocKeyDown","_savedRange","_mediaModal","_mediaModalCard","_mediaModalTitle","_mediaModalBody","_mediaModalResolver","_forceNewBlock","header","closeBtn","_renderList","_createMediaModal","open","anchorEl","forceNewBlock","_captureSelectionRange","_positionNearAnchor","_bindGlobalCloseHandlers","_unbindGlobalCloseHandlers","isOpen","_createBlockItem","cat","blockDef","info","_insertFromPopover","desiredLeft","innerWidth","desiredTop","innerHeight","commonAncestorContainer","_restoreSelectionRange","selectedId","selectedBlock","insertSingleBlockType","insertBlockAtSelection","source","_chooseMediaSource","_promptForMediaUrl","trimmed","_showToast","prompt","onChooseMediaSource","_openMediaSourceModal","card","_closeMediaModal","actions","urlBtn","cancelBtn","resolver","SettingsPanel","_activeTab","_postTab","_blockTab","_tagInput","_tags","_categories","_featuredImage","tabs","_postTabBtn","_blockTabBtn","_switchTab","_buildPostTab","_buildBlockTab","updateBlockSettings","_blockSettingsContent","section","fontSelect","l","lhInput","lineHeight","colorSection","textColors","swatch","background","bgColors","border","tab","summary","_section","_field","cats","catList","addCat","checked","tags","tagWrapper","tagInput","val","t","fi","fiArea","fiInput","exc","disc","_toggle","s","frag","createDocumentFragment","defaultOn","SlashMenu","_visible","_highlightIndex","_items","_targetBlock","_boundDocClick","destroy","editorRect","_filter","handleKeydown","_navigate","visible","_selectItem","dir","scrollIntoView","StatusBar","_wordEl","_charEl","_blockEl","_savedEl","bm","titleText","_titleEl","titleWords","words","chars","setSaved","NBDEditor","selector","siteName","authorName","showStatusBar","autoSaveInterval","onChange","onSave","onPublish","Error","blockRenderer","toolbar","slashMenu","_blocksContainer","_autoSaveTimer","_htmlEditorModal","_htmlEditorTextarea","_htmlEditorTitle","_htmlEditorBlockId","_boundGlobalKeydown","_handleGlobalKeydown","_init","canvas","_toast","_createHtmlEditorModal","_ensureAtLeastOneBlock","setInterval","_syncAllBlockContent","toLocaleTimeString","chunks","toAppend","tbContainer","tb","scrollLeft","requestAnimationFrame","_positionBlockToolbar","rendered","clickedContent","clickedEditable","clickedCell","clickedEditableIndex","editables","clickedCellPos","rowIndex","colIndex","nextCell","newWrapper","targetEditable","dd","fromIdx","toIdx","moved","appender","plusIcon","targetId","_getInsertionTargetBlock","insertBlockAtEnd","getCaretRect","_getSelectionTableCell","_handleTableTab","shiftKey","nodeRect","prev","placeCaretAtStart","_generateSlug","slug","slugEl","getElementById","modal","_closeBlockHtmlEditor","textarea","spellcheck","_applyBlockHtmlEditor","ctrlKey","metaKey","_parseBlockFromHTML","fallbackType","wrap","first","firstElementChild","onlyOneElement","childElementCount","every","n","styleWidth","_readPercentWidth","getAttribute","mod","__sourceType","parsed","openBlockHtmlEditor","getTitle","setTitle","didBlockUndo","didBlockRedo","clearInterval","msg","toolbarEl","toolbarRect","wrapperRect","shiftX","shouldPlaceBelow","currentCell","reverse","cellIndex","_placeCaretInCell","prevRowCells","nextRowCells","tbody","snippet","_snippetForType","_focusEditableTail","tail","lastElementChild","last","match","exec","ReactNBDEditor","React","forwardRef","props","onReady","editorOptions","hostRef","useRef","editorRef","lastContentRef","undefined","useEffect","initialOptions","nextContent","useImperativeHandle","getInstance","opts"],"mappings":"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"}
1
+ {"version":3,"file":"nbd-editor.esm.js","sources":["../src/utils/EventEmitter.js","../src/utils/dom.js","../src/utils/icons.js","../src/core/BlockManager.js","../src/core/MediaUploader.js","../src/core/DragDrop.js","../src/blocks/registry.js","../src/blocks/BlockRenderer.js","../src/ui/Header.js","../src/ui/Toolbar.js","../src/ui/InserterPanel.js","../src/ui/SettingsPanel.js","../src/ui/SlashMenu.js","../src/ui/StatusBar.js","../src/core/PluginRegistry.js","../src/core/Differ.js","../src/core/CollaborativeManager.js","../src/utils/sanitize.js","../src/utils/HtmlNormalizer.js","../src/formats/DeltaFormat.js","../src/NBDEditor.js","../src/react/ReactNBDEditor.js"],"sourcesContent":["/**\n * Lightweight event emitter for editor internals.\n */\nexport class EventEmitter {\n constructor() {\n this._listeners = {};\n }\n\n on(event, fn) {\n (this._listeners[event] ||= []).push(fn);\n return () => this.off(event, fn);\n }\n\n off(event, fn) {\n const list = this._listeners[event];\n if (!list) return;\n this._listeners[event] = list.filter((f) => f !== fn);\n }\n\n emit(event, ...args) {\n (this._listeners[event] || []).forEach((fn) => fn(...args));\n }\n\n once(event, fn) {\n const wrapper = (...args) => {\n this.off(event, wrapper);\n fn(...args);\n };\n this.on(event, wrapper);\n }\n}\n","/**\n * DOM helper utilities.\n */\n\nexport function el(tag, attrs = {}, children = []) {\n const node = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) {\n if (k === 'className') node.className = v;\n else if (k === 'style' && typeof v === 'object') Object.assign(node.style, v);\n else if (k === 'dataset' && typeof v === 'object') {\n for (const [dk, dv] of Object.entries(v)) node.dataset[dk] = dv;\n } else if (k.startsWith('on') && typeof v === 'function') {\n node.addEventListener(k.slice(2).toLowerCase(), v);\n } else if (k === 'contentEditable') {\n node.contentEditable = v;\n } else if (k === 'innerHTML') {\n node.innerHTML = v;\n } else {\n node.setAttribute(k, v);\n }\n }\n for (const child of (Array.isArray(children) ? children : [children])) {\n if (typeof child === 'string') node.appendChild(document.createTextNode(child));\n else if (child instanceof Node) node.appendChild(child);\n }\n return node;\n}\n\nexport function qs(sel, root = document) {\n return root.querySelector(sel);\n}\n\nexport function qsa(sel, root = document) {\n return [...root.querySelectorAll(sel)];\n}\n\nexport function generateId() {\n return 'blk_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);\n}\n\nexport function stripHTML(html) {\n const tmp = document.createElement('div');\n tmp.innerHTML = html;\n return tmp.textContent || '';\n}\n\nexport function getCaretRect() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n return range.getBoundingClientRect();\n}\n\nexport function placeCaretAtEnd(element) {\n element.focus();\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\nexport function placeCaretAtStart(element) {\n element.focus();\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n}\n","/**\n * SVG icons used throughout the editor.\n */\n\nconst svg = (inner, vb = '0 0 24 24') =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"${vb}\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${inner}</svg>`;\n\nconst filled = (inner, vb = '0 0 24 24') =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"${vb}\" fill=\"currentColor\">${inner}</svg>`;\n\nexport const icons = {\n plus: svg('<line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/>'),\n undo: svg('<path d=\"M3 10h13a4 4 0 010 8H7\"/><path d=\"M3 10l4-4M3 10l4 4\"/>'),\n redo: svg('<path d=\"M21 10H8a4 4 0 000 8h9\"/><path d=\"M21 10l-4-4M21 10l-4 4\"/>'),\n listView: svg('<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"/><line x1=\"3\" y1=\"6\" x2=\"3.01\" y2=\"6\"/><line x1=\"3\" y1=\"12\" x2=\"3.01\" y2=\"12\"/><line x1=\"3\" y1=\"18\" x2=\"3.01\" y2=\"18\"/>'),\n settings: svg('<circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z\"/>'),\n moreVert: filled('<circle cx=\"12\" cy=\"5\" r=\"1.5\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\"/><circle cx=\"12\" cy=\"19\" r=\"1.5\"/>'),\n bold: '<b>B</b>',\n italic: '<i>I</i>',\n underline: '<u>U</u>',\n strikethrough: '<s>S</s>',\n link: svg('<path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\"/>'),\n code: svg('<polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/>'),\n alignLeft: svg('<line x1=\"17\" y1=\"10\" x2=\"3\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"17\" y1=\"18\" x2=\"3\" y2=\"18\"/>'),\n alignCenter: svg('<line x1=\"18\" y1=\"10\" x2=\"6\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"18\" y1=\"18\" x2=\"6\" y2=\"18\"/>'),\n alignRight: svg('<line x1=\"21\" y1=\"10\" x2=\"7\" y2=\"10\"/><line x1=\"21\" y1=\"6\" x2=\"3\" y2=\"6\"/><line x1=\"21\" y1=\"14\" x2=\"3\" y2=\"14\"/><line x1=\"21\" y1=\"18\" x2=\"7\" y2=\"18\"/>'),\n image: svg('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><polyline points=\"21 15 16 10 5 21\"/>'),\n heading: '<b>H</b>',\n paragraph: '<span style=\"font-size:16px\">¶</span>',\n quote: '<span style=\"font-size:18px\">&#10077;</span>',\n list: svg('<line x1=\"8\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"8\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"8\" y1=\"18\" x2=\"21\" y2=\"18\"/><circle cx=\"4\" cy=\"6\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"4\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"4\" cy=\"18\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/>'),\n orderedList: svg('<line x1=\"10\" y1=\"6\" x2=\"21\" y2=\"6\"/><line x1=\"10\" y1=\"12\" x2=\"21\" y2=\"12\"/><line x1=\"10\" y1=\"18\" x2=\"21\" y2=\"18\"/><text x=\"3\" y=\"8\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">1</text><text x=\"3\" y=\"14\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">2</text><text x=\"3\" y=\"20\" font-size=\"7\" fill=\"currentColor\" stroke=\"none\" font-family=\"sans-serif\">3</text>'),\n separator: svg('<line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\"/>'),\n table: svg('<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/>'),\n button: svg('<rect x=\"3\" y=\"7\" width=\"18\" height=\"10\" rx=\"3\"/>'),\n columns: svg('<rect x=\"3\" y=\"3\" width=\"7\" height=\"18\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"18\" rx=\"1\"/>'),\n spacer: svg('<path d=\"M12 5v14M5 12h14\"/>', '0 0 24 24'),\n embed: svg('<path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\"/>'),\n gallery: svg('<rect x=\"2\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"14\" y=\"2\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"2\" y=\"14\" width=\"8\" height=\"8\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"8\" height=\"8\" rx=\"1\"/>'),\n video: svg('<polygon points=\"5 3 19 12 5 21 5 3\"/>'),\n audio: svg('<path d=\"M9 18V5l12-2v13\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><circle cx=\"18\" cy=\"16\" r=\"3\"/>'),\n file: svg('<path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/>'),\n dragHandle: filled('<circle cx=\"9\" cy=\"5\" r=\"1.2\"/><circle cx=\"15\" cy=\"5\" r=\"1.2\"/><circle cx=\"9\" cy=\"10\" r=\"1.2\"/><circle cx=\"15\" cy=\"10\" r=\"1.2\"/><circle cx=\"9\" cy=\"15\" r=\"1.2\"/><circle cx=\"15\" cy=\"15\" r=\"1.2\"/><circle cx=\"9\" cy=\"20\" r=\"1.2\"/><circle cx=\"15\" cy=\"20\" r=\"1.2\"/>'),\n arrowUp: svg('<polyline points=\"18 15 12 9 6 15\"/>'),\n arrowDown: svg('<polyline points=\"6 9 12 15 18 9\"/>'),\n trash: svg('<polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/>'),\n close: svg('<line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>'),\n check: svg('<polyline points=\"20 6 9 17 4 12\"/>'),\n inlineCode: '<span style=\"font-family:monospace;font-size:13px\">&lt;/&gt;</span>',\n upload: svg('<path d=\"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4\"/><polyline points=\"17 8 12 3 7 8\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"/>'),\n externalLink: svg('<path d=\"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6\"/><polyline points=\"15 3 21 3 21 9\"/><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"/>'),\n html: '<span style=\"font-family:monospace;font-size:11px\">&lt;HTML&gt;</span>',\n pullquote: svg('<path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z\"/><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"/>'),\n};\n","import { generateId } from '../utils/dom.js';\nimport { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Manages the block data model: add, remove, move, update, and undo/redo.\n */\nexport class BlockManager extends EventEmitter {\n constructor() {\n super();\n this.blocks = [];\n this._undoStack = [];\n this._redoStack = [];\n this._maxHistory = 100;\n this._undoStack.push(JSON.stringify(this.blocks));\n }\n\n /* ---- CRUD ---- */\n\n addBlock(type, data = {}, afterId = null) {\n const block = {\n id: generateId(),\n type,\n content: '',\n attrs: {},\n ...data,\n };\n\n if (afterId) {\n const idx = this.blocks.findIndex((b) => b.id === afterId);\n this.blocks.splice(idx + 1, 0, block);\n } else {\n this.blocks.push(block);\n }\n\n this._pushUndo();\n this.emit('block:added', block);\n this.emit('change', this.blocks);\n return block;\n }\n\n removeBlock(id) {\n const idx = this.blocks.findIndex((b) => b.id === id);\n if (idx === -1) return;\n if (this.blocks.length <= 1) return; // keep at least one block\n const [removed] = this.blocks.splice(idx, 1);\n this._pushUndo();\n this.emit('block:removed', removed, idx);\n this.emit('change', this.blocks);\n return removed;\n }\n\n updateBlock(id, patch) {\n const block = this.getBlock(id);\n if (!block) return;\n Object.assign(block, patch);\n this.emit('block:updated', block);\n this.emit('change', this.blocks);\n }\n\n changeBlockType(id, newType) {\n const block = this.getBlock(id);\n if (!block) return;\n block.type = newType;\n this._pushUndo();\n this.emit('block:typeChanged', block);\n this.emit('change', this.blocks);\n }\n\n moveBlock(id, direction) {\n const idx = this.blocks.findIndex((b) => b.id === id);\n const newIdx = idx + direction;\n if (newIdx < 0 || newIdx >= this.blocks.length) return;\n [this.blocks[idx], this.blocks[newIdx]] = [this.blocks[newIdx], this.blocks[idx]];\n this._pushUndo();\n this.emit('block:moved', this.blocks[newIdx], direction);\n this.emit('change', this.blocks);\n }\n\n duplicateBlock(id) {\n const block = this.getBlock(id);\n if (!block) return;\n const clone = { ...block, id: generateId(), content: block.content, attrs: { ...block.attrs } };\n const idx = this.blocks.findIndex((b) => b.id === id);\n this.blocks.splice(idx + 1, 0, clone);\n this._pushUndo();\n this.emit('block:added', clone);\n this.emit('change', this.blocks);\n return clone;\n }\n\n /* ---- Queries ---- */\n\n getBlock(id) {\n return this.blocks.find((b) => b.id === id) || null;\n }\n\n getIndex(id) {\n return this.blocks.findIndex((b) => b.id === id);\n }\n\n getPrevBlock(id) {\n const idx = this.getIndex(id);\n return idx > 0 ? this.blocks[idx - 1] : null;\n }\n\n getNextBlock(id) {\n const idx = this.getIndex(id);\n return idx < this.blocks.length - 1 ? this.blocks[idx + 1] : null;\n }\n\n /* ---- Serialization ---- */\n\n toJSON() {\n return this.blocks.map((b) => ({ ...b }));\n }\n\n fromJSON(data) {\n this.blocks = data.map((b) => ({ ...b }));\n this._undoStack = [JSON.stringify(this.blocks)];\n this._redoStack = [];\n this.emit('change', this.blocks);\n }\n\n toHTML() {\n return this.blocks.map((b) => this.blockToHTML(b)).join('\\n');\n }\n\n toHTMLBlocks() {\n return this.blocks.map((b) => ({\n ...b,\n html: this.blockToHTML(b),\n }));\n }\n\n blockToHTML(block) {\n return blockToHTML(block);\n }\n\n /* ---- Undo / Redo ---- */\n\n _pushUndo() {\n const next = JSON.stringify(this.blocks);\n const last = this._undoStack[this._undoStack.length - 1];\n if (next === last) return;\n this._undoStack.push(next);\n if (this._undoStack.length > this._maxHistory) this._undoStack.shift();\n this._redoStack = [];\n }\n\n saveSnapshot() {\n this._pushUndo();\n }\n\n undo() {\n if (this._undoStack.length < 2) return false;\n this._redoStack.push(this._undoStack.pop());\n this.blocks = JSON.parse(this._undoStack[this._undoStack.length - 1]);\n this.emit('change', this.blocks);\n return true;\n }\n\n redo() {\n if (this._redoStack.length === 0) return false;\n const state = this._redoStack.pop();\n this._undoStack.push(state);\n this.blocks = JSON.parse(state);\n this.emit('change', this.blocks);\n return true;\n }\n\n /* ---- Stats ---- */\n\n getWordCount() {\n let text = '';\n for (const b of this.blocks) {\n if (b.content) {\n const tmp = document.createElement('div');\n tmp.innerHTML = b.content;\n text += tmp.textContent + ' ';\n }\n }\n const words = text.trim().split(/\\s+/).filter((w) => w.length > 0);\n return words.length;\n }\n\n getCharCount() {\n let text = '';\n for (const b of this.blocks) {\n if (b.content) {\n const tmp = document.createElement('div');\n tmp.innerHTML = b.content;\n text += tmp.textContent;\n }\n }\n return text.replace(/\\s/g, '').length;\n }\n}\n\n/* ---- Helpers ---- */\n\n/**\n * Escape a string for safe use inside an HTML attribute value.\n * Prevents XSS via attribute injection (e.g. `\" onload=\"alert(1)`).\n */\nfunction _escAttr(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Escape a string for safe use as HTML text content.\n */\nfunction _escText(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\nfunction blockToHTML(block) {\n const c = block.content || '';\n switch (block.type) {\n case 'paragraph':\n return _containsBlockMarkup(c) ? c : `<p>${c}</p>`;\n case 'heading':\n return `<h2>${c}</h2>`;\n case 'heading-3':\n return `<h3>${c}</h3>`;\n case 'heading-4':\n return `<h4>${c}</h4>`;\n case 'quote':\n return `<blockquote>${c}</blockquote>`;\n case 'code':\n return `<pre><code>${_escText(c)}</code></pre>`;\n case 'list':\n return `<ul>${c}</ul>`;\n case 'ordered-list':\n return `<ol>${c}</ol>`;\n case 'image': {\n if (!c) return '';\n const width = Number(block.attrs?.width);\n const style = Number.isFinite(width) ? ` style=\"width:${Math.max(10, Math.min(100, Math.round(width)))}%\"` : '';\n return `<figure><img src=\"${_escAttr(c)}\" alt=\"${_escAttr(block.attrs?.alt || '')}\"${style}/>${block.attrs?.caption ? `<figcaption>${block.attrs.caption}</figcaption>` : ''}</figure>`;\n }\n case 'separator':\n return '<hr/>';\n case 'spacer':\n return `<div style=\"height:${Number(block.attrs?.height) || 48}px\"></div>`;\n case 'table':\n return c || '<table></table>';\n case 'button':\n return `<div class=\"wp-block-button\"><a class=\"wp-block-button__link\" href=\"${_escAttr(block.attrs?.url || '#')}\">${c || 'Button'}</a></div>`;\n case 'columns':\n return `<div class=\"wp-block-columns\">${c}</div>`;\n case 'embed':\n return `<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">${c}</div></figure>`;\n case 'gallery':\n return `<figure class=\"wp-block-gallery\">${c}</figure>`;\n case 'video':\n return c ? `<figure class=\"wp-block-video\"><video controls src=\"${_escAttr(c)}\"></video></figure>` : '';\n case 'audio':\n return c ? `<figure class=\"wp-block-audio\"><audio controls src=\"${_escAttr(c)}\"></audio></figure>` : '';\n case 'file':\n return c ? `<div class=\"wp-block-file\"><a href=\"${_escAttr(c)}\">${_escText(block.attrs?.filename || 'Download')}</a></div>` : '';\n case 'html':\n return c;\n case 'pullquote':\n return `<figure class=\"wp-block-pullquote\"><blockquote>${c}</blockquote></figure>`;\n default:\n return `<p>${c}</p>`;\n }\n}\n\nfunction _containsBlockMarkup(html) {\n if (!html || typeof html !== 'string') return false;\n return /<(h[1-6]|p|div|section|article|blockquote|ul|ol|li|table|thead|tbody|tr|td|th|figure|figcaption|img|pre|hr)\\b/i.test(html);\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Handles media uploads: images, video, audio, files.\n * Supports custom upload handlers, drag-and-drop, clipboard paste, and local preview.\n */\nexport class MediaUploader extends EventEmitter {\n constructor(options = {}) {\n super();\n this.uploadHandler = options.uploadHandler || null; // async (file) => { url, id }\n this.maxFileSize = options.maxFileSize || 10 * 1024 * 1024; // 10MB\n this.allowedImageTypes = options.allowedImageTypes || ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'];\n this.allowedVideoTypes = options.allowedVideoTypes || ['video/mp4', 'video/webm', 'video/ogg'];\n this.allowedAudioTypes = options.allowedAudioTypes || ['audio/mpeg', 'audio/ogg', 'audio/wav', 'audio/webm'];\n this._fileInput = null;\n }\n\n /**\n * Create a hidden file input and trigger it.\n */\n openFilePicker(accept = 'image/*', multiple = false) {\n return new Promise((resolve) => {\n if (this._fileInput) this._fileInput.remove();\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = accept;\n input.multiple = multiple;\n input.style.display = 'none';\n document.body.appendChild(input);\n this._fileInput = input;\n\n input.addEventListener('change', () => {\n const files = [...input.files];\n input.remove();\n this._fileInput = null;\n resolve(files);\n });\n\n input.addEventListener('cancel', () => {\n input.remove();\n this._fileInput = null;\n resolve([]);\n });\n\n input.click();\n });\n }\n\n /**\n * Process a file: validate, generate local preview, then optionally upload.\n * Returns { localUrl, remoteUrl?, file, error? }\n */\n async processFile(file) {\n // Validate size\n if (file.size > this.maxFileSize) {\n const err = `File \"${file.name}\" exceeds the ${(this.maxFileSize / 1024 / 1024).toFixed(0)}MB limit.`;\n this.emit('error', err);\n return { error: err, file };\n }\n\n // Generate local preview\n const localUrl = await this._readAsDataURL(file);\n this.emit('preview', { file, localUrl });\n\n // If a custom upload handler is provided, use it\n if (this.uploadHandler) {\n try {\n this.emit('upload:start', { file });\n const result = await this.uploadHandler(file);\n this.emit('upload:complete', { file, ...result });\n return { localUrl, remoteUrl: result.url, file, id: result.id };\n } catch (err) {\n this.emit('upload:error', { file, error: err });\n return { localUrl, file, error: err.message || 'Upload failed' };\n }\n }\n\n // No remote handler — just use local data URL\n return { localUrl, file };\n }\n\n /**\n * Process multiple files.\n */\n async processFiles(files) {\n return Promise.all(files.map((f) => this.processFile(f)));\n }\n\n /**\n * Handle a paste event for images.\n */\n async handlePaste(clipboardData) {\n const items = [...(clipboardData.items || [])];\n const imageItems = items.filter((item) => item.type.startsWith('image/'));\n if (imageItems.length === 0) return null;\n\n const files = imageItems.map((item) => item.getAsFile()).filter(Boolean);\n if (files.length === 0) return null;\n\n return this.processFiles(files);\n }\n\n /**\n * Handle drag-and-drop of files.\n */\n async handleDrop(dataTransfer) {\n const files = [...(dataTransfer.files || [])];\n if (files.length === 0) return null;\n return this.processFiles(files);\n }\n\n /**\n * Determine media type from file.\n */\n getMediaType(file) {\n if (file.type.startsWith('image/')) return 'image';\n if (file.type.startsWith('video/')) return 'video';\n if (file.type.startsWith('audio/')) return 'audio';\n return 'file';\n }\n\n /**\n * Read file as data URL.\n */\n _readAsDataURL(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n }\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Drag-and-drop reordering for blocks.\n */\nexport class DragDrop extends EventEmitter {\n constructor(container) {\n super();\n this.container = container;\n this._dragging = null;\n this._placeholder = null;\n this._offsetY = 0;\n this._bound = {};\n this._enabled = true;\n }\n\n enable() {\n this._enabled = true;\n }\n\n disable() {\n this._enabled = false;\n }\n\n /**\n * Initialise drag on a handle element within a block wrapper.\n */\n initDrag(handleEl, wrapperEl, blockId) {\n handleEl.setAttribute('draggable', 'true');\n handleEl.style.cursor = 'grab';\n\n handleEl.addEventListener('dragstart', (e) => {\n if (!this._enabled) return e.preventDefault();\n this._dragging = { el: wrapperEl, id: blockId };\n wrapperEl.style.opacity = '0.4';\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', blockId);\n this.emit('drag:start', blockId);\n });\n\n handleEl.addEventListener('dragend', () => {\n if (this._dragging) {\n this._dragging.el.style.opacity = '';\n this._dragging = null;\n }\n this._removePlaceholder();\n this.emit('drag:end');\n });\n\n wrapperEl.addEventListener('dragover', (e) => {\n if (!this._dragging || this._dragging.id === blockId) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n\n const rect = wrapperEl.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position = e.clientY < midY ? 'before' : 'after';\n\n this._showPlaceholder(wrapperEl, position);\n });\n\n wrapperEl.addEventListener('drop', (e) => {\n e.preventDefault();\n if (!this._dragging) return;\n const fromId = this._dragging.id;\n const toId = blockId;\n\n const rect = wrapperEl.getBoundingClientRect();\n const midY = rect.top + rect.height / 2;\n const position = e.clientY < midY ? 'before' : 'after';\n\n this._removePlaceholder();\n this._dragging.el.style.opacity = '';\n this._dragging = null;\n\n this.emit('drop', { fromId, toId, position });\n });\n }\n\n _showPlaceholder(referenceEl, position) {\n if (!this._placeholder) {\n this._placeholder = document.createElement('div');\n this._placeholder.className = 'fe-drag-placeholder';\n this._placeholder.style.cssText =\n 'height:4px;background:#2271b1;border-radius:2px;margin:4px 0;transition:all 0.15s;';\n }\n if (position === 'before') {\n referenceEl.parentNode.insertBefore(this._placeholder, referenceEl);\n } else {\n referenceEl.parentNode.insertBefore(this._placeholder, referenceEl.nextSibling);\n }\n }\n\n _removePlaceholder() {\n if (this._placeholder && this._placeholder.parentNode) {\n this._placeholder.parentNode.removeChild(this._placeholder);\n }\n }\n}\n","import { icons } from '../utils/icons.js';\n\n/**\n * Block type registry. Each entry describes a block type and how to render it.\n */\nexport const BLOCK_TYPES = {\n paragraph: {\n label: 'Paragraph',\n description: 'Start with the building block of all narrative.',\n icon: icons.paragraph,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Type / to choose a block',\n className: '',\n },\n heading: {\n label: 'Heading 2',\n description: 'Introduce new sections and organize content.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h2',\n placeholder: 'Heading 2',\n className: 'fe-heading-2',\n },\n 'heading-3': {\n label: 'Heading 3',\n description: 'A smaller heading for subsections.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h3',\n placeholder: 'Heading 3',\n className: 'fe-heading-3',\n },\n 'heading-4': {\n label: 'Heading 4',\n description: 'A small heading for nested subsections.',\n icon: icons.heading,\n category: 'text',\n hasContent: true,\n contentTag: 'h4',\n placeholder: 'Heading 4',\n className: 'fe-heading-4',\n },\n list: {\n label: 'List',\n description: 'Create a bulleted list.',\n icon: icons.list,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'List',\n className: 'fe-list-block',\n },\n 'ordered-list': {\n label: 'Ordered List',\n description: 'Create a numbered list.',\n icon: icons.orderedList,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'List',\n className: 'fe-ordered-list-block',\n },\n quote: {\n label: 'Quote',\n description: 'Give quoted text visual emphasis.',\n icon: icons.quote,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write quote...',\n className: 'fe-quote',\n },\n pullquote: {\n label: 'Pullquote',\n description: 'Highlight a key quote from your content.',\n icon: icons.pullquote,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write pullquote...',\n className: 'fe-pullquote',\n },\n code: {\n label: 'Code',\n description: 'Display code snippets that respect your spacing.',\n icon: icons.code,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write code...',\n className: 'fe-code-block',\n },\n html: {\n label: 'Custom HTML',\n description: 'Add custom HTML code.',\n icon: icons.html,\n category: 'text',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Write HTML...',\n className: 'fe-html-block',\n },\n image: {\n label: 'Image',\n description: 'Insert an image to make a visual statement.',\n icon: icons.image,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n gallery: {\n label: 'Gallery',\n description: 'Display multiple images in a gallery.',\n icon: icons.gallery,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n video: {\n label: 'Video',\n description: 'Embed a video from your media library or URL.',\n icon: icons.video,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n audio: {\n label: 'Audio',\n description: 'Embed an audio file.',\n icon: icons.audio,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n file: {\n label: 'File',\n description: 'Add a link to a downloadable file.',\n icon: icons.file,\n category: 'media',\n hasContent: false,\n isMedia: true,\n },\n separator: {\n label: 'Separator',\n description: 'Create a break between ideas or sections.',\n icon: icons.separator,\n category: 'design',\n hasContent: false,\n },\n spacer: {\n label: 'Spacer',\n description: 'Add white space between blocks.',\n icon: icons.spacer,\n category: 'design',\n hasContent: false,\n },\n columns: {\n label: 'Columns',\n description: 'Display content in multiple columns.',\n icon: icons.columns,\n category: 'design',\n hasContent: false,\n },\n table: {\n label: 'Table',\n description: 'Insert a table for sharing data.',\n icon: icons.table,\n category: 'design',\n hasContent: false,\n },\n button: {\n label: 'Button',\n description: 'Prompt visitors to take action with a button.',\n icon: icons.button,\n category: 'design',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Add text...',\n className: 'fe-button-block',\n },\n embed: {\n label: 'Embed',\n description: 'Embed content from YouTube, Twitter, etc.',\n icon: icons.embed,\n category: 'media',\n hasContent: true,\n contentTag: 'div',\n placeholder: 'Enter URL to embed...',\n className: 'fe-embed-block',\n },\n};\n\nexport const CATEGORIES = [\n { id: 'text', label: 'Text' },\n { id: 'media', label: 'Media' },\n { id: 'design', label: 'Design' },\n];\n\n/**\n * Get blocks for a category.\n */\nexport function getBlocksByCategory(catId) {\n return Object.entries(BLOCK_TYPES)\n .filter(([, def]) => def.category === catId)\n .map(([type, def]) => ({ type, ...def }));\n}\n\n/**\n * Search blocks by query.\n */\nexport function searchBlocks(query) {\n const q = query.toLowerCase();\n return Object.entries(BLOCK_TYPES)\n .filter(([type, def]) => type.includes(q) || def.label.toLowerCase().includes(q) || def.description.toLowerCase().includes(q))\n .map(([type, def]) => ({ type, ...def }));\n}\n","import { el, placeCaretAtEnd } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\nimport { BLOCK_TYPES } from './registry.js';\n\n/**\n * Creates the DOM for a single block based on its type and data.\n */\nexport class BlockRenderer {\n constructor(editor) {\n this.editor = editor;\n }\n\n render(block) {\n const def = BLOCK_TYPES[block.type];\n if (!def) return this._renderParagraph(block);\n\n if (def.isMedia) return this._renderMediaBlock(block, def);\n if (def.hasContent) return this._renderContentBlock(block, def);\n\n // Non-content blocks\n switch (block.type) {\n case 'separator': return this._renderSeparator(block);\n case 'spacer': return this._renderSpacer(block);\n case 'columns': return this._renderColumns(block);\n case 'table': return this._renderTable(block);\n default: return this._renderParagraph(block);\n }\n }\n\n /* ---- Content Blocks (editable) ---- */\n\n _renderContentBlock(block, def) {\n const isRawTextBlock = block.type === 'code' || block.type === 'html';\n const isEmpty = !block.content || block.content.trim() === '';\n const node = el(def.contentTag || 'div', {\n className: `fe-block-content ${def.className || ''}`.trim(),\n contentEditable: 'true',\n dataset: { \n placeholder: def.placeholder || '',\n empty: isEmpty ? 'true' : 'false'\n },\n innerHTML: isRawTextBlock ? '' : (block.content || '<br>'),\n });\n if (isRawTextBlock && block.content) {\n node.textContent = block.content;\n }\n\n this._bindContentEvents(node, block);\n return node;\n }\n\n _renderParagraph(block) {\n const isEmpty = !block.content || block.content.trim() === '';\n const node = el('div', {\n className: 'fe-block-content',\n contentEditable: 'true',\n dataset: { \n placeholder: 'Type / to choose a block',\n empty: isEmpty ? 'true' : 'false'\n },\n innerHTML: block.content || '<br>',\n });\n this._bindContentEvents(node, block);\n return node;\n }\n\n /* ---- Media Blocks ---- */\n\n _renderMediaBlock(block, def) {\n const container = el('div', { className: `fe-block-media fe-block-${block.type}` });\n\n switch (block.type) {\n case 'image':\n return this._renderImageBlock(block, container);\n case 'gallery':\n return this._renderGalleryBlock(block, container);\n case 'video':\n return this._renderVideoBlock(block, container);\n case 'audio':\n return this._renderAudioBlock(block, container);\n case 'file':\n return this._renderFileBlock(block, container);\n default:\n return this._renderMediaPlaceholder(block, container, def);\n }\n }\n\n _renderImageBlock(block, container) {\n if (block.content) {\n const width = _normalizeImageWidth(block.attrs?.width);\n const fig = el('figure', { className: 'fe-image-figure' });\n const img = el('img', { src: block.content, alt: block.attrs?.alt || '' });\n img.style.width = `${width}%`;\n img.style.maxWidth = '100%';\n img.style.borderRadius = '4px';\n img.style.display = 'block';\n fig.appendChild(img);\n\n // Caption\n const caption = el('figcaption', {\n className: 'fe-image-caption',\n contentEditable: 'true',\n dataset: { placeholder: 'Add caption...' },\n innerHTML: block.attrs?.caption || '',\n });\n caption.addEventListener('input', () => {\n block.attrs = block.attrs || {};\n block.attrs.caption = caption.innerHTML;\n });\n fig.appendChild(caption);\n\n // Toolbar overlay\n const overlay = el('div', { className: 'fe-image-overlay' });\n const replaceBtn = el('button', {\n className: 'fe-img-overlay-btn',\n innerHTML: 'Replace',\n onClick: () => this._triggerImageUpload(block),\n });\n const removeBtn = el('button', {\n className: 'fe-img-overlay-btn fe-img-overlay-btn-danger',\n innerHTML: 'Remove',\n onClick: () => {\n block.content = '';\n block.attrs = {};\n this.editor.render();\n },\n });\n overlay.appendChild(replaceBtn);\n overlay.appendChild(removeBtn);\n fig.appendChild(overlay);\n\n const resizeHandle = el('button', {\n type: 'button',\n className: 'fe-image-resize-handle',\n title: 'Drag to resize image',\n });\n resizeHandle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this.editor.selectBlock(block.id);\n\n const startX = e.clientX;\n const startWidth = img.getBoundingClientRect().width;\n const parentWidth = container.getBoundingClientRect().width || startWidth || 1;\n\n const onMove = (ev) => {\n const delta = ev.clientX - startX;\n const nextWidthPx = Math.max(80, Math.min(parentWidth, startWidth + delta));\n const nextPercent = _normalizeImageWidth((nextWidthPx / parentWidth) * 100);\n block.attrs = block.attrs || {};\n block.attrs.width = nextPercent;\n img.style.width = `${nextPercent}%`;\n };\n\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n this.editor.statusBar.update();\n };\n\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n fig.appendChild(resizeHandle);\n\n container.appendChild(fig);\n\n const sizeControls = el('div', { className: 'fe-image-size-controls' });\n [25, 50, 75, 100].forEach((pct) => {\n const btn = el('button', {\n type: 'button',\n className: `fe-img-size-btn ${width === pct ? 'is-active' : ''}`.trim(),\n innerHTML: `${pct}%`,\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.width = pct;\n this.editor.render();\n },\n });\n sizeControls.appendChild(btn);\n });\n container.appendChild(sizeControls);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.image);\n }\n\n return container;\n }\n\n _renderGalleryBlock(block, container) {\n const images = block.attrs?.images || [];\n if (images.length > 0) {\n const grid = el('div', { className: 'fe-gallery-grid' });\n images.forEach((src, i) => {\n const item = el('div', { className: 'fe-gallery-item' });\n item.appendChild(el('img', { src, alt: '' }));\n const removeBtn = el('button', {\n className: 'fe-gallery-remove',\n innerHTML: '&times;',\n onClick: () => {\n images.splice(i, 1);\n this.editor.render();\n },\n });\n item.appendChild(removeBtn);\n grid.appendChild(item);\n });\n container.appendChild(grid);\n\n const addMore = el('button', {\n className: 'fe-gallery-add',\n innerHTML: '+ Add Images',\n onClick: () => this._triggerGalleryUpload(block),\n });\n container.appendChild(addMore);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.gallery);\n }\n return container;\n }\n\n _renderVideoBlock(block, container) {\n if (block.content) {\n const video = el('video', { src: block.content });\n video.controls = true;\n video.style.maxWidth = '100%';\n video.style.borderRadius = '4px';\n container.appendChild(video);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.video);\n }\n return container;\n }\n\n _renderAudioBlock(block, container) {\n if (block.content) {\n const audio = el('audio', { src: block.content });\n audio.controls = true;\n audio.style.width = '100%';\n container.appendChild(audio);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.audio);\n }\n return container;\n }\n\n _renderFileBlock(block, container) {\n if (block.content) {\n const wrapper = el('div', { className: 'fe-file-wrapper' });\n\n const infoDiv = el('div', { className: 'fe-file-info' });\n infoDiv.appendChild(el('span', { className: 'fe-file-icon', innerHTML: icons.file }));\n infoDiv.appendChild(el('span', { className: 'fe-file-name' }, [block.attrs?.filename || 'File']));\n infoDiv.appendChild(el('span', { className: 'fe-file-size' }, [block.attrs?.filesize || '']));\n wrapper.appendChild(infoDiv);\n\n const downloadLink = el('a', { className: 'fe-file-download', href: block.content, download: '' }, ['Download']);\n wrapper.appendChild(downloadLink);\n\n container.appendChild(wrapper);\n } else {\n this._renderMediaPlaceholder(block, container, BLOCK_TYPES.file);\n }\n return container;\n }\n\n _renderMediaPlaceholder(block, container, def) {\n const placeholder = el('div', { className: 'fe-media-placeholder' });\n\n const iconEl = el('div', { className: 'fe-media-placeholder-icon', innerHTML: def.icon });\n const label = el('p', { className: 'fe-media-placeholder-label' }, [def.label]);\n const desc = el('p', { className: 'fe-media-placeholder-desc' }, ['Upload a file or pick one from your media library.']);\n\n const btnRow = el('div', { className: 'fe-media-placeholder-actions' });\n\n const uploadBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n innerHTML: `${icons.upload} Upload`,\n onClick: () => this._handleMediaUpload(block),\n });\n btnRow.appendChild(uploadBtn);\n\n // URL input for embeds, video, audio\n if (['embed', 'video', 'audio'].includes(block.type)) {\n const urlInput = el('input', {\n type: 'text',\n className: 'fe-media-url-input',\n placeholder: 'Or paste a URL...',\n });\n urlInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n block.content = urlInput.value;\n this.editor.render();\n }\n });\n btnRow.appendChild(urlInput);\n }\n\n placeholder.appendChild(iconEl);\n placeholder.appendChild(label);\n placeholder.appendChild(desc);\n placeholder.appendChild(btnRow);\n container.appendChild(placeholder);\n\n // Drop zone\n this._setupDropZone(placeholder, block);\n\n return container;\n }\n\n /* ---- Non-content Blocks ---- */\n\n _renderSeparator(block) {\n const node = el('div', { className: 'fe-block-separator' });\n node.appendChild(el('hr'));\n return node;\n }\n\n _renderSpacer(block) {\n const height = block.attrs?.height || 48;\n const node = el('div', {\n className: 'fe-block-spacer',\n style: { height: height + 'px' },\n });\n\n // Resize handle\n const handle = el('div', { className: 'fe-spacer-handle' });\n let startY, startH;\n handle.addEventListener('mousedown', (e) => {\n startY = e.clientY;\n startH = height;\n const onMove = (ev) => {\n const newH = Math.max(16, startH + ev.clientY - startY);\n node.style.height = newH + 'px';\n block.attrs = block.attrs || {};\n block.attrs.height = newH;\n };\n const onUp = () => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n node.appendChild(handle);\n return node;\n }\n\n _renderColumns(block) {\n const numCols = block.attrs?.columns || 2;\n const node = el('div', { className: 'fe-block-columns' });\n for (let i = 0; i < numCols; i++) {\n const col = el('div', {\n className: 'fe-column',\n contentEditable: 'true',\n dataset: { placeholder: `Column ${i + 1}` },\n innerHTML: block.attrs?.[`col${i}`] || '',\n });\n col.addEventListener('input', () => {\n block.attrs = block.attrs || {};\n block.attrs[`col${i}`] = col.innerHTML;\n });\n node.appendChild(col);\n }\n\n const controls = el('div', { className: 'fe-columns-controls' });\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n type: 'button',\n innerHTML: '+ Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.columns = Math.max(1, Number(block.attrs.columns || numCols) + 1);\n this.editor.render();\n },\n })\n );\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n type: 'button',\n innerHTML: '- Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n const current = Math.max(1, Number(block.attrs.columns || numCols));\n if (current <= 1) return;\n delete block.attrs[`col${current - 1}`];\n block.attrs.columns = current - 1;\n this.editor.render();\n },\n })\n );\n node.appendChild(controls);\n return node;\n }\n\n _renderTable(block) {\n const rows = block.attrs?.rows || 3;\n const cols = block.attrs?.cols || 3;\n const node = el('div', { className: 'fe-block-table' });\n const table = el('table');\n const data = block.attrs?.data || [];\n\n for (let r = 0; r < rows; r++) {\n const tr = el('tr');\n for (let c = 0; c < cols; c++) {\n const cellTag = r === 0 ? 'th' : 'td';\n const cell = el(cellTag, {\n contentEditable: 'true',\n innerHTML: data[r]?.[c] || '',\n });\n cell.addEventListener('input', () => {\n if (!block.attrs) block.attrs = {};\n if (!block.attrs.data) block.attrs.data = [];\n if (!block.attrs.data[r]) block.attrs.data[r] = [];\n block.attrs.data[r][c] = cell.innerHTML;\n });\n tr.appendChild(cell);\n }\n table.appendChild(tr);\n }\n\n node.appendChild(table);\n\n // Add row/column buttons\n const controls = el('div', { className: 'fe-table-controls' });\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: '+ Row',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.rows = (block.attrs.rows || 3) + 1;\n this.editor.render();\n },\n })\n );\n controls.appendChild(\n el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: '+ Column',\n onClick: () => {\n block.attrs = block.attrs || {};\n block.attrs.cols = (block.attrs.cols || 3) + 1;\n this.editor.render();\n },\n })\n );\n node.appendChild(controls);\n return node;\n }\n\n /* ---- Upload Helpers ---- */\n\n async _handleMediaUpload(block) {\n let accept = '*/*';\n if (block.type === 'image' || block.type === 'gallery') accept = 'image/*';\n else if (block.type === 'video') accept = 'video/*';\n else if (block.type === 'audio') accept = 'audio/*';\n\n const multiple = block.type === 'gallery';\n const files = await this.editor.mediaUploader.openFilePicker(accept, multiple);\n if (files.length === 0) return;\n\n if (block.type === 'gallery') {\n const results = await this.editor.mediaUploader.processFiles(files);\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n } else {\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) {\n block.content = result.remoteUrl || result.localUrl;\n if (block.type === 'file') {\n block.attrs = block.attrs || {};\n block.attrs.filename = files[0].name;\n block.attrs.filesize = _formatSize(files[0].size);\n }\n }\n }\n this.editor.render();\n }\n\n async _triggerImageUpload(block) {\n const files = await this.editor.mediaUploader.openFilePicker('image/*');\n if (files.length === 0) return;\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) block.content = result.remoteUrl || result.localUrl;\n this.editor.render();\n }\n\n async _triggerGalleryUpload(block) {\n const files = await this.editor.mediaUploader.openFilePicker('image/*', true);\n if (files.length === 0) return;\n const results = await this.editor.mediaUploader.processFiles(files);\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n this.editor.render();\n }\n\n _setupDropZone(element, block) {\n element.addEventListener('dragover', (e) => {\n e.preventDefault();\n element.classList.add('fe-drop-active');\n });\n element.addEventListener('dragleave', () => {\n element.classList.remove('fe-drop-active');\n });\n element.addEventListener('drop', async (e) => {\n e.preventDefault();\n element.classList.remove('fe-drop-active');\n const results = await this.editor.mediaUploader.handleDrop(e.dataTransfer);\n if (results && results.length > 0) {\n if (block.type === 'gallery') {\n block.attrs = block.attrs || {};\n block.attrs.images = block.attrs.images || [];\n for (const res of results) {\n if (!res.error) block.attrs.images.push(res.remoteUrl || res.localUrl);\n }\n } else {\n const res = results[0];\n if (!res.error) block.content = res.remoteUrl || res.localUrl;\n }\n this.editor.render();\n }\n });\n }\n\n /* ---- Content Events ---- */\n\n _bindContentEvents(node, block) {\n const isRawTextBlock = block.type === 'code' || block.type === 'html';\n\n // Helper to update empty state\n const updateEmptyState = () => {\n const text = node.textContent || '';\n const isEmpty = isRawTextBlock\n ? text.trim() === ''\n : text.trim() === '' && (node.innerHTML.trim() === '<br>' || node.innerHTML.trim() === '');\n node.dataset.empty = isEmpty ? 'true' : 'false';\n };\n\n // Update empty state initially\n updateEmptyState();\n\n // Ensure contenteditable gets focus when clicked\n node.addEventListener('mousedown', (e) => {\n // Let wrapper click handle first-time block selection to avoid losing focus on re-render\n if (this.editor._selectedBlockId !== block.id) return;\n // Stop propagation so wrapper click does not override caret placement on selected blocks\n e.stopPropagation();\n // Immediately focus on mousedown for better responsiveness\n if (document.activeElement !== node) {\n node.focus();\n // If empty (only has <br>), place caret correctly\n const text = node.textContent || '';\n if (text.trim() === '' && (node.innerHTML.trim() === '<br>' || node.innerHTML.trim() === '')) {\n // Ensure there's a <br> for cursor visibility\n if (node.innerHTML.trim() === '') {\n node.innerHTML = '<br>';\n }\n // Place caret after the <br>\n setTimeout(() => {\n const range = document.createRange();\n const sel = window.getSelection();\n range.selectNodeContents(node);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n }, 0);\n }\n }\n });\n\n node.addEventListener('input', () => {\n if (isRawTextBlock) {\n block.content = node.textContent || '';\n updateEmptyState();\n this.editor._onBlockInput(block, node);\n return;\n }\n\n // Clean up: if content is just <br> or empty, store as empty string\n let content = node.innerHTML.trim();\n if (content === '<br>' || content === '<br/>' || content === '') {\n content = '';\n // Keep the <br> in the DOM for cursor visibility, but don't save it\n if (!node.querySelector('br')) {\n node.innerHTML = '<br>';\n }\n }\n block.content = content;\n updateEmptyState();\n this.editor._onBlockInput(block, node);\n });\n\n node.addEventListener('keydown', (e) => {\n this.editor._onBlockKeydown(e, block, node);\n });\n\n node.addEventListener('focus', () => {\n this.editor.selectBlock(block.id);\n });\n\n node.addEventListener('paste', (e) => {\n // Code blocks: plain text only\n if (block.type === 'code' || block.type === 'html') {\n e.preventDefault();\n const text = e.clipboardData.getData('text/plain');\n document.execCommand('insertText', false, text);\n return;\n }\n\n // Image paste\n if (e.clipboardData.items) {\n const imageItems = [...e.clipboardData.items].filter((i) => i.type.startsWith('image/'));\n if (imageItems.length > 0) {\n e.preventDefault();\n this.editor.mediaUploader.handlePaste(e.clipboardData).then((results) => {\n if (results && results.length > 0) {\n const src = results[0].remoteUrl || results[0].localUrl;\n if (src) {\n document.execCommand('insertHTML', false, `<img src=\"${src}\" alt=\"\" />`);\n }\n }\n });\n return;\n }\n }\n });\n }\n}\n\nfunction _formatSize(bytes) {\n if (bytes < 1024) return bytes + ' B';\n if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n}\n\nfunction _normalizeImageWidth(value) {\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) return 100;\n return Math.max(10, Math.min(100, Math.round(numeric)));\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\n\n/**\n * Top editor header bar: inserter button, undo/redo, status, save/publish, settings toggle.\n */\nexport class Header {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-header' });\n\n // Left\n const left = el('div', { className: 'fe-header-left' });\n\n // Block inserter toggle\n const inserterBtn = el('button', {\n className: 'fe-inserter-toggle',\n innerHTML: icons.plus,\n title: 'Toggle block inserter',\n onClick: (e) => this.editor.inserterPanel.toggle(e.currentTarget),\n });\n left.appendChild(inserterBtn);\n left.appendChild(el('span', { className: 'fe-sep' }));\n\n // Undo / Redo\n left.appendChild(this._iconBtn(icons.undo, 'Undo (Ctrl+Z)', () => {\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.editor.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.editor.rootEl.contains(window.getSelection().anchorNode));\n this.editor.undo({ preferNative: inEditable });\n }));\n left.appendChild(this._iconBtn(icons.redo, 'Redo (Ctrl+Y)', () => {\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.editor.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.editor.rootEl.contains(window.getSelection().anchorNode));\n this.editor.redo({ preferNative: inEditable });\n }));\n this.el.appendChild(left);\n\n // Center spacer\n const center = el('div', { className: 'fe-header-center' });\n this.el.appendChild(center);\n\n // Right\n const right = el('div', { className: 'fe-header-right' });\n\n if (this.editor.options.showHeaderActions) {\n const draftBtn = el('button', {\n className: 'fe-btn fe-btn-outline',\n innerHTML: 'Save draft',\n onClick: () => this.editor.save(),\n });\n right.appendChild(draftBtn);\n\n const publishBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n innerHTML: 'Publish',\n onClick: () => this.editor.publish(),\n });\n right.appendChild(publishBtn);\n }\n\n if (this.editor.options.showSettingsPanel) {\n if (right.childNodes.length > 0) {\n right.appendChild(el('span', { className: 'fe-sep' }));\n }\n right.appendChild(this._iconBtn(icons.settings, 'Settings', () => {\n this.editor.settingsPanel.toggle();\n this.editor._updateCanvasMargin();\n }));\n }\n\n this.el.appendChild(right);\n return this.el;\n }\n\n setStatus(text, color) {\n // no-op: status text removed from header UI\n }\n\n _iconBtn(iconHTML, title, onClick) {\n return el('button', {\n className: 'fe-icon-btn',\n innerHTML: iconHTML,\n title,\n onClick,\n });\n }\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\n\n/**\n * Floating block toolbar for formatting and block controls.\n */\nexport class Toolbar {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._linkPopover = null;\n this._fontSizeSelect = null;\n this._onSelectionChange = null;\n this._statefulButtons = [];\n this._savedLinkRange = null;\n this._tableToolsSep = null;\n this._tableRowBtn = null;\n this._tableColBtn = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-block-toolbar' });\n this._linkPopover = this._createLinkPopover();\n this._fontSizeSelect = null;\n this._onSelectionChange = null;\n return this.el;\n }\n\n show(blockId) {\n const block = this.editor.blockManager.getBlock(blockId);\n if (!block) return this.hide();\n const getActiveBlockId = () => this.editor._selectedBlockId || blockId;\n\n this.el.innerHTML = '';\n this.el.classList.add('fe-visible');\n this._statefulButtons = [];\n\n // Drag handle — lets user reposition the toolbar\n const dragBtn = this._addBtn(icons.dragHandle, 'Drag toolbar', null, 'fe-tb-drag');\n this._initToolbarDrag(dragBtn);\n\n this._addSep();\n\n // Move buttons\n this._addBtn(icons.arrowUp, 'Move up', () => this.editor.blockManager.moveBlock(blockId, -1));\n this._addBtn(icons.arrowDown, 'Move down', () => this.editor.blockManager.moveBlock(blockId, 1));\n\n this._addSep();\n\n // Type-specific tools\n const type = block.type;\n const textTypes = ['paragraph', 'heading', 'heading-3', 'heading-4', 'quote', 'pullquote', 'list', 'ordered-list'];\n const htmlEditableTypes = [...textTypes, 'code', 'html'];\n\n if (textTypes.includes(type)) {\n // Block type selector\n const select = el('select', { className: 'fe-tb-select' });\n const options = [\n { value: 'paragraph', label: 'Paragraph' },\n { value: 'heading', label: 'Heading 2' },\n { value: 'heading-3', label: 'Heading 3' },\n { value: 'heading-4', label: 'Heading 4' },\n { value: 'quote', label: 'Quote' },\n { value: 'list', label: 'Bullet List' },\n { value: 'ordered-list', label: 'Numbered List' },\n { value: 'code', label: 'Code' },\n ];\n options.forEach((opt) => {\n const o = el('option', { value: opt.value }, [opt.label]);\n if (opt.value === type) o.selected = true;\n select.appendChild(o);\n });\n select.addEventListener('change', () => {\n const value = select.value;\n const blockNow = this.editor.blockManager.getBlock(blockId);\n if (!blockNow) return;\n\n const ensureParagraphContext = () => {\n if (blockNow.type !== 'paragraph') {\n this.editor.blockManager.changeBlockType(blockId, 'paragraph');\n this.editor.render();\n }\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.focus();\n return contentEl;\n };\n\n if (value === 'paragraph' || value === 'heading' || value === 'heading-3' || value === 'heading-4' || value === 'quote') {\n const contentEl = ensureParagraphContext();\n if (!contentEl) return;\n const tag = value === 'paragraph'\n ? 'P'\n : value === 'heading'\n ? 'H2'\n : value === 'heading-3'\n ? 'H3'\n : value === 'heading-4'\n ? 'H4'\n : 'BLOCKQUOTE';\n document.execCommand('formatBlock', false, tag);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (value === 'list' || value === 'ordered-list') {\n const contentEl = ensureParagraphContext();\n if (!contentEl) return;\n document.execCommand(value === 'list' ? 'insertUnorderedList' : 'insertOrderedList', false, null);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n this.editor.blockManager.changeBlockType(blockId, value);\n this.editor.render();\n this.editor.focusBlock(blockId);\n });\n this.el.appendChild(select);\n\n this._addSep();\n\n // Font size\n const fontSizeSelect = el('select', { className: 'fe-tb-select', title: 'Font size' });\n [\n { value: '', label: 'Size' },\n { value: '13', label: '13px' },\n { value: '16', label: '16px' },\n { value: '20', label: '20px' },\n { value: '28', label: '28px' },\n { value: '36', label: '36px' },\n ].forEach((opt) => {\n const o = el('option', { value: opt.value }, [opt.label]);\n fontSizeSelect.appendChild(o);\n });\n fontSizeSelect.addEventListener('change', () => {\n if (!fontSizeSelect.value) return;\n this._applyFontSize(fontSizeSelect.value);\n this._syncFontSizeSelect();\n });\n this.el.appendChild(fontSizeSelect);\n this._fontSizeSelect = fontSizeSelect;\n this._bindFontSizeTracking();\n this._syncFontSizeSelect();\n\n this._addSep();\n\n // Formatting\n this._addStatefulBtn('bold', icons.bold, 'Bold (Ctrl+B)', () => this._exec('bold'));\n this._addStatefulBtn('italic', icons.italic, 'Italic (Ctrl+I)', () => this._exec('italic'));\n this._addStatefulBtn('underline', icons.underline, 'Underline (Ctrl+U)', () => this._exec('underline'));\n this._addStatefulBtn('strikeThrough', icons.strikethrough, 'Strikethrough', () => this._exec('strikeThrough'));\n this._addBtn(icons.inlineCode, 'Inline Code', () => this._wrapInlineCode());\n this._addStatefulBtn('link', icons.link, 'Link (Ctrl+K)', () => this._showLinkPopover());\n\n this._addSep();\n\n // Alignment\n this._addBtn(icons.alignLeft, 'Align Left', () => this._exec('justifyLeft'));\n this._addBtn(icons.alignCenter, 'Align Center', () => this._exec('justifyCenter'));\n this._addBtn(icons.alignRight, 'Align Right', () => this._exec('justifyRight'));\n\n this._tableToolsSep = this._addSep();\n this._tableRowBtn = this._addTextBtn('+Row', 'Add table row', () => this._addTableRow());\n this._tableColBtn = this._addTextBtn('+Col', 'Add table column', () => this._addTableColumn());\n }\n\n if (htmlEditableTypes.includes(type)) {\n this._addSep();\n this._addBtn(\n icons.html,\n type === 'html' ? 'Switch to normal text mode' : 'Switch to HTML mode',\n () => this.editor.toggleBlockHtmlMode(getActiveBlockId()),\n type === 'html' ? 'active' : ''\n );\n }\n\n this._syncStatefulButtons();\n\n this._addSep();\n\n // Duplicate & Delete\n this._addBtn(icons.file, 'Duplicate', () => {\n const clone = this.editor.blockManager.duplicateBlock(getActiveBlockId());\n if (clone) this.editor.render();\n });\n this._addBtn(icons.trash, 'Delete', () => {\n const activeId = getActiveBlockId();\n const removed = this.editor.blockManager.removeBlock(activeId);\n if (removed) {\n this.editor.render();\n return;\n }\n\n // If only one block remains, make delete behave like \"clear block\".\n const blockToClear = this.editor.blockManager.getBlock(activeId);\n if (!blockToClear) return;\n blockToClear.type = 'paragraph';\n blockToClear.content = '';\n blockToClear.attrs = {};\n this.editor.render();\n this.editor.focusBlock(activeId);\n }, 'fe-tb-btn-danger');\n }\n\n hide() {\n if (this.el) this.el.classList.remove('fe-visible');\n this._hideLinkPopover();\n this._unbindFontSizeTracking();\n }\n\n /* ---- Private ---- */\n\n _initToolbarDrag(handle) {\n let startX, startY, origLeft, origTop, dragging = false;\n\n const onMouseMove = (e) => {\n if (!dragging) return;\n const dx = e.clientX - startX;\n const dy = e.clientY - startY;\n this.el.style.left = (origLeft + dx) + 'px';\n this.el.style.top = (origTop + dy) + 'px';\n };\n\n const onMouseUp = () => {\n dragging = false;\n this.el.classList.remove('fe-toolbar-dragging');\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n };\n\n handle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n dragging = true;\n startX = e.clientX;\n startY = e.clientY;\n origLeft = parseInt(this.el.style.left || '0', 10);\n origTop = parseInt(this.el.style.top || '0', 10);\n this.el.classList.add('fe-toolbar-dragging');\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n });\n }\n\n _addBtn(iconHTML, title, onClick, extraClass = '') {\n const btn = el('button', {\n className: `fe-tb-btn ${extraClass}`.trim(),\n type: 'button',\n innerHTML: iconHTML,\n title,\n });\n btn.addEventListener('mousedown', (e) => {\n // Preserve current editor selection for rich-text commands/popovers.\n e.preventDefault();\n e.stopPropagation();\n });\n if (onClick) btn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); onClick(); });\n this.el.appendChild(btn);\n return btn;\n }\n\n _addStatefulBtn(command, iconHTML, title, onClick) {\n const btn = this._addBtn(iconHTML, title, onClick);\n this._statefulButtons.push({ command, btn });\n return btn;\n }\n\n _addSep() {\n const sep = el('span', { className: 'fe-tb-sep' });\n this.el.appendChild(sep);\n return sep;\n }\n\n _addTextBtn(label, title, onClick) {\n const btn = el('button', {\n className: 'fe-tb-text-btn',\n type: 'button',\n title,\n innerHTML: label,\n });\n btn.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n btn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n onClick();\n });\n this.el.appendChild(btn);\n return btn;\n }\n\n _exec(cmd) {\n document.execCommand(cmd, false, null);\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n }\n\n _wrapInlineCode() {\n const sel = window.getSelection();\n if (!sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n const code = document.createElement('code');\n code.className = 'fe-inline-code';\n range.surroundContents(code);\n this.editor._syncCurrentBlockContent();\n }\n\n _applyFontSize(px) {\n const size = Number(px);\n if (!Number.isFinite(size)) return;\n\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n\n if (range.collapsed) {\n // Apply style for text typed from the current caret onward only.\n const marker = document.createElement('span');\n marker.style.fontSize = `${size}px`;\n marker.appendChild(document.createTextNode('\\u200B'));\n range.insertNode(marker);\n\n const nextRange = document.createRange();\n nextRange.setStart(marker.firstChild, 1);\n nextRange.collapse(true);\n sel.removeAllRanges();\n sel.addRange(nextRange);\n\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n const span = document.createElement('span');\n span.style.fontSize = `${size}px`;\n span.appendChild(range.extractContents());\n range.insertNode(span);\n\n const nextRange = document.createRange();\n nextRange.selectNodeContents(span);\n sel.removeAllRanges();\n sel.addRange(nextRange);\n this.editor._syncCurrentBlockContent();\n }\n\n _bindFontSizeTracking() {\n if (!this._fontSizeSelect || this._onSelectionChange) return;\n this._onSelectionChange = () => {\n this._syncFontSizeSelect();\n this._syncStatefulButtons();\n };\n document.addEventListener('selectionchange', this._onSelectionChange);\n }\n\n _unbindFontSizeTracking() {\n if (!this._onSelectionChange) return;\n document.removeEventListener('selectionchange', this._onSelectionChange);\n this._onSelectionChange = null;\n }\n\n _syncFontSizeSelect() {\n if (!this._fontSizeSelect) return;\n const px = this._currentSelectionFontSizePx();\n if (!px) {\n this._fontSizeSelect.value = '';\n return;\n }\n const snapped = _closestFontSize(px, [13, 16, 20, 28, 36]);\n this._fontSizeSelect.value = String(snapped);\n }\n\n _currentSelectionFontSizePx() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const node = sel.focusNode;\n if (!node) return null;\n const elNode = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n if (!elNode) return null;\n const wrapper = this.editor._getSelectedBlockEl();\n if (!wrapper || !wrapper.contains(elNode)) return null;\n const raw = window.getComputedStyle(elNode).fontSize;\n const px = Number.parseFloat(raw || '');\n return Number.isFinite(px) ? px : null;\n }\n\n _createLinkPopover() {\n const pop = el('div', { className: 'fe-link-popover' });\n const input = el('input', { type: 'text', placeholder: 'Paste URL or search...', className: 'fe-link-input' });\n const applyBtn = el('button', {\n className: 'fe-btn fe-btn-primary fe-btn-sm',\n innerHTML: 'Apply',\n });\n const removeBtn = el('button', {\n className: 'fe-btn fe-btn-sm',\n innerHTML: 'Remove',\n });\n\n applyBtn.addEventListener('click', () => {\n this._restoreSavedLinkRange();\n if (input.value) {\n document.execCommand('createLink', false, input.value);\n // Style links\n const wrapper = this.editor._getSelectedBlockEl();\n if (wrapper) {\n wrapper.querySelectorAll('a').forEach((a) => {\n a.classList.add('fe-link');\n a.target = '_blank';\n a.rel = 'noopener';\n });\n }\n }\n this._hideLinkPopover();\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n });\n\n removeBtn.addEventListener('click', () => {\n this._restoreSavedLinkRange();\n document.execCommand('unlink', false, null);\n this._hideLinkPopover();\n this.editor._syncCurrentBlockContent();\n this._syncStatefulButtons();\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') { e.preventDefault(); applyBtn.click(); }\n if (e.key === 'Escape') this._hideLinkPopover();\n });\n\n pop.appendChild(input);\n pop.appendChild(applyBtn);\n pop.appendChild(removeBtn);\n return pop;\n }\n\n _showLinkPopover() {\n const sel = window.getSelection();\n if (!sel.rangeCount) return;\n const range = sel.getRangeAt(0);\n this._savedLinkRange = range.cloneRange();\n const rect = range.getBoundingClientRect();\n const wrapper = this.el.parentElement;\n if (!wrapper) return;\n\n if (!this._linkPopover.parentElement) {\n wrapper.appendChild(this._linkPopover);\n }\n\n this._linkPopover.style.top = (rect.bottom - wrapper.getBoundingClientRect().top + 6) + 'px';\n this._linkPopover.style.left = '0px';\n this._linkPopover.classList.add('fe-open');\n\n // Pre-fill if there's an existing link\n const anchor = sel.anchorNode?.parentElement?.closest('a');\n const input = this._linkPopover.querySelector('input');\n input.value = anchor ? anchor.href : '';\n setTimeout(() => input.focus(), 10);\n }\n\n _hideLinkPopover() {\n if (this._linkPopover) this._linkPopover.classList.remove('fe-open');\n }\n\n _getCurrentTableContext() {\n const wrapper = this.editor._getSelectedBlockEl();\n if (!wrapper) return null;\n const contentEl = wrapper.querySelector('.fe-block-content');\n if (!contentEl) return null;\n\n const sel = window.getSelection();\n let cell = null;\n if (sel && sel.rangeCount > 0) {\n let node = sel.anchorNode;\n if (node && node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (node && typeof node.closest === 'function') {\n const maybeCell = node.closest('td,th');\n if (maybeCell && contentEl.contains(maybeCell)) cell = maybeCell;\n }\n }\n\n const table = cell ? cell.closest('table') : contentEl.querySelector('table');\n if (!table) return null;\n if (!cell) cell = table.querySelector('td,th');\n if (!cell) return null;\n return { table, cell };\n }\n\n _addTableRow() {\n const ctx = this._getCurrentTableContext();\n if (!ctx) return;\n const { table, cell } = ctx;\n const currentRow = cell.closest('tr');\n if (!currentRow) return;\n\n const rowCells = Array.from(currentRow.querySelectorAll('th,td'));\n const colCount = Math.max(1, rowCells.length);\n const newRow = document.createElement('tr');\n for (let i = 0; i < colCount; i++) {\n const td = document.createElement('td');\n td.innerHTML = '<br>';\n newRow.appendChild(td);\n }\n\n if (currentRow.nextSibling) currentRow.parentNode.insertBefore(newRow, currentRow.nextSibling);\n else currentRow.parentNode.appendChild(newRow);\n\n const range = document.createRange();\n range.selectNodeContents(newRow.querySelector('td'));\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n this.editor._syncCurrentBlockContent();\n }\n\n _addTableColumn() {\n const ctx = this._getCurrentTableContext();\n if (!ctx) return;\n const { table, cell } = ctx;\n const currentRow = cell.closest('tr');\n if (!currentRow) return;\n\n const idx = Array.from(currentRow.querySelectorAll('th,td')).indexOf(cell);\n if (idx < 0) return;\n\n const rows = Array.from(table.querySelectorAll('tr'));\n rows.forEach((row) => {\n const cells = Array.from(row.querySelectorAll('th,td'));\n const ref = cells[Math.min(idx, cells.length - 1)];\n const newCell = document.createElement(ref && ref.tagName.toLowerCase() === 'th' ? 'th' : 'td');\n newCell.innerHTML = '<br>';\n if (ref && ref.nextSibling) row.insertBefore(newCell, ref.nextSibling);\n else row.appendChild(newCell);\n });\n\n const targetRowCells = Array.from(currentRow.querySelectorAll('th,td'));\n const focusCell = targetRowCells[Math.min(idx + 1, targetRowCells.length - 1)];\n if (focusCell) {\n const range = document.createRange();\n range.selectNodeContents(focusCell);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n this.editor._syncCurrentBlockContent();\n }\n\n _restoreSavedLinkRange() {\n if (!this._savedLinkRange) return;\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedLinkRange);\n }\n\n _syncStatefulButtons() {\n const wrapper = this.editor._getSelectedBlockEl();\n const sel = window.getSelection();\n const anchor = sel?.anchorNode?.parentElement?.closest('a');\n const hasSelectionInEditor =\n wrapper &&\n sel &&\n sel.rangeCount > 0 &&\n wrapper.contains(sel.anchorNode);\n\n this._statefulButtons.forEach(({ command, btn }) => {\n let active = false;\n if (hasSelectionInEditor) {\n if (command === 'link') {\n active = Boolean(anchor && wrapper.contains(anchor));\n } else {\n try {\n active = document.queryCommandState(command);\n } catch {\n active = false;\n }\n }\n }\n btn.classList.toggle('active', Boolean(active));\n });\n\n const inTable = this._isSelectionInTable(wrapper);\n const tableDisplay = inTable ? '' : 'none';\n if (this._tableToolsSep) this._tableToolsSep.style.display = tableDisplay;\n if (this._tableRowBtn) this._tableRowBtn.style.display = tableDisplay;\n if (this._tableColBtn) this._tableColBtn.style.display = tableDisplay;\n }\n\n _isSelectionInTable(wrapper) {\n if (!wrapper) return false;\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return false;\n let node = sel.anchorNode;\n if (!node) return false;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || typeof node.closest !== 'function') return false;\n const table = node.closest('table');\n return Boolean(table && wrapper.contains(table));\n }\n}\n\nfunction _closestFontSize(value, sizes) {\n let best = sizes[0];\n let bestDelta = Math.abs(value - best);\n for (let i = 1; i < sizes.length; i++) {\n const delta = Math.abs(value - sizes[i]);\n if (delta < bestDelta) {\n best = sizes[i];\n bestDelta = delta;\n }\n }\n return best;\n}\n","import { el } from '../utils/dom.js';\nimport { icons } from '../utils/icons.js';\nimport { CATEGORIES, getBlocksByCategory, searchBlocks } from '../blocks/registry.js';\n\n/**\n * Side panel for browsing and inserting block types.\n */\nexport class InserterPanel {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._searchInput = null;\n this._listEl = null;\n this._anchorEl = null;\n this._onDocMouseDown = null;\n this._onDocKeyDown = null;\n this._savedRange = null;\n this._mediaModal = null;\n this._mediaModalCard = null;\n this._mediaModalTitle = null;\n this._mediaModalBody = null;\n this._mediaModalResolver = null;\n this._forceNewBlock = false;\n }\n\n create() {\n this.el = el('div', { className: 'fe-inserter-panel' });\n\n // Header\n const header = el('div', { className: 'fe-inserter-header' });\n header.appendChild(el('h3', {}, ['Blocks']));\n const closeBtn = el('button', {\n className: 'fe-icon-btn fe-icon-btn-sm',\n innerHTML: icons.close,\n onClick: () => this.close(),\n });\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n // Search\n this._searchInput = el('input', {\n type: 'text',\n className: 'fe-inserter-search',\n placeholder: 'Search blocks...',\n });\n this._searchInput.addEventListener('input', () => this._renderList());\n this.el.appendChild(this._searchInput);\n\n // List\n this._listEl = el('div', { className: 'fe-inserter-list' });\n this.el.appendChild(this._listEl);\n\n this._renderList();\n this._createMediaModal();\n return this.el;\n }\n\n open(anchorEl = null, options = {}) {\n this._anchorEl = anchorEl || this._anchorEl;\n this._forceNewBlock = Boolean(options.forceNewBlock);\n this._savedRange = this._captureSelectionRange();\n this._positionNearAnchor();\n this.el.classList.add('fe-open');\n this._searchInput.value = '';\n this._renderList();\n this._bindGlobalCloseHandlers();\n setTimeout(() => this._searchInput.focus(), 20);\n }\n\n close() {\n this.el.classList.remove('fe-open');\n this._forceNewBlock = false;\n this._unbindGlobalCloseHandlers();\n }\n\n toggle(anchorEl = null, options = {}) {\n if (anchorEl) this._anchorEl = anchorEl;\n this.el.classList.contains('fe-open') ? this.close() : this.open(anchorEl, options);\n }\n\n isOpen() {\n return this.el.classList.contains('fe-open');\n }\n\n _renderList() {\n this._listEl.innerHTML = '';\n const query = this._searchInput?.value?.trim() || '';\n\n if (query) {\n const results = searchBlocks(query);\n if (results.length === 0) {\n this._listEl.appendChild(el('p', { className: 'fe-inserter-empty' }, ['No blocks found.']));\n return;\n }\n results.forEach((block) => this._listEl.appendChild(this._createBlockItem(block)));\n } else {\n for (const cat of CATEGORIES) {\n const blocks = getBlocksByCategory(cat.id);\n if (blocks.length === 0) continue;\n this._listEl.appendChild(el('div', { className: 'fe-inserter-category' }, [cat.label]));\n blocks.forEach((block) => this._listEl.appendChild(this._createBlockItem(block)));\n }\n }\n }\n\n _createBlockItem(blockDef) {\n const item = el('div', { className: 'fe-inserter-item' });\n item.appendChild(el('div', { className: 'fe-inserter-item-icon', innerHTML: blockDef.icon }));\n const info = el('div', { className: 'fe-inserter-item-info' });\n info.appendChild(el('h4', {}, [blockDef.label]));\n info.appendChild(el('p', {}, [blockDef.description]));\n item.appendChild(info);\n\n item.addEventListener('click', () => {\n this._insertFromPopover(blockDef.type);\n this.close();\n });\n\n return item;\n }\n\n _positionNearAnchor() {\n if (!this.el || !this._anchorEl) return;\n const rect = this._anchorEl.getBoundingClientRect();\n const gap = 8;\n const desiredLeft = Math.max(8, Math.min(window.innerWidth - 368, rect.left));\n const desiredTop = Math.max(8, Math.min(window.innerHeight - 520, rect.bottom + gap));\n this.el.style.left = `${desiredLeft}px`;\n this.el.style.top = `${desiredTop}px`;\n }\n\n _bindGlobalCloseHandlers() {\n this._onDocMouseDown = (e) => {\n if (!this.el?.classList.contains('fe-open')) return;\n if (this.el.contains(e.target)) return;\n if (this._anchorEl && this._anchorEl.contains(e.target)) return;\n this.close();\n };\n this._onDocKeyDown = (e) => {\n if (e.key === 'Escape') this.close();\n };\n document.addEventListener('mousedown', this._onDocMouseDown);\n document.addEventListener('keydown', this._onDocKeyDown);\n window.addEventListener('resize', () => this._positionNearAnchor(), { once: true });\n }\n\n _unbindGlobalCloseHandlers() {\n if (this._onDocMouseDown) {\n document.removeEventListener('mousedown', this._onDocMouseDown);\n this._onDocMouseDown = null;\n }\n if (this._onDocKeyDown) {\n document.removeEventListener('keydown', this._onDocKeyDown);\n this._onDocKeyDown = null;\n }\n }\n\n _captureSelectionRange() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n const range = sel.getRangeAt(0);\n const container = range.commonAncestorContainer;\n if (!this.editor.rootEl.contains(container)) return null;\n return range.cloneRange();\n }\n\n _restoreSelectionRange() {\n if (!this._savedRange) return false;\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(this._savedRange);\n return true;\n }\n\n async _insertFromPopover(type) {\n if (this._forceNewBlock) {\n const selectedId = this.editor._selectedBlockId;\n const block = this.editor.blockManager.addBlock(type, {}, selectedId || null);\n this.editor.render();\n this.editor.focusBlock(block.id);\n return;\n }\n\n const selectedId = this.editor._selectedBlockId;\n const selectedBlock = selectedId ? this.editor.blockManager.getBlock(selectedId) : null;\n const canInline =\n selectedBlock &&\n selectedBlock.type !== 'code' &&\n selectedBlock.type !== 'html' &&\n selectedBlock.type !== 'image' &&\n selectedBlock.type !== 'gallery' &&\n selectedBlock.type !== 'video' &&\n selectedBlock.type !== 'audio' &&\n selectedBlock.type !== 'file';\n\n if (!canInline) {\n if (!this.editor.insertSingleBlockType(type)) {\n this.editor.insertBlockAtSelection(type);\n }\n return;\n }\n\n this._restoreSelectionRange();\n const contentEl = this.editor._getBlockContentEl(selectedId);\n if (contentEl) contentEl.focus();\n\n if (type === 'paragraph' || type === 'heading' || type === 'heading-3' || type === 'heading-4' || type === 'quote') {\n const tag = type === 'paragraph'\n ? 'P'\n : type === 'heading'\n ? 'H2'\n : type === 'heading-3'\n ? 'H3'\n : type === 'heading-4'\n ? 'H4'\n : 'BLOCKQUOTE';\n document.execCommand('formatBlock', false, tag);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'list' || type === 'ordered-list') {\n document.execCommand(type === 'list' ? 'insertUnorderedList' : 'insertOrderedList', false, null);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'image') {\n const files = await this.editor.mediaUploader.openFilePicker('image/*');\n if (!files.length) return;\n const result = await this.editor.mediaUploader.processFile(files[0]);\n if (!result.error) {\n const src = result.remoteUrl || result.localUrl;\n document.execCommand('insertHTML', false, `<img src=\"${src}\" alt=\"\" />`);\n this.editor._syncCurrentBlockContent();\n }\n return;\n }\n\n if (type === 'video' || type === 'audio') {\n const source = await this._chooseMediaSource(type);\n if (!source) return;\n\n if (source === 'url') {\n const url = await this._promptForMediaUrl(type);\n if (!url) return;\n const trimmed = url.trim();\n if (!trimmed) return;\n if (type === 'video') {\n document.execCommand('insertHTML', false, `<video controls style=\"width:100%;max-width:100%;\" src=\"${trimmed}\"></video><p><br></p>`);\n } else {\n document.execCommand('insertHTML', false, `<audio controls style=\"width:100%;\" src=\"${trimmed}\"></audio><p><br></p>`);\n }\n this.editor._syncCurrentBlockContent();\n return;\n }\n }\n\n if (type === 'video' || type === 'audio' || type === 'file') {\n const accept = type === 'video' ? 'video/*' : type === 'audio' ? 'audio/*' : '*/*';\n const files = await this.editor.mediaUploader.openFilePicker(accept);\n if (!files.length) return;\n const file = files[0];\n const result = await this.editor.mediaUploader.processFile(file);\n if (result.error) {\n if (typeof this.editor._showToast === 'function') this.editor._showToast(result.error);\n return;\n }\n const src = result.remoteUrl || result.localUrl;\n if (!src) return;\n\n if (type === 'video') {\n document.execCommand('insertHTML', false, `<video controls style=\"width:100%;max-width:100%;\" src=\"${src}\"></video><p><br></p>`);\n } else if (type === 'audio') {\n document.execCommand('insertHTML', false, `<audio controls style=\"width:100%;\" src=\"${src}\"></audio><p><br></p>`);\n } else {\n document.execCommand('insertHTML', false, `<p><a href=\"${src}\" target=\"_blank\" rel=\"noopener\">${file.name || 'Download file'}</a></p><p><br></p>`);\n }\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (type === 'embed') {\n const url = window.prompt('Paste embed URL');\n if (!url) return;\n const trimmed = url.trim();\n if (!trimmed) return;\n document.execCommand('insertHTML', false, `<p><a href=\"${trimmed}\" target=\"_blank\" rel=\"noopener\">${trimmed}</a></p><p><br></p>`);\n this.editor._syncCurrentBlockContent();\n return;\n }\n\n if (!this.editor.insertSingleBlockType(type)) {\n this.editor.insertBlockAtSelection(type);\n }\n }\n\n async _chooseMediaSource(type) {\n if (typeof this.editor.options.onChooseMediaSource === 'function') {\n const selected = await this.editor.options.onChooseMediaSource(type);\n if (selected === 'url' || selected === 'upload') return selected;\n }\n return this._openMediaSourceModal(type);\n }\n\n _createMediaModal() {\n const overlay = el('div', { className: 'fe-media-modal-overlay' });\n const card = el('div', { className: 'fe-media-modal-card' });\n const title = el('h3', { className: 'fe-media-modal-title' }, ['Insert media']);\n const body = el('div', { className: 'fe-media-modal-body' });\n\n card.appendChild(title);\n card.appendChild(body);\n overlay.appendChild(card);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this._closeMediaModal(null);\n });\n\n this.editor.rootEl.appendChild(overlay);\n this._mediaModal = overlay;\n this._mediaModalCard = card;\n this._mediaModalTitle = title;\n this._mediaModalBody = body;\n }\n\n _openMediaSourceModal(type) {\n return new Promise((resolve) => {\n this._mediaModalResolver = resolve;\n this._mediaModalTitle.textContent = `Insert ${type}`;\n this._mediaModalBody.innerHTML = '';\n\n const desc = el('p', { className: 'fe-media-modal-desc' }, ['Choose how you want to add media']);\n const actions = el('div', { className: 'fe-media-modal-actions' });\n const uploadBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n type: 'button',\n innerHTML: 'Upload File',\n onClick: () => this._closeMediaModal('upload'),\n });\n const urlBtn = el('button', {\n className: 'fe-btn fe-btn-outline',\n type: 'button',\n innerHTML: 'Use URL',\n onClick: () => this._closeMediaModal('url'),\n });\n const cancelBtn = el('button', {\n className: 'fe-btn',\n type: 'button',\n innerHTML: 'Cancel',\n onClick: () => this._closeMediaModal(null),\n });\n actions.appendChild(uploadBtn);\n actions.appendChild(urlBtn);\n actions.appendChild(cancelBtn);\n this._mediaModalBody.appendChild(desc);\n this._mediaModalBody.appendChild(actions);\n\n this._mediaModal.classList.add('fe-open');\n });\n }\n\n _promptForMediaUrl(type) {\n return new Promise((resolve) => {\n this._mediaModalResolver = resolve;\n this._mediaModalTitle.textContent = `${type} URL`;\n this._mediaModalBody.innerHTML = '';\n\n const desc = el('p', { className: 'fe-media-modal-desc' }, ['Paste a direct media URL']);\n const input = el('input', {\n type: 'url',\n className: 'fe-media-modal-input',\n placeholder: `https://example.com/${type}.mp4`,\n });\n const actions = el('div', { className: 'fe-media-modal-actions' });\n const applyBtn = el('button', {\n className: 'fe-btn fe-btn-primary',\n type: 'button',\n innerHTML: 'Insert',\n onClick: () => this._closeMediaModal(input.value || null),\n });\n const cancelBtn = el('button', {\n className: 'fe-btn',\n type: 'button',\n innerHTML: 'Cancel',\n onClick: () => this._closeMediaModal(null),\n });\n\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this._closeMediaModal(input.value || null);\n }\n if (e.key === 'Escape') this._closeMediaModal(null);\n });\n\n actions.appendChild(applyBtn);\n actions.appendChild(cancelBtn);\n this._mediaModalBody.appendChild(desc);\n this._mediaModalBody.appendChild(input);\n this._mediaModalBody.appendChild(actions);\n this._mediaModal.classList.add('fe-open');\n setTimeout(() => input.focus(), 0);\n });\n }\n\n _closeMediaModal(value) {\n if (!this._mediaModal) return;\n this._mediaModal.classList.remove('fe-open');\n const resolver = this._mediaModalResolver;\n this._mediaModalResolver = null;\n if (resolver) resolver(value);\n }\n}\n","import { el } from '../utils/dom.js';\n\n/**\n * Right-hand settings panel with Post and Block tabs.\n */\nexport class SettingsPanel {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._activeTab = 'post';\n this._postTab = null;\n this._blockTab = null;\n this._tagInput = null;\n this._tags = [];\n this._categories = ['Uncategorized', 'Technology', 'Design', 'Business', 'Lifestyle'];\n this._featuredImage = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-settings-panel' });\n\n // Tabs\n const tabs = el('div', { className: 'fe-panel-tabs' });\n this._postTabBtn = el('button', { className: 'fe-panel-tab fe-active' }, ['Post']);\n this._blockTabBtn = el('button', { className: 'fe-panel-tab' }, ['Block']);\n this._postTabBtn.addEventListener('click', () => this._switchTab('post'));\n this._blockTabBtn.addEventListener('click', () => this._switchTab('block'));\n tabs.appendChild(this._postTabBtn);\n tabs.appendChild(this._blockTabBtn);\n this.el.appendChild(tabs);\n\n // Post tab content\n this._postTab = el('div', { className: 'fe-tab-content' });\n this._buildPostTab();\n this.el.appendChild(this._postTab);\n\n // Block tab content\n this._blockTab = el('div', { className: 'fe-tab-content', style: { display: 'none' } });\n this._buildBlockTab();\n this.el.appendChild(this._blockTab);\n\n return this.el;\n }\n\n open() { this.el.classList.add('fe-open'); }\n close() { this.el.classList.remove('fe-open'); }\n toggle() { this.el.classList.contains('fe-open') ? this.close() : this.open(); }\n isOpen() { return this.el.classList.contains('fe-open'); }\n\n updateBlockSettings(blockId) {\n this._blockSettingsContent.innerHTML = '';\n const block = this.editor.blockManager.getBlock(blockId);\n if (!block) {\n this._blockSettingsContent.innerHTML = '<p class=\"fe-muted fe-text-center\">Select a block to see its settings.</p>';\n return;\n }\n\n // Typography\n const section = el('div', { className: 'fe-panel-section' });\n section.appendChild(el('h3', { className: 'fe-section-title' }, ['Typography']));\n\n // Font size\n section.appendChild(el('label', {}, ['Font size']));\n const fontSelect = el('select', { className: 'fe-input' });\n [{ v: '', l: 'Default' }, { v: '13px', l: 'Small' }, { v: '16px', l: 'Medium' }, { v: '20px', l: 'Large' }, { v: '28px', l: 'Extra Large' }, { v: '36px', l: 'Huge' }]\n .forEach(({ v, l }) => fontSelect.appendChild(el('option', { value: v }, [l])));\n fontSelect.addEventListener('change', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.fontSize = fontSelect.value;\n });\n section.appendChild(fontSelect);\n\n // Line height\n section.appendChild(el('label', {}, ['Line height']));\n const lhInput = el('input', { type: 'text', className: 'fe-input', placeholder: '1.7' });\n lhInput.addEventListener('change', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl && lhInput.value) contentEl.style.lineHeight = lhInput.value;\n });\n section.appendChild(lhInput);\n\n this._blockSettingsContent.appendChild(section);\n\n // Color\n const colorSection = el('div', { className: 'fe-panel-section' });\n colorSection.appendChild(el('h3', { className: 'fe-section-title' }, ['Color']));\n\n // Text colors\n colorSection.appendChild(el('label', {}, ['Text color']));\n const textColors = el('div', { className: 'fe-color-grid' });\n ['#1e1e1e', '#cf2e2e', '#ff6900', '#fcb900', '#7bdcb5', '#00d084', '#0693e3', '#9b51e0'].forEach((c) => {\n const swatch = el('div', { className: 'fe-color-swatch', style: { background: c } });\n swatch.addEventListener('click', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.color = c;\n });\n textColors.appendChild(swatch);\n });\n colorSection.appendChild(textColors);\n\n // BG colors\n colorSection.appendChild(el('label', {}, ['Background color']));\n const bgColors = el('div', { className: 'fe-color-grid' });\n ['transparent', '#fcf0f0', '#fef8ee', '#fefce8', '#edf7f2', '#eef6fc', '#f3eafa', '#f0f0f1'].forEach((c) => {\n const swatch = el('div', { className: 'fe-color-swatch', style: { background: c === 'transparent' ? '#fff' : c, border: c === 'transparent' ? '2px solid #ddd' : 'none' } });\n swatch.addEventListener('click', () => {\n const contentEl = this.editor._getBlockContentEl(blockId);\n if (contentEl) contentEl.style.background = c;\n });\n bgColors.appendChild(swatch);\n });\n colorSection.appendChild(bgColors);\n\n this._blockSettingsContent.appendChild(colorSection);\n }\n\n _switchTab(tab) {\n this._activeTab = tab;\n this._postTabBtn.classList.toggle('fe-active', tab === 'post');\n this._blockTabBtn.classList.toggle('fe-active', tab === 'block');\n this._postTab.style.display = tab === 'post' ? 'block' : 'none';\n this._blockTab.style.display = tab === 'block' ? 'block' : 'none';\n }\n\n _buildPostTab() {\n // Summary\n const summary = this._section('Summary');\n summary.appendChild(this._field('Visibility', 'select', ['Public', 'Private', 'Password Protected']));\n summary.appendChild(this._field('Publish', 'select', ['Immediately', 'Schedule']));\n summary.appendChild(this._field('URL Slug', 'text', null, 'fe-url-slug'));\n summary.appendChild(this._field('Author', 'select', ['Admin', 'Editor', 'Author']));\n this._postTab.appendChild(summary);\n\n // Categories\n const cats = this._section('Categories');\n const catList = el('div', { className: 'fe-category-list' });\n this._categories.forEach((cat) => {\n const label = el('label', { className: 'fe-checkbox-label' });\n label.appendChild(el('input', { type: 'checkbox' }));\n label.appendChild(document.createTextNode(' ' + cat));\n catList.appendChild(label);\n });\n cats.appendChild(catList);\n const addCat = el('a', { href: '#', className: 'fe-add-link' }, ['+ Add New Category']);\n addCat.addEventListener('click', (e) => {\n e.preventDefault();\n const name = prompt('Category name:');\n if (name) {\n this._categories.push(name);\n const label = el('label', { className: 'fe-checkbox-label' });\n label.appendChild(el('input', { type: 'checkbox', checked: true }));\n label.appendChild(document.createTextNode(' ' + name));\n catList.appendChild(label);\n }\n });\n cats.appendChild(addCat);\n this._postTab.appendChild(cats);\n\n // Tags\n const tags = this._section('Tags');\n const tagWrapper = el('div', { className: 'fe-tag-input-wrapper' });\n const tagInput = el('input', { type: 'text', placeholder: 'Add tag...' });\n tagInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ',') {\n e.preventDefault();\n const val = tagInput.value.replace(',', '').trim();\n if (!val) return;\n this._tags.push(val);\n const tag = el('span', { className: 'fe-tag' });\n tag.appendChild(document.createTextNode(val + ' '));\n const remove = el('span', { className: 'fe-tag-remove', innerHTML: '&times;' });\n remove.addEventListener('click', () => {\n this._tags = this._tags.filter((t) => t !== val);\n tag.remove();\n });\n tag.appendChild(remove);\n tagWrapper.insertBefore(tag, tagInput);\n tagInput.value = '';\n }\n });\n tagWrapper.appendChild(tagInput);\n tagWrapper.addEventListener('click', () => tagInput.focus());\n tags.appendChild(tagWrapper);\n tags.appendChild(el('p', { className: 'fe-hint' }, ['Separate with commas or Enter key']));\n this._postTab.appendChild(tags);\n\n // Featured Image\n const fi = this._section('Featured Image');\n const fiArea = el('div', { className: 'fe-featured-image-area' });\n fiArea.appendChild(el('p', {}, ['Set featured image']));\n const fiInput = el('input', { type: 'file', accept: 'image/*', style: { display: 'none' } });\n fiInput.addEventListener('change', (e) => {\n const file = e.target.files[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (ev) => {\n fiArea.innerHTML = '';\n const img = el('img', { src: ev.target.result });\n img.style.maxWidth = '100%';\n img.style.borderRadius = '4px';\n fiArea.appendChild(img);\n this._featuredImage = ev.target.result;\n this.editor.emit('featuredImage:change', this._featuredImage);\n };\n reader.readAsDataURL(file);\n });\n fiArea.addEventListener('click', () => fiInput.click());\n fi.appendChild(fiArea);\n fi.appendChild(fiInput);\n this._postTab.appendChild(fi);\n\n // Excerpt\n const exc = this._section('Excerpt');\n exc.appendChild(el('textarea', { className: 'fe-input fe-textarea', placeholder: 'Write an excerpt (optional)' }));\n this._postTab.appendChild(exc);\n\n // Discussion\n const disc = this._section('Discussion');\n disc.appendChild(this._toggle('Allow comments', true));\n disc.appendChild(this._toggle('Allow pingbacks', false));\n this._postTab.appendChild(disc);\n }\n\n _buildBlockTab() {\n const section = el('div', { className: 'fe-panel-section' });\n section.appendChild(el('h3', { className: 'fe-section-title' }, ['Block Settings']));\n this._blockSettingsContent = el('div');\n this._blockSettingsContent.innerHTML = '<p class=\"fe-muted fe-text-center\">Select a block to see its settings.</p>';\n section.appendChild(this._blockSettingsContent);\n this._blockTab.appendChild(section);\n }\n\n _section(title) {\n const s = el('div', { className: 'fe-panel-section' });\n s.appendChild(el('h3', { className: 'fe-section-title' }, [title]));\n return s;\n }\n\n _field(label, type, options, id) {\n const frag = document.createDocumentFragment();\n frag.appendChild(el('label', {}, [label]));\n if (type === 'select') {\n const select = el('select', { className: 'fe-input' });\n if (id) select.id = id;\n (options || []).forEach((o) => select.appendChild(el('option', {}, [o])));\n frag.appendChild(select);\n } else {\n const input = el('input', { type, className: 'fe-input', placeholder: label.toLowerCase() });\n if (id) input.id = id;\n frag.appendChild(input);\n }\n return frag;\n }\n\n _toggle(label, defaultOn) {\n const row = el('div', { className: 'fe-toggle-row' });\n row.appendChild(el('label', {}, [label]));\n const btn = el('button', { className: `fe-toggle-switch ${defaultOn ? 'fe-on' : ''}` });\n btn.addEventListener('click', () => btn.classList.toggle('fe-on'));\n row.appendChild(btn);\n return row;\n }\n}\n","import { el } from '../utils/dom.js';\nimport { searchBlocks, BLOCK_TYPES } from '../blocks/registry.js';\n\n/**\n * Inline slash-command menu that appears when user types \"/\".\n */\nexport class SlashMenu {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._visible = false;\n this._highlightIndex = 0;\n this._items = [];\n this._targetBlock = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-slash-menu' });\n this._boundDocClick = (e) => {\n if (!e.target.closest('.fe-slash-menu')) this.close();\n };\n document.addEventListener('click', this._boundDocClick);\n return this.el;\n }\n\n /** Remove global listeners. Called by editor.destroy(). */\n destroy() {\n if (this._boundDocClick) {\n document.removeEventListener('click', this._boundDocClick);\n this._boundDocClick = null;\n }\n }\n\n open(block, rect) {\n this._targetBlock = block;\n this._visible = true;\n this._highlightIndex = 0;\n this.el.classList.add('fe-open');\n\n // Position near the caret\n const editorRect = this.editor.el.getBoundingClientRect();\n this.el.style.top = (rect.bottom - editorRect.top + 4) + 'px';\n this.el.style.left = (rect.left - editorRect.left) + 'px';\n\n this._filter('');\n }\n\n close() {\n this._visible = false;\n this._targetBlock = null;\n this.el.classList.remove('fe-open');\n }\n\n isOpen() {\n return this._visible;\n }\n\n filter(query) {\n this._filter(query);\n }\n\n handleKeydown(e) {\n if (!this._visible) return false;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._navigate(1);\n return true;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n this._navigate(-1);\n return true;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n const visible = this._items.filter((i) => i.el.style.display !== 'none');\n if (visible[this._highlightIndex]) {\n this._selectItem(visible[this._highlightIndex].type);\n }\n return true;\n }\n if (e.key === 'Escape') {\n this.close();\n return true;\n }\n return false;\n }\n\n _filter(query) {\n this.el.innerHTML = '';\n this._items = [];\n\n const allBlocks = query ? searchBlocks(query) : Object.entries(BLOCK_TYPES).map(([type, def]) => ({ type, ...def }));\n\n allBlocks.forEach((blockDef, i) => {\n const item = el('div', { className: `fe-slash-item ${i === 0 ? 'fe-highlighted' : ''}` });\n item.appendChild(el('div', { className: 'fe-slash-icon', innerHTML: blockDef.icon }));\n const info = el('div', { className: 'fe-slash-info' });\n info.appendChild(el('div', { className: 'fe-slash-label' }, [blockDef.label]));\n info.appendChild(el('div', { className: 'fe-slash-desc' }, [blockDef.description]));\n item.appendChild(info);\n\n item.addEventListener('click', () => this._selectItem(blockDef.type));\n item.addEventListener('mouseenter', () => {\n this.el.querySelectorAll('.fe-slash-item').forEach((el) => el.classList.remove('fe-highlighted'));\n item.classList.add('fe-highlighted');\n });\n\n this.el.appendChild(item);\n this._items.push({ el: item, type: blockDef.type });\n });\n\n if (this._items.length === 0) {\n this.el.appendChild(el('div', { className: 'fe-slash-empty' }, ['No blocks found']));\n }\n\n this._highlightIndex = 0;\n }\n\n _navigate(dir) {\n const visible = this._items.filter((i) => i.el.style.display !== 'none');\n visible.forEach((i) => i.el.classList.remove('fe-highlighted'));\n this._highlightIndex = Math.max(0, Math.min(visible.length - 1, this._highlightIndex + dir));\n if (visible[this._highlightIndex]) {\n visible[this._highlightIndex].el.classList.add('fe-highlighted');\n visible[this._highlightIndex].el.scrollIntoView({ block: 'nearest' });\n }\n }\n\n _selectItem(type) {\n if (!this._targetBlock) return;\n const block = this._targetBlock;\n const inserted = this.editor.insertSingleBlockType(type);\n if (inserted) {\n this.close();\n this.editor.render();\n this.editor.focusBlock(block.id);\n return;\n }\n\n // Change the block type and clear content\n this.editor.blockManager.changeBlockType(block.id, type);\n block.content = '';\n this.close();\n this.editor.render();\n this.editor.focusBlock(block.id);\n }\n}\n","import { el } from '../utils/dom.js';\n\n/**\n * Bottom status bar showing word count, character count, block count.\n */\nexport class StatusBar {\n constructor(editor) {\n this.editor = editor;\n this.el = null;\n this._wordEl = null;\n this._charEl = null;\n this._blockEl = null;\n this._savedEl = null;\n }\n\n create() {\n this.el = el('div', { className: 'fe-status-bar' });\n this._wordEl = el('span', {}, ['Words: 0']);\n this._charEl = el('span', {}, ['Characters: 0']);\n this._blockEl = el('span', {}, ['Blocks: 0']);\n this._savedEl = el('span', { className: 'fe-status-right' });\n\n this.el.appendChild(this._wordEl);\n this.el.appendChild(this._charEl);\n this.el.appendChild(this._blockEl);\n this.el.appendChild(this._savedEl);\n\n return this.el;\n }\n\n update() {\n const bm = this.editor.blockManager;\n const titleText = this.editor._titleEl ? this.editor._titleEl.value : '';\n const titleWords = titleText.trim().split(/\\s+/).filter((w) => w.length).length;\n const words = bm.getWordCount() + titleWords;\n const chars = bm.getCharCount() + titleText.replace(/\\s/g, '').length;\n\n this._wordEl.textContent = `Words: ${words}`;\n this._charEl.textContent = `Characters: ${chars}`;\n this._blockEl.textContent = `Blocks: ${bm.blocks.length}`;\n }\n\n setSaved(text) {\n this._savedEl.textContent = text;\n }\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\n\n/**\n * Dynamic plugin and block-type registry.\n *\n * Replaces the old static BLOCK_TYPES object with a dynamic system\n * that supports registering custom block types and plugins at runtime.\n *\n * @example\n * // Register a custom block type\n * editor.registerBlockType('callout', {\n * label: 'Callout',\n * description: 'A highlighted callout box.',\n * icon: '<svg>...</svg>',\n * category: 'design',\n * hasContent: true,\n * contentTag: 'div',\n * placeholder: 'Write callout...',\n * className: 'fe-callout-block',\n * });\n *\n * // Register a plugin (bundles block types + lifecycle hooks)\n * editor.registerPlugin({\n * name: 'my-plugin',\n * version: '1.0.0',\n * blocks: {\n * callout: { label: 'Callout', ... },\n * },\n * init(editor) { ... },\n * destroy() { ... },\n * });\n */\nexport class PluginRegistry extends EventEmitter {\n constructor() {\n super();\n /** @type {Map<string, Object>} Block type definitions keyed by type name */\n this._blockTypes = new Map();\n /** @type {Map<string, Object>} Registered plugins keyed by name */\n this._plugins = new Map();\n /** @type {Array<{id:string,label:string}>} Category list */\n this._categories = [];\n }\n\n /* ---- Block Type Registration ---- */\n\n /**\n * Register a new block type or override an existing one.\n * @param {string} type - Block type identifier (e.g. 'callout').\n * @param {Object} definition - Block type definition.\n * @returns {void}\n */\n registerBlockType(type, definition) {\n if (!type || typeof type !== 'string') {\n throw new Error('PluginRegistry: block type must be a non-empty string.');\n }\n if (!definition || typeof definition !== 'object') {\n throw new Error(`PluginRegistry: definition for \"${type}\" must be an object.`);\n }\n\n const def = {\n label: definition.label || type,\n description: definition.description || '',\n icon: definition.icon || '',\n category: definition.category || 'custom',\n hasContent: definition.hasContent !== false,\n contentTag: definition.contentTag || 'div',\n placeholder: definition.placeholder || '',\n className: definition.className || '',\n isMedia: Boolean(definition.isMedia),\n // Custom renderer (optional) — function(block, editor) => HTMLElement\n render: definition.render || null,\n // Custom HTML serializer (optional) — function(block) => string\n toHTML: definition.toHTML || null,\n // Custom HTML parser (optional) — function(html) => { type, content, attrs }\n fromHTML: definition.fromHTML || null,\n };\n\n const isNew = !this._blockTypes.has(type);\n this._blockTypes.set(type, def);\n\n // Auto-register category if it doesn't exist\n if (def.category && !this._categories.find(c => c.id === def.category)) {\n this._categories.push({ id: def.category, label: _capitalize(def.category) });\n }\n\n this.emit(isNew ? 'blockType:registered' : 'blockType:updated', type, def);\n }\n\n /**\n * Unregister a block type.\n */\n unregisterBlockType(type) {\n if (this._blockTypes.has(type)) {\n this._blockTypes.delete(type);\n this.emit('blockType:unregistered', type);\n }\n }\n\n /**\n * Get a block type definition.\n * @returns {Object|undefined}\n */\n getBlockType(type) {\n return this._blockTypes.get(type);\n }\n\n /**\n * Get all block types as a plain object (for backward compatibility).\n * @returns {Record<string, Object>}\n */\n getAllBlockTypes() {\n const obj = {};\n for (const [type, def] of this._blockTypes) {\n obj[type] = def;\n }\n return obj;\n }\n\n /**\n * Get blocks for a category.\n */\n getBlocksByCategory(catId) {\n const result = [];\n for (const [type, def] of this._blockTypes) {\n if (def.category === catId) result.push({ type, ...def });\n }\n return result;\n }\n\n /**\n * Search blocks by query string.\n */\n searchBlocks(query) {\n const q = query.toLowerCase();\n const result = [];\n for (const [type, def] of this._blockTypes) {\n if (\n type.includes(q) ||\n def.label.toLowerCase().includes(q) ||\n def.description.toLowerCase().includes(q)\n ) {\n result.push({ type, ...def });\n }\n }\n return result;\n }\n\n /**\n * Get registered categories.\n */\n getCategories() {\n return [...this._categories];\n }\n\n /**\n * Register a category.\n */\n registerCategory(id, label) {\n if (!this._categories.find(c => c.id === id)) {\n this._categories.push({ id, label: label || _capitalize(id) });\n this.emit('category:registered', id);\n }\n }\n\n /* ---- Plugin Registration ---- */\n\n /**\n * Register a plugin.\n * @param {Object} plugin - Plugin descriptor.\n * @param {string} plugin.name - Unique plugin name.\n * @param {string} [plugin.version] - Plugin version string.\n * @param {Object} [plugin.blocks] - Block type definitions to register.\n * @param {Function} [plugin.init] - Initialization function, receives editor instance.\n * @param {Function} [plugin.destroy] - Cleanup function.\n */\n registerPlugin(plugin) {\n if (!plugin || !plugin.name) {\n throw new Error('PluginRegistry: plugin must have a name.');\n }\n\n if (this._plugins.has(plugin.name)) {\n console.warn(`PluginRegistry: plugin \"${plugin.name}\" is already registered. Overwriting.`);\n this.unregisterPlugin(plugin.name);\n }\n\n this._plugins.set(plugin.name, plugin);\n\n // Register any block types bundled with the plugin\n if (plugin.blocks && typeof plugin.blocks === 'object') {\n for (const [type, def] of Object.entries(plugin.blocks)) {\n this.registerBlockType(type, { ...def, _plugin: plugin.name });\n }\n }\n\n this.emit('plugin:registered', plugin.name, plugin);\n return plugin;\n }\n\n /**\n * Initialize all registered plugins with the given editor instance.\n */\n initPlugins(editor) {\n for (const [, plugin] of this._plugins) {\n if (typeof plugin.init === 'function') {\n try {\n plugin.init(editor);\n } catch (err) {\n console.error(`PluginRegistry: error initializing plugin \"${plugin.name}\":`, err);\n }\n }\n }\n }\n\n /**\n * Unregister a plugin and its block types.\n */\n unregisterPlugin(name) {\n const plugin = this._plugins.get(name);\n if (!plugin) return;\n\n // Call destroy if available\n if (typeof plugin.destroy === 'function') {\n try { plugin.destroy(); } catch { /* ignore */ }\n }\n\n // Unregister block types that belong to this plugin\n if (plugin.blocks) {\n for (const type of Object.keys(plugin.blocks)) {\n this.unregisterBlockType(type);\n }\n }\n\n this._plugins.delete(name);\n this.emit('plugin:unregistered', name);\n }\n\n /**\n * Get a registered plugin.\n */\n getPlugin(name) {\n return this._plugins.get(name) || null;\n }\n\n /**\n * Get all registered plugin names.\n */\n getPluginNames() {\n return Array.from(this._plugins.keys());\n }\n\n /**\n * Destroy all plugins.\n */\n destroyAll() {\n for (const name of this._plugins.keys()) {\n this.unregisterPlugin(name);\n }\n }\n}\n\nfunction _capitalize(str) {\n if (!str) return '';\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n","/**\n * Block-level diff engine for change tracking.\n *\n * Tracks structural and content changes between block snapshots:\n * - Block added / removed / moved\n * - Block content or attributes changed\n *\n * @example\n * const differ = new Differ();\n * differ.setBaseline(blockManager.toJSON());\n * // ... user edits ...\n * const patches = differ.diff(blockManager.toJSON());\n * // => [{ op: 'update', id: 'blk_1', changes: { content: { from: '...', to: '...' } } }]\n */\nexport class Differ {\n constructor() {\n /** @type {Array<Object>|null} Previous snapshot */\n this._baseline = null;\n /** @type {Array<Object>} Accumulated patches since last getChanges() */\n this._pendingPatches = [];\n }\n\n /**\n * Set the baseline snapshot for diffing.\n * @param {Array<Object>} blocks - Array of block objects from toJSON().\n */\n setBaseline(blocks) {\n this._baseline = _deepClone(blocks);\n }\n\n /**\n * Compute diff between baseline and current state.\n * Updates baseline to current state after diffing.\n *\n * @param {Array<Object>} currentBlocks - Current block state.\n * @returns {Array<Object>} Array of patch operations.\n */\n diff(currentBlocks) {\n if (!this._baseline) {\n this._baseline = _deepClone(currentBlocks);\n return [];\n }\n\n const patches = _computeDiff(this._baseline, currentBlocks);\n this._baseline = _deepClone(currentBlocks);\n this._pendingPatches.push(...patches);\n return patches;\n }\n\n /**\n * Get all accumulated patches and clear the buffer.\n * @returns {Array<Object>}\n */\n getChanges() {\n const changes = [...this._pendingPatches];\n this._pendingPatches = [];\n return changes;\n }\n\n /**\n * Check if there are pending changes.\n * @returns {boolean}\n */\n hasChanges() {\n return this._pendingPatches.length > 0;\n }\n\n /**\n * Clear all state.\n */\n reset() {\n this._baseline = null;\n this._pendingPatches = [];\n }\n}\n\n/**\n * Apply an array of patches to a blocks array.\n * @param {Array<Object>} blocks - Original blocks.\n * @param {Array<Object>} patches - Patches to apply.\n * @returns {Array<Object>} New blocks array with patches applied.\n */\nexport function applyPatches(blocks, patches) {\n let result = _deepClone(blocks);\n\n for (const patch of patches) {\n switch (patch.op) {\n case 'add': {\n const newBlock = { ...patch.block };\n if (typeof patch.index === 'number' && patch.index <= result.length) {\n result.splice(patch.index, 0, newBlock);\n } else {\n result.push(newBlock);\n }\n break;\n }\n\n case 'remove': {\n result = result.filter(b => b.id !== patch.id);\n break;\n }\n\n case 'update': {\n const block = result.find(b => b.id === patch.id);\n if (block && patch.changes) {\n for (const [key, change] of Object.entries(patch.changes)) {\n block[key] = change.to;\n }\n }\n break;\n }\n\n case 'move': {\n const fromIdx = result.findIndex(b => b.id === patch.id);\n if (fromIdx !== -1) {\n const [moved] = result.splice(fromIdx, 1);\n result.splice(patch.toIndex, 0, moved);\n }\n break;\n }\n }\n }\n\n return result;\n}\n\n/* ---- Internal ---- */\n\nfunction _computeDiff(oldBlocks, newBlocks) {\n const patches = [];\n const oldMap = new Map(oldBlocks.map(b => [b.id, b]));\n const newMap = new Map(newBlocks.map(b => [b.id, b]));\n\n // Detect removed blocks\n for (const old of oldBlocks) {\n if (!newMap.has(old.id)) {\n patches.push({\n op: 'remove',\n id: old.id,\n block: { ...old },\n });\n }\n }\n\n // Detect added blocks\n for (let i = 0; i < newBlocks.length; i++) {\n const block = newBlocks[i];\n if (!oldMap.has(block.id)) {\n patches.push({\n op: 'add',\n id: block.id,\n index: i,\n block: { ...block },\n });\n }\n }\n\n // Detect updated blocks\n for (const newBlock of newBlocks) {\n const oldBlock = oldMap.get(newBlock.id);\n if (!oldBlock) continue;\n\n const changes = {};\n if (oldBlock.type !== newBlock.type) {\n changes.type = { from: oldBlock.type, to: newBlock.type };\n }\n if (oldBlock.content !== newBlock.content) {\n changes.content = { from: oldBlock.content, to: newBlock.content };\n }\n if (JSON.stringify(oldBlock.attrs) !== JSON.stringify(newBlock.attrs)) {\n changes.attrs = { from: oldBlock.attrs, to: newBlock.attrs };\n }\n\n if (Object.keys(changes).length > 0) {\n patches.push({\n op: 'update',\n id: newBlock.id,\n changes,\n });\n }\n }\n\n // Detect moved blocks (position changes among surviving blocks)\n const survivingOld = oldBlocks.filter(b => newMap.has(b.id)).map(b => b.id);\n const survivingNew = newBlocks.filter(b => oldMap.has(b.id)).map(b => b.id);\n\n if (survivingOld.length === survivingNew.length && survivingOld.length > 0) {\n for (let i = 0; i < survivingOld.length; i++) {\n if (survivingOld[i] !== survivingNew[i]) {\n // Find what moved\n const id = survivingNew[i];\n const oldIdx = survivingOld.indexOf(id);\n if (oldIdx !== i) {\n patches.push({\n op: 'move',\n id,\n fromIndex: oldIdx,\n toIndex: i,\n });\n }\n }\n }\n }\n\n return patches;\n}\n\nfunction _deepClone(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\n","import { EventEmitter } from '../utils/EventEmitter.js';\nimport { Differ, applyPatches } from './Differ.js';\n\n/**\n * Foundation for collaborative editing via WebSocket.\n *\n * Provides block-level synchronization using diffs. Each client\n * sends local changes to a server, which broadcasts them to\n * other clients. Conflicts are resolved at the block level using\n * version numbers.\n *\n * @example\n * const collab = editor.connectCollaborative('wss://my-server.com/doc/123', {\n * userId: 'user_abc',\n * token: 'jwt_...',\n * });\n *\n * collab.on('connected', () => console.log('Connected'));\n * collab.on('remote:change', (patches) => console.log('Remote changes:', patches));\n * collab.on('disconnected', () => console.log('Disconnected'));\n *\n * // Later:\n * collab.disconnect();\n */\nexport class CollaborativeManager extends EventEmitter {\n /**\n * @param {Object} editor - NBDEditor instance.\n * @param {string} wsUrl - WebSocket server URL.\n * @param {Object} [options]\n * @param {string} [options.userId] - Current user identifier.\n * @param {string} [options.token] - Auth token for WebSocket.\n * @param {number} [options.debounceMs=500] - Debounce interval for sending local changes.\n * @param {number} [options.reconnectMs=3000] - Reconnect delay after disconnection.\n * @param {number} [options.maxReconnectAttempts=10] - Max reconnection attempts.\n */\n constructor(editor, wsUrl, options = {}) {\n super();\n this.editor = editor;\n this.wsUrl = wsUrl;\n this.options = {\n userId: options.userId || `user_${Date.now().toString(36)}`,\n token: options.token || null,\n debounceMs: options.debounceMs || 500,\n reconnectMs: options.reconnectMs || 3000,\n maxReconnectAttempts: options.maxReconnectAttempts || 10,\n };\n\n this._ws = null;\n this._differ = new Differ();\n this._connected = false;\n this._reconnectAttempts = 0;\n this._debounceTimer = null;\n this._version = 0;\n this._pendingOps = [];\n this._localChanges = [];\n this._cleanup = null;\n }\n\n /**\n * Connect to the WebSocket server.\n */\n connect() {\n if (this._ws) return;\n\n try {\n const url = new URL(this.wsUrl);\n if (this.options.token) {\n url.searchParams.set('token', this.options.token);\n }\n url.searchParams.set('userId', this.options.userId);\n\n this._ws = new WebSocket(url.toString());\n this._setupWebSocket();\n } catch (err) {\n this.emit('error', err);\n }\n\n // Set baseline for diffing\n this._differ.setBaseline(this.editor.blockManager.toJSON());\n\n // Listen for local changes\n this._cleanup = this.editor.blockManager.on('change', () => {\n this._onLocalChange();\n });\n\n return this;\n }\n\n /**\n * Disconnect from the server.\n */\n disconnect() {\n if (this._debounceTimer) clearTimeout(this._debounceTimer);\n if (this._cleanup) this._cleanup();\n\n if (this._ws) {\n this._ws.onclose = null; // Prevent reconnect\n this._ws.close(1000, 'Client disconnect');\n this._ws = null;\n }\n\n this._connected = false;\n this._reconnectAttempts = 0;\n this.emit('disconnected');\n }\n\n /**\n * Check if currently connected.\n */\n isConnected() {\n return this._connected;\n }\n\n /**\n * Send a manual sync request to get the latest document state.\n */\n requestSync() {\n this._send({ type: 'sync:request', version: this._version });\n }\n\n /* ---- Internal ---- */\n\n _setupWebSocket() {\n if (!this._ws) return;\n\n this._ws.onopen = () => {\n this._connected = true;\n this._reconnectAttempts = 0;\n this.emit('connected');\n\n // Send join message\n this._send({\n type: 'join',\n userId: this.options.userId,\n version: this._version,\n });\n };\n\n this._ws.onmessage = (event) => {\n try {\n const msg = JSON.parse(event.data);\n this._handleMessage(msg);\n } catch {\n // Ignore malformed messages\n }\n };\n\n this._ws.onclose = (event) => {\n this._connected = false;\n this.emit('disconnected', event.code, event.reason);\n\n // Auto-reconnect\n if (this._reconnectAttempts < this.options.maxReconnectAttempts) {\n this._reconnectAttempts++;\n setTimeout(() => {\n this._ws = null;\n this.connect();\n this.emit('reconnecting', this._reconnectAttempts);\n }, this.options.reconnectMs);\n } else {\n this.emit('reconnect:failed');\n }\n };\n\n this._ws.onerror = (err) => {\n this.emit('error', err);\n };\n }\n\n _handleMessage(msg) {\n switch (msg.type) {\n case 'sync:state': {\n // Full document state from server\n if (Array.isArray(msg.blocks)) {\n this.editor.blockManager.fromJSON(msg.blocks);\n this.editor.render();\n this._differ.setBaseline(msg.blocks);\n this._version = msg.version || 0;\n }\n break;\n }\n\n case 'patches': {\n // Remote patches from another client\n if (msg.userId === this.options.userId) break; // Skip own echoes\n if (!Array.isArray(msg.patches)) break;\n\n const currentBlocks = this.editor.blockManager.toJSON();\n const updatedBlocks = applyPatches(currentBlocks, msg.patches);\n this.editor.blockManager.fromJSON(updatedBlocks);\n this.editor.render();\n this._differ.setBaseline(updatedBlocks);\n this._version = msg.version || this._version + 1;\n\n this.emit('remote:change', msg.patches, msg.userId);\n break;\n }\n\n case 'ack': {\n // Server acknowledged our patches\n this._version = msg.version || this._version;\n this.emit('ack', msg.version);\n break;\n }\n\n case 'error': {\n this.emit('server:error', msg.message);\n break;\n }\n }\n }\n\n _onLocalChange() {\n // Debounce sending changes\n if (this._debounceTimer) clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._sendLocalChanges();\n }, this.options.debounceMs);\n }\n\n _sendLocalChanges() {\n if (!this._connected || !this._ws) return;\n\n const currentBlocks = this.editor.blockManager.toJSON();\n const patches = this._differ.diff(currentBlocks);\n\n if (patches.length === 0) return;\n\n this._send({\n type: 'patches',\n userId: this.options.userId,\n version: this._version,\n patches,\n });\n\n this.emit('local:change', patches);\n }\n\n _send(data) {\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify(data));\n }\n }\n}\n","/**\n * HTML sanitization utility.\n *\n * Uses DOMPurify when available; falls back to a simple DOM-based\n * sanitizer that strips <script>, event attributes, and javascript: URIs.\n */\n\nlet _DOMPurify = null;\n\n// Try to load DOMPurify (optional peer dependency)\ntry {\n _DOMPurify = require('isomorphic-dompurify');\n if (_DOMPurify && _DOMPurify.default) _DOMPurify = _DOMPurify.default;\n} catch {\n // DOMPurify not installed — use fallback\n}\n\n/**\n * Default allowed tags and attributes for the editor.\n */\nconst DEFAULT_CONFIG = {\n ALLOWED_TAGS: [\n 'p', 'br', 'b', 'i', 'u', 's', 'em', 'strong', 'a', 'img',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'ul', 'ol', 'li',\n 'blockquote', 'pre', 'code',\n 'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td',\n 'figure', 'figcaption', 'hr',\n 'div', 'span', 'section',\n 'video', 'audio', 'source', 'iframe',\n 'sub', 'sup', 'mark', 'del', 'ins',\n ],\n ALLOWED_ATTR: [\n 'href', 'target', 'rel', 'title',\n 'src', 'alt', 'width', 'height',\n 'class', 'id', 'style',\n 'controls', 'autoplay', 'loop', 'muted', 'preload',\n 'colspan', 'rowspan', 'scope',\n 'border', 'cellpadding', 'cellspacing',\n 'download', 'type',\n 'data-*',\n ],\n ALLOW_DATA_ATTR: true,\n ADD_ATTR: ['target'],\n};\n\n/**\n * Fallback sanitizer when DOMPurify is not available.\n * Uses the browser's DOMParser to strip dangerous content.\n */\nfunction _fallbackSanitize(html, config) {\n if (!html || typeof html !== 'string') return '';\n if (typeof document === 'undefined') return html; // SSR: return as-is\n\n const allowedTags = new Set((config.ALLOWED_TAGS || DEFAULT_CONFIG.ALLOWED_TAGS).map(t => t.toLowerCase()));\n const allowedAttrs = new Set((config.ALLOWED_ATTR || DEFAULT_CONFIG.ALLOWED_ATTR).map(a => a.toLowerCase()));\n const allowDataAttr = config.ALLOW_DATA_ATTR !== false;\n\n const doc = new DOMParser().parseFromString(html, 'text/html');\n const body = doc.body;\n\n // Remove disallowed elements\n const allElements = Array.from(body.querySelectorAll('*'));\n for (const el of allElements) {\n const tag = el.tagName.toLowerCase();\n\n // Remove scripts and dangerous tags entirely\n if (tag === 'script' || tag === 'style' || tag === 'link' || tag === 'meta' || tag === 'noscript') {\n el.remove();\n continue;\n }\n\n // If tag not allowed, unwrap (keep children)\n if (!allowedTags.has(tag)) {\n while (el.firstChild) el.parentNode.insertBefore(el.firstChild, el);\n el.remove();\n continue;\n }\n\n // Remove disallowed attributes\n const attrs = Array.from(el.attributes);\n for (const attr of attrs) {\n const name = attr.name.toLowerCase();\n\n // Always remove event handlers\n if (name.startsWith('on')) {\n el.removeAttribute(attr.name);\n continue;\n }\n\n // Allow data-* attributes if enabled\n if (name.startsWith('data-') && allowDataAttr) continue;\n\n // Check against allowed list\n if (!allowedAttrs.has(name) && !allowedAttrs.has('data-*')) {\n el.removeAttribute(attr.name);\n continue;\n }\n\n // Strip javascript: URIs\n if ((name === 'href' || name === 'src' || name === 'action') &&\n /^\\s*javascript\\s*:/i.test(attr.value)) {\n el.removeAttribute(attr.name);\n }\n }\n }\n\n return body.innerHTML;\n}\n\n/**\n * Create a sanitizer function with the given configuration.\n *\n * @param {Object} [config] - DOMPurify-compatible config overrides.\n * @returns {(html: string) => string} A sanitizer function.\n *\n * @example\n * const sanitize = createSanitizer();\n * sanitize('<p>Hello</p><script>alert(\"xss\")</script>');\n * // => '<p>Hello</p>'\n */\nexport function createSanitizer(config = {}) {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config };\n\n if (_DOMPurify && typeof _DOMPurify.sanitize === 'function') {\n return function sanitize(html) {\n if (!html || typeof html !== 'string') return '';\n return _DOMPurify.sanitize(html, mergedConfig);\n };\n }\n\n // Fallback\n return function sanitize(html) {\n if (!html || typeof html !== 'string') return '';\n return _fallbackSanitize(html, mergedConfig);\n };\n}\n\n/**\n * Default sanitizer instance with standard editor config.\n */\nexport const sanitize = createSanitizer();\n","/**\n * HTML Normalizer — canonicalizes HTML for consistent round-tripping.\n *\n * Addresses the problem where:\n * editor.setData(html) → editor.toHTML()\n * produces slightly different HTML due to whitespace, attribute ordering,\n * or empty tag differences.\n *\n * @example\n * import { normalizeHTML } from './HtmlNormalizer.js';\n * const canonical = normalizeHTML('<p> Hello </p>');\n * // => '<p>Hello</p>'\n */\n\n/**\n * Normalize an HTML string to a canonical form.\n * @param {string} html - Raw HTML string.\n * @returns {string} Normalized HTML.\n */\nexport function normalizeHTML(html) {\n if (!html || typeof html !== 'string') return '';\n\n // SSR guard\n if (typeof document === 'undefined') return html.trim();\n\n const doc = new DOMParser().parseFromString(`<div>${html}</div>`, 'text/html');\n const container = doc.body.firstChild;\n\n _normalizeNode(container);\n\n return container.innerHTML.trim();\n}\n\n/**\n * Compare two HTML strings for semantic equality.\n * @param {string} a\n * @param {string} b\n * @returns {boolean}\n */\nexport function htmlEquals(a, b) {\n return normalizeHTML(a) === normalizeHTML(b);\n}\n\n/* ---- Internal ---- */\n\nfunction _normalizeNode(node) {\n if (!node) return;\n\n // Process children first (bottom-up)\n const children = Array.from(node.childNodes);\n for (const child of children) {\n if (child.nodeType === 3) { // TEXT_NODE\n // Collapse internal whitespace (but preserve single spaces)\n let text = child.textContent;\n text = text.replace(/[\\t\\r\\n]+/g, ' '); // tabs/newlines → space\n text = text.replace(/ {2,}/g, ' '); // multiple spaces → single\n child.textContent = text;\n\n // Remove empty text nodes\n if (text.trim() === '' && _isBlockElement(node)) {\n node.removeChild(child);\n }\n } else if (child.nodeType === 1) { // ELEMENT_NODE\n _normalizeElement(child);\n _normalizeNode(child);\n }\n }\n\n // Remove empty inline elements (e.g. <strong></strong>)\n for (const child of Array.from(node.childNodes)) {\n if (child.nodeType === 1 && _isEmptyInline(child)) {\n node.removeChild(child);\n }\n }\n}\n\nfunction _normalizeElement(el) {\n // Sort attributes alphabetically for consistent output\n const attrs = Array.from(el.attributes)\n .sort((a, b) => a.name.localeCompare(b.name));\n\n // Remove and re-add in sorted order\n for (const attr of Array.from(el.attributes)) {\n el.removeAttributeNode(attr);\n }\n for (const attr of attrs) {\n // Normalize attribute values\n let value = attr.value;\n\n // Normalize style attribute\n if (attr.name === 'style') {\n value = _normalizeStyle(value);\n if (!value) continue; // Skip empty styles\n }\n\n // Remove empty class attributes\n if (attr.name === 'class' && !value.trim()) continue;\n\n el.setAttribute(attr.name, value);\n }\n\n // Normalize self-closing tags (img, br, hr, input)\n // (handled by browser serialization already)\n}\n\nfunction _normalizeStyle(style) {\n if (!style || typeof style !== 'string') return '';\n\n return style\n .split(';')\n .map(s => s.trim())\n .filter(Boolean)\n .map(s => {\n const [prop, ...vals] = s.split(':');\n return `${prop.trim().toLowerCase()}:${vals.join(':').trim()}`;\n })\n .sort()\n .join(';');\n}\n\nfunction _isBlockElement(node) {\n if (node.nodeType !== 1) return false;\n const tag = node.tagName.toLowerCase();\n return /^(div|p|h[1-6]|blockquote|pre|ul|ol|li|table|thead|tbody|tr|td|th|figure|figcaption|section|article|main|header|footer|nav|aside|form|fieldset|details|summary|hr)$/.test(tag);\n}\n\nfunction _isEmptyInline(node) {\n if (node.nodeType !== 1) return false;\n const tag = node.tagName.toLowerCase();\n // Don't remove self-closing or semantic elements\n if (/^(br|hr|img|input|video|audio|iframe|source)$/.test(tag)) return false;\n // Check if inline\n if (_isBlockElement(node)) return false;\n // Empty if no text content and no meaningful children\n return node.textContent.trim() === '' && !node.querySelector('img,video,audio,iframe,br');\n}\n","/**\n * Delta-like structured data format for NBDEditor.\n *\n * Provides an opt-in alternative representation alongside HTML.\n * Each block is converted to an array of inline operations (ops),\n * preserving formatting information in a structured way.\n *\n * Format:\n * [\n * {\n * blockId: 'blk_...',\n * blockType: 'paragraph',\n * blockAttrs: {},\n * ops: [\n * { insert: 'Hello ', attrs: {} },\n * { insert: 'world', attrs: { bold: true } },\n * { insert: '\\n', attrs: {} },\n * ]\n * },\n * ...\n * ]\n *\n * @example\n * import { htmlToDelta, deltaToHTML } from './DeltaFormat.js';\n * const delta = blocksToDelta(blocks);\n * const html = deltaToHTML(delta);\n */\n\n/**\n * Convert an array of blocks to Delta format.\n * @param {Array<{id, type, content, attrs}>} blocks\n * @returns {Array<Object>} Delta representation.\n */\nexport function blocksToDelta(blocks) {\n if (!Array.isArray(blocks)) return [];\n return blocks.map((block) => ({\n blockId: block.id,\n blockType: block.type,\n blockAttrs: { ...(block.attrs || {}) },\n ops: _htmlToOps(block.content || '', block.type),\n }));\n}\n\n/**\n * Convert Delta format back to blocks array.\n * @param {Array<Object>} delta\n * @returns {Array<{id, type, content, attrs}>}\n */\nexport function deltaToBlocks(delta) {\n if (!Array.isArray(delta)) return [];\n return delta.map((entry) => ({\n id: entry.blockId,\n type: entry.blockType,\n content: _opsToHTML(entry.ops || [], entry.blockType),\n attrs: { ...(entry.blockAttrs || {}) },\n }));\n}\n\n/**\n * Convert a single HTML string to Delta ops.\n * @param {string} html\n * @param {string} blockType\n * @returns {Array<{insert: string, attrs: Object}>}\n */\nexport function htmlToOps(html, blockType = 'paragraph') {\n return _htmlToOps(html, blockType);\n}\n\n/**\n * Convert Delta ops to HTML string.\n * @param {Array<{insert: string, attrs: Object}>} ops\n * @param {string} blockType\n * @returns {string}\n */\nexport function opsToHTML(ops, blockType = 'paragraph') {\n return _opsToHTML(ops, blockType);\n}\n\n/* ---- Internal Helpers ---- */\n\nfunction _htmlToOps(html, blockType) {\n if (!html || typeof html !== 'string') return [{ insert: '\\n', attrs: {} }];\n\n // For code blocks, treat as plain text\n if (blockType === 'code' || blockType === 'html') {\n return [{ insert: html, attrs: {} }];\n }\n\n // Parse HTML using DOM\n if (typeof document === 'undefined') {\n // SSR fallback: return raw HTML as single op\n return [{ insert: html, attrs: { _raw: true } }];\n }\n\n const doc = new DOMParser().parseFromString(`<div>${html}</div>`, 'text/html');\n const container = doc.body.firstChild;\n const ops = [];\n\n _walkNodes(container, {}, ops);\n\n // Ensure we end with a newline\n if (ops.length === 0 || !ops[ops.length - 1].insert.endsWith('\\n')) {\n ops.push({ insert: '\\n', attrs: {} });\n }\n\n return ops;\n}\n\nfunction _walkNodes(node, parentAttrs, ops) {\n for (const child of node.childNodes) {\n if (child.nodeType === 3) { // TEXT_NODE\n const text = child.textContent;\n if (text) {\n ops.push({ insert: text, attrs: { ...parentAttrs } });\n }\n } else if (child.nodeType === 1) { // ELEMENT_NODE\n const tag = child.tagName.toLowerCase();\n const attrs = { ...parentAttrs };\n\n // Track inline formatting\n if (tag === 'strong' || tag === 'b') attrs.bold = true;\n if (tag === 'em' || tag === 'i') attrs.italic = true;\n if (tag === 'u') attrs.underline = true;\n if (tag === 's' || tag === 'del' || tag === 'strike') attrs.strike = true;\n if (tag === 'code') attrs.code = true;\n if (tag === 'sub') attrs.sub = true;\n if (tag === 'sup') attrs.sup = true;\n if (tag === 'mark') attrs.highlight = true;\n\n // Links\n if (tag === 'a') {\n attrs.link = child.getAttribute('href') || '';\n if (child.getAttribute('target')) attrs.target = child.getAttribute('target');\n }\n\n // Images (inline)\n if (tag === 'img') {\n ops.push({\n insert: { type: 'image', src: child.getAttribute('src') || '' },\n attrs: {\n alt: child.getAttribute('alt') || '',\n width: child.getAttribute('width') || '',\n },\n });\n continue;\n }\n\n // Line breaks\n if (tag === 'br') {\n ops.push({ insert: '\\n', attrs: {} });\n continue;\n }\n\n // Block-level elements add newlines\n const isBlock = /^(p|div|h[1-6]|li|blockquote|pre|tr|figure|figcaption)$/.test(tag);\n\n _walkNodes(child, attrs, ops);\n\n if (isBlock) {\n ops.push({ insert: '\\n', attrs: {} });\n }\n }\n }\n}\n\nfunction _opsToHTML(ops, blockType) {\n if (!Array.isArray(ops) || ops.length === 0) return '';\n\n // For code/html blocks, return plain text\n if (blockType === 'code' || blockType === 'html') {\n return ops.map(op => typeof op.insert === 'string' ? op.insert : '').join('');\n }\n\n let html = '';\n for (const op of ops) {\n if (typeof op.insert === 'object' && op.insert !== null) {\n // Embedded object (e.g. image)\n if (op.insert.type === 'image') {\n html += `<img src=\"${_escAttr(op.insert.src)}\" alt=\"${_escAttr(op.attrs?.alt || '')}\">`;\n }\n continue;\n }\n\n if (typeof op.insert !== 'string') continue;\n\n let text = op.insert;\n // Don't convert trailing newlines to <br>\n if (text === '\\n') continue;\n\n // Escape HTML entities in text\n text = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n\n // Replace internal newlines with <br>\n text = text.replace(/\\n/g, '<br>');\n\n // Apply formatting\n const a = op.attrs || {};\n if (a.code) text = `<code>${text}</code>`;\n if (a.bold) text = `<strong>${text}</strong>`;\n if (a.italic) text = `<em>${text}</em>`;\n if (a.underline) text = `<u>${text}</u>`;\n if (a.strike) text = `<s>${text}</s>`;\n if (a.sub) text = `<sub>${text}</sub>`;\n if (a.sup) text = `<sup>${text}</sup>`;\n if (a.highlight) text = `<mark>${text}</mark>`;\n if (a.link) text = `<a href=\"${_escAttr(a.link)}\"${a.target ? ` target=\"${_escAttr(a.target)}\"` : ''}>${text}</a>`;\n\n html += text;\n }\n\n return html;\n}\n\nfunction _escAttr(str) {\n if (!str) return '';\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n","import { EventEmitter } from './utils/EventEmitter.js';\nimport { el, placeCaretAtEnd, placeCaretAtStart, getCaretRect } from './utils/dom.js';\nimport { icons } from './utils/icons.js';\nimport { BlockManager } from './core/BlockManager.js';\nimport { MediaUploader } from './core/MediaUploader.js';\nimport { DragDrop } from './core/DragDrop.js';\nimport { BlockRenderer } from './blocks/BlockRenderer.js';\nimport { Header } from './ui/Header.js';\nimport { Toolbar } from './ui/Toolbar.js';\nimport { InserterPanel } from './ui/InserterPanel.js';\nimport { SettingsPanel } from './ui/SettingsPanel.js';\nimport { SlashMenu } from './ui/SlashMenu.js';\nimport { StatusBar } from './ui/StatusBar.js';\nimport { PluginRegistry } from './core/PluginRegistry.js';\nimport { Differ } from './core/Differ.js';\nimport { CollaborativeManager } from './core/CollaborativeManager.js';\nimport { createSanitizer } from './utils/sanitize.js';\nimport { normalizeHTML } from './utils/HtmlNormalizer.js';\nimport { blocksToDelta, deltaToBlocks } from './formats/DeltaFormat.js';\nimport { BLOCK_TYPES, CATEGORIES } from './blocks/registry.js';\n\n/**\n * NBDEditor — Gutenberg-style block editor.\n *\n * Usage:\n * const editor = new NBDEditor('#app', { ... });\n */\nexport class NBDEditor extends EventEmitter {\n constructor(selector, options = {}) {\n super();\n\n this.options = {\n siteName: 'My Site',\n authorName: 'Admin',\n showStatusBar: true,\n showSettingsPanel: false,\n showHeaderActions: false,\n placeholder: 'Start writing...',\n autoSaveInterval: 30000,\n uploadHandler: null, // async (file) => { url, id }\n maxFileSize: 10 * 1024 * 1024,\n onChooseMediaSource: null, // async/sync (type: 'video'|'audio') => 'url' | 'upload'\n content: null, // initial HTML content\n onChange: null,\n onSave: null,\n onPublish: null,\n sanitize: true, // Enable HTML sanitization\n sanitizeConfig: null, // Custom DOMPurify config\n ...options,\n };\n\n // Root element\n this.rootEl = typeof selector === 'string' ? document.querySelector(selector) : selector;\n if (!this.rootEl) throw new Error(`NBDEditor: element \"${selector}\" not found.`);\n\n // Plugin registry\n this.pluginRegistry = new PluginRegistry();\n\n // Register built-in block types\n for (const cat of CATEGORIES) {\n this.pluginRegistry.registerCategory(cat.id, cat.label);\n }\n for (const [type, def] of Object.entries(BLOCK_TYPES)) {\n this.pluginRegistry.registerBlockType(type, def);\n }\n\n // Sanitizer\n this._sanitize = this.options.sanitize\n ? createSanitizer(this.options.sanitizeConfig || {})\n : (html) => html;\n\n // Differ (change tracking)\n this.differ = new Differ();\n\n // Core modules\n this.blockManager = new BlockManager();\n this.mediaUploader = new MediaUploader({\n uploadHandler: this.options.uploadHandler,\n maxFileSize: this.options.maxFileSize,\n });\n\n // UI modules\n this.blockRenderer = new BlockRenderer(this);\n this.header = new Header(this);\n this.toolbar = new Toolbar(this);\n this.inserterPanel = new InserterPanel(this);\n this.settingsPanel = new SettingsPanel(this);\n this.slashMenu = new SlashMenu(this);\n this.statusBar = new StatusBar(this);\n\n // Collaborative manager (initialized on connect)\n this._collaborative = null;\n\n // State\n this._selectedBlockId = null;\n this._titleEl = null;\n this._blocksContainer = null;\n this._autoSaveTimer = null;\n this.el = null;\n this._htmlEditorModal = null;\n this._htmlEditorTextarea = null;\n this._htmlEditorTitle = null;\n this._htmlEditorBlockId = null;\n\n // Bound handlers for cleanup\n this._boundGlobalKeydown = (e) => this._handleGlobalKeydown(e);\n\n this._init();\n\n // Initialize plugins after editor is ready\n this.pluginRegistry.initPlugins(this);\n }\n\n /* ===== Initialization ===== */\n\n _init() {\n this.rootEl.innerHTML = '';\n this.rootEl.className = 'fe-root';\n\n // Header\n this.rootEl.appendChild(this.header.create());\n\n // Inserter panel\n this.rootEl.appendChild(this.inserterPanel.create());\n\n // Main wrapper\n this.el = el('div', { className: 'fe-editor-main' });\n\n // Canvas\n const canvas = el('div', { className: 'fe-editor-canvas', id: 'fe-canvas' });\n const content = el('div', { className: 'fe-editor-content' });\n\n // Blocks container — with ARIA attributes for accessibility\n this._blocksContainer = el('div', {\n className: 'fe-blocks-container',\n role: 'region',\n 'aria-label': 'Editor content',\n });\n content.appendChild(this._blocksContainer);\n\n canvas.appendChild(content);\n this.el.appendChild(canvas);\n\n // Settings panel\n if (this.options.showSettingsPanel) {\n this.el.appendChild(this.settingsPanel.create());\n }\n\n this.rootEl.appendChild(this.el);\n\n // Slash menu (appended to editor main for positioning)\n this.el.appendChild(this.slashMenu.create());\n\n // Status bar\n if (this.options.showStatusBar) {\n this.rootEl.appendChild(this.statusBar.create());\n }\n\n // Toast element with ARIA live region for screen readers\n this._toast = el('div', { className: 'fe-toast', role: 'status', 'aria-live': 'polite' });\n this.rootEl.appendChild(this._toast);\n\n // ARIA live region for non-visual notifications\n this._ariaLive = el('div', {\n className: 'fe-sr-only',\n role: 'log',\n 'aria-live': 'polite',\n 'aria-relevant': 'additions',\n style: { position: 'absolute', width: '1px', height: '1px', overflow: 'hidden', clip: 'rect(0,0,0,0)' },\n });\n this.rootEl.appendChild(this._ariaLive);\n this._createHtmlEditorModal();\n\n // Load initial content or create first block\n if (typeof this.options.content === 'string') {\n this.blockManager.fromJSON([{\n id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\n type: 'paragraph',\n content: this.options.content,\n attrs: {},\n }]);\n } else if (this.options.content) {\n this.blockManager.fromJSON(this.options.content);\n } else {\n this.blockManager.addBlock('paragraph');\n }\n this._ensureAtLeastOneBlock();\n\n // Initialize differ baseline for change tracking\n this.differ.setBaseline(this.blockManager.toJSON());\n\n this.render();\n\n // Open settings panel by default\n if (this.options.showSettingsPanel) {\n this.settingsPanel.open();\n this._updateCanvasMargin();\n }\n\n // Keyboard shortcuts\n document.addEventListener('keydown', this._boundGlobalKeydown);\n\n // Auto-save\n if (this.options.autoSaveInterval > 0) {\n this._autoSaveTimer = setInterval(() => {\n this._syncAllBlockContent();\n this.statusBar.setSaved('Auto-saved: ' + new Date().toLocaleTimeString());\n this.emit('autosave', this.getData());\n }, this.options.autoSaveInterval);\n }\n\n // Listen for structural block changes (add, remove, move, type-change)\n this.blockManager.on('change', () => {\n const data = this.getData();\n if (this.options.onChange) this.options.onChange(data);\n this.emit('change', data);\n });\n\n // Drag & drop files onto the editor\n this._blocksContainer.addEventListener('dragover', (e) => e.preventDefault());\n this._blocksContainer.addEventListener('drop', async (e) => {\n if (e.dataTransfer.files.length > 0) {\n e.preventDefault();\n const results = await this.mediaUploader.handleDrop(e.dataTransfer);\n if (results) {\n const target =\n (this._selectedBlockId && this.blockManager.getBlock(this._selectedBlockId)) ||\n this.blockManager.blocks[0] ||\n this.blockManager.addBlock('paragraph');\n if (!target) return;\n const chunks = [];\n for (const res of results) {\n if (res.error) continue;\n const type = this.mediaUploader.getMediaType(res.file);\n const src = res.remoteUrl || res.localUrl;\n if (!src) continue;\n if (type === 'image') chunks.push(`<img src=\"${src}\" alt=\"\">`);\n else if (type === 'video') chunks.push(`<video controls src=\"${src}\"></video>`);\n else if (type === 'audio') chunks.push(`<audio controls src=\"${src}\"></audio>`);\n else if (type === 'file') chunks.push(`<a href=\"${src}\" target=\"_blank\" rel=\"noopener\">${res.file.name || 'Download file'}</a>`);\n }\n const toAppend = chunks.join('\\n');\n if (toAppend) target.content = `${target.content || ''}${target.content ? '\\n' : ''}${toAppend}`;\n this.render();\n this.focusBlock(target.id);\n }\n }\n });\n\n // Click outside any block → deselect\n content.addEventListener('click', (e) => {\n if (!e.target.closest('.fe-block-wrapper') && !e.target.closest('.fe-block-appender') && !e.target.closest('.fe-block-toolbar')) {\n if (this._selectedBlockId) {\n this._selectedBlockId = null;\n this.render();\n }\n }\n });\n }\n\n /* ===== Rendering ===== */\n\n render() {\n this._ensureAtLeastOneBlock();\n this._blocksContainer.innerHTML = '';\n\n this.blockManager.blocks.forEach((block) => {\n const wrapper = el('section', {\n className: `fe-block-wrapper ${this._selectedBlockId === block.id ? 'fe-selected' : ''}`,\n dataset: { blockId: block.id },\n });\n\n // Toolbar (per-block, shown on selection)\n const tbContainer = el('div', { className: 'fe-block-toolbar-container' });\n if (this._selectedBlockId === block.id) {\n const tb = this.toolbar.create();\n this.toolbar.show(block.id);\n tb.scrollLeft = 0;\n tbContainer.appendChild(tb);\n requestAnimationFrame(() => this._positionBlockToolbar(tb, wrapper));\n }\n wrapper.appendChild(tbContainer);\n\n // Block content\n const rendered = this.blockRenderer.render(block);\n wrapper.appendChild(rendered);\n\n // Click to select\n wrapper.addEventListener('click', (e) => {\n const clickedContent = e.target.closest('.fe-block-content');\n const clickedEditable = e.target.closest('[contenteditable]');\n const clickedCell = e.target.closest('td,th');\n let clickedEditableIndex = -1;\n if (clickedEditable && wrapper.contains(clickedEditable)) {\n const editables = Array.from(wrapper.querySelectorAll('[contenteditable]'));\n clickedEditableIndex = editables.indexOf(clickedEditable);\n }\n let clickedCellPos = null;\n if (clickedCell) {\n const row = clickedCell.closest('tr');\n const table = clickedCell.closest('table');\n if (row && table) {\n const rows = Array.from(table.querySelectorAll('tr'));\n const rowIndex = rows.indexOf(row);\n const cols = Array.from(row.querySelectorAll('th,td'));\n const colIndex = cols.indexOf(clickedCell);\n if (rowIndex >= 0 && colIndex >= 0) clickedCellPos = { rowIndex, colIndex };\n }\n }\n if (!e.target.closest('.fe-block-toolbar') && !e.target.closest('.fe-link-popover')) {\n if (this._selectedBlockId === block.id && (clickedContent || clickedEditable || clickedCell)) {\n return;\n }\n const blockId = block.id;\n this.selectBlock(blockId);\n // selectBlock calls render() which destroys DOM; focus the NEW contenteditable\n // Use double-rAF to ensure DOM is fully painted before focusing\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n const contentEl = this._getBlockContentEl(blockId);\n if (contentEl) {\n if (clickedCellPos) {\n const rows = Array.from(contentEl.querySelectorAll('tr'));\n const row = rows[clickedCellPos.rowIndex];\n const cols = row ? Array.from(row.querySelectorAll('th,td')) : [];\n const nextCell = cols[clickedCellPos.colIndex] || cols[cols.length - 1] || null;\n if (nextCell) {\n nextCell.focus();\n const range = document.createRange();\n range.selectNodeContents(nextCell);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n }\n }\n if (clickedEditableIndex >= 0) {\n const newWrapper = this._blocksContainer.querySelector(`[data-block-id=\"${blockId}\"]`);\n const editables = newWrapper ? Array.from(newWrapper.querySelectorAll('[contenteditable]')) : [];\n const targetEditable = editables[clickedEditableIndex] || editables[0] || null;\n if (targetEditable) {\n targetEditable.focus();\n placeCaretAtEnd(targetEditable);\n return;\n }\n }\n placeCaretAtEnd(contentEl);\n }\n });\n });\n }\n });\n\n // Drag handle setup\n const dragHandle = wrapper.querySelector('.fe-tb-drag');\n if (dragHandle) {\n const dd = new DragDrop(this._blocksContainer);\n dd.initDrag(dragHandle, wrapper, block.id);\n dd.on('drop', ({ fromId, toId, position }) => {\n const fromIdx = this.blockManager.getIndex(fromId);\n let toIdx = this.blockManager.getIndex(toId);\n if (position === 'after') toIdx++;\n if (fromIdx < toIdx) toIdx--;\n const [moved] = this.blockManager.blocks.splice(fromIdx, 1);\n this.blockManager.blocks.splice(toIdx, 0, moved);\n this.blockManager.saveSnapshot();\n this.render();\n });\n }\n\n this._blocksContainer.appendChild(wrapper);\n });\n\n // Single global appender (outside blocks) to match WP-like flow.\n const appender = el('button', {\n type: 'button',\n className: 'fe-block-appender',\n 'aria-label': 'Add block',\n });\n const plusIcon = el('span', { className: 'fe-plus-icon', innerHTML: icons.plus });\n const label = el('span', {}, ['Add block']);\n appender.appendChild(plusIcon);\n appender.appendChild(label);\n appender.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const targetId = this._selectedBlockId || this.blockManager.blocks[this.blockManager.blocks.length - 1]?.id;\n if (targetId) this.selectBlock(targetId);\n this.inserterPanel.open(appender, { forceNewBlock: true });\n });\n this._blocksContainer.appendChild(appender);\n\n this.statusBar.update();\n }\n\n /* ===== Block Operations ===== */\n\n selectBlock(id) {\n if (this._selectedBlockId === id) {\n if (this.options.showSettingsPanel) {\n this.settingsPanel.updateBlockSettings(id);\n }\n return;\n }\n this._selectedBlockId = id;\n this.render();\n if (this.options.showSettingsPanel) {\n this.settingsPanel.updateBlockSettings(id);\n }\n this.emit('block:select', id);\n }\n\n focusBlock(id) {\n this.selectBlock(id);\n setTimeout(() => {\n const contentEl = this._getBlockContentEl(id);\n if (contentEl) {\n contentEl.focus();\n placeCaretAtEnd(contentEl);\n }\n }, 0);\n }\n\n insertBlockAtSelection(type, data = {}) {\n if (this.insertSingleBlockType(type, data)) {\n const block = this._getInsertionTargetBlock();\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n const selectedId = this._selectedBlockId;\n const block = this.blockManager.addBlock(type, data, selectedId || null);\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n\n insertBlockAtEnd(type, data = {}) {\n if (this.insertSingleBlockType(type, data)) {\n const block = this._getInsertionTargetBlock();\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n const block = this.blockManager.addBlock(type, data);\n this.render();\n this.focusBlock(block.id);\n return block;\n }\n\n /* ===== Block Input Handling ===== */\n\n _onBlockInput(block, node) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (node.textContent || '')\n : node.innerHTML;\n this.statusBar.update();\n\n // Slash command detection\n const text = node.textContent;\n if (text === '/') {\n const rect = getCaretRect() || node.getBoundingClientRect();\n this.slashMenu.open(block, rect);\n } else if (text.startsWith('/') && text.length > 1) {\n if (this.slashMenu.isOpen()) {\n this.slashMenu.filter(text.slice(1).toLowerCase());\n }\n } else {\n if (this.slashMenu.isOpen()) this.slashMenu.close();\n }\n\n const data = this.getData();\n if (this.options.onChange) this.options.onChange(data);\n this.emit('change', data);\n this.emit('input', block);\n }\n\n _onBlockKeydown(e, block, node) {\n // Slash menu takes priority\n if (this.slashMenu.isOpen() && this.slashMenu.handleKeydown(e)) return;\n // Keep Enter behavior inside the same block.\n // New blocks are created explicitly via inserter/add controls.\n\n // Table navigation + row creation with Tab\n if (e.key === 'Tab') {\n const cell = this._getSelectionTableCell();\n if (cell) {\n e.preventDefault();\n this._handleTableTab(cell, e.shiftKey);\n this._syncCurrentBlockContent();\n return;\n }\n }\n\n // Arrow Up at start: focus previous block\n if (e.key === 'ArrowUp') {\n const sel = window.getSelection();\n if (sel.rangeCount) {\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n const nodeRect = node.getBoundingClientRect();\n if (rect.top <= nodeRect.top + 2) {\n const prev = this.blockManager.getPrevBlock(block.id);\n if (prev) {\n e.preventDefault();\n this.focusBlock(prev.id);\n }\n }\n }\n }\n\n // Arrow Down at end: focus next block\n if (e.key === 'ArrowDown') {\n const sel = window.getSelection();\n if (sel.rangeCount) {\n const range = sel.getRangeAt(0);\n const rect = range.getBoundingClientRect();\n const nodeRect = node.getBoundingClientRect();\n if (rect.bottom >= nodeRect.bottom - 2) {\n const next = this.blockManager.getNextBlock(block.id);\n if (next) {\n e.preventDefault();\n const contentEl = this._getBlockContentEl(next.id);\n if (contentEl) {\n contentEl.focus();\n placeCaretAtStart(contentEl);\n this.selectBlock(next.id);\n }\n }\n }\n }\n }\n\n // Tab in code block\n if (e.key === 'Tab' && (block.type === 'code' || block.type === 'html')) {\n e.preventDefault();\n document.execCommand('insertText', false, ' ');\n }\n }\n\n /* ===== Helpers ===== */\n\n _getBlockContentEl(blockId) {\n const wrapper = this._blocksContainer.querySelector(`[data-block-id=\"${blockId}\"]`);\n return wrapper?.querySelector('.fe-block-content') || wrapper?.querySelector('[contenteditable]');\n }\n\n _getSelectedBlockEl() {\n if (!this._selectedBlockId) return null;\n return this._blocksContainer.querySelector(`[data-block-id=\"${this._selectedBlockId}\"]`);\n }\n\n _syncCurrentBlockContent() {\n if (!this._selectedBlockId) return;\n const block = this.blockManager.getBlock(this._selectedBlockId);\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (block && contentEl) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (contentEl.textContent || '')\n : contentEl.innerHTML;\n }\n }\n\n _syncAllBlockContent() {\n this.blockManager.blocks.forEach((block) => {\n const contentEl = this._getBlockContentEl(block.id);\n if (contentEl) {\n block.content = (block.type === 'code' || block.type === 'html')\n ? (contentEl.textContent || '')\n : contentEl.innerHTML;\n }\n });\n }\n\n _generateSlug() {\n const slug = (this._titleEl?.value || '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n const slugEl = document.getElementById('fe-url-slug');\n if (slugEl) slugEl.value = slug;\n }\n\n _updateCanvasMargin() {\n if (!this.options.showSettingsPanel) return;\n const canvas = this.el.querySelector('.fe-editor-canvas');\n if (canvas) {\n canvas.classList.toggle('fe-panel-open', this.settingsPanel.isOpen());\n }\n }\n\n _createHtmlEditorModal() {\n const overlay = el('div', { className: 'fe-html-modal-overlay' });\n const modal = el('div', { className: 'fe-html-modal' });\n const header = el('div', { className: 'fe-html-modal-header' });\n const title = el('h3', { className: 'fe-html-modal-title' }, ['Edit as HTML']);\n const closeBtn = el('button', {\n type: 'button',\n className: 'fe-icon-btn fe-icon-btn-sm',\n innerHTML: icons.close,\n onClick: () => this._closeBlockHtmlEditor(),\n });\n header.appendChild(title);\n header.appendChild(closeBtn);\n\n const textarea = el('textarea', {\n className: 'fe-html-modal-textarea',\n spellcheck: 'false',\n placeholder: 'Edit block HTML...',\n });\n\n const actions = el('div', { className: 'fe-html-modal-actions' });\n const cancelBtn = el('button', {\n type: 'button',\n className: 'fe-btn fe-btn-outline',\n innerHTML: 'Cancel',\n onClick: () => this._closeBlockHtmlEditor(),\n });\n const applyBtn = el('button', {\n type: 'button',\n className: 'fe-btn fe-btn-primary',\n innerHTML: 'Apply HTML',\n onClick: () => this._applyBlockHtmlEditor(),\n });\n actions.appendChild(cancelBtn);\n actions.appendChild(applyBtn);\n\n modal.appendChild(header);\n modal.appendChild(textarea);\n modal.appendChild(actions);\n overlay.appendChild(modal);\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this._closeBlockHtmlEditor();\n });\n textarea.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') this._closeBlockHtmlEditor();\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') this._applyBlockHtmlEditor();\n });\n\n this.rootEl.appendChild(overlay);\n this._htmlEditorModal = overlay;\n this._htmlEditorTextarea = textarea;\n this._htmlEditorTitle = title;\n }\n\n _parseBlockFromHTML(html, fallbackType = 'paragraph') {\n const raw = (html || '').trim();\n if (!raw) return { type: fallbackType, content: '', attrs: {} };\n if (typeof document === 'undefined') return { type: 'html', content: raw, attrs: {} };\n\n const wrap = document.createElement('div');\n wrap.innerHTML = raw;\n const first = wrap.firstElementChild;\n const onlyOneElement =\n wrap.childElementCount === 1 &&\n Array.from(wrap.childNodes).every((n) => n.nodeType === Node.ELEMENT_NODE || n.textContent.trim() === '');\n\n if (!first || !onlyOneElement) {\n return { type: 'html', content: raw, attrs: {} };\n }\n\n const tag = first.tagName.toLowerCase();\n if (tag === 'p') return { type: 'paragraph', content: first.innerHTML, attrs: {} };\n if (tag === 'h2') return { type: 'heading', content: first.innerHTML, attrs: {} };\n if (tag === 'h3') return { type: 'heading-3', content: first.innerHTML, attrs: {} };\n if (tag === 'h4') return { type: 'heading-4', content: first.innerHTML, attrs: {} };\n if (tag === 'blockquote') return { type: 'quote', content: first.innerHTML, attrs: {} };\n if (tag === 'ul') return { type: 'list', content: first.innerHTML, attrs: {} };\n if (tag === 'ol') return { type: 'ordered-list', content: first.innerHTML, attrs: {} };\n if (tag === 'hr') return { type: 'separator', content: '', attrs: {} };\n if (tag === 'img') {\n const styleWidth = _readPercentWidth(first.getAttribute('style') || '');\n return {\n type: 'image',\n content: first.getAttribute('src') || '',\n attrs: {\n alt: first.getAttribute('alt') || '',\n ...(styleWidth ? { width: styleWidth } : {}),\n },\n };\n }\n if (tag === 'figure') {\n const img = first.querySelector('img');\n if (img) {\n const caption = first.querySelector('figcaption');\n const styleWidth = _readPercentWidth(img.getAttribute('style') || '');\n return {\n type: 'image',\n content: img.getAttribute('src') || '',\n attrs: {\n alt: img.getAttribute('alt') || '',\n caption: caption ? caption.innerHTML : '',\n ...(styleWidth ? { width: styleWidth } : {}),\n },\n };\n }\n }\n if (tag === 'pre') {\n const code = first.querySelector('code');\n return {\n type: 'code',\n content: code ? (code.textContent || '') : (first.textContent || ''),\n attrs: {},\n };\n }\n\n return { type: 'html', content: raw, attrs: {} };\n }\n\n /* ===== Global Keyboard Shortcuts ===== */\n\n _handleGlobalKeydown(e) {\n const mod = e.ctrlKey || e.metaKey;\n const activeEl = document.activeElement;\n const inEditable =\n Boolean(activeEl && activeEl.isContentEditable && this.rootEl.contains(activeEl)) ||\n Boolean(window.getSelection()?.anchorNode && this.rootEl.contains(window.getSelection().anchorNode));\n\n if (mod && e.key === 'z' && !e.shiftKey) {\n e.preventDefault();\n this.undo({ preferNative: inEditable });\n }\n if (mod && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {\n e.preventDefault();\n this.redo({ preferNative: inEditable });\n }\n if (mod && e.key === 's') {\n e.preventDefault();\n this.save();\n }\n if (mod && e.key === 'b') {\n e.preventDefault();\n document.execCommand('bold', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'i') {\n e.preventDefault();\n document.execCommand('italic', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'u') {\n e.preventDefault();\n document.execCommand('underline', false, null);\n this._syncCurrentBlockContent();\n }\n if (mod && e.key === 'k') {\n e.preventDefault();\n this.toolbar._showLinkPopover();\n }\n if (mod && e.key === 'a') {\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (contentEl && this.rootEl.contains(document.activeElement)) {\n e.preventDefault();\n const range = document.createRange();\n range.selectNodeContents(contentEl);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n }\n\n /* ===== Public API ===== */\n\n /** Get all editor data as a JSON object. */\n getData() {\n this._syncAllBlockContent();\n const mergedHtml = this.blockManager.toHTML();\n return { content: mergedHtml };\n }\n\n /** Set editor content from a content string or { content } object. */\n setData(data) {\n let content = typeof data === 'string'\n ? data\n : (typeof data?.content === 'string' ? data.content : '');\n\n // Sanitize incoming content\n content = this._sanitize(content);\n\n this.blockManager.fromJSON([\n {\n id: `blk_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,\n type: 'paragraph',\n content,\n attrs: {},\n },\n ]);\n this.differ.setBaseline(this.blockManager.toJSON());\n this.render();\n }\n\n /** Export blocks as HTML string. */\n toHTML() {\n this._syncAllBlockContent();\n return this.blockManager.toHTML();\n }\n\n toggleBlockHtmlMode(blockId = this._selectedBlockId) {\n if (!blockId) return;\n this._syncCurrentBlockContent();\n const block = this.blockManager.getBlock(blockId);\n if (!block) return;\n\n if (block.type === 'html') {\n const fallbackType = block.attrs?.__sourceType || 'paragraph';\n const parsed = this._parseBlockFromHTML(block.content || '', fallbackType);\n block.type = parsed.type === 'html' ? fallbackType : parsed.type;\n block.content = parsed.content;\n block.attrs = parsed.attrs || {};\n this.render();\n this.focusBlock(blockId);\n return;\n }\n\n const html = this.blockManager.blockToHTML(block);\n block.attrs = { ...(block.attrs || {}), __sourceType: block.type };\n block.type = 'html';\n block.content = html;\n this.render();\n this.focusBlock(blockId);\n }\n\n openBlockHtmlEditor(blockId = this._selectedBlockId) {\n if (!blockId || !this._htmlEditorModal || !this._htmlEditorTextarea) return;\n this._syncCurrentBlockContent();\n const block = this.blockManager.getBlock(blockId);\n if (!block) return;\n\n this._htmlEditorBlockId = blockId;\n this._htmlEditorTitle.textContent = `Edit as HTML: ${block.type}`;\n this._htmlEditorTextarea.value = this.blockManager.blockToHTML(block);\n this._htmlEditorModal.classList.add('fe-open');\n setTimeout(() => {\n this._htmlEditorTextarea.focus();\n this._htmlEditorTextarea.select();\n }, 0);\n }\n\n _closeBlockHtmlEditor() {\n if (!this._htmlEditorModal) return;\n this._htmlEditorModal.classList.remove('fe-open');\n this._htmlEditorBlockId = null;\n }\n\n _applyBlockHtmlEditor() {\n if (!this._htmlEditorBlockId || !this._htmlEditorTextarea) return;\n const block = this.blockManager.getBlock(this._htmlEditorBlockId);\n if (!block) return this._closeBlockHtmlEditor();\n\n const parsed = this._parseBlockFromHTML(this._htmlEditorTextarea.value, block.type);\n block.type = parsed.type;\n block.content = parsed.content;\n block.attrs = parsed.attrs || {};\n this._closeBlockHtmlEditor();\n this.render();\n this.focusBlock(block.id);\n }\n\n /** Save draft (emits save event). */\n save() {\n const data = this.getData();\n this.header.setStatus('Draft saved');\n this.statusBar.setSaved('Last saved: ' + new Date().toLocaleTimeString());\n this._showToast('Draft saved');\n if (this.options.onSave) this.options.onSave(data);\n this.emit('save', data);\n }\n\n /** Publish (emits publish event). */\n publish() {\n const data = this.getData();\n this.header.setStatus('Published', '#00a32a');\n this._showToast('Post published!');\n if (this.options.onPublish) this.options.onPublish(data);\n this.emit('publish', data);\n }\n\n /** Get / set the title. */\n getTitle() { return this._titleEl?.value || ''; }\n setTitle(title) { if (this._titleEl) this._titleEl.value = title; }\n\n undo({ preferNative = false } = {}) {\n if (preferNative) {\n const didNative = document.execCommand('undo', false, null);\n if (didNative) {\n this._syncCurrentBlockContent();\n return true;\n }\n }\n\n const didBlockUndo = this.blockManager.undo();\n if (didBlockUndo) this.render();\n return didBlockUndo;\n }\n\n redo({ preferNative = false } = {}) {\n if (preferNative) {\n const didNative = document.execCommand('redo', false, null);\n if (didNative) {\n this._syncCurrentBlockContent();\n return true;\n }\n }\n\n const didBlockRedo = this.blockManager.redo();\n if (didBlockRedo) this.render();\n return didBlockRedo;\n }\n\n /* ===== Plugin System ===== */\n\n /** Register a custom block type at runtime. */\n registerBlockType(type, definition) {\n this.pluginRegistry.registerBlockType(type, definition);\n }\n\n /** Register a plugin (bundles block types + lifecycle hooks). */\n registerPlugin(plugin) {\n const registered = this.pluginRegistry.registerPlugin(plugin);\n // Initialize the plugin immediately if editor is already set up\n if (registered && typeof registered.init === 'function') {\n try { registered.init(this); } catch (e) { console.error(e); }\n }\n return registered;\n }\n\n /* ===== Delta Format ===== */\n\n /** Export blocks as Delta format (structured ops). */\n getDelta() {\n this._syncAllBlockContent();\n return blocksToDelta(this.blockManager.toJSON());\n }\n\n /** Import content from Delta format. */\n setDelta(delta) {\n const blocks = deltaToBlocks(delta);\n this.blockManager.fromJSON(blocks);\n this.render();\n }\n\n /* ===== HTML Normalization ===== */\n\n /** Normalize an HTML string for consistent round-tripping. */\n normalizeHTML(html) {\n return normalizeHTML(html);\n }\n\n /* ===== Sanitization ===== */\n\n /** Sanitize HTML content (strips XSS vectors). */\n sanitizeHTML(html) {\n return this._sanitize(html);\n }\n\n /* ===== Diff / Patch ===== */\n\n /** Get accumulated block-level changes since last call. */\n getChanges() {\n this._syncAllBlockContent();\n this.differ.diff(this.blockManager.toJSON());\n return this.differ.getChanges();\n }\n\n /* ===== Collaborative Editing ===== */\n\n /**\n * Connect to a collaborative editing server.\n * @param {string} wsUrl - WebSocket URL.\n * @param {Object} [options] - Connection options.\n * @returns {CollaborativeManager}\n */\n connectCollaborative(wsUrl, options = {}) {\n if (this._collaborative) {\n this._collaborative.disconnect();\n }\n this._collaborative = new CollaborativeManager(this, wsUrl, options);\n this._collaborative.connect();\n return this._collaborative;\n }\n\n /** Disconnect from collaborative server. */\n disconnectCollaborative() {\n if (this._collaborative) {\n this._collaborative.disconnect();\n this._collaborative = null;\n }\n }\n\n /** Destroy editor instance. */\n destroy() {\n if (this._autoSaveTimer) clearInterval(this._autoSaveTimer);\n if (this._collaborative) this._collaborative.disconnect();\n this.pluginRegistry.destroyAll();\n document.removeEventListener('keydown', this._boundGlobalKeydown);\n this.slashMenu.destroy();\n this.toolbar.hide();\n this.rootEl.innerHTML = '';\n this._listeners = {};\n }\n\n _showToast(msg) {\n this._toast.textContent = msg;\n this._toast.classList.add('fe-show');\n setTimeout(() => this._toast.classList.remove('fe-show'), 2500);\n // Also announce to screen readers\n this._announce(msg);\n }\n\n /** Announce a message to screen readers via ARIA live region. */\n _announce(msg) {\n if (this._ariaLive) {\n const node = document.createElement('span');\n node.textContent = msg;\n this._ariaLive.appendChild(node);\n // Clean up old announcements to prevent DOM bloat\n if (this._ariaLive.childNodes.length > 5) {\n this._ariaLive.removeChild(this._ariaLive.firstChild);\n }\n }\n }\n\n _positionBlockToolbar(toolbarEl, wrapperEl) {\n if (!toolbarEl || !wrapperEl) return;\n const viewportPadding = 8;\n\n toolbarEl.classList.remove('fe-toolbar-below');\n toolbarEl.style.top = '-44px';\n toolbarEl.style.left = '0px';\n\n const toolbarRect = toolbarEl.getBoundingClientRect();\n const wrapperRect = wrapperEl.getBoundingClientRect();\n\n let shiftX = 0;\n if (toolbarRect.right > window.innerWidth - viewportPadding) {\n shiftX -= toolbarRect.right - (window.innerWidth - viewportPadding);\n }\n if (toolbarRect.left + shiftX < viewportPadding) {\n shiftX += viewportPadding - (toolbarRect.left + shiftX);\n }\n toolbarEl.style.left = `${Math.round(shiftX)}px`;\n\n const topIfAbove = wrapperRect.top - toolbarRect.height - 6;\n const shouldPlaceBelow = topIfAbove < viewportPadding;\n if (shouldPlaceBelow) {\n toolbarEl.classList.add('fe-toolbar-below');\n toolbarEl.style.top = '6px';\n }\n wrapperEl.classList.toggle('fe-toolbar-inset', shouldPlaceBelow);\n }\n\n _getSelectionTableCell() {\n const sel = window.getSelection();\n if (!sel || !sel.rangeCount) return null;\n let node = sel.anchorNode;\n if (!node) return null;\n if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;\n if (!node || typeof node.closest !== 'function') return null;\n const cell = node.closest('td,th');\n if (!cell) return null;\n const contentEl = this._getBlockContentEl(this._selectedBlockId);\n if (!contentEl || !contentEl.contains(cell)) return null;\n return cell;\n }\n\n _handleTableTab(currentCell, reverse = false) {\n const row = currentCell.closest('tr');\n const table = currentCell.closest('table');\n if (!row || !table) return;\n\n const rowCells = Array.from(row.querySelectorAll('th,td'));\n const cellIndex = rowCells.indexOf(currentCell);\n const rows = Array.from(table.querySelectorAll('tr'));\n const rowIndex = rows.indexOf(row);\n\n if (reverse) {\n if (cellIndex > 0) {\n this._placeCaretInCell(rowCells[cellIndex - 1]);\n return;\n }\n if (rowIndex > 0) {\n const prevRowCells = Array.from(rows[rowIndex - 1].querySelectorAll('th,td'));\n this._placeCaretInCell(prevRowCells[prevRowCells.length - 1]);\n }\n return;\n }\n\n if (cellIndex < rowCells.length - 1) {\n this._placeCaretInCell(rowCells[cellIndex + 1]);\n return;\n }\n\n if (rowIndex < rows.length - 1) {\n const nextRowCells = Array.from(rows[rowIndex + 1].querySelectorAll('th,td'));\n this._placeCaretInCell(nextRowCells[0]);\n return;\n }\n\n const colCount = Math.max(1, rowCells.length);\n const newRow = document.createElement('tr');\n for (let i = 0; i < colCount; i++) {\n const td = document.createElement('td');\n td.innerHTML = '<br>';\n newRow.appendChild(td);\n }\n\n const tbody = table.querySelector('tbody');\n if (tbody) tbody.appendChild(newRow);\n else table.appendChild(newRow);\n this._placeCaretInCell(newRow.querySelector('td'));\n }\n\n _placeCaretInCell(cell) {\n if (!cell) return;\n if ((cell.innerHTML || '').trim() === '') cell.innerHTML = '<br>';\n const range = document.createRange();\n range.selectNodeContents(cell);\n range.collapse(true);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n insertSingleBlockType(type, data = {}) {\n const block = this._getInsertionTargetBlock();\n if (!block) return false;\n\n const snippet = this._snippetForType(type, data);\n if (!snippet) return false;\n\n if (typeof document.execCommand === 'function') {\n const contentEl = this._getBlockContentEl(block.id);\n if (contentEl) {\n contentEl.focus();\n const ok = document.execCommand('insertHTML', false, snippet);\n if (ok) {\n this._focusEditableTail(contentEl);\n this._syncCurrentBlockContent();\n return true;\n }\n }\n }\n\n block.content = `${block.content || ''}${block.content ? '\\n' : ''}${snippet}`;\n return true;\n }\n\n _snippetForType(type, data = {}) {\n if (type === 'separator') return '<hr><p><br></p>';\n if (type === 'spacer') return `<div style=\"height:${Number(data?.height) || 48}px\"></div><p><br></p>`;\n if (type === 'table') {\n return [\n '<table border=\"1\" style=\"width:100%;border-collapse:collapse;\">',\n '<tbody>',\n '<tr><td>Cell 1</td><td>Cell 2</td></tr>',\n '<tr><td>Cell 3</td><td>Cell 4</td></tr>',\n '</tbody>',\n '</table>',\n '<p><br></p>',\n ].join('');\n }\n if (type === 'columns') {\n return [\n '<div class=\"fe-inline-columns\">',\n '<div class=\"fe-inline-column\"><p>Column 1</p></div>',\n '<div class=\"fe-inline-column\"><p>Column 2</p></div>',\n '</div>',\n '<p><br></p>',\n ].join('');\n }\n\n if (type === 'button') {\n return '<p><a href=\"#\" style=\"display:inline-block;background:#2271b1;color:#fff;padding:10px 24px;border-radius:4px;text-decoration:none;\" contenteditable=\"false\">Button</a></p><p><br></p>';\n }\n if (type === 'video') {\n const src = String(data?.url || '').trim();\n return src\n ? `<video controls style=\"width:100%;max-width:100%;\" src=\"${src}\"></video><p><br></p>`\n : '<video controls style=\"width:100%;max-width:100%;\"></video><p><br></p>';\n }\n if (type === 'audio') {\n const src = String(data?.url || '').trim();\n return src\n ? `<audio controls style=\"width:100%;\" src=\"${src}\"></audio><p><br></p>`\n : '<audio controls style=\"width:100%;\"></audio><p><br></p>';\n }\n if (type === 'file') {\n const url = String(data?.url || '').trim();\n const name = String(data?.name || 'Download file').trim();\n return url ? `<p><a href=\"${url}\" target=\"_blank\" rel=\"noopener\">${name}</a></p><p><br></p>` : null;\n }\n if (type === 'embed') {\n const url = String(data?.url || '').trim();\n return url\n ? `<p><a href=\"${url}\" target=\"_blank\" rel=\"noopener\">${url}</a></p><p><br></p>`\n : '<p>Paste embed URL here</p><p><br></p>';\n }\n return null;\n }\n\n _focusEditableTail(contentEl) {\n if (!contentEl) return;\n let tail = contentEl.lastElementChild;\n const needsTail = !tail || tail.tagName !== 'P';\n if (needsTail) {\n tail = document.createElement('p');\n tail.innerHTML = '<br>';\n contentEl.appendChild(tail);\n } else if ((tail.innerHTML || '').trim() === '') {\n tail.innerHTML = '<br>';\n }\n\n const range = document.createRange();\n range.selectNodeContents(tail);\n range.collapse(false);\n const sel = window.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n _ensureAtLeastOneBlock() {\n if (!Array.isArray(this.blockManager.blocks) || this.blockManager.blocks.length === 0) {\n return this.blockManager.addBlock('paragraph');\n }\n return this.blockManager.blocks[0];\n }\n\n _getInsertionTargetBlock() {\n const selected =\n this._selectedBlockId\n ? this.blockManager.getBlock(this._selectedBlockId)\n : null;\n if (selected) return selected;\n\n const last = this.blockManager.blocks[this.blockManager.blocks.length - 1];\n if (last) return last;\n\n return this.blockManager.addBlock('paragraph');\n }\n}\n\nfunction _readPercentWidth(style) {\n const match = /width\\s*:\\s*([0-9.]+)%/i.exec(style || '');\n if (!match) return null;\n const value = Number(match[1]);\n if (!Number.isFinite(value)) return null;\n return Math.max(10, Math.min(100, Math.round(value)));\n}\n","/**\n * React wrapper for NBDEditor.\n *\n * Supports both controlled and uncontrolled usage:\n *\n * Controlled (like React Quill):\n * const [content, setContent] = useState('<p>Hello</p>');\n * <ReactNBDEditor content={content} onChange={(d) => setContent(d.content)} />\n *\n * Uncontrolled (initial value + ref):\n * <ReactNBDEditor content=\"<p>Hello</p>\" ref={editorRef} />\n *\n * Guarded so the module can be safely imported in environments where React\n * is not available (e.g. vanilla-JS UMD usage). When React is missing,\n * `ReactNBDEditor` will be `null`.\n */\nimport * as React from 'react';\nimport { NBDEditor } from '../NBDEditor.js';\n\n// Guard: React may be undefined in vanilla-JS / UMD without React loaded.\nconst _hasReact = typeof React !== 'undefined' && React !== null && typeof React.forwardRef === 'function';\n\nfunction ReactNBDEditorComponent(props, ref) {\n const {\n className,\n style,\n content,\n onChange,\n onSave,\n onPublish,\n onReady,\n debounceMs,\n ...editorOptions\n } = props || {};\n\n const hostRef = React.useRef(null);\n const editorRef = React.useRef(null);\n const lastContentRef = React.useRef(undefined);\n\n // Use refs for callbacks so the editor always calls the latest version.\n // This fixes the stale closure issue where onChange/onSave/onPublish\n // captured at mount time would never update.\n const onChangeRef = React.useRef(onChange);\n const onSaveRef = React.useRef(onSave);\n const onPublishRef = React.useRef(onPublish);\n const debounceTimerRef = React.useRef(null);\n\n onChangeRef.current = onChange;\n onSaveRef.current = onSave;\n onPublishRef.current = onPublish;\n\n // ── Initialize editor (one-time) ──────────────────────────────────\n React.useEffect(() => {\n if (!hostRef.current) return undefined;\n\n const initialOptions = {\n ...editorOptions,\n // Wire up onChange through a ref so it always calls the latest prop\n onChange: (data) => {\n const nextContent = typeof data?.content === 'string' ? data.content : '';\n lastContentRef.current = nextContent;\n\n const notify = () => {\n if (typeof onChangeRef.current === 'function') onChangeRef.current(data);\n };\n\n // Optional debounce for controlled mode performance\n if (debounceMs && debounceMs > 0) {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = setTimeout(notify, debounceMs);\n } else {\n notify();\n }\n },\n onSave: (data) => {\n if (typeof onSaveRef.current === 'function') onSaveRef.current(data);\n },\n onPublish: (data) => {\n if (typeof onPublishRef.current === 'function') onPublishRef.current(data);\n },\n ...(typeof content === 'string' ? { content } : {}),\n };\n\n const editor = new NBDEditor(hostRef.current, initialOptions);\n editorRef.current = editor;\n lastContentRef.current = typeof content === 'string' ? content : undefined;\n if (typeof onReady === 'function') onReady(editor);\n\n return () => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n if (editorRef.current) {\n editorRef.current.destroy();\n editorRef.current = null;\n }\n };\n // Intentionally one-time init; options should be stable at mount.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ── Sync content prop → editor (controlled mode) ─────────────────\n React.useEffect(() => {\n if (!editorRef.current) return;\n if (typeof content !== 'string') return;\n\n // Skip if this content came from the editor's own onChange\n if (content === lastContentRef.current) return;\n\n // Normalize: compare trimmed versions to avoid whitespace mismatches\n const currentHTML = editorRef.current.toHTML();\n if (content.trim() === currentHTML.trim()) {\n lastContentRef.current = content;\n return;\n }\n\n // Actually different content from outside — update the editor\n editorRef.current.setData({ content });\n lastContentRef.current = content;\n }, [content]);\n\n // ── Imperative ref handle ─────────────────────────────────────────\n React.useImperativeHandle(ref, () => ({\n getInstance: () => editorRef.current,\n getData: () => editorRef.current?.getData(),\n setData: (data) => editorRef.current?.setData(data),\n toHTML: () => editorRef.current?.toHTML(),\n save: () => editorRef.current?.save(),\n publish: () => editorRef.current?.publish(),\n undo: (opts) => editorRef.current?.undo(opts),\n redo: (opts) => editorRef.current?.redo(opts),\n destroy: () => editorRef.current?.destroy(),\n }), []);\n\n return React.createElement('div', {\n ref: hostRef,\n className,\n style,\n });\n}\n\nexport const ReactNBDEditor = _hasReact ? React.forwardRef(ReactNBDEditorComponent) : null;\n"],"names":["EventEmitter","constructor","this","_listeners","on","event","fn","push","off","list","filter","f","emit","args","forEach","once","wrapper","el","tag","attrs","children","node","document","createElement","k","v","Object","entries","className","assign","style","dk","dv","dataset","startsWith","addEventListener","slice","toLowerCase","contentEditable","innerHTML","setAttribute","child","Array","isArray","appendChild","createTextNode","Node","generateId","Date","now","toString","Math","random","placeCaretAtEnd","element","focus","range","createRange","selectNodeContents","collapse","sel","window","getSelection","removeAllRanges","addRange","svg","inner","vb","icons","plus","undo","redo","settings","bold","italic","underline","strikethrough","link","code","alignLeft","alignCenter","alignRight","image","heading","paragraph","quote","orderedList","separator","table","button","columns","spacer","embed","gallery","video","audio","file","dragHandle","filled","arrowUp","arrowDown","trash","close","inlineCode","upload","html","pullquote","BlockManager","super","blocks","_undoStack","_redoStack","_maxHistory","JSON","stringify","addBlock","type","data","afterId","block","id","content","idx","findIndex","b","splice","_pushUndo","removeBlock","length","removed","updateBlock","patch","getBlock","changeBlockType","newType","moveBlock","direction","newIdx","duplicateBlock","clone","find","getIndex","getPrevBlock","getNextBlock","toJSON","map","fromJSON","toHTML","blockToHTML","join","toHTMLBlocks","c","test","_escText","width","Number","isFinite","max","min","round","_escAttr","alt","caption","height","url","filename","next","shift","saveSnapshot","pop","parse","state","getWordCount","text","tmp","textContent","trim","split","w","getCharCount","replace","str","String","MediaUploader","options","uploadHandler","maxFileSize","allowedImageTypes","allowedVideoTypes","allowedAudioTypes","_fileInput","openFilePicker","accept","multiple","Promise","resolve","remove","input","display","body","files","click","processFile","size","err","name","toFixed","error","localUrl","_readAsDataURL","result","remoteUrl","message","processFiles","all","handlePaste","clipboardData","imageItems","items","item","getAsFile","Boolean","handleDrop","dataTransfer","getMediaType","reject","reader","FileReader","onload","onerror","readAsDataURL","DragDrop","container","_dragging","_placeholder","_offsetY","_bound","_enabled","enable","disable","initDrag","handleEl","wrapperEl","blockId","cursor","e","preventDefault","opacity","effectAllowed","setData","_removePlaceholder","dropEffect","rect","getBoundingClientRect","midY","top","position","clientY","_showPlaceholder","fromId","toId","referenceEl","cssText","parentNode","insertBefore","nextSibling","removeChild","BLOCK_TYPES","label","description","icon","category","hasContent","contentTag","placeholder","isMedia","CATEGORIES","getBlocksByCategory","catId","def","searchBlocks","query","q","includes","BlockRenderer","editor","render","_renderParagraph","_renderMediaBlock","_renderContentBlock","_renderSeparator","_renderSpacer","_renderColumns","_renderTable","isRawTextBlock","isEmpty","empty","_bindContentEvents","_renderImageBlock","_renderGalleryBlock","_renderVideoBlock","_renderAudioBlock","_renderFileBlock","_renderMediaPlaceholder","_normalizeImageWidth","fig","img","src","maxWidth","borderRadius","overlay","replaceBtn","onClick","_triggerImageUpload","removeBtn","resizeHandle","title","stopPropagation","selectBlock","startX","clientX","startWidth","parentWidth","onMove","ev","delta","nextPercent","onUp","removeEventListener","statusBar","update","sizeControls","pct","btn","images","grid","i","addMore","_triggerGalleryUpload","controls","infoDiv","filesize","downloadLink","href","download","iconEl","desc","btnRow","uploadBtn","_handleMediaUpload","urlInput","key","value","_setupDropZone","handle","startY","startH","newH","numCols","col","current","rows","cols","r","tr","cell","mediaUploader","results","res","bytes","classList","add","async","updateEmptyState","_selectedBlockId","activeElement","setTimeout","_onBlockInput","querySelector","_onBlockKeydown","getData","execCommand","then","numeric","Header","create","left","inserterBtn","inserterPanel","toggle","currentTarget","_iconBtn","activeEl","inEditable","isContentEditable","rootEl","contains","anchorNode","preferNative","center","right","showHeaderActions","draftBtn","save","publishBtn","publish","showSettingsPanel","childNodes","settingsPanel","_updateCanvasMargin","setStatus","color","iconHTML","Toolbar","_linkPopover","_fontSizeSelect","_onSelectionChange","_statefulButtons","_savedLinkRange","_tableToolsSep","_tableRowBtn","_tableColBtn","_createLinkPopover","show","blockManager","hide","getActiveBlockId","dragBtn","_addBtn","_initToolbarDrag","_addSep","textTypes","htmlEditableTypes","select","opt","o","selected","blockNow","ensureParagraphContext","contentEl","_getBlockContentEl","_syncCurrentBlockContent","focusBlock","fontSizeSelect","_applyFontSize","_syncFontSizeSelect","_bindFontSizeTracking","_addStatefulBtn","_exec","_wrapInlineCode","_showLinkPopover","_addTextBtn","_addTableRow","_addTableColumn","toggleBlockHtmlMode","_syncStatefulButtons","activeId","blockToClear","_hideLinkPopover","_unbindFontSizeTracking","origLeft","origTop","dragging","onMouseMove","dx","dy","onMouseUp","parseInt","extraClass","command","sep","cmd","rangeCount","getRangeAt","surroundContents","px","collapsed","marker","fontSize","insertNode","nextRange","setStart","firstChild","span","extractContents","_currentSelectionFontSizePx","snapped","sizes","best","bestDelta","abs","_closestFontSize","focusNode","elNode","nodeType","ELEMENT_NODE","parentElement","_getSelectedBlockEl","raw","getComputedStyle","parseFloat","applyBtn","_restoreSavedLinkRange","querySelectorAll","a","target","rel","cloneRange","bottom","anchor","closest","_getCurrentTableContext","TEXT_NODE","maybeCell","ctx","currentRow","rowCells","from","colCount","newRow","td","indexOf","row","cells","ref","newCell","tagName","targetRowCells","focusCell","hasSelectionInEditor","active","queryCommandState","tableDisplay","_isSelectionInTable","InserterPanel","_searchInput","_listEl","_anchorEl","_onDocMouseDown","_onDocKeyDown","_savedRange","_mediaModal","_mediaModalCard","_mediaModalTitle","_mediaModalBody","_mediaModalResolver","_forceNewBlock","header","closeBtn","_renderList","_createMediaModal","open","anchorEl","forceNewBlock","_captureSelectionRange","_positionNearAnchor","_bindGlobalCloseHandlers","_unbindGlobalCloseHandlers","isOpen","_createBlockItem","cat","blockDef","info","_insertFromPopover","desiredLeft","innerWidth","desiredTop","innerHeight","commonAncestorContainer","_restoreSelectionRange","selectedId","selectedBlock","insertSingleBlockType","insertBlockAtSelection","source","_chooseMediaSource","_promptForMediaUrl","trimmed","_showToast","prompt","onChooseMediaSource","_openMediaSourceModal","card","_closeMediaModal","actions","urlBtn","cancelBtn","resolver","SettingsPanel","_activeTab","_postTab","_blockTab","_tagInput","_tags","_categories","_featuredImage","tabs","_postTabBtn","_blockTabBtn","_switchTab","_buildPostTab","_buildBlockTab","updateBlockSettings","_blockSettingsContent","section","fontSelect","l","lhInput","lineHeight","colorSection","textColors","swatch","background","bgColors","border","tab","summary","_section","_field","cats","catList","addCat","checked","tags","tagWrapper","tagInput","val","t","fi","fiArea","fiInput","exc","disc","_toggle","s","frag","createDocumentFragment","defaultOn","SlashMenu","_visible","_highlightIndex","_items","_targetBlock","_boundDocClick","destroy","editorRect","_filter","handleKeydown","_navigate","visible","_selectItem","dir","scrollIntoView","StatusBar","_wordEl","_charEl","_blockEl","_savedEl","bm","titleText","_titleEl","titleWords","words","chars","setSaved","PluginRegistry","_blockTypes","Map","_plugins","registerBlockType","definition","Error","fromHTML","isNew","has","set","_capitalize","unregisterBlockType","delete","getBlockType","get","getAllBlockTypes","obj","getCategories","registerCategory","registerPlugin","plugin","console","warn","unregisterPlugin","_plugin","initPlugins","init","keys","getPlugin","getPluginNames","destroyAll","charAt","toUpperCase","Differ","_baseline","_pendingPatches","setBaseline","_deepClone","diff","currentBlocks","patches","oldBlocks","newBlocks","oldMap","newMap","old","op","index","newBlock","oldBlock","changes","to","survivingOld","survivingNew","oldIdx","fromIndex","toIndex","_computeDiff","getChanges","hasChanges","reset","applyPatches","change","fromIdx","moved","CollaborativeManager","wsUrl","userId","token","debounceMs","reconnectMs","maxReconnectAttempts","_ws","_differ","_connected","_reconnectAttempts","_debounceTimer","_version","_pendingOps","_localChanges","_cleanup","connect","URL","searchParams","WebSocket","_setupWebSocket","_onLocalChange","disconnect","clearTimeout","onclose","isConnected","requestSync","_send","version","onopen","onmessage","msg","_handleMessage","reason","updatedBlocks","_sendLocalChanges","readyState","OPEN","send","_DOMPurify","require","default","DEFAULT_CONFIG","ALLOWED_TAGS","ALLOWED_ATTR","ALLOW_DATA_ATTR","ADD_ATTR","createSanitizer","config","mergedConfig","sanitize","allowedTags","Set","allowedAttrs","allowDataAttr","DOMParser","parseFromString","allElements","attributes","attr","removeAttribute","_fallbackSanitize","normalizeHTML","_normalizeNode","htmlEquals","_isBlockElement","_normalizeElement","_isEmptyInline","sort","localeCompare","removeAttributeNode","_normalizeStyle","prop","vals","blocksToDelta","blockType","blockAttrs","ops","_htmlToOps","deltaToBlocks","entry","_opsToHTML","htmlToOps","opsToHTML","insert","_raw","_walkNodes","endsWith","parentAttrs","strike","sub","sup","highlight","getAttribute","isBlock","NBDEditor","selector","siteName","authorName","showStatusBar","autoSaveInterval","onChange","onSave","onPublish","sanitizeConfig","pluginRegistry","_sanitize","differ","blockRenderer","toolbar","slashMenu","_collaborative","_blocksContainer","_autoSaveTimer","_htmlEditorModal","_htmlEditorTextarea","_htmlEditorTitle","_htmlEditorBlockId","_boundGlobalKeydown","_handleGlobalKeydown","_init","canvas","role","_toast","_ariaLive","overflow","clip","_createHtmlEditorModal","_ensureAtLeastOneBlock","setInterval","_syncAllBlockContent","toLocaleTimeString","chunks","toAppend","tbContainer","tb","scrollLeft","requestAnimationFrame","_positionBlockToolbar","rendered","clickedContent","clickedEditable","clickedCell","clickedEditableIndex","editables","clickedCellPos","rowIndex","colIndex","nextCell","newWrapper","targetEditable","dd","toIdx","appender","plusIcon","targetId","_getInsertionTargetBlock","insertBlockAtEnd","getCaretRect","_getSelectionTableCell","_handleTableTab","shiftKey","nodeRect","prev","placeCaretAtStart","_generateSlug","slug","slugEl","getElementById","modal","_closeBlockHtmlEditor","textarea","spellcheck","_applyBlockHtmlEditor","ctrlKey","metaKey","_parseBlockFromHTML","fallbackType","wrap","first","firstElementChild","onlyOneElement","childElementCount","every","n","styleWidth","_readPercentWidth","mod","__sourceType","parsed","openBlockHtmlEditor","getTitle","setTitle","didBlockUndo","didBlockRedo","registered","getDelta","setDelta","sanitizeHTML","connectCollaborative","disconnectCollaborative","clearInterval","_announce","toolbarEl","toolbarRect","wrapperRect","shiftX","shouldPlaceBelow","currentCell","reverse","cellIndex","_placeCaretInCell","prevRowCells","nextRowCells","tbody","snippet","_snippetForType","_focusEditableTail","tail","lastElementChild","last","match","exec","ReactNBDEditor","React","forwardRef","props","onReady","editorOptions","hostRef","useRef","editorRef","lastContentRef","undefined","onChangeRef","onSaveRef","onPublishRef","debounceTimerRef","useEffect","initialOptions","nextContent","notify","currentHTML","useImperativeHandle","getInstance","opts"],"mappings":"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"}