@sofereditor/react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +27 -0
- package/dist/index.cjs +3759 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +353 -0
- package/dist/index.d.ts +353 -0
- package/dist/index.js +3778 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Editor.tsx","../src/dom-bridge.ts","../src/EditorContext.tsx","../src/LinkDialog.tsx","../src/PageConfigDialog.tsx","../src/ImageCaptionDialog.tsx","../src/ImageResizeOverlay.tsx","../src/NodeView.tsx","../src/renderInline.tsx","../src/sliceDelta.ts","../src/TableResizeOverlay.tsx","../src/usePagination.ts","../src/useEditor.ts","../src/usePageSettings.ts","../src/Toolbar.tsx"],"sourcesContent":["export { Editor } from \"./Editor\";\nexport type { EditorProps, PageRenderContext, PageRenderProp } from \"./Editor\";\nexport { useEditor } from \"./useEditor\";\nexport type {\n LinkRequest,\n PendingMarks,\n UseEditorOptions,\n UseEditorResult,\n} from \"./useEditor\";\nexport { LinkDialog } from \"./LinkDialog\";\nexport { PageConfigDialog } from \"./PageConfigDialog\";\nexport { ImageCaptionDialog } from \"./ImageCaptionDialog\";\nexport { usePageSettings } from \"./usePageSettings\";\nexport type {\n CaptionAlign,\n ImageCaptionRequest,\n ImageCaptionResult,\n PageConfigRequest,\n} from \"./useEditor\";\nexport { NodeView } from \"./NodeView\";\nexport { renderInline } from \"./renderInline\";\nexport { EditorProvider, useEditorContext } from \"./EditorContext\";\nexport type { EditorProviderProps } from \"./EditorContext\";\nexport { Toolbar } from \"./Toolbar\";\nexport type { ToolbarProps } from \"./Toolbar\";\nexport {\n A4_PAGE,\n contentHeight,\n contentWidth,\n defaultPageLayout,\n usePageLayout,\n} from \"./usePagination\";\nexport type {\n BlockFragment,\n PageEntry,\n PageGeometry,\n PageLayout,\n PageSlot,\n TableRowFragment,\n} from \"./usePagination\";\nexport { sliceDelta, deltaLength } from \"./sliceDelta\";\nexport type { NodeViewFragment } from \"./NodeView\";\nexport * from \"./dom-bridge\";\n","import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n type JSX,\n type KeyboardEvent,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport {\n deleteBackward,\n deleteForward,\n insertParagraph,\n insertText,\n type CommandContext,\n type ListKind,\n type MarkName,\n type SerializedBlock,\n} from \"@sofereditor/core\";\nimport { applyDomSelection, readDomSelection, selectionsEqual } from \"./dom-bridge\";\nimport { EditorProvider } from \"./EditorContext\";\nimport { ImageResizeOverlay } from \"./ImageResizeOverlay\";\nimport { NodeView, type NodeViewFragment } from \"./NodeView\";\nimport {\n A4_PAGE,\n defaultPageLayout,\n usePageLayout,\n type PageGeometry,\n type PageLayout,\n type PageSlot,\n} from \"./usePagination\";\nimport { useEditor, type UseEditorResult } from \"./useEditor\";\nimport { usePageSettings } from \"./usePageSettings\";\n\nexport interface PageRenderContext {\n pageNumber: number;\n pageCount: number;\n}\n\nexport type PageRenderProp = (ctx: PageRenderContext) => ReactNode;\n\nexport interface EditorProps {\n editor?: UseEditorResult;\n className?: string;\n /**\n * Page geometry override. When **omitted**, the editor reads page settings\n * from `editor.doc` (the `docSettings` Y.Map populated via `setPageSettings`\n * or `import-docx`). When **set**, this value wins for rendering — but is\n * NOT written back to the Y.Doc (view-only override; useful when the host\n * app must pin a size regardless of doc state, e.g. a prova generator).\n * Pass **null** to disable pagination entirely (flat flow).\n */\n pageGeometry?: PageGeometry | null;\n /**\n * Custom page header. Receives `{ pageNumber, pageCount }` and renders inside\n * the top margin of every page (above the content area). Pass `null` to omit.\n */\n renderPageHeader?: PageRenderProp | null;\n /**\n * Custom page footer. Receives `{ pageNumber, pageCount }`. Defaults to\n * `\"<n> / <total>\"` centered. Pass `null` to omit.\n */\n renderPageFooter?: PageRenderProp | null;\n}\n\nconst defaultFooter: PageRenderProp = ({ pageNumber, pageCount }) =>\n `${pageNumber} / ${pageCount}`;\n\nexport function Editor({\n editor: providedEditor,\n className,\n pageGeometry,\n renderPageHeader,\n renderPageFooter = defaultFooter,\n}: EditorProps): JSX.Element {\n const internal = useEditor();\n const editor = providedEditor ?? internal;\n const { doc, history, snapshot, getSelection, setSelection } = editor;\n\n const rootRef = useRef<HTMLDivElement>(null);\n const isComposingRef = useRef(false);\n const suppressSelectionSyncRef = useRef(false);\n\n const ctxRef = useRef<CommandContext>({ doc, getSelection, setSelection });\n ctxRef.current = { doc, getSelection, setSelection };\n const historyRef = useRef(history);\n historyRef.current = history;\n const editorRef = useRef(editor);\n editorRef.current = editor;\n\n // Run after every render — not just when selection or snapshot change — so\n // we re-apply the caret after pagination's two-phase render cycle (which\n // mutates `layout` state without touching `editor.selection` or `snapshot`,\n // and tears down/rebuilds the text nodes the prior DOM selection was attached\n // to). The early-return when DOM already matches the model keeps this cheap.\n useLayoutEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n if (isComposingRef.current) return;\n if (document.activeElement !== root) return;\n const current = readDomSelection(root);\n if (current && selectionsEqual(current, editor.selection)) return;\n suppressSelectionSyncRef.current = true;\n applyDomSelection(root, editor.selection);\n queueMicrotask(() => {\n suppressSelectionSyncRef.current = false;\n });\n });\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n const handler = () => {\n if (suppressSelectionSyncRef.current) return;\n if (isComposingRef.current) return;\n if (document.activeElement !== root) return;\n const modelSel = readDomSelection(root);\n if (modelSel) setSelection(modelSel);\n };\n document.addEventListener(\"selectionchange\", handler);\n return () => document.removeEventListener(\"selectionchange\", handler);\n }, [setSelection]);\n\n // ---------- Sub-phase 4.5: rectangular table-cell drag ----------\n //\n // mousedown captures the anchor cell. mousemove flips into \"rect mode\" the\n // moment the pointer enters a DIFFERENT cell of the same table, at which\n // point we suppress the native cross-cell selection and write a rectangular\n // selection to the model. The visual highlight is drawn by TableView via\n // CSS classes (see isTableRectSelection in dom-bridge).\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n interface DragState {\n blockIndex: number;\n anchorCellIndex: number;\n anchorTableEl: HTMLTableElement;\n rectActive: boolean;\n }\n let drag: DragState | null = null;\n\n function cellFromTarget(target: EventTarget | null): {\n blockIndex: number;\n cellIndex: number;\n tableEl: HTMLTableElement;\n } | null {\n if (!(target instanceof Node)) return null;\n let n: Node | null = target;\n let cellEl: HTMLElement | null = null;\n let tableEl: HTMLTableElement | null = null;\n while (n && n !== root) {\n if (n.nodeType === Node.ELEMENT_NODE) {\n const e = n as HTMLElement;\n if (!cellEl && e.dataset.cellIndex != null) cellEl = e;\n if (e.tagName === \"TABLE\" && e.dataset.blockIndex != null) {\n tableEl = e as HTMLTableElement;\n break;\n }\n }\n n = n.parentNode;\n }\n if (!cellEl || !tableEl) return null;\n const cellIndex = Number.parseInt(cellEl.dataset.cellIndex!, 10);\n const blockIndex = Number.parseInt(tableEl.dataset.blockIndex!, 10);\n return { blockIndex, cellIndex, tableEl };\n }\n\n const onPointerDown = (e: PointerEvent) => {\n if (e.button !== 0) return;\n const hit = cellFromTarget(e.target);\n if (!hit) {\n drag = null;\n return;\n }\n drag = {\n blockIndex: hit.blockIndex,\n anchorCellIndex: hit.cellIndex,\n anchorTableEl: hit.tableEl,\n rectActive: false,\n };\n };\n\n const onPointerMove = (e: PointerEvent) => {\n if (!drag) return;\n // Only treat as drag when the primary button is still pressed.\n if ((e.buttons & 1) === 0) {\n drag = null;\n return;\n }\n const hit = cellFromTarget(e.target);\n if (!hit) return;\n if (hit.blockIndex !== drag.blockIndex) return; // never cross tables\n if (hit.cellIndex === drag.anchorCellIndex && !drag.rectActive) return;\n\n if (!drag.rectActive) {\n drag.rectActive = true;\n // Kill any in-progress native cross-cell selection.\n window.getSelection()?.removeAllRanges();\n }\n e.preventDefault();\n ctxRef.current.setSelection({\n anchor: { blockIndex: drag.blockIndex, cellIndex: drag.anchorCellIndex, offset: 0 },\n focus: { blockIndex: drag.blockIndex, cellIndex: hit.cellIndex, offset: 0 },\n });\n };\n\n const onPointerUp = () => {\n drag = null;\n };\n\n root.addEventListener(\"pointerdown\", onPointerDown);\n document.addEventListener(\"pointermove\", onPointerMove);\n document.addEventListener(\"pointerup\", onPointerUp);\n return () => {\n root.removeEventListener(\"pointerdown\", onPointerDown);\n document.removeEventListener(\"pointermove\", onPointerMove);\n document.removeEventListener(\"pointerup\", onPointerUp);\n };\n }, []);\n\n // ---------- Fase 5: drag-drop de imagens ----------\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n const onDragOver = (e: DragEvent) => {\n if (!e.dataTransfer) return;\n const hasFiles = Array.from(e.dataTransfer.items ?? []).some(\n (i) => i.kind === \"file\",\n );\n if (!hasFiles) return;\n e.preventDefault();\n e.dataTransfer.dropEffect = \"copy\";\n };\n const onDrop = (e: DragEvent) => {\n if (!e.dataTransfer) return;\n const images = Array.from(e.dataTransfer.files).filter((f) =>\n f.type.startsWith(\"image/\"),\n );\n if (images.length === 0) return;\n e.preventDefault();\n // Position the caret at the drop point so the insertion lands there.\n const range = caretRangeFromPoint(e.clientX, e.clientY);\n if (range) {\n const dom = window.getSelection();\n dom?.removeAllRanges();\n dom?.addRange(range);\n const sel = readDomSelection(root);\n if (sel) ctxRef.current.setSelection(sel);\n }\n void (async () => {\n for (const f of images) await editorRef.current.insertImageFromFile(f);\n })();\n };\n root.addEventListener(\"dragover\", onDragOver);\n root.addEventListener(\"drop\", onDrop);\n return () => {\n root.removeEventListener(\"dragover\", onDragOver);\n root.removeEventListener(\"drop\", onDrop);\n };\n }, []);\n\n // ---------- Fase 5: clique numa imagem seleciona o embed ----------\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n const onPointerDown = (e: PointerEvent) => {\n if (e.button !== 0) return;\n const target = e.target;\n if (!(target instanceof Element)) return;\n const img = target.closest('img[data-embed=\"image\"]') as HTMLElement | null;\n if (!img) return;\n const blockEl = img.closest(\"[data-block-index]\") as HTMLElement | null;\n if (!blockEl) return;\n const blockIndex = Number.parseInt(blockEl.dataset.blockIndex!, 10);\n const offsetAttr = img.dataset.embedOffset;\n if (offsetAttr == null) return;\n const localOffset = Number.parseInt(offsetAttr, 10);\n const fragmentStart = Number.parseInt(blockEl.dataset.fragmentStart ?? \"0\", 10) || 0;\n const cellEl = img.closest(\"[data-cell-index]\") as HTMLElement | null;\n const cellIndex = cellEl\n ? Number.parseInt(cellEl.dataset.cellIndex!, 10)\n : undefined;\n const offset = fragmentStart + localOffset;\n e.preventDefault();\n ctxRef.current.setSelection({\n anchor: { blockIndex, cellIndex, offset },\n focus: { blockIndex, cellIndex, offset: offset + 1 },\n });\n };\n root.addEventListener(\"pointerdown\", onPointerDown);\n return () => root.removeEventListener(\"pointerdown\", onPointerDown);\n }, []);\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n\n const handler = (e: InputEvent) => {\n const ctx = ctxRef.current;\n const hist = historyRef.current;\n const ed = editorRef.current;\n const type = e.inputType;\n\n if (isComposingRef.current && type === \"insertCompositionText\") return;\n\n switch (type) {\n case \"insertText\": {\n const data = e.data ?? \"\";\n if (data.length > 0) {\n e.preventDefault();\n insertText(ctx, data, ed.consumePendingMarks());\n }\n return;\n }\n case \"insertParagraph\":\n case \"insertLineBreak\": {\n e.preventDefault();\n // If an embed is the entire selection, drop the caret RIGHT AFTER it\n // before splitting — otherwise the default \"delete range then insert\n // paragraph\" path would remove the image.\n const selectedEmbed = ed.getSelectedEmbed();\n if (selectedEmbed) {\n const off = selectedEmbed.offset + 1;\n ctx.setSelection({\n anchor: {\n blockIndex: selectedEmbed.blockIndex,\n cellIndex: selectedEmbed.cellIndex,\n offset: off,\n },\n focus: {\n blockIndex: selectedEmbed.blockIndex,\n cellIndex: selectedEmbed.cellIndex,\n offset: off,\n },\n });\n }\n if (ed.splitListItem()) return;\n insertParagraph(ctx);\n return;\n }\n case \"insertReplacementText\": {\n const text = e.data ?? e.dataTransfer?.getData(\"text/plain\") ?? \"\";\n if (text.length > 0) {\n e.preventDefault();\n insertText(ctx, text, ed.consumePendingMarks());\n }\n return;\n }\n case \"insertFromPaste\": {\n e.preventDefault();\n const images = Array.from(e.dataTransfer?.files ?? []).filter((f) =>\n f.type.startsWith(\"image/\"),\n );\n if (images.length > 0) {\n void (async () => {\n for (const f of images) await editorRef.current.insertImageFromFile(f);\n })();\n return;\n }\n const text = e.dataTransfer?.getData(\"text/plain\") ?? \"\";\n if (text.length === 0) return;\n const lines = text.split(/\\r\\n|\\r|\\n/);\n lines.forEach((line, i) => {\n if (i > 0) insertParagraph(ctx);\n if (line.length > 0) insertText(ctx, line);\n });\n return;\n }\n case \"deleteContentBackward\":\n case \"deleteWordBackward\":\n case \"deleteSoftLineBackward\":\n case \"deleteHardLineBackward\": {\n e.preventDefault();\n deleteBackward(ctx);\n return;\n }\n case \"deleteContentForward\":\n case \"deleteWordForward\":\n case \"deleteSoftLineForward\":\n case \"deleteHardLineForward\": {\n e.preventDefault();\n deleteForward(ctx);\n return;\n }\n case \"historyUndo\": {\n e.preventDefault();\n hist.undo();\n return;\n }\n case \"historyRedo\": {\n e.preventDefault();\n hist.redo();\n return;\n }\n default: {\n e.preventDefault();\n return;\n }\n }\n };\n\n root.addEventListener(\"beforeinput\", handler);\n return () => root.removeEventListener(\"beforeinput\", handler);\n }, []);\n\n const onKeyDown = useCallback((e: KeyboardEvent<HTMLDivElement>) => {\n const ed = editorRef.current;\n const mod = e.metaKey || e.ctrlKey;\n\n if (e.key === \"Tab\") {\n e.preventDefault();\n // Inside a table, Tab/Shift+Tab navigates between cells; at the last\n // cell Tab appends a new row.\n if (ed.isInTable()) {\n if (e.shiftKey) ed.moveToPrevCell();\n else ed.moveToNextCell();\n return;\n }\n if (e.shiftKey) ed.dedentList();\n else ed.indentList();\n return;\n }\n\n if (!mod) return;\n const key = e.key.toLowerCase();\n\n if (!e.shiftKey && !e.altKey && key === \"z\") {\n e.preventDefault();\n historyRef.current.undo();\n return;\n }\n if (!e.altKey && (key === \"y\" || (e.shiftKey && key === \"z\"))) {\n e.preventDefault();\n historyRef.current.redo();\n return;\n }\n\n if (e.altKey && !e.shiftKey && /^[0-6]$/.test(key)) {\n e.preventDefault();\n const n = Number(key);\n if (n === 0) ed.setBlockType(\"paragraph\");\n else ed.setBlockType(\"heading\", { level: n as 1 | 2 | 3 | 4 | 5 | 6 });\n return;\n }\n\n if (e.shiftKey && !e.altKey && (key === \"7\" || key === \"8\")) {\n e.preventDefault();\n ed.toggleList(key === \"7\" ? \"ordered\" : \"bullet\");\n return;\n }\n\n const markToggle = !e.shiftKey && !e.altKey\n ? (BOOLEAN_SHORTCUTS[key] as MarkName | undefined)\n : undefined;\n if (markToggle) {\n e.preventDefault();\n ed.toggleMark(markToggle);\n return;\n }\n if (e.shiftKey && !e.altKey && key === \"x\") {\n e.preventDefault();\n ed.toggleMark(\"strike\");\n return;\n }\n\n if (!e.altKey && !e.shiftKey && key === \"k\") {\n e.preventDefault();\n const active = ed.getActiveMarks();\n const currentHref =\n active.link && typeof active.link === \"object\" && \"href\" in active.link\n ? (active.link.href as string)\n : \"\";\n void ed.requestLink(currentHref).then((href) => {\n if (href === null) return;\n if (href === \"\") ed.removeMark(\"link\");\n else ed.setMark(\"link\", { href });\n });\n }\n }, []);\n\n const onCompositionStart = useCallback(() => {\n isComposingRef.current = true;\n }, []);\n\n const onCompositionEnd = useCallback((e: React.CompositionEvent<HTMLDivElement>) => {\n isComposingRef.current = false;\n if (e.data && e.data.length > 0) {\n insertText(ctxRef.current, e.data);\n }\n }, []);\n\n const topLevels = useMemo(() => groupTopLevels(snapshot.blocks), [snapshot]);\n // Page geometry sources, in precedence order:\n // 1. `pageGeometry` prop when explicitly set (view-only override — does NOT\n // write back to the Y.Doc; useful for apps that force a fixed size, e.g.\n // prova generator pinned to A4).\n // 2. `editor.doc` page settings (Y.Doc-backed, sync-aware).\n // 3. `A4_PAGE` fallback when both unavailable.\n // `pageGeometry={null}` continues to disable pagination entirely.\n const docSettings = usePageSettings(editor.doc);\n const propIsSet = pageGeometry !== undefined;\n const geom: PageGeometry = propIsSet ? (pageGeometry ?? A4_PAGE) : docSettings;\n const paginated = pageGeometry !== null;\n // Reads from snapshot + selection; recomputed on every render.\n const selectedEmbed = editor.getSelectedEmbed();\n\n const layout = usePageLayout(\n rootRef as RefObject<HTMLElement>,\n geom,\n topLevels.length,\n [topLevels, pageGeometry],\n );\n\n const effectiveLayout: PageLayout = paginated ? layout : defaultPageLayout(topLevels.length);\n\n const pageStyle = paginated\n ? ({\n \"--ed-page-width\": `${geom.width}px`,\n \"--ed-page-height\": `${geom.height}px`,\n \"--ed-page-margin-top\": `${geom.marginTop}px`,\n \"--ed-page-margin-bottom\": `${geom.marginBottom}px`,\n \"--ed-page-margin-left\": `${geom.marginLeft}px`,\n \"--ed-page-margin-right\": `${geom.marginRight}px`,\n } as React.CSSProperties)\n : undefined;\n\n const body = (\n <div\n ref={rootRef}\n contentEditable\n suppressContentEditableWarning\n spellCheck\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n role=\"textbox\"\n aria-multiline=\"true\"\n className={\n (className ?? \"ed-root\") + (paginated ? \" ed-root--paged\" : \" ed-root--flat\")\n }\n style={pageStyle}\n onKeyDown={onKeyDown}\n onCompositionStart={onCompositionStart}\n onCompositionEnd={onCompositionEnd}\n >\n {paginated\n ? effectiveLayout.pages.map((page, pi) => {\n const ctx: PageRenderContext = {\n pageNumber: pi + 1,\n pageCount: effectiveLayout.pages.length,\n };\n return (\n <div\n key={`page-${pi}`}\n className=\"ed-page\"\n data-page-number={ctx.pageNumber}\n data-page-total={ctx.pageCount}\n >\n {renderPageHeader && (\n <div className=\"ed-page-header\" contentEditable={false}>\n {renderPageHeader(ctx)}\n </div>\n )}\n <div className=\"ed-page-content\">\n {page.slots.map((slot) => renderSlot(slot, topLevels))}\n </div>\n {renderPageFooter && (\n <div className=\"ed-page-footer\" contentEditable={false}>\n {renderPageFooter(ctx)}\n </div>\n )}\n </div>\n );\n })\n : topLevels.map((t) => renderTopLevel(t))}\n {selectedEmbed && (\n <ImageResizeOverlay\n rootRef={rootRef}\n blockIndex={selectedEmbed.blockIndex}\n offset={selectedEmbed.offset}\n cellIndex={selectedEmbed.cellIndex}\n embed={selectedEmbed.embed}\n onCommit={(w, h) =>\n editor.setImageAttrs(\n selectedEmbed.blockIndex,\n selectedEmbed.offset,\n { width: w, height: h },\n selectedEmbed.cellIndex,\n )\n }\n onCommitMove={(ox, oy) =>\n editor.setImageAttrs(\n selectedEmbed.blockIndex,\n selectedEmbed.offset,\n { offsetX: ox, offsetY: oy },\n selectedEmbed.cellIndex,\n )\n }\n />\n )}\n </div>\n );\n\n return <EditorProvider editor={editor}>{body}</EditorProvider>;\n}\n\n// ---------- Top-level grouping (data, not JSX) ----------\n\ninterface ListEntry {\n block: SerializedBlock;\n index: number;\n}\n\ntype TopLevel =\n | { kind: \"block\"; block: SerializedBlock; blockIndex: number; key: number }\n | { kind: \"list\"; items: ListEntry[]; listKind: ListKind; key: number };\n\nfunction groupTopLevels(snapshot: SerializedBlock[]): TopLevel[] {\n const out: TopLevel[] = [];\n let i = 0;\n while (i < snapshot.length) {\n const block = snapshot[i];\n if (block.type === \"listItem\") {\n const groupStart = i;\n const items: ListEntry[] = [];\n const kind: ListKind = block.attrs.listKind === \"ordered\" ? \"ordered\" : \"bullet\";\n while (\n i < snapshot.length &&\n snapshot[i].type === \"listItem\" &&\n (snapshot[i].attrs.listKind ?? \"bullet\") === kind\n ) {\n items.push({ block: snapshot[i], index: i });\n i++;\n }\n out.push({ kind: \"list\", items, listKind: kind, key: groupStart });\n continue;\n }\n out.push({ kind: \"block\", block, blockIndex: i, key: i });\n i++;\n }\n return out;\n}\n\nfunction renderSlot(slot: PageSlot, topLevels: TopLevel[]): JSX.Element | null {\n const top = topLevels[slot.topLevelIndex];\n if (!top) return null;\n if (slot.fragment && top.kind === \"block\") {\n const f: NodeViewFragment = {\n index: slot.fragment.index,\n start: slot.fragment.start,\n end: slot.fragment.end,\n };\n return (\n <NodeView\n key={`${top.key}-f${f.index}`}\n block={top.block}\n index={top.blockIndex}\n fragment={f}\n />\n );\n }\n if (slot.tableFragment && top.kind === \"block\" && top.block.type === \"table\") {\n return (\n <NodeView\n key={`${top.key}-tf${slot.tableFragment.index}`}\n block={top.block}\n index={top.blockIndex}\n tableFragment={slot.tableFragment}\n />\n );\n }\n return renderTopLevel(top);\n}\n\nfunction renderTopLevel(top: TopLevel): JSX.Element {\n if (top.kind === \"list\") {\n const tree = buildListTree(top.items);\n return renderListTree(tree, top.listKind, `list-${top.key}`);\n }\n return <NodeView key={top.key} block={top.block} index={top.blockIndex} />;\n}\n\ninterface ListNode {\n entry: ListEntry;\n children: ListNode[];\n}\n\nfunction buildListTree(items: ListEntry[]): ListNode[] {\n const roots: ListNode[] = [];\n const stack: { children: ListNode[]; level: number }[] = [{ children: roots, level: -1 }];\n for (const it of items) {\n const level = clampListLevel(it.block.attrs.listLevel);\n while (stack.length > 1 && stack[stack.length - 1].level >= level) stack.pop();\n const node: ListNode = { entry: it, children: [] };\n stack[stack.length - 1].children.push(node);\n stack.push({ children: node.children, level });\n }\n return roots;\n}\n\nfunction renderListTree(tree: ListNode[], kind: ListKind, key: string): JSX.Element {\n const Tag = kind === \"ordered\" ? \"ol\" : \"ul\";\n return (\n <Tag key={key} className={`ed-list ed-list-${kind}`} data-list-kind={kind}>\n {tree.map((node) => (\n <NodeView key={node.entry.index} block={node.entry.block} index={node.entry.index}>\n {node.children.length > 0\n ? renderListTree(node.children, kind, `nested-${node.entry.index}`)\n : null}\n </NodeView>\n ))}\n </Tag>\n );\n}\n\nfunction clampListLevel(l: unknown): number {\n if (typeof l !== \"number\" || !Number.isFinite(l)) return 0;\n return Math.max(0, Math.min(5, Math.trunc(l)));\n}\n\nconst BOOLEAN_SHORTCUTS: Record<string, MarkName> = {\n b: \"bold\",\n i: \"italic\",\n u: \"underline\",\n};\n\ninterface CaretRangeFromPoint {\n caretRangeFromPoint(x: number, y: number): Range | null;\n}\ninterface CaretPositionFromPoint {\n caretPositionFromPoint(\n x: number,\n y: number,\n ): { offsetNode: Node; offset: number } | null;\n}\n\nfunction caretRangeFromPoint(x: number, y: number): Range | null {\n const doc = document as unknown as Partial<CaretRangeFromPoint & CaretPositionFromPoint>;\n if (typeof doc.caretRangeFromPoint === \"function\") {\n return doc.caretRangeFromPoint(x, y);\n }\n if (typeof doc.caretPositionFromPoint === \"function\") {\n const pos = doc.caretPositionFromPoint(x, y);\n if (!pos) return null;\n const range = document.createRange();\n range.setStart(pos.offsetNode, pos.offset);\n range.collapse(true);\n return range;\n }\n return null;\n}\n","import type { Position, Selection } from \"@sofereditor/core\";\n\n/**\n * Mapping between the model and the contenteditable DOM.\n *\n * Each block is rendered as one or more elements carrying `data-block-index`.\n * Unfragmented blocks have a single such element. A paragraph fragmented across\n * pages (Sub-phase 3.2) has multiple elements with the same `data-block-index`,\n * each carrying `data-fragment-start` / `data-fragment-end` indicating the\n * character offsets within the block's text that the element covers.\n *\n * Table blocks (Sub-phase 4.1) render the `<table>` itself with `data-block-index`.\n * Each `<td>` cell carries `data-cell-index` (flat row-major). Model positions\n * inside a table always include `cellIndex`; their `offset` is local to that\n * cell's text.\n */\n\n/** Walks up from `node` to the first ancestor that carries `data-block-index`. */\nfunction findContainingBlockElement(node: Node, root: HTMLElement): HTMLElement | null {\n let cur: Node | null = node;\n while (cur && cur !== root) {\n if (cur.nodeType === Node.ELEMENT_NODE) {\n const el = cur as HTMLElement;\n if (el.dataset.blockIndex != null) return el;\n }\n cur = cur.parentNode;\n }\n return null;\n}\n\n/** Walks up to the first ancestor carrying `data-cell-index`, stopping at the block element. */\nfunction findContainingCellElement(\n node: Node,\n blockEl: HTMLElement,\n): HTMLElement | null {\n let cur: Node | null = node;\n while (cur && cur !== blockEl) {\n if (cur.nodeType === Node.ELEMENT_NODE) {\n const el = cur as HTMLElement;\n if (el.dataset.cellIndex != null) return el;\n }\n cur = cur.parentNode;\n }\n return null;\n}\n\nexport function findBlockIndex(node: Node, root: HTMLElement): number | null {\n const el = findContainingBlockElement(node, root);\n if (!el) return null;\n return Number.parseInt(el.dataset.blockIndex!, 10);\n}\n\n/**\n * Returns the first DOM element for `blockIndex`. For a fragmented block this\n * is the first fragment. Prefer `getFragmentForOffset` when you need the\n * fragment that contains a specific offset.\n */\nexport function getBlockElement(root: HTMLElement, blockIndex: number): HTMLElement | null {\n return root.querySelector<HTMLElement>(`[data-block-index=\"${blockIndex}\"]`);\n}\n\nfunction readFragmentStart(el: HTMLElement): number {\n const s = el.dataset.fragmentStart;\n if (s == null) return 0;\n const n = Number.parseInt(s, 10);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction readFragmentEnd(el: HTMLElement): number | undefined {\n const s = el.dataset.fragmentEnd;\n if (s == null) return undefined;\n const n = Number.parseInt(s, 10);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/**\n * Returns the DOM element responsible for `offset` inside `blockIndex`.\n * - Unfragmented block (single element): returns it.\n * - Fragmented block: returns the fragment whose `[start, end)` covers `offset`.\n * For the end-of-block offset, returns the last fragment.\n */\nexport function getFragmentForOffset(\n root: HTMLElement,\n blockIndex: number,\n offset: number,\n): HTMLElement | null {\n const candidates = root.querySelectorAll<HTMLElement>(`[data-block-index=\"${blockIndex}\"]`);\n if (candidates.length === 0) return null;\n if (candidates.length === 1) return candidates[0];\n let last: HTMLElement | null = null;\n for (const el of candidates) {\n last = el;\n const start = readFragmentStart(el);\n const end = readFragmentEnd(el);\n if (end == null) return el;\n if (offset >= start && offset < end) return el;\n }\n return last; // end-of-block offset falls on the last fragment\n}\n\n/**\n * Returns the `<td>` element for `(blockIndex, cellIndex)`. Tables are\n * unfragmented in 4.1 so there's at most one block element to search inside.\n */\nexport function getCellElement(\n root: HTMLElement,\n blockIndex: number,\n cellIndex: number,\n): HTMLElement | null {\n const blockEl = getBlockElement(root, blockIndex);\n if (!blockEl) return null;\n return blockEl.querySelector<HTMLElement>(`[data-cell-index=\"${cellIndex}\"]`);\n}\n\n/**\n * `true` when `el` is an image embed (a length-1 atomic insert in the model).\n * Image embeds participate in offset arithmetic as 1 char each. Intentionally\n * not a type predicate — narrowing `n is HTMLElement` would collapse the\n * \"already an HTMLElement\" path to `never` and break downstream code.\n */\nfunction isImgEmbed(n: Node): boolean {\n return (\n n.nodeType === Node.ELEMENT_NODE &&\n (n as HTMLElement).dataset.embed === \"image\"\n );\n}\n\n/**\n * `true` when `el` is the float-wrap anchor `<img>` rendered at the START of a\n * block (so CSS float can wrap text around it). The model places this embed at\n * its original offset — represented in the DOM by a zero-width phantom span —\n * so the anchor itself must be SKIPPED during offset counting.\n */\nfunction isWrapAnchorImg(n: Node): boolean {\n return (\n n.nodeType === Node.ELEMENT_NODE &&\n (n as HTMLElement).dataset.wrapAnchor === \"true\"\n );\n}\n\n/**\n * `true` when `el` is the zero-width sentinel left at the model offset of a\n * float-wrap image. Counts as 1 char in offset arithmetic, mirroring how the\n * embed counts in the model.\n */\nfunction isPhantomEmbed(n: Node): boolean {\n return (\n n.nodeType === Node.ELEMENT_NODE &&\n (n as HTMLElement).dataset.embedPhantom === \"true\"\n );\n}\n\n/** Index of `n` within its parent's `childNodes`. */\nfunction indexInParent(n: Node): number {\n const parent = n.parentNode;\n if (!parent) return 0;\n let i = 0;\n for (const c of Array.from(parent.childNodes)) {\n if (c === n) return i;\n i++;\n }\n return 0;\n}\n\n/**\n * `true` when the subtree rooted at `el` should be skipped during a\n * container-scoped walk — i.e. it belongs to a different block or to a sibling\n * cell when scoping a cell container.\n */\nfunction isRejectedSubtree(el: HTMLElement, container: HTMLElement): boolean {\n if (el === container) return false;\n if (el.dataset.blockIndex != null) return true;\n if (container.dataset.cellIndex != null && el.dataset.cellIndex != null) return true;\n return false;\n}\n\n/**\n * Sum length of all text nodes plus 1 for each image embed inside `container`,\n * up to the boundary defined by `(node, offsetInNode)`. Mirrors how the model\n * counts characters: embeds are atomic length-1 inserts.\n */\nexport function textOffsetWithin(\n container: HTMLElement,\n node: Node,\n offsetInNode: number,\n): number {\n // Normalize an anchor pointing AT an image embed to (parent, indexOfImg).\n let target: Node = node;\n let targetOff = offsetInNode;\n if (isImgEmbed(target) && target.parentNode) {\n targetOff = indexInParent(target);\n target = target.parentNode as Node;\n }\n\n let offset = 0;\n let done = false;\n\n function visit(n: Node): void {\n if (done) return;\n if (n === target) {\n if (n.nodeType === Node.TEXT_NODE) {\n offset += targetOff;\n done = true;\n return;\n }\n // Element target: consume childNodes[0..targetOff-1] recursively.\n const children = n.childNodes;\n for (let i = 0; i < targetOff && i < children.length; i++) {\n visit(children[i]);\n if (done) return;\n }\n done = true;\n return;\n }\n if (n.nodeType === Node.TEXT_NODE) {\n offset += (n.textContent ?? \"\").length;\n return;\n }\n if (n.nodeType !== Node.ELEMENT_NODE) return;\n const el = n as HTMLElement;\n if (isRejectedSubtree(el, container)) return;\n // Float-wrap anchor `<img>` is rendered at the block start as a pure\n // visual; its model position lives in the phantom span downstream.\n if (isImgEmbed(el) && isWrapAnchorImg(el)) return;\n if (isImgEmbed(el) || isPhantomEmbed(el)) {\n offset += 1;\n return;\n }\n for (const child of Array.from(el.childNodes)) {\n visit(child);\n if (done) return;\n }\n }\n\n visit(container);\n return offset;\n}\n\ninterface ResolvedAnchor {\n blockIdx: number;\n cellIdx: number | undefined;\n /** The element whose text content offsets are computed against. */\n container: HTMLElement;\n /** Number to add to within-container offsets — non-zero only for fragmented blocks. */\n containerStart: number;\n}\n\nfunction resolveAnchorElement(\n node: Node,\n root: HTMLElement,\n): ResolvedAnchor | null {\n const blockEl = findContainingBlockElement(node, root);\n if (!blockEl) return null;\n const blockIdx = Number.parseInt(blockEl.dataset.blockIndex!, 10);\n const blockType = blockEl.dataset.blockType;\n if (blockType === \"table\") {\n const cellEl = findContainingCellElement(node, blockEl);\n if (!cellEl) {\n // Click landed inside the table but not in any cell — snap to first cell.\n const firstCell = blockEl.querySelector<HTMLElement>(\"[data-cell-index]\");\n if (!firstCell) return null;\n return {\n blockIdx,\n cellIdx: 0,\n container: firstCell,\n containerStart: 0,\n };\n }\n const cellIdx = Number.parseInt(cellEl.dataset.cellIndex!, 10);\n return {\n blockIdx,\n cellIdx,\n container: cellEl,\n containerStart: 0,\n };\n }\n return {\n blockIdx,\n cellIdx: undefined,\n container: blockEl,\n containerStart: readFragmentStart(blockEl),\n };\n}\n\nexport function readDomSelection(root: HTMLElement): Selection | null {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n if (!sel.anchorNode || !sel.focusNode) return null;\n if (!root.contains(sel.anchorNode) || !root.contains(sel.focusNode)) return null;\n\n const a = resolveAnchorElement(sel.anchorNode, root);\n const f = resolveAnchorElement(sel.focusNode, root);\n if (!a || !f) return null;\n\n const anchor: Position = {\n blockIndex: a.blockIdx,\n cellIndex: a.cellIdx,\n offset: a.containerStart + textOffsetWithin(a.container, sel.anchorNode, sel.anchorOffset),\n };\n const focus: Position = {\n blockIndex: f.blockIdx,\n cellIndex: f.cellIdx,\n offset: f.containerStart + textOffsetWithin(f.container, sel.focusNode, sel.focusOffset),\n };\n return { anchor, focus };\n}\n\ninterface DomPoint {\n node: Node;\n offset: number;\n}\n\nfunction locatePoint(root: HTMLElement, pos: Position): DomPoint | null {\n let container: HTMLElement | null;\n let containerStart = 0;\n\n if (pos.cellIndex != null) {\n container = getCellElement(root, pos.blockIndex, pos.cellIndex);\n if (!container) return null;\n } else {\n container = getFragmentForOffset(root, pos.blockIndex, pos.offset);\n if (!container) return null;\n containerStart = readFragmentStart(container);\n }\n\n let remaining = Math.max(0, pos.offset - containerStart);\n let result: DomPoint | null = null;\n let lastImg: HTMLElement | null = null;\n\n function visit(n: Node): void {\n if (result) return;\n if (n.nodeType === Node.TEXT_NODE) {\n const len = (n.textContent ?? \"\").length;\n if (remaining <= len) {\n result = { node: n, offset: remaining };\n return;\n }\n remaining -= len;\n lastImg = null;\n return;\n }\n if (n.nodeType !== Node.ELEMENT_NODE) return;\n const el = n as HTMLElement;\n if (isRejectedSubtree(el, container!)) return;\n // Skip the float-wrap anchor — its slot in the model lives on the phantom.\n if (isImgEmbed(el) && isWrapAnchorImg(el)) return;\n if (isImgEmbed(el) || isPhantomEmbed(el)) {\n if (remaining === 0) {\n const parent = el.parentNode;\n if (parent) {\n result = { node: parent, offset: indexInParent(el) };\n return;\n }\n }\n remaining -= 1;\n lastImg = el;\n return;\n }\n for (const child of Array.from(el.childNodes)) {\n visit(child);\n if (result) return;\n }\n }\n\n visit(container);\n if (result) return result;\n\n // Walked the whole container without consuming `remaining` — caret lands\n // just AFTER the last embed if it was the last visited node, otherwise at\n // the container's start as a last-resort fallback.\n if (lastImg && remaining === 0) {\n const parent = (lastImg as HTMLElement).parentNode;\n if (parent) return { node: parent, offset: indexInParent(lastImg) + 1 };\n }\n return { node: container, offset: 0 };\n}\n\nexport function selectionsEqual(a: Selection, b: Selection): boolean {\n return (\n a.anchor.blockIndex === b.anchor.blockIndex &&\n (a.anchor.cellIndex ?? -1) === (b.anchor.cellIndex ?? -1) &&\n a.anchor.offset === b.anchor.offset &&\n a.focus.blockIndex === b.focus.blockIndex &&\n (a.focus.cellIndex ?? -1) === (b.focus.cellIndex ?? -1) &&\n a.focus.offset === b.focus.offset\n );\n}\n\n/**\n * `true` when the selection is a rectangular table-cell range — both endpoints\n * inside cells of the same block, addressing different cells. The visual\n * highlight comes from CSS classes applied by `<TableView>`; we deliberately\n * leave the native DOM selection empty so the browser doesn't draw a confusing\n * cross-`<td>` range.\n */\nexport function isTableRectSelection(sel: Selection): boolean {\n if (sel.anchor.blockIndex !== sel.focus.blockIndex) return false;\n if (sel.anchor.cellIndex == null || sel.focus.cellIndex == null) return false;\n return sel.anchor.cellIndex !== sel.focus.cellIndex;\n}\n\nexport function applyDomSelection(root: HTMLElement, modelSel: Selection): void {\n const domSel = window.getSelection();\n if (!domSel) return;\n if (isTableRectSelection(modelSel)) {\n // Don't paint a native range — TableView highlights the rect via classes.\n domSel.removeAllRanges();\n return;\n }\n const anchorPt = locatePoint(root, modelSel.anchor);\n const focusPt = locatePoint(root, modelSel.focus);\n if (!anchorPt || !focusPt) return;\n\n try {\n domSel.removeAllRanges();\n domSel.setBaseAndExtent(anchorPt.node, anchorPt.offset, focusPt.node, focusPt.offset);\n } catch {\n // ignore — node may not be attached yet\n }\n}\n","import { createContext, useContext, type JSX, type ReactNode } from \"react\";\nimport { LinkDialog } from \"./LinkDialog\";\nimport { PageConfigDialog } from \"./PageConfigDialog\";\nimport { ImageCaptionDialog } from \"./ImageCaptionDialog\";\nimport type { UseEditorResult } from \"./useEditor\";\n\nconst EditorContext = createContext<UseEditorResult | null>(null);\n\nexport interface EditorProviderProps {\n editor: UseEditorResult;\n children: ReactNode;\n}\n\nexport function EditorProvider({ editor, children }: EditorProviderProps): JSX.Element {\n return (\n <EditorContext.Provider value={editor}>\n {children}\n <LinkDialog />\n <PageConfigDialog />\n <ImageCaptionDialog />\n </EditorContext.Provider>\n );\n}\n\nexport function useEditorContext(): UseEditorResult {\n const ctx = useContext(EditorContext);\n if (!ctx) {\n throw new Error(\"useEditorContext must be used inside an <EditorProvider>\");\n }\n return ctx;\n}\n","import {\n useEffect,\n useRef,\n useState,\n type FormEvent,\n type JSX,\n} from \"react\";\nimport { useEditorContext } from \"./EditorContext\";\n\n/**\n * Modal dialog for entering a link URL. Replaces the bare `window.prompt`\n * previously wired to Cmd+K and the toolbar link button. Renders only when\n * `editor.linkRequest` is set; consumes that state via `resolveLinkRequest`.\n *\n * Uses the native `<dialog>` element for focus trapping, ESC handling, and the\n * browser-provided backdrop.\n */\nexport function LinkDialog(): JSX.Element | null {\n const { linkRequest, resolveLinkRequest } = useEditorContext();\n const dialogRef = useRef<HTMLDialogElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const [href, setHref] = useState(\"\");\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (linkRequest) {\n setHref(linkRequest.initialHref);\n if (!dialog.open) dialog.showModal();\n // Defer focus + select-all to after the dialog finishes opening.\n queueMicrotask(() => {\n const input = inputRef.current;\n if (input) {\n input.focus();\n input.select();\n }\n });\n } else if (dialog.open) {\n dialog.close();\n }\n }, [linkRequest]);\n\n if (!linkRequest) return null;\n\n const onSubmit = (e: FormEvent) => {\n e.preventDefault();\n resolveLinkRequest(href.trim());\n };\n\n const onRemove = () => {\n // Empty string signals \"remove the link mark\".\n resolveLinkRequest(\"\");\n };\n\n const onCancel = () => {\n resolveLinkRequest(null);\n };\n\n return (\n <dialog\n ref={dialogRef}\n className=\"ed-link-dialog\"\n onClose={onCancel}\n onCancel={(e) => {\n e.preventDefault();\n onCancel();\n }}\n >\n <form onSubmit={onSubmit} className=\"ed-link-dialog-form\">\n <div className=\"ed-link-dialog-row\">\n <label htmlFor=\"ed-link-href\">URL</label>\n <input\n id=\"ed-link-href\"\n ref={inputRef}\n type=\"url\"\n inputMode=\"url\"\n value={href}\n onChange={(e) => setHref(e.target.value)}\n placeholder=\"https://exemplo.com\"\n autoComplete=\"off\"\n />\n </div>\n <div className=\"ed-link-dialog-actions\">\n {linkRequest.initialHref ? (\n <button type=\"button\" onClick={onRemove} className=\"ed-link-dialog-remove\">\n Remover link\n </button>\n ) : (\n <span />\n )}\n <div className=\"ed-link-dialog-confirm\">\n <button type=\"button\" onClick={onCancel}>\n Cancelar\n </button>\n <button type=\"submit\" className=\"ed-link-dialog-apply\">\n Aplicar\n </button>\n </div>\n </div>\n </form>\n </dialog>\n );\n}\n","import { useEffect, useMemo, useRef, useState, type FormEvent, type JSX } from \"react\";\nimport {\n MARGIN_PRESETS,\n PAGE_PRESETS,\n detectPreset,\n mmToPx,\n pxToMm,\n type PageSettings,\n type PagePreset,\n} from \"@sofereditor/core\";\nimport { useEditorContext } from \"./EditorContext\";\n\ntype MarginPreset = \"normal\" | \"narrow\" | \"wide\" | \"custom\";\n\n/**\n * Modal dialog to configure page size and margins. Mirrors `LinkDialog` —\n * driven by `editor.pageConfigRequest`. On apply, writes via\n * `editor.setPageSettings`; on cancel, no write.\n */\nexport function PageConfigDialog(): JSX.Element | null {\n const { pageConfigRequest, resolvePageConfigRequest, setPageSettings } = useEditorContext();\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n // Form state. Sizes are kept in mm for user-facing inputs; we convert to px\n // when applying. Width/height pair determines the size preset.\n const [sizePreset, setSizePreset] = useState<PagePreset>(\"a4\");\n const [widthMm, setWidthMm] = useState(210);\n const [heightMm, setHeightMm] = useState(297);\n const [marginPreset, setMarginPreset] = useState<MarginPreset>(\"normal\");\n const [marginTopMm, setMarginTopMm] = useState(25.4);\n const [marginBottomMm, setMarginBottomMm] = useState(25.4);\n const [marginLeftMm, setMarginLeftMm] = useState(25.4);\n const [marginRightMm, setMarginRightMm] = useState(25.4);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (pageConfigRequest) {\n hydrateFromSettings(pageConfigRequest.initial, {\n setSizePreset,\n setWidthMm,\n setHeightMm,\n setMarginPreset,\n setMarginTopMm,\n setMarginBottomMm,\n setMarginLeftMm,\n setMarginRightMm,\n });\n if (!dialog.open) dialog.showModal();\n } else if (dialog.open) {\n dialog.close();\n }\n }, [pageConfigRequest]);\n\n // When the user picks a size preset, snap width/height back to the canonical\n // values. \"custom\" leaves the user free to edit.\n useEffect(() => {\n if (sizePreset === \"custom\") return;\n const p = PAGE_PRESETS[sizePreset];\n setWidthMm(roundMm(pxToMm(p.width)));\n setHeightMm(roundMm(pxToMm(p.height)));\n }, [sizePreset]);\n\n // When the user picks a margin preset, set all 4 margins to that value.\n useEffect(() => {\n if (marginPreset === \"custom\") return;\n const px = MARGIN_PRESETS[marginPreset];\n const mm = roundMm(pxToMm(px));\n setMarginTopMm(mm);\n setMarginBottomMm(mm);\n setMarginLeftMm(mm);\n setMarginRightMm(mm);\n }, [marginPreset]);\n\n const customWidth = sizePreset === \"custom\";\n\n // Live preview of the dimensions in px so the test/QA loop is easy to read.\n const previewPx = useMemo(\n () => ({\n width: Math.round(mmToPx(widthMm)),\n height: Math.round(mmToPx(heightMm)),\n }),\n [widthMm, heightMm],\n );\n\n if (!pageConfigRequest) return null;\n\n const onApply = (e: FormEvent) => {\n e.preventDefault();\n const next: Partial<PageSettings> = {\n width: mmToPx(widthMm),\n height: mmToPx(heightMm),\n marginTop: mmToPx(marginTopMm),\n marginBottom: mmToPx(marginBottomMm),\n marginLeft: mmToPx(marginLeftMm),\n marginRight: mmToPx(marginRightMm),\n };\n setPageSettings(next);\n resolvePageConfigRequest(true);\n };\n const onCancel = () => resolvePageConfigRequest(false);\n\n return (\n <dialog\n ref={dialogRef}\n className=\"ed-page-config-dialog\"\n onClose={onCancel}\n onCancel={(e) => {\n e.preventDefault();\n onCancel();\n }}\n >\n <form onSubmit={onApply} className=\"ed-page-config-form\">\n <h2>Configurar página</h2>\n\n <fieldset>\n <legend>Tamanho</legend>\n <div className=\"ed-page-config-row\">\n <label>\n <input\n type=\"radio\"\n name=\"size\"\n checked={sizePreset === \"a4\"}\n onChange={() => setSizePreset(\"a4\")}\n />{\" \"}\n A4 (210 × 297 mm)\n </label>\n <label>\n <input\n type=\"radio\"\n name=\"size\"\n checked={sizePreset === \"letter\"}\n onChange={() => setSizePreset(\"letter\")}\n />{\" \"}\n Carta (216 × 279 mm)\n </label>\n <label>\n <input\n type=\"radio\"\n name=\"size\"\n checked={sizePreset === \"oficio\"}\n onChange={() => setSizePreset(\"oficio\")}\n />{\" \"}\n Ofício (216 × 330 mm)\n </label>\n <label>\n <input\n type=\"radio\"\n name=\"size\"\n checked={sizePreset === \"custom\"}\n onChange={() => setSizePreset(\"custom\")}\n />{\" \"}\n Personalizado\n </label>\n </div>\n <div className=\"ed-page-config-row\">\n <label>\n Largura (mm){\" \"}\n <input\n type=\"number\"\n step={0.1}\n min={50}\n max={1000}\n value={widthMm}\n onChange={(e) => setWidthMm(Number(e.target.value))}\n disabled={!customWidth}\n />\n </label>\n <label>\n Altura (mm){\" \"}\n <input\n type=\"number\"\n step={0.1}\n min={50}\n max={1000}\n value={heightMm}\n onChange={(e) => setHeightMm(Number(e.target.value))}\n disabled={!customWidth}\n />\n </label>\n <span className=\"ed-page-config-preview\">\n {previewPx.width} × {previewPx.height} px\n </span>\n </div>\n </fieldset>\n\n <fieldset>\n <legend>Margens</legend>\n <div className=\"ed-page-config-row\">\n <label>\n <input\n type=\"radio\"\n name=\"margin\"\n checked={marginPreset === \"normal\"}\n onChange={() => setMarginPreset(\"normal\")}\n />{\" \"}\n Normal (25,4 mm)\n </label>\n <label>\n <input\n type=\"radio\"\n name=\"margin\"\n checked={marginPreset === \"narrow\"}\n onChange={() => setMarginPreset(\"narrow\")}\n />{\" \"}\n Estreita (12,7 mm)\n </label>\n <label>\n <input\n type=\"radio\"\n name=\"margin\"\n checked={marginPreset === \"wide\"}\n onChange={() => setMarginPreset(\"wide\")}\n />{\" \"}\n Larga (50,8 mm)\n </label>\n <label>\n <input\n type=\"radio\"\n name=\"margin\"\n checked={marginPreset === \"custom\"}\n onChange={() => setMarginPreset(\"custom\")}\n />{\" \"}\n Personalizada\n </label>\n </div>\n <div className=\"ed-page-config-row\">\n <label>\n Topo{\" \"}\n <input\n type=\"number\"\n step={0.1}\n min={0}\n max={200}\n value={marginTopMm}\n onChange={(e) => {\n setMarginTopMm(Number(e.target.value));\n setMarginPreset(\"custom\");\n }}\n />\n </label>\n <label>\n Inferior{\" \"}\n <input\n type=\"number\"\n step={0.1}\n min={0}\n max={200}\n value={marginBottomMm}\n onChange={(e) => {\n setMarginBottomMm(Number(e.target.value));\n setMarginPreset(\"custom\");\n }}\n />\n </label>\n <label>\n Esquerda{\" \"}\n <input\n type=\"number\"\n step={0.1}\n min={0}\n max={200}\n value={marginLeftMm}\n onChange={(e) => {\n setMarginLeftMm(Number(e.target.value));\n setMarginPreset(\"custom\");\n }}\n />\n </label>\n <label>\n Direita{\" \"}\n <input\n type=\"number\"\n step={0.1}\n min={0}\n max={200}\n value={marginRightMm}\n onChange={(e) => {\n setMarginRightMm(Number(e.target.value));\n setMarginPreset(\"custom\");\n }}\n />\n </label>\n </div>\n </fieldset>\n\n <div className=\"ed-page-config-actions\">\n <button type=\"button\" onClick={onCancel}>\n Cancelar\n </button>\n <button type=\"submit\" className=\"ed-page-config-apply\">\n Aplicar\n </button>\n </div>\n </form>\n </dialog>\n );\n}\n\nfunction roundMm(mm: number): number {\n return Math.round(mm * 10) / 10;\n}\n\nfunction hydrateFromSettings(\n s: PageSettings,\n setters: {\n setSizePreset: (v: PagePreset) => void;\n setWidthMm: (v: number) => void;\n setHeightMm: (v: number) => void;\n setMarginPreset: (v: MarginPreset) => void;\n setMarginTopMm: (v: number) => void;\n setMarginBottomMm: (v: number) => void;\n setMarginLeftMm: (v: number) => void;\n setMarginRightMm: (v: number) => void;\n },\n): void {\n const preset = detectPreset(s.width, s.height);\n setters.setSizePreset(preset);\n setters.setWidthMm(roundMm(pxToMm(s.width)));\n setters.setHeightMm(roundMm(pxToMm(s.height)));\n const top = roundMm(pxToMm(s.marginTop));\n const bottom = roundMm(pxToMm(s.marginBottom));\n const left = roundMm(pxToMm(s.marginLeft));\n const right = roundMm(pxToMm(s.marginRight));\n setters.setMarginTopMm(top);\n setters.setMarginBottomMm(bottom);\n setters.setMarginLeftMm(left);\n setters.setMarginRightMm(right);\n setters.setMarginPreset(detectMarginPreset(s));\n}\n\nfunction detectMarginPreset(s: PageSettings): MarginPreset {\n const TOL = 1; // px\n const allEqual =\n Math.abs(s.marginTop - s.marginBottom) <= TOL &&\n Math.abs(s.marginTop - s.marginLeft) <= TOL &&\n Math.abs(s.marginTop - s.marginRight) <= TOL;\n if (!allEqual) return \"custom\";\n for (const [name, px] of Object.entries(MARGIN_PRESETS) as Array<[keyof typeof MARGIN_PRESETS, number]>) {\n if (Math.abs(s.marginTop - px) <= TOL) return name as MarginPreset;\n }\n return \"custom\";\n}\n","import { useEffect, useRef, useState, type FormEvent, type JSX } from \"react\";\nimport { useEditorContext } from \"./EditorContext\";\nimport type { CaptionAlign } from \"./useEditor\";\n\n/**\n * Modal dialog for entering an image caption. Mirrors `LinkDialog` — driven by\n * `editor.imageCaptionRequest`. Empty input is treated as \"remove caption\".\n *\n * The only configurable property besides the text itself is the caption's\n * horizontal alignment (left / center / right). Word-style figure-caption\n * controls stop here intentionally — see `ImageEmbed.captionAlign`.\n */\nexport function ImageCaptionDialog(): JSX.Element | null {\n const { imageCaptionRequest, resolveImageCaptionRequest } = useEditorContext();\n const dialogRef = useRef<HTMLDialogElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const [caption, setCaption] = useState(\"\");\n const [align, setAlign] = useState<CaptionAlign>(\"center\");\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (imageCaptionRequest) {\n setCaption(imageCaptionRequest.initialCaption);\n setAlign(imageCaptionRequest.initialAlign);\n if (!dialog.open) dialog.showModal();\n queueMicrotask(() => {\n const input = inputRef.current;\n if (input) {\n input.focus();\n input.select();\n }\n });\n } else if (dialog.open) {\n dialog.close();\n }\n }, [imageCaptionRequest]);\n\n if (!imageCaptionRequest) return null;\n\n const onSubmit = (e: FormEvent) => {\n e.preventDefault();\n resolveImageCaptionRequest({ caption, align });\n };\n const onRemove = () => resolveImageCaptionRequest({ caption: \"\", align });\n const onCancel = () => resolveImageCaptionRequest(null);\n\n return (\n <dialog\n ref={dialogRef}\n className=\"ed-caption-dialog ed-link-dialog\"\n onClose={onCancel}\n onCancel={(e) => {\n e.preventDefault();\n onCancel();\n }}\n >\n <form onSubmit={onSubmit} className=\"ed-link-dialog-form\">\n <div className=\"ed-link-dialog-row\">\n <label htmlFor=\"ed-caption-input\">Legenda</label>\n <input\n id=\"ed-caption-input\"\n ref={inputRef}\n type=\"text\"\n value={caption}\n onChange={(e) => setCaption(e.target.value)}\n placeholder=\"Ex.: Figura 1 — Mapa do Brasil\"\n autoComplete=\"off\"\n />\n </div>\n <div className=\"ed-link-dialog-row\">\n <span>Alinhamento</span>\n <div className=\"ed-caption-align-group\" role=\"radiogroup\" aria-label=\"Alinhamento da legenda\">\n {([\"left\", \"center\", \"right\"] as const).map((value) => (\n <label key={value} className=\"ed-caption-align-option\">\n <input\n type=\"radio\"\n name=\"caption-align\"\n value={value}\n checked={align === value}\n onChange={() => setAlign(value)}\n />\n {value === \"left\" ? \"Esquerda\" : value === \"center\" ? \"Centro\" : \"Direita\"}\n </label>\n ))}\n </div>\n </div>\n <div className=\"ed-link-dialog-actions\">\n {imageCaptionRequest.initialCaption ? (\n <button type=\"button\" onClick={onRemove} className=\"ed-link-dialog-remove\">\n Remover legenda\n </button>\n ) : (\n <span />\n )}\n <div className=\"ed-link-dialog-confirm\">\n <button type=\"button\" onClick={onCancel}>\n Cancelar\n </button>\n <button type=\"submit\" className=\"ed-link-dialog-apply\">\n Aplicar\n </button>\n </div>\n </div>\n </form>\n </dialog>\n );\n}\n","import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type JSX,\n type PointerEvent as ReactPointerEvent,\n type RefObject,\n} from \"react\";\nimport type { ImageEmbed } from \"@sofereditor/core\";\nimport { getFragmentForOffset } from \"./dom-bridge\";\n\ninterface ImageResizeOverlayProps {\n rootRef: RefObject<HTMLDivElement>;\n blockIndex: number;\n offset: number;\n cellIndex?: number;\n embed: ImageEmbed;\n /** Called once on pointer-up with the final width/height (in CSS px). */\n onCommit: (width: number, height: number) => void;\n /**\n * Called once on pointer-up after a move-drag with the new offset\n * coordinates (CSS px). Only fired when `embed.layout` is non-inline.\n */\n onCommitMove?: (offsetX: number, offsetY: number) => void;\n}\n\ntype Corner = \"nw\" | \"ne\" | \"sw\" | \"se\";\n\ninterface Rect {\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\n/**\n * Floating overlay drawn over the currently-selected image embed: 4 corner\n * handles + outline. Drag a handle to resize keeping aspect ratio. Changes are\n * applied live to the `<img>` style during the drag (no Y.Doc transactions per\n * frame); a single commit happens on pointer-up so Undo treats it as one step.\n */\nexport function ImageResizeOverlay({\n rootRef,\n blockIndex,\n offset,\n cellIndex,\n embed,\n onCommit,\n onCommitMove,\n}: ImageResizeOverlayProps): JSX.Element | null {\n const [rect, setRect] = useState<Rect | null>(null);\n const imgRef = useRef<HTMLImageElement | null>(null);\n\n const locateImage = useCallback((): HTMLImageElement | null => {\n const root = rootRef.current;\n if (!root) return null;\n let container: HTMLElement | null = null;\n if (cellIndex != null) {\n container = root.querySelector<HTMLElement>(\n `[data-block-index=\"${blockIndex}\"] [data-cell-index=\"${cellIndex}\"]`,\n );\n } else {\n container = getFragmentForOffset(root, blockIndex, offset);\n }\n if (!container) return null;\n // The renderInline data-embed-offset is LOCAL to the fragment / container.\n const fragmentStart = container.dataset.fragmentStart\n ? Number.parseInt(container.dataset.fragmentStart, 10) || 0\n : 0;\n const localOffset = offset - fragmentStart;\n return container.querySelector<HTMLImageElement>(\n `img[data-embed=\"image\"][data-embed-offset=\"${localOffset}\"]`,\n );\n }, [rootRef, blockIndex, offset, cellIndex]);\n\n const measure = useCallback(() => {\n const img = locateImage();\n if (!img) {\n setRect((prev) => (prev === null ? prev : null));\n return;\n }\n imgRef.current = img;\n const root = rootRef.current;\n if (!root) return;\n const r = img.getBoundingClientRect();\n const rr = root.getBoundingClientRect();\n const next: Rect = {\n top: r.top - rr.top + root.scrollTop,\n left: r.left - rr.left + root.scrollLeft,\n width: r.width,\n height: r.height,\n };\n setRect((prev) =>\n prev &&\n prev.top === next.top &&\n prev.left === next.left &&\n prev.width === next.width &&\n prev.height === next.height\n ? prev\n : next,\n );\n }, [locateImage, rootRef]);\n\n useLayoutEffect(() => {\n measure();\n // Pagination runs in a separate effect after this one, and can shift the\n // image vertically by dozens of pixels (e.g. when `align: center` flips\n // the layout to `display: block`). Re-measure on the next frame to catch\n // the post-reflow position. Falls back to a microtask in non-browser envs.\n let cancelled = false;\n const remeasure = () => {\n if (cancelled) return;\n measure();\n };\n const id =\n typeof requestAnimationFrame === \"function\"\n ? requestAnimationFrame(remeasure)\n : (queueMicrotask(remeasure), 0);\n return () => {\n cancelled = true;\n if (typeof cancelAnimationFrame === \"function\" && typeof id === \"number\" && id > 0) {\n cancelAnimationFrame(id);\n }\n };\n }, [\n measure,\n embed.width,\n embed.height,\n embed.align,\n embed.src,\n embed.layout,\n embed.offsetX,\n embed.offsetY,\n ]);\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n const onScroll = () => measure();\n window.addEventListener(\"resize\", onScroll);\n root.addEventListener(\"scroll\", onScroll);\n return () => {\n window.removeEventListener(\"resize\", onScroll);\n root.removeEventListener(\"scroll\", onScroll);\n };\n }, [measure, rootRef]);\n\n /*\n * The `useLayoutEffect` above re-measures synchronously when embed props\n * change — but the pagination engine runs its own re-layout in a SEPARATE\n * effect right after. That post-pagination shift can move the image by\n * dozens of pixels (e.g. when `align: center` flips it to `display: block`\n * and the paragraph reflows), leaving the overlay at the pre-shift\n * coordinates.\n *\n * A ResizeObserver on both the image AND the editor root fires whenever\n * either box changes — covers reflow, resize, font load, page repagination,\n * and image-load-late-decoded scenarios. Falls back to no-op in jsdom etc.\n */\n useEffect(() => {\n if (typeof ResizeObserver === \"undefined\") return;\n const img = locateImage();\n const root = rootRef.current;\n if (!img || !root) return;\n const ro = new ResizeObserver(() => measure());\n ro.observe(img);\n ro.observe(root);\n return () => ro.disconnect();\n }, [locateImage, measure, rootRef, embed.layout, embed.align, embed.src]);\n\n if (!rect) return null;\n\n const layout = embed.layout ?? \"inline\";\n const movable = layout !== \"inline\" && onCommitMove !== undefined;\n\n return (\n <div\n className=\"ed-image-overlay\"\n style={{ top: rect.top, left: rect.left, width: rect.width, height: rect.height }}\n contentEditable={false}\n >\n {movable && (\n <MoveHandle\n layout={layout}\n startOffsetX={embed.offsetX ?? 0}\n startOffsetY={embed.offsetY ?? 0}\n imgRef={imgRef}\n onCommit={onCommitMove!}\n onLiveChange={measure}\n />\n )}\n <Handle\n corner=\"nw\"\n startW={embed.width}\n startH={embed.height}\n imgRef={imgRef}\n onCommit={onCommit}\n onLiveChange={measure}\n />\n <Handle\n corner=\"ne\"\n startW={embed.width}\n startH={embed.height}\n imgRef={imgRef}\n onCommit={onCommit}\n onLiveChange={measure}\n />\n <Handle\n corner=\"sw\"\n startW={embed.width}\n startH={embed.height}\n imgRef={imgRef}\n onCommit={onCommit}\n onLiveChange={measure}\n />\n <Handle\n corner=\"se\"\n startW={embed.width}\n startH={embed.height}\n imgRef={imgRef}\n onCommit={onCommit}\n onLiveChange={measure}\n />\n </div>\n );\n}\n\ninterface MoveHandleProps {\n layout: \"wrap-left\" | \"wrap-right\" | \"behind\" | \"front\" | \"inline\";\n startOffsetX: number;\n startOffsetY: number;\n imgRef: RefObject<HTMLImageElement | null>;\n onCommit: (ox: number, oy: number) => void;\n onLiveChange: () => void;\n}\n\nfunction MoveHandle({\n layout,\n startOffsetX,\n startOffsetY,\n imgRef,\n onCommit,\n onLiveChange,\n}: MoveHandleProps): JSX.Element {\n const dragRef = useRef<{\n startX: number;\n startY: number;\n liveOX: number;\n liveOY: number;\n } | null>(null);\n\n const onPointerDown = (e: ReactPointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n if (!imgRef.current) return;\n e.preventDefault();\n e.stopPropagation();\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n dragRef.current = {\n startX: e.clientX,\n startY: e.clientY,\n liveOX: startOffsetX,\n liveOY: startOffsetY,\n };\n };\n\n const onPointerMove = (e: ReactPointerEvent<HTMLDivElement>) => {\n const d = dragRef.current;\n if (!d || !imgRef.current) return;\n const dx = e.clientX - d.startX;\n const dy = e.clientY - d.startY;\n const img = imgRef.current;\n let nox = startOffsetX;\n let noy = startOffsetY;\n if (layout === \"wrap-left\") {\n // dx → right margin (gap to text); negative dx clamped to 8 (min gap).\n nox = Math.max(8, startOffsetX + dx);\n noy = Math.max(0, startOffsetY + dy);\n img.style.marginRight = `${nox}px`;\n img.style.marginTop = `${noy}px`;\n } else if (layout === \"wrap-right\") {\n // dx is mirrored: dragging LEFT increases the gap to text.\n nox = Math.max(8, startOffsetX - dx);\n noy = Math.max(0, startOffsetY + dy);\n img.style.marginLeft = `${nox}px`;\n img.style.marginTop = `${noy}px`;\n } else if (layout === \"behind\" || layout === \"front\") {\n nox = startOffsetX + dx;\n noy = startOffsetY + dy;\n img.style.left = `${nox}px`;\n img.style.top = `${noy}px`;\n }\n d.liveOX = nox;\n d.liveOY = noy;\n onLiveChange();\n };\n\n const finish = (e: ReactPointerEvent<HTMLDivElement>) => {\n const d = dragRef.current;\n if (!d) return;\n dragRef.current = null;\n try {\n (e.target as HTMLElement).releasePointerCapture(e.pointerId);\n } catch {\n // ignore\n }\n onCommit(Math.round(d.liveOX), Math.round(d.liveOY));\n };\n\n return (\n <div\n className=\"ed-image-move\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={finish}\n onPointerCancel={finish}\n />\n );\n}\n\ninterface HandleProps {\n corner: Corner;\n startW: number;\n startH: number;\n imgRef: RefObject<HTMLImageElement | null>;\n onCommit: (w: number, h: number) => void;\n onLiveChange: () => void;\n}\n\nconst MIN_W = 20;\n\nfunction Handle({\n corner,\n startW,\n startH,\n imgRef,\n onCommit,\n onLiveChange,\n}: HandleProps): JSX.Element {\n const dragRef = useRef<{\n startX: number;\n startY: number;\n startW: number;\n startH: number;\n aspect: number;\n liveW: number;\n liveH: number;\n } | null>(null);\n\n const onPointerDown = (e: ReactPointerEvent<HTMLDivElement>) => {\n if (e.button !== 0) return;\n if (!imgRef.current) return;\n e.preventDefault();\n e.stopPropagation();\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n const aspect = startW > 0 && startH > 0 ? startW / startH : 1;\n dragRef.current = {\n startX: e.clientX,\n startY: e.clientY,\n startW,\n startH,\n aspect,\n liveW: startW,\n liveH: startH,\n };\n };\n\n const onPointerMove = (e: ReactPointerEvent<HTMLDivElement>) => {\n const d = dragRef.current;\n if (!d || !imgRef.current) return;\n const dxRaw = e.clientX - d.startX;\n // SE/NE handles grow with +dx; NW/SW grow with -dx.\n const dx = corner === \"se\" || corner === \"ne\" ? dxRaw : -dxRaw;\n let w = Math.max(MIN_W, d.startW + dx);\n let h = w / d.aspect;\n // Apply live to the img element directly — no transaction.\n imgRef.current.style.width = `${w}px`;\n imgRef.current.style.height = `${h}px`;\n imgRef.current.width = Math.round(w);\n imgRef.current.height = Math.round(h);\n d.liveW = w;\n d.liveH = h;\n onLiveChange();\n };\n\n const finish = (e: ReactPointerEvent<HTMLDivElement>) => {\n const d = dragRef.current;\n if (!d) return;\n dragRef.current = null;\n try {\n (e.target as HTMLElement).releasePointerCapture(e.pointerId);\n } catch {\n // ignore\n }\n onCommit(Math.round(d.liveW), Math.round(d.liveH));\n };\n\n return (\n <div\n className={`ed-image-handle ${corner}`}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={finish}\n onPointerCancel={finish}\n />\n );\n}\n","import { useMemo, useRef, type CSSProperties, type JSX, type ReactNode } from \"react\";\nimport { tableRectSelection, type BlockAttrs, type SerializedBlock } from \"@sofereditor/core\";\nimport { useEditorContext } from \"./EditorContext\";\nimport { renderInline } from \"./renderInline\";\nimport { sliceDelta } from \"./sliceDelta\";\nimport { TableResizeOverlay } from \"./TableResizeOverlay\";\n\nexport interface NodeViewFragment {\n index: number;\n start: number;\n end: number;\n}\n\ninterface NodeViewProps {\n block: SerializedBlock;\n index: number;\n /** Optional nested content. Used by `listItem` to host the nested <ol>/<ul>. */\n children?: ReactNode;\n /** Optional fragment slice — when present, the rendered DOM covers only chars [start, end). */\n fragment?: NodeViewFragment;\n /**\n * Optional table-row fragmentation slice for Sub-phase 4.6. When set, only\n * the rows in `[rowStart, rowEnd)` are rendered, and the resize overlay is\n * suppressed except on the FIRST fragment.\n */\n tableFragment?: { index: number; rowStart: number; rowEnd: number };\n}\n\nexport function NodeView({ block, index, children, fragment, tableFragment }: NodeViewProps): JSX.Element {\n if (block.type === \"table\") {\n return <TableView block={block} index={index} tableFragment={tableFragment} />;\n }\n const inline = fragment\n ? renderInline(sliceDelta(block.delta, fragment.start, fragment.end), index)\n : renderInline(block.delta, index);\n const common = commonBlockProps(block.attrs, index, block.type, fragment);\n\n switch (block.type) {\n case \"heading\": {\n const level = clampLevel(block.attrs.level);\n const Tag = (`h${level}` as unknown) as keyof JSX.IntrinsicElements;\n return (\n <Tag\n {...common}\n className={`ed-block ed-heading ed-heading-${level}${alignClass(block.attrs.align)}${fragmentClass(fragment)}`}\n >\n {inline}\n </Tag>\n );\n }\n case \"blockquote\":\n return (\n <blockquote\n {...common}\n className={`ed-block ed-blockquote${alignClass(block.attrs.align)}${fragmentClass(fragment)}`}\n >\n {inline}\n </blockquote>\n );\n case \"codeBlock\":\n return (\n <pre\n {...common}\n data-language={block.attrs.language ?? undefined}\n className={`ed-block ed-codeblock${alignClass(block.attrs.align)}`}\n >\n <code>{inline}</code>\n </pre>\n );\n case \"listItem\": {\n const level = clampListLevel(block.attrs.listLevel);\n return (\n <li\n {...common}\n data-list-kind={block.attrs.listKind ?? \"bullet\"}\n data-list-level={level}\n className={`ed-block ed-listitem${alignClass(block.attrs.align)}`}\n >\n {inline}\n {children}\n </li>\n );\n }\n case \"paragraph\":\n default:\n return (\n <div\n {...common}\n className={`ed-block ed-paragraph${alignClass(block.attrs.align)}${fragmentClass(fragment)}`}\n >\n {inline}\n </div>\n );\n }\n}\n\nfunction commonBlockProps(\n attrs: BlockAttrs,\n index: number,\n type: string,\n fragment: NodeViewFragment | undefined,\n) {\n const style: CSSProperties = {};\n if (attrs.align) style.textAlign = attrs.align;\n const base: Record<string, unknown> = {\n \"data-block-index\": index,\n \"data-block-type\": type,\n dir: attrs.dir,\n style: Object.keys(style).length > 0 ? style : undefined,\n };\n if (!fragment) return base;\n base[\"data-fragment-index\"] = fragment.index;\n base[\"data-fragment-start\"] = fragment.start;\n base[\"data-fragment-end\"] = fragment.end;\n return base;\n}\n\nfunction fragmentClass(f?: NodeViewFragment): string {\n if (!f) return \"\";\n // First fragment keeps top margin, last keeps bottom; intermediate fragments drop both.\n return ` ed-fragment ed-fragment-${f.index}`;\n}\n\nfunction alignClass(a?: BlockAttrs[\"align\"]): string {\n return a ? ` ed-align-${a}` : \"\";\n}\n\nfunction clampLevel(l: BlockAttrs[\"level\"]): 1 | 2 | 3 | 4 | 5 | 6 {\n if (l === 2 || l === 3 || l === 4 || l === 5 || l === 6) return l;\n return 1;\n}\n\nfunction clampListLevel(l: BlockAttrs[\"listLevel\"]): number {\n if (typeof l !== \"number\" || !Number.isFinite(l)) return 0;\n return Math.max(0, Math.min(5, Math.trunc(l)));\n}\n\ninterface TableViewProps {\n block: SerializedBlock;\n index: number;\n tableFragment?: { index: number; rowStart: number; rowEnd: number };\n}\n\nfunction TableView({ block, index, tableFragment }: TableViewProps): JSX.Element {\n const rows = clampPositive(block.attrs.rows);\n const cols = clampPositive(block.attrs.cols);\n const cells = block.cells ?? [];\n const widths = readColWidths(block.attrs.colWidths, cols);\n const tableRef = useRef<HTMLTableElement | null>(null);\n\n // Row range to render. Default = full table.\n const rowStart = tableFragment?.rowStart ?? 0;\n const rowEnd = tableFragment?.rowEnd ?? rows;\n const isFirstFragment = !tableFragment || tableFragment.index === 0;\n\n // Recompute the rectangular cell selection each render. Reading the snapshot\n // off `editor.snapshot` ties this to the same render that NodeView is in.\n const editor = useEditorContext();\n const rect = useMemo(() => {\n if (editor.selection.anchor.blockIndex !== index) return null;\n if (editor.selection.focus.blockIndex !== index) return null;\n return tableRectSelection(editor.doc, editor.selection);\n }, [editor.doc, editor.selection, index]);\n\n return (\n <div className=\"ed-table-wrap\">\n <table\n ref={tableRef}\n data-block-index={index}\n data-block-type=\"table\"\n className=\"ed-block ed-table\"\n >\n {widths && (\n <colgroup>\n {widths.map((w, c) => (\n <col key={c} style={w != null ? { width: `${w}px` } : undefined} />\n ))}\n </colgroup>\n )}\n <tbody>\n {Array.from({ length: rowEnd - rowStart }, (_, i) => {\n const r = rowStart + i;\n return (\n <tr key={r} data-cell-row={r}>\n {Array.from({ length: cols }, (_, c) => {\n const flat = r * cols + c;\n const cell = cells[flat];\n if (cell?.attrs.covered === true) return null;\n const rowspan = spanAttr(cell?.attrs.rowspan);\n const colspan = spanAttr(cell?.attrs.colspan);\n const delta = cell?.delta ?? [];\n const inRect =\n rect !== null &&\n r >= rect.top && r <= rect.bottom &&\n c >= rect.left && c <= rect.right;\n return (\n <td\n key={c}\n data-cell-index={flat}\n data-cell-row={r}\n data-cell-col={c}\n data-cell-rowspan={rowspan}\n data-cell-colspan={colspan}\n rowSpan={rowspan > 1 ? rowspan : undefined}\n colSpan={colspan > 1 ? colspan : undefined}\n className={inRect ? \"ed-cell ed-cell--selected\" : \"ed-cell\"}\n >\n {renderInline(delta, `t${index}-c${flat}`)}\n </td>\n );\n })}\n </tr>\n );\n })}\n </tbody>\n </table>\n {isFirstFragment && (\n <TableResizeOverlay tableRef={tableRef} blockIndex={index} cols={cols} />\n )}\n </div>\n );\n}\n\nfunction readColWidths(raw: unknown, cols: number): (number | null)[] | null {\n if (!Array.isArray(raw)) return null;\n const out: (number | null)[] = [];\n for (let i = 0; i < cols; i++) {\n const v = raw[i];\n out.push(typeof v === \"number\" && Number.isFinite(v) && v > 0 ? v : null);\n }\n return out;\n}\n\nfunction spanAttr(v: unknown): number {\n if (typeof v !== \"number\" || !Number.isFinite(v) || v < 1) return 1;\n return Math.trunc(v);\n}\n\nfunction clampPositive(n: unknown): number {\n if (typeof n !== \"number\" || !Number.isFinite(n) || n <= 0) return 1;\n return Math.trunc(n);\n}\n","import { Fragment, memo, type CSSProperties, type ReactNode } from \"react\";\nimport { isImageEmbed, type DeltaOp, type ImageEmbed, type MarkAttrs } from \"@sofereditor/core\";\n\n/**\n * Convert a Y.Text delta into ReactNodes.\n *\n * Wrap order (innermost → outermost): bold → italic → underline → strike → font/color span → link.\n * Semantic tags carry bold/italic/underline/strike; color and fonts go on a styled <span>.\n *\n * Keys are stable on `${blockIndex}-${runningOffset}` so React reconciliation\n * survives split/merge of runs under collaboration.\n */\nexport function renderInline(delta: DeltaOp[], keyPrefix: number | string): ReactNode {\n if (\n delta.length === 0 ||\n (delta.length === 1 &&\n typeof delta[0].insert === \"string\" &&\n delta[0].insert === \"\")\n ) {\n return <br data-empty=\"true\" />;\n }\n let offset = 0;\n // Float-wrap images (wrap-left / wrap-right) are emitted as the FIRST DOM\n // children of the block so CSS float can flow the whole paragraph around\n // them — float only wraps siblings that come after it in DOM order. A\n // zero-width phantom span is left at the embed's original offset so the\n // caret-position math in dom-bridge keeps counting the embed as 1 char in\n // its true model position.\n const wrapAnchors: ReactNode[] = [];\n const body: ReactNode[] = [];\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n const text = op.insert;\n if (text.length === 0) continue;\n const key = `${keyPrefix}-${offset}`;\n body.push(<Fragment key={key}>{wrap(text, op.attributes)}</Fragment>);\n offset += text.length;\n } else if (isImageEmbed(op.insert)) {\n const key = `${keyPrefix}-${offset}`;\n const layout = op.insert.layout ?? \"inline\";\n if (layout === \"wrap-left\" || layout === \"wrap-right\") {\n wrapAnchors.push(\n <ImageEmbedView key={`${key}-anchor`} embed={op.insert} offset={offset} wrapAnchor />,\n );\n body.push(\n <span\n key={`${key}-phantom`}\n data-embed-phantom=\"true\"\n data-embed-offset={offset}\n contentEditable={false}\n style={PHANTOM_STYLE}\n />,\n );\n } else {\n body.push(<ImageEmbedView key={key} embed={op.insert} offset={offset} />);\n }\n offset += 1;\n } else if (op.insert != null) {\n // Unknown embed kind — reserve the offset slot so caret math stays correct.\n offset += 1;\n }\n }\n if (wrapAnchors.length === 0 && body.length === 0) return <br data-empty=\"true\" />;\n return [...wrapAnchors, ...body];\n}\n\nconst PHANTOM_STYLE: CSSProperties = {\n display: \"inline-block\",\n width: 0,\n height: 0,\n overflow: \"hidden\",\n verticalAlign: \"baseline\",\n};\n\ninterface ImageEmbedViewProps {\n embed: ImageEmbed;\n offset: number;\n wrapAnchor?: boolean;\n}\n\n/**\n * `embed.src` is a (potentially huge) base64 data URL. Y.Text.toDelta() builds\n * a fresh `ImageEmbed` object every time the parent snapshot recomputes — so\n * by default React would re-render `<img src={...}>` on every keystroke even\n * when nothing about the image changed. Memoizing by *value* on the cheap\n * fields and skipping the src deep-compare (it's stable while the embed is\n * stable; if src actually changes, width/height typically change too) keeps\n * the `<img>` DOM node fully stable across keystrokes.\n */\nfunction imageEmbedPropsEqual(a: ImageEmbedViewProps, b: ImageEmbedViewProps): boolean {\n if (a.offset !== b.offset || a.wrapAnchor !== b.wrapAnchor) return false;\n const x = a.embed;\n const y = b.embed;\n if (x === y) return true;\n return (\n x.width === y.width &&\n x.height === y.height &&\n x.layout === y.layout &&\n x.align === y.align &&\n x.offsetX === y.offsetX &&\n x.offsetY === y.offsetY &&\n x.caption === y.caption &&\n x.captionAlign === y.captionAlign &&\n // src is the expensive compare — only fall back to ref equality. Fresh\n // toDelta() objects share the same string reference for embed payloads\n // because Y.js stores the embed in its content map and re-exposes it.\n x.src === y.src\n );\n}\n\nconst ImageEmbedView = memo(ImageEmbedViewImpl, imageEmbedPropsEqual);\n\nfunction ImageEmbedViewImpl({\n embed,\n offset,\n wrapAnchor,\n}: ImageEmbedViewProps): ReactNode {\n const layout = embed.layout ?? \"inline\";\n const align = embed.align;\n const ox = embed.offsetX ?? 0;\n const oy = embed.offsetY ?? 0;\n const hasCaption = !!embed.caption && embed.caption.length > 0;\n\n // The outer style positions the wrapper (float / absolute / inline-block /\n // block-with-align). The img itself stays at intrinsic width × height so the\n // existing caret-position math (`data-embed-offset`) and ImageResizeOverlay\n // queries (`img[data-embed=\"image\"]`) keep working. A `<figcaption>` lives\n // inside the wrapper when a caption is set.\n let outerStyle: CSSProperties;\n switch (layout) {\n case \"wrap-left\":\n outerStyle = {\n float: \"left\",\n width: embed.width,\n marginRight: Math.max(8, ox),\n marginTop: Math.max(0, oy),\n marginBottom: 4,\n };\n break;\n case \"wrap-right\":\n outerStyle = {\n float: \"right\",\n width: embed.width,\n marginLeft: Math.max(8, ox),\n marginTop: Math.max(0, oy),\n marginBottom: 4,\n };\n break;\n case \"behind\":\n case \"front\":\n outerStyle = {\n position: \"absolute\",\n left: ox,\n top: oy,\n width: embed.width,\n zIndex: layout === \"behind\" ? -1 : 2,\n };\n break;\n case \"inline\":\n default:\n outerStyle = align\n ? {\n display: \"block\",\n width: embed.width,\n marginLeft: align === \"left\" ? 0 : \"auto\",\n marginRight: align === \"right\" ? 0 : \"auto\",\n }\n : {\n display: \"inline-block\",\n verticalAlign: \"text-bottom\",\n width: embed.width,\n };\n break;\n }\n\n // The img always carries the data-* attributes used by Editor/Overlay; the\n // style is either the outer positioning (no caption — bare img) or just the\n // intrinsic size (with caption — figure carries the outer positioning).\n const imgStyle: CSSProperties = hasCaption\n ? { width: embed.width, height: embed.height, display: \"block\" }\n : outerStyle;\n\n const img = (\n <img\n src={embed.src}\n width={embed.width}\n height={embed.height}\n contentEditable={false}\n draggable={false}\n data-embed=\"image\"\n data-embed-offset={offset}\n data-embed-align={align ?? \"\"}\n data-embed-layout={layout}\n data-wrap-anchor={wrapAnchor ? \"true\" : undefined}\n style={imgStyle}\n alt=\"\"\n />\n );\n\n if (!hasCaption) return img;\n\n const captionAlign = embed.captionAlign ?? \"center\";\n return (\n <figure\n className=\"ed-figure\"\n contentEditable={false}\n data-embed-figure=\"true\"\n data-embed-layout={layout}\n style={outerStyle}\n >\n {img}\n <figcaption\n className=\"ed-figcaption\"\n data-caption-align={captionAlign}\n style={{ textAlign: captionAlign }}\n >\n {embed.caption}\n </figcaption>\n </figure>\n );\n}\n\nfunction wrap(text: string, attrs?: MarkAttrs): ReactNode {\n let node: ReactNode = text;\n if (!attrs) return node;\n\n if (attrs.bold) node = <strong>{node}</strong>;\n if (attrs.italic) node = <em>{node}</em>;\n if (attrs.underline) node = <u>{node}</u>;\n if (attrs.strike) node = <s>{node}</s>;\n\n const styleParts: CSSProperties = {};\n if (attrs.color) styleParts.color = attrs.color;\n if (attrs.fontFamily) styleParts.fontFamily = attrs.fontFamily;\n if (attrs.fontSize) styleParts.fontSize = attrs.fontSize;\n if (Object.keys(styleParts).length > 0) {\n node = <span style={styleParts}>{node}</span>;\n }\n\n if (attrs.link?.href) {\n node = (\n <a\n href={attrs.link.href}\n title={attrs.link.title}\n rel=\"noopener noreferrer\"\n target=\"_blank\"\n onClick={(e) => {\n // In the editor the link should not navigate on plain click — Cmd/Ctrl+click does.\n if (!(e.metaKey || e.ctrlKey)) e.preventDefault();\n }}\n >\n {node}\n </a>\n );\n }\n\n if (attrs.comment?.markId) {\n node = (\n <span data-comment-id={attrs.comment.markId} className=\"ed-comment\">\n {node}\n </span>\n );\n }\n\n return node;\n}\n","import type { DeltaOp } from \"@sofereditor/core\";\n\n/** Total number of inserted characters. Embeds (non-string inserts) count as 1. */\nexport function deltaLength(delta: DeltaOp[]): number {\n let sum = 0;\n for (const op of delta) {\n if (typeof op.insert === \"string\") sum += op.insert.length;\n else if (op.insert != null) sum += 1;\n }\n return sum;\n}\n\n/**\n * Return the subset of `delta` covering `[start, end)` characters. Attributes\n * are preserved on each intersecting op. Embeds are atomic length-1 ops:\n * included whole if their slot intersects the range.\n */\nexport function sliceDelta(delta: DeltaOp[], start: number, end: number): DeltaOp[] {\n if (end <= start) return [];\n const out: DeltaOp[] = [];\n let cursor = 0;\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n const opStart = cursor;\n const opEnd = cursor + op.insert.length;\n cursor = opEnd;\n if (opEnd <= start) continue;\n if (opStart >= end) break;\n const sliceFrom = Math.max(opStart, start) - opStart;\n const sliceTo = Math.min(opEnd, end) - opStart;\n out.push({\n insert: op.insert.slice(sliceFrom, sliceTo),\n attributes: op.attributes,\n });\n } else if (op.insert != null) {\n const opStart = cursor;\n const opEnd = cursor + 1;\n cursor = opEnd;\n if (opEnd <= start) continue;\n if (opStart >= end) break;\n out.push({ insert: op.insert, attributes: op.attributes });\n }\n }\n return out;\n}\n","import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type JSX,\n type RefObject,\n} from \"react\";\nimport { useEditorContext } from \"./EditorContext\";\n\ninterface Props {\n /** Ref to the underlying `<table>` element. */\n tableRef: RefObject<HTMLTableElement | null>;\n blockIndex: number;\n cols: number;\n}\n\n/**\n * Renders absolute-positioned drag handles aligned with each column boundary\n * (except the table's left edge). While dragging, calls the editor's\n * `setColumnWidth` with the live width so the model — and therefore the\n * `<colgroup>` — updates in real time.\n *\n * Lives as a sibling of the `<table>` inside a `position: relative` wrapper.\n * Handles are `contentEditable={false}` so they don't interfere with caret\n * placement inside cells.\n */\nexport function TableResizeOverlay({ tableRef, blockIndex, cols }: Props): JSX.Element | null {\n const editor = useEditorContext();\n const [positions, setPositions] = useState<{ x: number; height: number } | null>(null);\n // The handle X positions and the table's total height. Recomputed after every layout.\n const [layout, setLayout] = useState<{ rights: number[]; height: number } | null>(null);\n const draggingRef = useRef<{ col: number; startX: number; startWidth: number } | null>(null);\n\n // Measure column right-edges relative to the table's left edge.\n const measure = useCallback(() => {\n const table = tableRef.current;\n if (!table) return;\n const tableRect = table.getBoundingClientRect();\n // Prefer measuring via `<col>` elements when present.\n const cgCols = table.querySelectorAll<HTMLTableColElement>(\"colgroup > col\");\n let rights: number[] = [];\n if (cgCols.length === cols) {\n let acc = 0;\n cgCols.forEach((c) => {\n acc += c.getBoundingClientRect().width;\n rights.push(acc);\n });\n } else {\n // Fallback: use the first row's <td> bounding rects.\n const firstRowCells = table.querySelectorAll<HTMLTableCellElement>(\"tbody > tr:first-child > td\");\n let acc = 0;\n firstRowCells.forEach((td) => {\n // Account for colSpan: split the width evenly across the spanned cols.\n const cs = Math.max(1, td.colSpan || 1);\n const w = td.getBoundingClientRect().width / cs;\n for (let i = 0; i < cs; i++) {\n acc += w;\n rights.push(acc);\n }\n });\n }\n if (rights.length !== cols) {\n // Shape mismatch — bail out rather than place handles in wrong spots.\n setLayout(null);\n return;\n }\n setLayout({ rights, height: tableRect.height });\n }, [cols, tableRef]);\n\n useLayoutEffect(() => {\n measure();\n }, [measure]);\n\n useEffect(() => {\n const table = tableRef.current;\n if (!table) return;\n const ro = new ResizeObserver(() => measure());\n ro.observe(table);\n return () => ro.disconnect();\n }, [measure, tableRef]);\n\n const onPointerDown = useCallback(\n (col: number) => (e: React.PointerEvent<HTMLDivElement>) => {\n // Prevent the editor from losing focus / caret being placed on the handle.\n e.preventDefault();\n e.stopPropagation();\n const table = tableRef.current;\n if (!table) return;\n const cgCols = table.querySelectorAll<HTMLTableColElement>(\"colgroup > col\");\n const startWidth = cgCols[col]?.getBoundingClientRect().width ?? 100;\n draggingRef.current = { col, startX: e.clientX, startWidth };\n setPositions({ x: e.clientX, height: layout?.height ?? 0 });\n (e.currentTarget as Element).setPointerCapture(e.pointerId);\n },\n [layout, tableRef],\n );\n\n const onPointerMove = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n const d = draggingRef.current;\n if (!d) return;\n const dx = e.clientX - d.startX;\n const next = Math.max(40, d.startWidth + dx);\n editor.setColumnWidth(blockIndex, d.col, next);\n },\n [blockIndex, editor],\n );\n\n const onPointerUp = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n draggingRef.current = null;\n setPositions(null);\n try {\n (e.currentTarget as Element).releasePointerCapture(e.pointerId);\n } catch {\n /* ignore */\n }\n }, []);\n\n if (!layout) return null;\n const handleStyle = (x: number): CSSProperties => ({\n position: \"absolute\",\n top: 0,\n left: `${x - 3}px`,\n width: \"6px\",\n height: `${layout.height}px`,\n cursor: \"col-resize\",\n zIndex: 5,\n });\n\n // Render handles for every column EXCEPT we don't need a left-edge handle\n // (the table's left edge isn't a resizable boundary). Each handle resizes\n // the column whose right edge it sits on.\n void positions;\n return (\n <>\n {layout.rights.map((x, c) => (\n <div\n key={c}\n contentEditable={false}\n className=\"ed-col-resize-handle\"\n style={handleStyle(x)}\n onPointerDown={onPointerDown(c)}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n aria-label={`Redimensionar coluna ${c + 1}`}\n role=\"separator\"\n />\n ))}\n </>\n );\n}\n","import { useLayoutEffect, useRef, useState, type RefObject } from \"react\";\n\n/**\n * Sub-phase 3.2 — page layout with intra-paragraph fragmentation.\n *\n * Two-phase render cycle:\n * 1. \"measure\" phase: editor renders with the default (unfragmented) layout\n * — every top-level on page 1. After the DOM commits, `usePageLayout`\n * reads each top-level's geometry, runs `computeLayout`, and sets the\n * real layout (with page splits and fragment offsets).\n * 2. \"stable\" phase: editor renders the real layout. No further measurement\n * until `deps` change (typically `[topLevels]`), at which point we go\n * back to step 1.\n *\n * Fragmentation only applies to \"fragmentable\" top-levels (paragraph, heading,\n * blockquote — single Y.Text blocks). List groups and code blocks are placed\n * atomically: if they don't fit they jump to the next page and bleed if larger\n * than a page.\n */\n\nexport interface PageGeometry {\n /** Page width in CSS px (A4 @ 96dpi = ~794). */\n width: number;\n /** Page height in CSS px (A4 @ 96dpi = ~1123). */\n height: number;\n marginTop: number;\n marginBottom: number;\n marginLeft: number;\n marginRight: number;\n}\n\nexport const A4_PAGE: PageGeometry = {\n width: 794,\n height: 1123,\n marginTop: 96,\n marginBottom: 96,\n marginLeft: 96,\n marginRight: 96,\n};\n\nexport function contentHeight(g: PageGeometry): number {\n return g.height - g.marginTop - g.marginBottom;\n}\n\nexport function contentWidth(g: PageGeometry): number {\n return g.width - g.marginLeft - g.marginRight;\n}\n\nexport interface BlockFragment {\n index: number;\n start: number;\n end: number;\n}\n\nexport interface TableRowFragment {\n /** 0, 1, 2... sequential fragment id within the table. */\n index: number;\n /** First row included (inclusive). */\n rowStart: number;\n /** First row NOT included (exclusive). */\n rowEnd: number;\n}\n\nexport interface PageSlot {\n topLevelIndex: number;\n /** Set when this slot represents a paragraph/heading/blockquote line-level fragment. */\n fragment?: BlockFragment;\n /** Set when this slot is a row-range fragment of a table (Sub-phase 4.6). */\n tableFragment?: TableRowFragment;\n}\n\nexport interface PageEntry {\n slots: PageSlot[];\n}\n\nexport interface PageLayout {\n pages: PageEntry[];\n}\n\nexport function defaultPageLayout(topLevelCount: number): PageLayout {\n return {\n pages: [\n {\n slots: Array.from({ length: topLevelCount }, (_, i) => ({ topLevelIndex: i })),\n },\n ],\n };\n}\n\ntype Phase = \"measure\" | \"stable\";\n\nexport function usePageLayout(\n rootRef: RefObject<HTMLElement>,\n geometry: PageGeometry,\n topLevelCount: number,\n deps: ReadonlyArray<unknown>,\n): PageLayout {\n const [phase, setPhase] = useState<Phase>(\"measure\");\n const [layout, setLayout] = useState<PageLayout>(() => defaultPageLayout(topLevelCount));\n const lastDepsRef = useRef<unknown[]>([]);\n\n // Detect deps change → reset to measure phase with unfragmented layout.\n //\n // Use `layoutsDeepEqual` (fragment-aware) for the reset check. With shallow\n // equality, a stale fragmented layout whose shape happens to match the\n // unfragmented default (1 page × 1 slot is the common case) would survive the\n // reset — the next `useLayoutEffect` would then early-return on\n // `!isUnfragmented(layout)` and never recompute, leaving the block stuck\n // showing only the first fragment's slice.\n const currentDeps = [...deps, topLevelCount, geometry];\n if (!shallowArrayEqual(lastDepsRef.current, currentDeps)) {\n lastDepsRef.current = currentDeps;\n if (phase !== \"measure\") setPhase(\"measure\");\n const next = defaultPageLayout(topLevelCount);\n if (!layoutsDeepEqual(layout, next)) setLayout(next);\n }\n\n useLayoutEffect(() => {\n if (phase !== \"measure\") return;\n const root = rootRef.current;\n if (!root) return;\n // Only safe to measure when the DOM is in the unfragmented state.\n if (!isUnfragmented(layout)) return;\n const next = computeLayout(root, geometry, topLevelCount);\n if (!layoutsDeepEqual(layout, next)) setLayout(next);\n setPhase(\"stable\");\n }, [phase, layout, geometry, topLevelCount, rootRef]);\n\n return layout;\n}\n\n// ---------- Layout computation ----------\n\nfunction isUnfragmented(layout: PageLayout): boolean {\n return (\n layout.pages.length === 1 &&\n layout.pages[0].slots.every(\n (s) => s.fragment === undefined && s.tableFragment === undefined,\n )\n );\n}\n\nfunction computeLayout(\n root: HTMLElement,\n geometry: PageGeometry,\n topLevelCount: number,\n): PageLayout {\n const tops = collectTopLevelElements(root);\n if (tops.length === 0) return defaultPageLayout(topLevelCount);\n\n const limit = contentHeight(geometry);\n const pages: PageEntry[] = [{ slots: [] }];\n let currentPage = pages[0];\n let used = 0;\n\n const cap = Math.min(tops.length, topLevelCount);\n for (let i = 0; i < cap; i++) {\n const el = tops[i];\n const h = elTotalHeight(el);\n\n if (used + h <= limit) {\n currentPage.slots.push({ topLevelIndex: i });\n used += h;\n continue;\n }\n\n if (isFragmentable(el)) {\n const result = placeFragmentedBlock(el, i, pages, used, limit);\n currentPage = pages[pages.length - 1];\n used = result.lastUsed;\n continue;\n }\n\n if (isTableTopLevel(el)) {\n const result = placeFragmentedTable(el, i, pages, used, limit);\n currentPage = pages[pages.length - 1];\n used = result.lastUsed;\n continue;\n }\n\n // Atomic top-level that doesn't fit\n if (currentPage.slots.length === 0) {\n // empty current page; place anyway (bleed if huge)\n currentPage.slots.push({ topLevelIndex: i });\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n used = 0;\n } else {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n currentPage.slots.push({ topLevelIndex: i });\n used = h;\n }\n }\n\n // Strip trailing empty page if any\n if (pages.length > 1 && pages[pages.length - 1].slots.length === 0) pages.pop();\n\n return { pages };\n}\n\nfunction placeFragmentedBlock(\n el: HTMLElement,\n topLevelIndex: number,\n pages: PageEntry[],\n startUsed: number,\n limit: number,\n): { lastUsed: number } {\n const totalChars = getBlockTextLength(el);\n if (totalChars === 0) {\n const h = elTotalHeight(el);\n let currentPage = pages[pages.length - 1];\n if (startUsed + h > limit && currentPage.slots.length > 0) {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n startUsed = 0;\n }\n currentPage.slots.push({ topLevelIndex });\n return { lastUsed: startUsed + h };\n }\n\n // Measure every original line. Splitting only at line boundaries is what\n // makes fragmentation work correctly: when fragment K starts at an original\n // line boundary AND is rendered at the same width, its line wrapping matches\n // the original exactly, so our measured height predicts the rendered height.\n const lines = measureLines(el);\n if (lines.length === 0) {\n // Couldn't measure (no text nodes?) — place atomically as last resort.\n const h = elTotalHeight(el);\n let currentPage = pages[pages.length - 1];\n if (startUsed + h > limit && currentPage.slots.length > 0) {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n startUsed = 0;\n }\n currentPage.slots.push({ topLevelIndex });\n return { lastUsed: startUsed + h };\n }\n\n let lineIdx = 0;\n let currentPage = pages[pages.length - 1];\n let used = startUsed;\n let fragIndex = 0;\n\n while (lineIdx < lines.length) {\n const available = Math.max(0, limit - used);\n if (available <= 0) {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n used = 0;\n continue;\n }\n\n // Greedy: include as many consecutive lines as fit. bestK is the last fitting line index.\n const startTop = lines[lineIdx].top;\n let bestK = -1;\n for (let k = lineIdx; k < lines.length; k++) {\n const h = lines[k].bottom - startTop;\n if (h <= available) bestK = k;\n else break;\n }\n\n if (bestK < 0) {\n // Not even one line fits in the remaining space.\n if (currentPage.slots.length === 0) {\n // Page is empty; force-place a single oversized line (bleed).\n bestK = lineIdx;\n } else {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n used = 0;\n continue;\n }\n }\n\n const fragStart = lines[lineIdx].start;\n const fragEnd = bestK + 1 < lines.length ? lines[bestK + 1].start : totalChars;\n const fragHeight = lines[bestK].bottom - startTop;\n\n currentPage.slots.push({\n topLevelIndex,\n fragment: { index: fragIndex, start: fragStart, end: fragEnd },\n });\n used += fragHeight;\n fragIndex++;\n lineIdx = bestK + 1;\n\n if (lineIdx < lines.length) {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n used = 0;\n }\n }\n\n return { lastUsed: used };\n}\n\ninterface LineMetric {\n /** Char offset (within the block) of the first char on this line. */\n start: number;\n /** Viewport-y top of the line. */\n top: number;\n /** Viewport-y bottom of the line. */\n bottom: number;\n}\n\n/**\n * Walk every text node inside `el`, measuring each character's rect to detect\n * line boundaries. Linear in total character count.\n *\n * Memoized by `(offsetWidth, textContent)`: a block whose width and text\n * haven't changed (the common case during typing — only ONE block changes per\n * keystroke) skips the measurement entirely. This is the perf core of Sub-phase\n * 3.3's incremental repagination story.\n *\n * NOTE: cached `top`/`bottom` are viewport-absolute, but `placeFragmentedBlock`\n * only ever uses RELATIVE differences (`lines[k].bottom - lines[j].top`), which\n * are invariant to scroll/layout offsets — so cached values stay correct.\n */\nconst lineMetricsCache = new Map<string, LineMetric[]>();\nconst LINE_METRICS_CACHE_LIMIT = 200;\n\nfunction measureLines(el: HTMLElement): LineMetric[] {\n const text = el.textContent ?? \"\";\n const cacheKey = `${el.offsetWidth}|${text}`;\n const cached = lineMetricsCache.get(cacheKey);\n if (cached) {\n // LRU touch\n lineMetricsCache.delete(cacheKey);\n lineMetricsCache.set(cacheKey, cached);\n return cached;\n }\n\n const fresh = measureLinesUncached(el);\n lineMetricsCache.set(cacheKey, fresh);\n if (lineMetricsCache.size > LINE_METRICS_CACHE_LIMIT) {\n const oldest = lineMetricsCache.keys().next().value;\n if (oldest !== undefined) lineMetricsCache.delete(oldest);\n }\n return fresh;\n}\n\nfunction measureLinesUncached(el: HTMLElement): LineMetric[] {\n const range = document.createRange();\n const lines: LineMetric[] = [];\n\n // Walk text nodes AND image embeds — embeds count as 1 char in offset\n // arithmetic and contribute their bounding rect as a line (or part of one).\n const walker = document.createTreeWalker(\n el,\n NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,\n blockBoundaryFilter(el),\n );\n let n: Node | null;\n let charOffset = 0;\n\n while ((n = walker.nextNode())) {\n if (n.nodeType === Node.TEXT_NODE) {\n const text = n.textContent ?? \"\";\n for (let i = 0; i < text.length; i++) {\n try {\n range.setStart(n, i);\n range.setEnd(n, i + 1);\n } catch {\n continue;\n }\n const rect = range.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) continue;\n const last = lines[lines.length - 1];\n if (!last || rect.top >= last.bottom) {\n lines.push({ start: charOffset + i, top: rect.top, bottom: rect.bottom });\n } else {\n last.top = Math.min(last.top, rect.top);\n last.bottom = Math.max(last.bottom, rect.bottom);\n }\n }\n charOffset += text.length;\n continue;\n }\n if (\n n.nodeType === Node.ELEMENT_NODE &&\n (n as HTMLElement).dataset.embed === \"image\"\n ) {\n const rect = (n as HTMLElement).getBoundingClientRect();\n if (rect.height > 0) {\n const last = lines[lines.length - 1];\n if (!last || rect.top >= last.bottom) {\n lines.push({ start: charOffset, top: rect.top, bottom: rect.bottom });\n } else {\n last.top = Math.min(last.top, rect.top);\n last.bottom = Math.max(last.bottom, rect.bottom);\n }\n }\n charOffset += 1;\n }\n }\n return lines;\n}\n\n// ---------- DOM measurement primitives ----------\n\nfunction elTotalHeight(el: HTMLElement): number {\n const cs = getComputedStyle(el);\n const m = parseFloat(cs.marginTop || \"0\") + parseFloat(cs.marginBottom || \"0\");\n return el.offsetHeight + m;\n}\n\nfunction isFragmentable(el: HTMLElement): boolean {\n // Top-level fragmentable types: paragraph, heading, blockquote.\n // Tables fragment via `placeFragmentedTable` (row-level), not the line engine.\n const type = el.getAttribute(\"data-block-type\");\n if (type === \"paragraph\") return true;\n if (type === \"heading\") return true;\n if (type === \"blockquote\") return true;\n return false;\n}\n\n/**\n * The top-level for a table block is a `<div class=\"ed-table-wrap\">` wrapper —\n * the `data-block-type=\"table\"` attribute lives on the nested `<table>`.\n */\nfunction isTableTopLevel(el: HTMLElement): boolean {\n return el.querySelector(':scope > table[data-block-type=\"table\"]') !== null;\n}\n\ninterface PlaceFragmentedTableResult { lastUsed: number; }\n\n/**\n * Sub-phase 4.6 — split a table that doesn't fit on the current page across\n * pages at row boundaries.\n *\n * Constraints:\n * - A break between rows `r` and `r+1` is INVALID when any cell with\n * `rowSpan > 1` whose owner sits at row `r' <= r` extends into row `r+1`.\n * We compute this by walking each row's `<td>`s: a `rowSpan = N > 1` at row\n * `r` blocks the boundaries `(r, r+1), (r+1, r+2), … (r+N-2, r+N-1)`.\n *\n * - If no clean break fits the available height (e.g. a very tall span at the\n * top of the table), and the current page already has content, we move to\n * the next page and try again. If even an empty page can't fit a valid\n * prefix, we bleed the smallest legal prefix rather than loop forever.\n *\n * Heights come from `<tr>.getBoundingClientRect()` — these are measured against\n * the unfragmented render, but row layout is invariant under fragmentation as\n * long as the `<colgroup>` widths don't change (they don't), and as long as a\n * span isn't cut (which is exactly the constraint above).\n */\nfunction placeFragmentedTable(\n el: HTMLElement,\n topLevelIndex: number,\n pages: PageEntry[],\n startUsed: number,\n limit: number,\n): PlaceFragmentedTableResult {\n const table = el.querySelector(':scope > table[data-block-type=\"table\"]') as HTMLTableElement | null;\n const tbody = table?.querySelector(':scope > tbody');\n const trs = tbody ? (Array.from(tbody.children) as HTMLTableRowElement[]) : [];\n if (trs.length === 0) {\n // Empty / no rows — fall back to atomic.\n const h = elTotalHeight(el);\n let currentPage = pages[pages.length - 1];\n if (startUsed + h > limit && currentPage.slots.length > 0) {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n startUsed = 0;\n }\n currentPage.slots.push({ topLevelIndex });\n return { lastUsed: startUsed + h };\n }\n\n const rowHeights = trs.map((tr) => tr.getBoundingClientRect().height);\n\n // Invalid break boundaries — indices `k` for which the break between row `k`\n // and `k+1` is blocked by a rowspan crossing it.\n const invalid = new Set<number>();\n for (let r = 0; r < trs.length; r++) {\n const tds = Array.from(trs[r].children) as HTMLTableCellElement[];\n for (const td of tds) {\n const rs = td.rowSpan || 1;\n if (rs > 1) {\n for (let k = r; k <= r + rs - 2 && k < trs.length - 1; k++) {\n invalid.add(k);\n }\n }\n }\n }\n\n // Vertical padding/margin around the table proper, distributed conservatively\n // onto the FIRST fragment only — keeps subsequent fragments compact.\n const wrapHeight = elTotalHeight(el);\n const tableHeight = table ? table.getBoundingClientRect().height : 0;\n const chrome = Math.max(0, wrapHeight - tableHeight);\n\n let rowIdx = 0;\n let used = startUsed;\n let fragIndex = 0;\n let currentPage = pages[pages.length - 1];\n\n while (rowIdx < trs.length) {\n const overhead = fragIndex === 0 ? chrome : 0;\n const available = Math.max(0, limit - used - overhead);\n if (available <= 0) {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n used = 0;\n continue;\n }\n\n // Greedy: keep extending the run as long as height fits and we haven't\n // passed a valid break boundary. Track the LAST valid `bestEnd`.\n let bestEnd = -1;\n let accH = 0;\n for (let k = rowIdx; k < trs.length; k++) {\n accH += rowHeights[k];\n if (accH > available) break;\n if (k === trs.length - 1 || !invalid.has(k)) bestEnd = k + 1;\n }\n\n if (bestEnd < 0) {\n if (currentPage.slots.length === 0) {\n // Empty page yet still no valid prefix fits — find the smallest legal\n // prefix and bleed (better than an infinite loop).\n let k = rowIdx;\n while (k < trs.length - 1 && invalid.has(k)) k++;\n bestEnd = k + 1;\n } else {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n used = 0;\n continue;\n }\n }\n\n let fragHeight = 0;\n for (let k = rowIdx; k < bestEnd; k++) fragHeight += rowHeights[k];\n if (fragIndex === 0) fragHeight += chrome;\n\n currentPage.slots.push({\n topLevelIndex,\n tableFragment: { index: fragIndex, rowStart: rowIdx, rowEnd: bestEnd },\n });\n used += fragHeight;\n fragIndex++;\n rowIdx = bestEnd;\n\n if (rowIdx < trs.length) {\n pages.push({ slots: [] });\n currentPage = pages[pages.length - 1];\n used = 0;\n }\n }\n\n return { lastUsed: used };\n}\n\nfunction collectTopLevelElements(root: HTMLElement): HTMLElement[] {\n // The root may be in one of three shapes:\n // - flat: root > top1, top2, ...\n // - paged simple: root > .ed-page > .ed-page-content > top1, top2, ...\n // - paged + fragments: same as above, but some \"tops\" are fragments of the\n // same block index. We don't expect to be called in\n // that state (caller guards on isUnfragmented), so\n // collecting direct children is fine.\n const pageContents = root.querySelectorAll<HTMLElement>(\":scope > .ed-page > .ed-page-content\");\n if (pageContents.length > 0) {\n const out: HTMLElement[] = [];\n pageContents.forEach((pc) => {\n Array.from(pc.children).forEach((c) => out.push(c as HTMLElement));\n });\n return out;\n }\n return Array.from(root.children) as HTMLElement[];\n}\n\n/**\n * Sum text-node lengths inside `el` plus 1 for each image embed, skipping any\n * descendant `[data-block-index]`. Mirrors the model's notion of \"length\".\n */\nfunction getBlockTextLength(el: HTMLElement): number {\n const walker = document.createTreeWalker(\n el,\n NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,\n blockBoundaryFilter(el),\n );\n let n: Node | null;\n let sum = 0;\n while ((n = walker.nextNode())) {\n if (n.nodeType === Node.TEXT_NODE) {\n sum += (n.textContent ?? \"\").length;\n } else if (\n n.nodeType === Node.ELEMENT_NODE &&\n (n as HTMLElement).dataset.embed === \"image\"\n ) {\n sum += 1;\n }\n }\n return sum;\n}\n\nfunction blockBoundaryFilter(blockEl: HTMLElement): NodeFilter {\n return {\n acceptNode(n: Node) {\n let p: Node | null = n.parentNode;\n while (p && p !== blockEl) {\n if (p.nodeType === Node.ELEMENT_NODE) {\n const e = p as HTMLElement;\n if (e.dataset.blockIndex != null) return NodeFilter.FILTER_REJECT;\n }\n p = p.parentNode;\n }\n return NodeFilter.FILTER_ACCEPT;\n },\n };\n}\n\n// ---------- Equality helpers ----------\n\nfunction shallowArrayEqual(a: unknown[], b: unknown[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n\nfunction layoutsDeepEqual(a: PageLayout, b: PageLayout): boolean {\n if (a.pages.length !== b.pages.length) return false;\n for (let i = 0; i < a.pages.length; i++) {\n const sA = a.pages[i].slots;\n const sB = b.pages[i].slots;\n if (sA.length !== sB.length) return false;\n for (let j = 0; j < sA.length; j++) {\n if (sA[j].topLevelIndex !== sB[j].topLevelIndex) return false;\n const fA = sA[j].fragment;\n const fB = sB[j].fragment;\n if (fA || fB) {\n if (!fA || !fB) return false;\n if (fA.index !== fB.index || fA.start !== fB.start || fA.end !== fB.end) return false;\n }\n const tA = sA[j].tableFragment;\n const tB = sB[j].tableFragment;\n if (tA || tB) {\n if (!tA || !tB) return false;\n if (tA.index !== tB.index || tA.rowStart !== tB.rowStart || tA.rowEnd !== tB.rowEnd) {\n return false;\n }\n }\n }\n }\n return true;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { usePageSettings } from \"./usePageSettings\";\nimport {\n EditorDocument,\n EditorHistory,\n collapsedSelection,\n dedentList as cmdDedentList,\n deleteTable as cmdDeleteTable,\n deleteTableColumn as cmdDeleteColumn,\n deleteTableRow as cmdDeleteRow,\n insertImage as cmdInsertImage,\n mergeDown as cmdMergeDown,\n mergeRight as cmdMergeRight,\n mergeSelection as cmdMergeSelection,\n setColumnWidth as cmdSetColumnWidth,\n setImageAttrs as cmdSetImageAttrs,\n splitCell as cmdSplitCell,\n tableRectSelection,\n getMarksInRange,\n indentList as cmdIndentList,\n insertTable as cmdInsertTable,\n insertTableColumn as cmdInsertColumn,\n insertTableRow as cmdInsertRow,\n isImageEmbed,\n isMarkUniformInRange,\n moveToNextCell as cmdMoveNextCell,\n moveToPrevCell as cmdMovePrevCell,\n orderedRange,\n removeMark as cmdRemoveMark,\n setBlockAttr as cmdSetBlockAttr,\n setBlockType as cmdSetBlockType,\n setMark as cmdSetMark,\n splitListItem as cmdSplitListItem,\n tableLocationOf,\n toggleList as cmdToggleList,\n toggleMark as cmdToggleMark,\n type BlockAttrs,\n type BlockType,\n type CommandContext,\n type DeltaOp,\n type ImageEmbed,\n type ListKind,\n type MarkAttrs,\n type MarkName,\n type PageSettings,\n type SerializedDocument,\n type Selection,\n type TableLocation,\n type TableRect,\n} from \"@sofereditor/core\";\n\nexport interface UseEditorOptions {\n document?: EditorDocument;\n /**\n * Quando definido, `insertImageFromFile` chama esta função pra obter a URL\n * final em vez de embutir o arquivo como data URL base64 no Y.Doc.\n *\n * Use isto quando o app tem storage externo (S3, Azure Blob, etc.) e não quer\n * inflar o documento com imagens base64. O componente `<Editor>` propaga o\n * mesmo upload para paste/drop/file picker.\n */\n uploadImage?: (file: File) => Promise<string>;\n}\n\nexport type PendingMarks = Partial<Record<MarkName, MarkAttrs[MarkName] | null>>;\n\nexport interface LinkRequest {\n initialHref: string;\n resolve: (href: string | null) => void;\n}\n\nexport interface PageConfigRequest {\n initial: PageSettings;\n resolve: (applied: boolean) => void;\n}\n\nexport type CaptionAlign = \"left\" | \"center\" | \"right\";\n\nexport interface ImageCaptionResult {\n caption: string;\n align: CaptionAlign;\n}\n\nexport interface ImageCaptionRequest {\n initialCaption: string;\n initialAlign: CaptionAlign;\n /**\n * Resolves with the new caption + alignment, or null on cancel. An empty\n * `caption` string means \"remove caption\" (align is ignored in that case).\n */\n resolve: (result: ImageCaptionResult | null) => void;\n}\n\nexport interface UseEditorResult {\n doc: EditorDocument;\n history: EditorHistory;\n /** Snapshot of the model, re-computed on every Y.js update. */\n snapshot: SerializedDocument;\n /** Current model selection. Use `setSelection` to move the caret. */\n selection: Selection;\n setSelection: (sel: Selection) => void;\n /** Stable getter — commands read this to know where the caret is. */\n getSelection: () => Selection;\n\n // ---- Mark API (added in Sub-phase 2.1) ----\n isMarkActive: (name: MarkName, value?: MarkAttrs[MarkName]) => boolean;\n getActiveMarks: () => Partial<Record<MarkName, MarkAttrs[MarkName] | \"mixed\">>;\n toggleMark: (name: MarkName, value?: MarkAttrs[MarkName]) => void;\n setMark: (name: MarkName, value: MarkAttrs[MarkName]) => void;\n removeMark: (name: MarkName) => void;\n\n // ---- Block API (added in Sub-phase 2.2) ----\n /** Returns the type of the focus block (or \"mixed\" when the selection covers heterogeneous blocks). */\n getBlockType: () => BlockType | \"mixed\";\n /** Returns one block attribute at the focus block, or \"mixed\" when not uniform across the selection. */\n getBlockAttr: <K extends keyof BlockAttrs>(key: K) => BlockAttrs[K] | \"mixed\" | undefined;\n setBlockType: (type: BlockType, attrs?: BlockAttrs) => void;\n setBlockAttr: <K extends keyof BlockAttrs>(key: K, value: BlockAttrs[K] | null) => void;\n\n // ---- List API (added in Sub-phase 2.3) ----\n isListActive: (kind: ListKind) => boolean;\n toggleList: (kind: ListKind) => void;\n indentList: () => void;\n dedentList: () => void;\n /** Returns true when handled (current block is a listItem); false to fall back to insertParagraph. */\n splitListItem: () => boolean;\n\n /** Marks queued for the next `insertText` (e.g. user pressed Cmd+B with a collapsed caret). */\n pendingMarks: PendingMarks;\n /** Consumed by the input layer right before calling `insertText`. */\n consumePendingMarks: () => PendingMarks | undefined;\n\n // ---- Link dialog (Polish iteration) ----\n linkRequest: LinkRequest | null;\n /** Open the link dialog; resolves with the entered href, empty string to remove, or null on cancel. */\n requestLink: (initialHref?: string) => Promise<string | null>;\n /** Called by the LinkDialog itself when the user submits or cancels. */\n resolveLinkRequest: (href: string | null) => void;\n\n // ---- Page settings (Fase 9.6) ----\n /** Reactive page settings snapshot (re-renders when the Y.Doc docSettings changes). */\n pageSettings: PageSettings;\n /** Merge a partial PageSettings into the Y.Doc. Not undoable. */\n setPageSettings: (partial: Partial<PageSettings>) => void;\n /** Page-config dialog request (null when closed). */\n pageConfigRequest: PageConfigRequest | null;\n /** Open the page-config dialog; resolves true on apply, false on cancel. */\n requestPageConfig: () => Promise<boolean>;\n /** Resolver called by `<PageConfigDialog>` on apply/cancel. */\n resolvePageConfigRequest: (applied: boolean) => void;\n\n // ---- Image caption (Fase 9.6+) ----\n imageCaptionRequest: ImageCaptionRequest | null;\n /** Open the image-caption dialog with the current caption + alignment pre-filled. */\n requestImageCaption: (\n initialCaption?: string,\n initialAlign?: CaptionAlign,\n ) => Promise<ImageCaptionResult | null>;\n /** Resolver called by `<ImageCaptionDialog>` on apply/cancel. */\n resolveImageCaptionRequest: (result: ImageCaptionResult | null) => void;\n\n // ---- Tables (Phase 4) ----\n /** True iff the focus position lies inside a table cell. */\n isInTable: () => boolean;\n /** Returns `{blockIndex, row, col}` for the focus position, or null when outside a table. */\n getTableLocation: () => TableLocation | null;\n insertTable: (rows: number, cols: number) => void;\n /** Removes the table at `blockIndex`. Defaults to the current focus table. */\n deleteTable: (blockIndex?: number) => void;\n insertRowAbove: () => void;\n insertRowBelow: () => void;\n deleteCurrentRow: () => void;\n insertColumnLeft: () => void;\n insertColumnRight: () => void;\n deleteCurrentColumn: () => void;\n moveToNextCell: () => void;\n moveToPrevCell: () => void;\n mergeRight: () => boolean;\n mergeDown: () => boolean;\n splitCell: () => boolean;\n setColumnWidth: (blockIndex: number, col: number, widthPx: number) => void;\n /** Returns the table rectangle if the current selection is a multi-cell range, else null. */\n getTableRect: () => TableRect | null;\n /** True when there's a rectangular table-cell selection. */\n hasTableRectSelection: () => boolean;\n /** Merge every cell in the rectangular selection. Returns true on success. */\n mergeSelection: () => boolean;\n\n // ---- Inline images (Fase 5) ----\n insertImage: (embed: ImageEmbed) => void;\n setImageAttrs: (\n blockIndex: number,\n offset: number,\n partial: Partial<ImageEmbed>,\n cellIndex?: number,\n newOffset?: number,\n ) => void;\n /** Read a File (image) and insert it inline at the caret as a data-URL embed. */\n insertImageFromFile: (file: File) => Promise<void>;\n /**\n * Returns the embed currently selected (single 1-char range over an image),\n * or null when no embed is solely selected.\n */\n getSelectedEmbed: () =>\n | { blockIndex: number; offset: number; cellIndex?: number; embed: ImageEmbed }\n | null;\n}\n\n/** Max display width when inserting an image. Larger sources are scaled keeping aspect ratio. */\nconst MAX_INSERT_WIDTH = 600;\n\nexport function useEditor(opts: UseEditorOptions = {}): UseEditorResult {\n const doc = useMemo(() => opts.document ?? new EditorDocument(), [opts.document]);\n const history = useMemo(() => new EditorHistory(doc), [doc]);\n\n const [snapshot, setSnapshot] = useState<SerializedDocument>(() => doc.toJSON());\n const [selection, setSelectionState] = useState<Selection>(() =>\n collapsedSelection({ blockIndex: 0, offset: 0 }),\n );\n const selectionRef = useRef(selection);\n selectionRef.current = selection;\n\n // pendingMarks lives on a ref so the beforeinput handler reads the latest value\n // without re-binding listeners on every render. The state copy exists so the\n // Toolbar can render a \"pressed\" hint when a mark is armed at a collapsed caret.\n const pendingMarksRef = useRef<PendingMarks>({});\n const [pendingMarks, setPendingMarksState] = useState<PendingMarks>({});\n\n const setPendingMarks = useCallback((next: PendingMarks) => {\n pendingMarksRef.current = next;\n setPendingMarksState(next);\n }, []);\n\n useEffect(() => {\n // Coalesce snapshot recomputation: `afterTransaction` fires per Y.js\n // transaction, which means once per keystroke for normal typing — but on\n // paste / multi-op commands it can fire N times in a microtask burst.\n // `toJSON()` is expensive for docs with embedded images (each call deep-\n // clones every block's delta, including base64 image src). Coalescing\n // into rAF guarantees at most one recompute per animation frame regardless\n // of how many transactions fire underneath. A pending flag avoids\n // scheduling multiple rAFs.\n let scheduled = false;\n let cancelled = false;\n let frame = 0 as number | ReturnType<typeof requestAnimationFrame>;\n const flush = () => {\n scheduled = false;\n if (cancelled) return;\n setSnapshot(doc.toJSON());\n };\n const schedule = () => {\n if (scheduled) return;\n scheduled = true;\n // Use rAF when available (browser), fall back to microtask in jsdom/Node.\n if (typeof requestAnimationFrame === \"function\") {\n frame = requestAnimationFrame(flush);\n } else {\n queueMicrotask(flush);\n }\n };\n doc.ydoc.on(\"afterTransaction\", schedule);\n return () => {\n cancelled = true;\n if (\n scheduled &&\n typeof requestAnimationFrame === \"function\" &&\n typeof cancelAnimationFrame === \"function\"\n ) {\n cancelAnimationFrame(frame as number);\n }\n doc.ydoc.off(\"afterTransaction\", schedule);\n };\n }, [doc]);\n\n const getSelection = useCallback(() => selectionRef.current, []);\n const setSelection = useCallback(\n (sel: Selection) => {\n const prev = selectionRef.current;\n selectionRef.current = sel;\n setSelectionState(sel);\n // Any caret movement that isn't a direct typing follow-up clears the queue.\n if (\n Object.keys(pendingMarksRef.current).length > 0 &&\n (prev.focus.blockIndex !== sel.focus.blockIndex || prev.focus.offset !== sel.focus.offset)\n ) {\n // Heuristic: typing advances the caret by exactly 1; everything else clears.\n const advancedByOne =\n prev.focus.blockIndex === sel.focus.blockIndex &&\n sel.focus.offset === prev.focus.offset + 1;\n if (!advancedByOne) {\n pendingMarksRef.current = {};\n setPendingMarksState({});\n }\n }\n },\n [],\n );\n\n const ctxRef = useRef<CommandContext>({ doc, getSelection, setSelection });\n ctxRef.current = { doc, getSelection, setSelection };\n\n const consumePendingMarks = useCallback((): PendingMarks | undefined => {\n const current = pendingMarksRef.current;\n if (Object.keys(current).length === 0) return undefined;\n pendingMarksRef.current = {};\n setPendingMarksState({});\n return current;\n }, []);\n\n const isMarkActive = useCallback(\n (name: MarkName, value?: MarkAttrs[MarkName]): boolean => {\n const sel = selectionRef.current;\n const { start, end } = orderedRange(sel);\n if (start.blockIndex === end.blockIndex && start.offset === end.offset) {\n // Collapsed: union of pending and ambient (mark of the char immediately before caret).\n const pending = pendingMarksRef.current[name];\n if (pending !== undefined) {\n if (pending === null) return false;\n return value === undefined ? true : sameValue(pending, value);\n }\n const yText = doc.getBlockText(start.blockIndex);\n if (!yText || start.offset === 0) return false;\n return isMarkUniformInRange(yText, start.offset - 1, start.offset, name, value);\n }\n if (start.blockIndex !== end.blockIndex) {\n // Multi-block: active only if uniformly active on every covered slice.\n for (let i = start.blockIndex; i <= end.blockIndex; i++) {\n const yText = doc.getBlockText(i);\n if (!yText) return false;\n const s = i === start.blockIndex ? start.offset : 0;\n const e = i === end.blockIndex ? end.offset : yText.length;\n if (s >= e) continue;\n if (!isMarkUniformInRange(yText, s, e, name, value)) return false;\n }\n return true;\n }\n const yText = doc.getBlockText(start.blockIndex);\n if (!yText) return false;\n return isMarkUniformInRange(yText, start.offset, end.offset, name, value);\n },\n [doc],\n );\n\n const getActiveMarks = useCallback(() => {\n const sel = selectionRef.current;\n const { start, end } = orderedRange(sel);\n if (start.blockIndex !== end.blockIndex) {\n // For Sub-phase 2.1 we conservatively report empty across multi-block selections.\n return {};\n }\n const yText = doc.getBlockText(start.blockIndex);\n if (!yText) return {};\n if (start.offset === end.offset) {\n if (start.offset === 0) return {};\n return getMarksInRange(yText, start.offset - 1, start.offset);\n }\n return getMarksInRange(yText, start.offset, end.offset);\n }, [doc]);\n\n const toggleMark = useCallback(\n (name: MarkName, value?: MarkAttrs[MarkName]) => {\n const sel = selectionRef.current;\n const { start, end } = orderedRange(sel);\n const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;\n if (isCollapsed) {\n // Queue for next insert.\n const next: PendingMarks = { ...pendingMarksRef.current };\n const currentlyActive = isMarkActive(name, value);\n if (currentlyActive) {\n next[name] = null;\n } else {\n next[name] = value ?? (booleanMarks.has(name) ? true : null);\n }\n setPendingMarks(next);\n return;\n }\n cmdToggleMark(ctxRef.current, name, value);\n },\n [isMarkActive, setPendingMarks],\n );\n\n const setMark = useCallback(\n (name: MarkName, value: MarkAttrs[MarkName]) => {\n const sel = selectionRef.current;\n const { start, end } = orderedRange(sel);\n const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;\n if (isCollapsed) {\n setPendingMarks({ ...pendingMarksRef.current, [name]: value });\n return;\n }\n cmdSetMark(ctxRef.current, name, value);\n },\n [setPendingMarks],\n );\n\n const removeMark = useCallback(\n (name: MarkName) => {\n const sel = selectionRef.current;\n const { start, end } = orderedRange(sel);\n const isCollapsed = start.blockIndex === end.blockIndex && start.offset === end.offset;\n if (isCollapsed) {\n setPendingMarks({ ...pendingMarksRef.current, [name]: null });\n return;\n }\n cmdRemoveMark(ctxRef.current, name);\n },\n [setPendingMarks],\n );\n\n const getBlockType = useCallback((): BlockType | \"mixed\" => {\n const sel = selectionRef.current;\n const { start, end } = orderedRange(sel);\n const first = doc.getBlockType(start.blockIndex);\n if (first === undefined) return \"paragraph\";\n for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {\n if (doc.getBlockType(i) !== first) return \"mixed\";\n }\n return first;\n }, [doc]);\n\n const getBlockAttr = useCallback(\n <K extends keyof BlockAttrs>(key: K): BlockAttrs[K] | \"mixed\" | undefined => {\n const sel = selectionRef.current;\n const { start, end } = orderedRange(sel);\n const first = doc.getBlockAttrs(start.blockIndex)[key];\n for (let i = start.blockIndex + 1; i <= end.blockIndex; i++) {\n const next = doc.getBlockAttrs(i)[key];\n if (next !== first) return \"mixed\";\n }\n return first;\n },\n [doc],\n );\n\n const setBlockType = useCallback((type: BlockType, attrs?: BlockAttrs) => {\n cmdSetBlockType(ctxRef.current, type, attrs);\n }, []);\n\n const setBlockAttr = useCallback(\n <K extends keyof BlockAttrs>(key: K, value: BlockAttrs[K] | null) => {\n cmdSetBlockAttr(ctxRef.current, key, value);\n },\n [],\n );\n\n const isListActive = useCallback(\n (kind: ListKind): boolean => {\n const sel = selectionRef.current;\n const { start, end } = orderedRange(sel);\n for (let i = start.blockIndex; i <= end.blockIndex; i++) {\n if (doc.getBlockType(i) !== \"listItem\") return false;\n if (doc.getBlockAttrs(i).listKind !== kind) return false;\n }\n return true;\n },\n [doc],\n );\n\n const toggleList = useCallback((kind: ListKind) => {\n cmdToggleList(ctxRef.current, kind);\n }, []);\n const indentList = useCallback(() => {\n cmdIndentList(ctxRef.current);\n }, []);\n const dedentList = useCallback(() => {\n cmdDedentList(ctxRef.current);\n }, []);\n const splitListItem = useCallback((): boolean => {\n return cmdSplitListItem(ctxRef.current);\n }, []);\n\n // ---- Tables ----\n const isInTable = useCallback((): boolean => {\n return selectionRef.current.focus.cellIndex != null;\n }, []);\n const getTableLocation = useCallback((): TableLocation | null => {\n return tableLocationOf(doc, selectionRef.current.focus);\n }, [doc]);\n const insertTable = useCallback((rows: number, cols: number) => {\n cmdInsertTable(ctxRef.current, rows, cols);\n }, []);\n const deleteTable = useCallback((blockIndex?: number) => {\n const idx = blockIndex ?? selectionRef.current.focus.blockIndex;\n cmdDeleteTable(ctxRef.current, idx);\n }, []);\n const insertRowAbove = useCallback(() => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return;\n cmdInsertRow(ctxRef.current, loc.blockIndex, loc.row, \"before\");\n }, [doc]);\n const insertRowBelow = useCallback(() => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return;\n cmdInsertRow(ctxRef.current, loc.blockIndex, loc.row, \"after\");\n }, [doc]);\n const deleteCurrentRow = useCallback(() => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return;\n cmdDeleteRow(ctxRef.current, loc.blockIndex, loc.row);\n }, [doc]);\n const insertColumnLeft = useCallback(() => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return;\n cmdInsertColumn(ctxRef.current, loc.blockIndex, loc.col, \"before\");\n }, [doc]);\n const insertColumnRight = useCallback(() => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return;\n cmdInsertColumn(ctxRef.current, loc.blockIndex, loc.col, \"after\");\n }, [doc]);\n const deleteCurrentColumn = useCallback(() => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return;\n cmdDeleteColumn(ctxRef.current, loc.blockIndex, loc.col);\n }, [doc]);\n const moveToNextCell = useCallback(() => {\n cmdMoveNextCell(ctxRef.current);\n }, []);\n const moveToPrevCell = useCallback(() => {\n cmdMovePrevCell(ctxRef.current);\n }, []);\n const mergeRight = useCallback((): boolean => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return false;\n return cmdMergeRight(ctxRef.current, loc.blockIndex, loc.row, loc.col);\n }, [doc]);\n const mergeDown = useCallback((): boolean => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return false;\n return cmdMergeDown(ctxRef.current, loc.blockIndex, loc.row, loc.col);\n }, [doc]);\n const splitCell = useCallback((): boolean => {\n const loc = tableLocationOf(doc, selectionRef.current.focus);\n if (!loc) return false;\n return cmdSplitCell(ctxRef.current, loc.blockIndex, loc.row, loc.col);\n }, [doc]);\n const setColumnWidth = useCallback(\n (blockIndex: number, col: number, widthPx: number) => {\n cmdSetColumnWidth(ctxRef.current, blockIndex, col, widthPx);\n },\n [],\n );\n const getTableRect = useCallback(\n () => tableRectSelection(doc, selectionRef.current),\n [doc],\n );\n const hasTableRectSelection = useCallback((): boolean => {\n return tableRectSelection(doc, selectionRef.current) !== null;\n }, [doc]);\n const mergeSelection = useCallback((): boolean => {\n return cmdMergeSelection(ctxRef.current);\n }, []);\n\n // ---- Inline images ----\n const insertImage = useCallback((embed: ImageEmbed) => {\n cmdInsertImage(ctxRef.current, embed);\n }, []);\n const setImageAttrs = useCallback(\n (\n blockIndex: number,\n offset: number,\n partial: Partial<ImageEmbed>,\n cellIndex?: number,\n newOffset?: number,\n ) => {\n cmdSetImageAttrs(ctxRef.current, blockIndex, offset, partial, cellIndex, newOffset);\n },\n [],\n );\n const uploadImageRef = useRef(opts.uploadImage);\n uploadImageRef.current = opts.uploadImage;\n const insertImageFromFile = useCallback(async (file: File): Promise<void> => {\n if (!file.type.startsWith(\"image/\")) return;\n // Lê dimensões a partir de um dataUrl temporário em ambos os caminhos\n // (lê o arquivo só uma vez; o uploadImage decide se persiste essa data\n // ou faz upload pra um storage externo).\n const dataUrl = await readAsDataURL(file);\n const dims = await readImageDimensions(dataUrl);\n let w = dims.width;\n let h = dims.height;\n if (w > MAX_INSERT_WIDTH) {\n h = Math.round((h * MAX_INSERT_WIDTH) / w);\n w = MAX_INSERT_WIDTH;\n }\n const upload = uploadImageRef.current;\n const src = upload ? await upload(file) : dataUrl;\n cmdInsertImage(ctxRef.current, { type: \"image\", src, width: w, height: h });\n }, []);\n const getSelectedEmbed = useCallback(() => {\n const sel = selectionRef.current;\n if (sel.anchor.blockIndex !== sel.focus.blockIndex) return null;\n if ((sel.anchor.cellIndex ?? -1) !== (sel.focus.cellIndex ?? -1)) return null;\n const a = sel.anchor.offset;\n const b = sel.focus.offset;\n if (Math.abs(a - b) !== 1) return null;\n const start = Math.min(a, b);\n const yText = doc.textAt(sel.anchor.blockIndex, sel.anchor.cellIndex);\n if (!yText) return null;\n const delta = yText.toDelta() as DeltaOp[];\n let cursor = 0;\n for (const op of delta) {\n if (typeof op.insert === \"string\") {\n cursor += op.insert.length;\n continue;\n }\n if (cursor === start && isImageEmbed(op.insert)) {\n return {\n blockIndex: sel.anchor.blockIndex,\n cellIndex: sel.anchor.cellIndex,\n offset: start,\n embed: op.insert,\n };\n }\n cursor += 1;\n }\n return null;\n }, [doc]);\n\n const [linkRequest, setLinkRequest] = useState<LinkRequest | null>(null);\n const requestLink = useCallback((initialHref = \"\"): Promise<string | null> => {\n return new Promise((resolve) => {\n setLinkRequest({ initialHref, resolve });\n });\n }, []);\n const resolveLinkRequest = useCallback((href: string | null) => {\n setLinkRequest((prev) => {\n if (prev) prev.resolve(href);\n return null;\n });\n }, []);\n\n // ---- Page settings ----\n const pageSettings = usePageSettings(doc);\n const setPageSettings = useCallback(\n (partial: Partial<PageSettings>) => {\n doc.setPageSettings(partial);\n },\n [doc],\n );\n const [pageConfigRequest, setPageConfigRequest] = useState<PageConfigRequest | null>(null);\n const requestPageConfig = useCallback((): Promise<boolean> => {\n return new Promise((resolve) => {\n setPageConfigRequest({ initial: doc.getPageSettings(), resolve });\n });\n }, [doc]);\n const resolvePageConfigRequest = useCallback((applied: boolean) => {\n setPageConfigRequest((prev) => {\n if (prev) prev.resolve(applied);\n return null;\n });\n }, []);\n\n // ---- Image caption ----\n const [imageCaptionRequest, setImageCaptionRequest] =\n useState<ImageCaptionRequest | null>(null);\n const requestImageCaption = useCallback(\n (initialCaption = \"\", initialAlign: CaptionAlign = \"center\"): Promise<ImageCaptionResult | null> => {\n return new Promise((resolve) => {\n setImageCaptionRequest({ initialCaption, initialAlign, resolve });\n });\n },\n [],\n );\n const resolveImageCaptionRequest = useCallback((result: ImageCaptionResult | null) => {\n setImageCaptionRequest((prev) => {\n if (prev) prev.resolve(result);\n return null;\n });\n }, []);\n\n return {\n doc,\n history,\n snapshot,\n selection,\n setSelection,\n getSelection,\n isMarkActive,\n getActiveMarks,\n toggleMark,\n setMark,\n removeMark,\n pendingMarks,\n consumePendingMarks,\n getBlockType,\n getBlockAttr,\n setBlockType,\n setBlockAttr,\n isListActive,\n toggleList,\n indentList,\n dedentList,\n splitListItem,\n linkRequest,\n requestLink,\n resolveLinkRequest,\n isInTable,\n getTableLocation,\n insertTable,\n deleteTable,\n insertRowAbove,\n insertRowBelow,\n deleteCurrentRow,\n insertColumnLeft,\n insertColumnRight,\n deleteCurrentColumn,\n moveToNextCell,\n moveToPrevCell,\n mergeRight,\n mergeDown,\n splitCell,\n setColumnWidth,\n getTableRect,\n hasTableRectSelection,\n mergeSelection,\n insertImage,\n setImageAttrs,\n insertImageFromFile,\n getSelectedEmbed,\n pageSettings,\n setPageSettings,\n pageConfigRequest,\n requestPageConfig,\n resolvePageConfigRequest,\n imageCaptionRequest,\n requestImageCaption,\n resolveImageCaptionRequest,\n };\n}\n\nfunction readAsDataURL(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = () => reject(reader.error ?? new Error(\"FileReader error\"));\n reader.onload = () => resolve(reader.result as string);\n reader.readAsDataURL(file);\n });\n}\n\nfunction readImageDimensions(src: string): Promise<{ width: number; height: number }> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onerror = () => reject(new Error(\"image load failed\"));\n img.onload = () => resolve({ width: img.naturalWidth, height: img.naturalHeight });\n img.src = src;\n });\n}\n\nconst booleanMarks: Set<MarkName> = new Set([\"bold\", \"italic\", \"underline\", \"strike\"]);\n\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a === \"object\" && a && b && typeof b === \"object\") {\n const ak = Object.keys(a);\n const bk = Object.keys(b);\n if (ak.length !== bk.length) return false;\n return ak.every((k) => (a as Record<string, unknown>)[k] === (b as Record<string, unknown>)[k]);\n }\n return false;\n}\n","import { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport type { EditorDocument, PageSettings } from \"@sofereditor/core\";\n\n/**\n * Reactive snapshot of an `EditorDocument`'s page settings. Re-renders the\n * component when `docSettings` changes (either locally via `setPageSettings`\n * or remotely via Y.js sync).\n *\n * Caches the snapshot reference to satisfy `useSyncExternalStore`'s stable-\n * identity requirement — `getPageSettings` returns a fresh object each call,\n * which would loop the store forever without this caching.\n */\nexport function usePageSettings(doc: EditorDocument): PageSettings {\n const cacheRef = useRef<PageSettings | null>(null);\n\n const subscribe = useCallback(\n (notify: () => void) => doc.observePageSettings(notify),\n [doc],\n );\n\n const getSnapshot = useCallback((): PageSettings => {\n const next = doc.getPageSettings();\n const prev = cacheRef.current;\n if (prev && shallowEqual(prev, next)) return prev;\n cacheRef.current = next;\n return next;\n }, [doc]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nfunction shallowEqual(a: PageSettings, b: PageSettings): boolean {\n return (\n a.width === b.width &&\n a.height === b.height &&\n a.marginTop === b.marginTop &&\n a.marginBottom === b.marginBottom &&\n a.marginLeft === b.marginLeft &&\n a.marginRight === b.marginRight &&\n a.preset === b.preset\n );\n}\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type JSX,\n type MouseEvent,\n type ReactNode,\n} from \"react\";\nimport { useEditorContext } from \"./EditorContext\";\nimport type { AlignValue, BlockType, DirValue, ImageLayout, MarkName } from \"@sofereditor/core\";\n\n// School standard: Arial only. The dropdown is kept (instead of removed) so\n// that the surrounding font-size / color UI stays balanced and future font\n// additions are a one-liner.\nconst FONT_FAMILIES = [\"Arial\"];\nconst FONT_SIZES = [\"8pt\", \"10pt\", \"11pt\", \"12pt\", \"14pt\", \"16pt\", \"18pt\", \"24pt\", \"32pt\", \"48pt\"];\n\ninterface BlockOption {\n value: string;\n label: string;\n type: BlockType;\n level?: 1 | 2 | 3 | 4 | 5 | 6;\n}\n\nconst BLOCK_OPTIONS: BlockOption[] = [\n { value: \"paragraph\", label: \"Parágrafo\", type: \"paragraph\" },\n { value: \"h1\", label: \"Título 1\", type: \"heading\", level: 1 },\n { value: \"h2\", label: \"Título 2\", type: \"heading\", level: 2 },\n { value: \"h3\", label: \"Título 3\", type: \"heading\", level: 3 },\n { value: \"h4\", label: \"Título 4\", type: \"heading\", level: 4 },\n { value: \"h5\", label: \"Título 5\", type: \"heading\", level: 5 },\n { value: \"h6\", label: \"Título 6\", type: \"heading\", level: 6 },\n { value: \"blockquote\", label: \"Citação\", type: \"blockquote\" },\n { value: \"codeBlock\", label: \"Código\", type: \"codeBlock\" },\n];\n\nconst ALIGN_OPTIONS: { value: AlignValue; label: string; title: string }[] = [\n { value: \"left\", label: \"⇤\", title: \"Alinhar à esquerda\" },\n { value: \"center\", label: \"≡\", title: \"Centralizar\" },\n { value: \"right\", label: \"⇥\", title: \"Alinhar à direita\" },\n { value: \"justify\", label: \"☰\", title: \"Justificar\" },\n];\n\nconst IMAGE_ALIGN_VALUES = new Set<AlignValue>([\"left\", \"center\", \"right\"]);\n\nconst IMAGE_LAYOUT_OPTIONS: { value: ImageLayout; label: string; title: string }[] = [\n { value: \"inline\", label: \"↔\", title: \"Inline (no fluxo do texto)\" },\n { value: \"wrap-left\", label: \"◧\", title: \"Texto contorna à direita\" },\n { value: \"wrap-right\", label: \"◨\", title: \"Texto contorna à esquerda\" },\n { value: \"behind\", label: \"▢↓\", title: \"Atrás do texto\" },\n { value: \"front\", label: \"▢↑\", title: \"Na frente do texto\" },\n];\n\nexport interface ToolbarProps {\n className?: string;\n}\n\nexport function Toolbar({ className }: ToolbarProps): JSX.Element {\n const editor = useEditorContext();\n const {\n isMarkActive,\n getActiveMarks,\n toggleMark,\n setMark,\n removeMark,\n getBlockType,\n getBlockAttr,\n setBlockType,\n setBlockAttr,\n isListActive,\n toggleList,\n indentList,\n dedentList,\n } = editor;\n const active = getActiveMarks();\n const blockType = getBlockType();\n const blockLevel = getBlockAttr(\"level\");\n const blockAlign = getBlockAttr(\"align\");\n const blockDir = getBlockAttr(\"dir\");\n\n // Preserve contenteditable focus when clicking the toolbar background or buttons,\n // BUT let native form controls (select/input) receive mousedown normally so their\n // dropdowns/pickers can open.\n const stop = (e: MouseEvent) => {\n const t = e.target as HTMLElement | null;\n if (t && (t.tagName === \"SELECT\" || t.tagName === \"INPUT\" || t.tagName === \"OPTION\")) {\n return;\n }\n e.preventDefault();\n };\n\n const onToggle = (name: MarkName) => (e: MouseEvent) => {\n e.preventDefault();\n toggleMark(name);\n };\n\n const onColorChange = (e: ChangeEvent<HTMLInputElement>) => {\n setMark(\"color\", e.target.value);\n };\n\n const onFontFamilyChange = (e: ChangeEvent<HTMLSelectElement>) => {\n const v = e.target.value;\n if (v === \"\") removeMark(\"fontFamily\");\n else setMark(\"fontFamily\", v);\n };\n\n const onFontSizeChange = (e: ChangeEvent<HTMLSelectElement>) => {\n const v = e.target.value;\n if (v === \"\") removeMark(\"fontSize\");\n else setMark(\"fontSize\", v);\n };\n\n const onBlockChange = (e: ChangeEvent<HTMLSelectElement>) => {\n const opt = BLOCK_OPTIONS.find((o) => o.value === e.target.value);\n if (!opt) return;\n setBlockType(opt.type, opt.level !== undefined ? { level: opt.level } : undefined);\n };\n\n const onAlign = (value: AlignValue) => (e: MouseEvent) => {\n e.preventDefault();\n // When an image embed is selected, the three image-friendly alignments\n // (left/center/right) target the embed itself; otherwise fall through to\n // the block-level align attribute (which also handles \"justify\").\n const selectedEmbed = editor.getSelectedEmbed();\n if (selectedEmbed && IMAGE_ALIGN_VALUES.has(value)) {\n editor.setImageAttrs(\n selectedEmbed.blockIndex,\n selectedEmbed.offset,\n { align: value as \"left\" | \"center\" | \"right\" },\n selectedEmbed.cellIndex,\n );\n return;\n }\n setBlockAttr(\"align\", value);\n };\n\n const onInsertImageClick = useCallback(\n (e: MouseEvent) => {\n e.preventDefault();\n imageInputRef.current?.click();\n },\n [],\n );\n const onImageInputChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (file) void editor.insertImageFromFile(file);\n e.target.value = \"\";\n },\n [editor],\n );\n const imageInputRef = useRef<HTMLInputElement>(null);\n\n const onToggleDir = (e: MouseEvent) => {\n e.preventDefault();\n const next: DirValue = blockDir === \"rtl\" ? \"ltr\" : \"rtl\";\n setBlockAttr(\"dir\", next);\n };\n\n const linkActive = isMarkActive(\"link\");\n const onLinkClick = useCallback(\n (e: MouseEvent) => {\n e.preventDefault();\n const currentHref =\n active.link && typeof active.link === \"object\" && \"href\" in active.link\n ? (active.link.href as string)\n : \"\";\n void editor.requestLink(currentHref).then((href) => {\n if (href === null) return;\n if (href === \"\") removeMark(\"link\");\n else setMark(\"link\", { href });\n });\n },\n [active.link, editor, removeMark, setMark],\n );\n\n const colorValue = typeof active.color === \"string\" ? active.color : \"#000000\";\n const fontFamilyValue = typeof active.fontFamily === \"string\" ? active.fontFamily : \"\";\n const fontSizeValue = typeof active.fontSize === \"string\" ? active.fontSize : \"\";\n const blockValue = blockSelectValue(blockType, blockLevel);\n\n // The image layout group is only visible when an image embed is selected.\n // We read it fresh every render so the visibility tracks selection changes.\n const selectedEmbed = editor.getSelectedEmbed();\n const currentImageLayout: ImageLayout = selectedEmbed\n ? (selectedEmbed.embed.layout ?? \"inline\")\n : \"inline\";\n\n const onImageLayoutClick = (layout: ImageLayout) => (e: MouseEvent) => {\n e.preventDefault();\n const sel = editor.getSelectedEmbed();\n if (!sel) return;\n // Reset position offsets when switching modes; the previous values would\n // refer to a different coordinate system (margins vs. left/top).\n const reset =\n layout !== (sel.embed.layout ?? \"inline\")\n ? { offsetX: 0, offsetY: 0 }\n : {};\n editor.setImageAttrs(\n sel.blockIndex,\n sel.offset,\n { layout, ...reset },\n sel.cellIndex,\n );\n };\n\n return (\n <div\n className={className ?? \"ed-toolbar\"}\n role=\"toolbar\"\n aria-label=\"Editor toolbar\"\n onMouseDown={stop}\n >\n <Group>\n <select\n className=\"ed-toolbar-select\"\n value={blockValue}\n onChange={onBlockChange}\n onMouseDown={stop}\n aria-label=\"Tipo de bloco\"\n >\n {blockValue === \"\" && <option value=\"\">— (misto)</option>}\n {BLOCK_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>{o.label}</option>\n ))}\n </select>\n </Group>\n\n <Group>\n <MarkButton title=\"Negrito (⌘B)\" pressed={isMarkActive(\"bold\")} onClick={onToggle(\"bold\")}>\n <strong>B</strong>\n </MarkButton>\n <MarkButton title=\"Itálico (⌘I)\" pressed={isMarkActive(\"italic\")} onClick={onToggle(\"italic\")}>\n <em>I</em>\n </MarkButton>\n <MarkButton title=\"Sublinhado (⌘U)\" pressed={isMarkActive(\"underline\")} onClick={onToggle(\"underline\")}>\n <u>U</u>\n </MarkButton>\n <MarkButton title=\"Tachado (⌘⇧X)\" pressed={isMarkActive(\"strike\")} onClick={onToggle(\"strike\")}>\n <s>S</s>\n </MarkButton>\n </Group>\n\n <Group>\n <label className=\"ed-toolbar-label\">\n <span className=\"ed-toolbar-swatch\" aria-hidden style={{ background: colorValue }} />\n <input type=\"color\" value={colorValue} onChange={onColorChange} onMouseDown={stop} aria-label=\"Cor do texto\" />\n </label>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title=\"Remover cor\"\n onMouseDown={stop}\n onClick={(e) => {\n e.preventDefault();\n removeMark(\"color\");\n }}\n >\n ⌫\n </button>\n </Group>\n\n <Group>\n <select\n className=\"ed-toolbar-select\"\n value={fontFamilyValue}\n onChange={onFontFamilyChange}\n onMouseDown={stop}\n aria-label=\"Família da fonte\"\n >\n <option value=\"\">Fonte…</option>\n {FONT_FAMILIES.map((f) => (\n <option key={f} value={f}>{f}</option>\n ))}\n </select>\n <select\n className=\"ed-toolbar-select\"\n value={fontSizeValue}\n onChange={onFontSizeChange}\n onMouseDown={stop}\n aria-label=\"Tamanho da fonte\"\n >\n <option value=\"\">Tamanho…</option>\n {FONT_SIZES.map((s) => (\n <option key={s} value={s}>{s}</option>\n ))}\n </select>\n </Group>\n\n <Group>\n {ALIGN_OPTIONS.map((a) => (\n <button\n key={a.value}\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title={a.title}\n aria-pressed={blockAlign === a.value}\n onMouseDown={stop}\n onClick={onAlign(a.value)}\n >\n {a.label}\n </button>\n ))}\n </Group>\n\n <Group>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n aria-pressed={blockDir === \"rtl\"}\n title={blockDir === \"rtl\" ? \"Mudar para LTR\" : \"Mudar para RTL (hebraico)\"}\n onMouseDown={stop}\n onClick={onToggleDir}\n >\n {blockDir === \"rtl\" ? \"RTL\" : \"LTR\"}\n </button>\n </Group>\n\n <Group>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n aria-pressed={isListActive(\"bullet\")}\n title=\"Lista com marcadores (⌘⇧8)\"\n onMouseDown={stop}\n onClick={(e) => {\n e.preventDefault();\n toggleList(\"bullet\");\n }}\n >\n •\n </button>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n aria-pressed={isListActive(\"ordered\")}\n title=\"Lista numerada (⌘⇧7)\"\n onMouseDown={stop}\n onClick={(e) => {\n e.preventDefault();\n toggleList(\"ordered\");\n }}\n >\n 1.\n </button>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title=\"Diminuir recuo (⇧Tab)\"\n onMouseDown={stop}\n onClick={(e) => {\n e.preventDefault();\n dedentList();\n }}\n >\n ⇤\n </button>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title=\"Aumentar recuo (Tab)\"\n onMouseDown={stop}\n onClick={(e) => {\n e.preventDefault();\n indentList();\n }}\n >\n ⇥\n </button>\n </Group>\n\n <Group>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n aria-pressed={linkActive}\n title={linkActive ? \"Remover link (⌘K)\" : \"Adicionar link (⌘K)\"}\n onMouseDown={stop}\n onClick={onLinkClick}\n >\n 🔗\n </button>\n </Group>\n\n <Group>\n <TableMenu />\n </Group>\n\n <Group>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title=\"Inserir imagem\"\n onMouseDown={stop}\n onClick={onInsertImageClick}\n >\n 🖼\n </button>\n <input\n ref={imageInputRef}\n type=\"file\"\n accept=\"image/*\"\n hidden\n onChange={onImageInputChange}\n />\n </Group>\n\n {selectedEmbed && (\n <Group>\n {IMAGE_LAYOUT_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title={opt.title}\n aria-pressed={currentImageLayout === opt.value}\n onMouseDown={stop}\n onClick={onImageLayoutClick(opt.value)}\n >\n {opt.label}\n </button>\n ))}\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title=\"Legenda da imagem\"\n aria-pressed={!!selectedEmbed.embed.caption}\n onMouseDown={stop}\n onClick={(e) => {\n e.preventDefault();\n const initialCaption = selectedEmbed.embed.caption ?? \"\";\n const initialAlign = selectedEmbed.embed.captionAlign ?? \"center\";\n void editor.requestImageCaption(initialCaption, initialAlign).then((result) => {\n if (result === null) return; // cancelled\n const empty = result.caption.length === 0;\n editor.setImageAttrs(\n selectedEmbed.blockIndex,\n selectedEmbed.offset,\n {\n caption: empty ? undefined : result.caption,\n captionAlign: empty ? undefined : result.align,\n },\n selectedEmbed.cellIndex,\n );\n });\n }}\n >\n Legenda\n </button>\n </Group>\n )}\n\n <Group>\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title=\"Configurar página (tamanho, margens)\"\n onMouseDown={stop}\n onClick={(e) => {\n e.preventDefault();\n void editor.requestPageConfig();\n }}\n >\n ⚙\n </button>\n </Group>\n </div>\n );\n}\n\n// ---------- Table menu ----------\n\nfunction TableMenu(): JSX.Element {\n const editor = useEditorContext();\n const inTable = editor.isInTable();\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onDown = (e: globalThis.MouseEvent) => {\n if (!rootRef.current) return;\n if (rootRef.current.contains(e.target as Node)) return;\n setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDown);\n return () => document.removeEventListener(\"mousedown\", onDown);\n }, [open]);\n\n return (\n <div ref={rootRef} className=\"ed-toolbar-tablemenu\">\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n title=\"Tabela\"\n aria-pressed={open}\n onMouseDown={(e) => e.preventDefault()}\n onClick={(e) => {\n e.preventDefault();\n setOpen((v) => !v);\n }}\n >\n ▦\n </button>\n {open && (\n <div\n className=\"ed-table-popover\"\n role=\"menu\"\n onMouseDown={(e) => {\n // Do not let mousedown clear the editor selection.\n const t = e.target as HTMLElement | null;\n if (!t || (t.tagName !== \"INPUT\" && t.tagName !== \"BUTTON\")) {\n e.preventDefault();\n }\n }}\n >\n <TableSizePicker\n onPick={(rows, cols) => {\n setOpen(false);\n editor.insertTable(rows, cols);\n }}\n />\n {inTable && (\n <div className=\"ed-table-actions\">\n <hr />\n <button type=\"button\" onClick={() => { setOpen(false); editor.insertRowAbove(); }}>\n Inserir linha acima\n </button>\n <button type=\"button\" onClick={() => { setOpen(false); editor.insertRowBelow(); }}>\n Inserir linha abaixo\n </button>\n <button type=\"button\" onClick={() => { setOpen(false); editor.insertColumnLeft(); }}>\n Inserir coluna à esquerda\n </button>\n <button type=\"button\" onClick={() => { setOpen(false); editor.insertColumnRight(); }}>\n Inserir coluna à direita\n </button>\n <button type=\"button\" onClick={() => { setOpen(false); editor.deleteCurrentRow(); }}>\n Excluir linha\n </button>\n <button type=\"button\" onClick={() => { setOpen(false); editor.deleteCurrentColumn(); }}>\n Excluir coluna\n </button>\n <hr />\n {editor.hasTableRectSelection() && (\n <button\n type=\"button\"\n onClick={() => { setOpen(false); editor.mergeSelection(); }}\n >\n Mesclar células selecionadas\n </button>\n )}\n <button type=\"button\" onClick={() => { setOpen(false); editor.mergeRight(); }}>\n Mesclar com célula à direita\n </button>\n <button type=\"button\" onClick={() => { setOpen(false); editor.mergeDown(); }}>\n Mesclar com célula abaixo\n </button>\n <button type=\"button\" onClick={() => { setOpen(false); editor.splitCell(); }}>\n Dividir células mescladas\n </button>\n <button\n type=\"button\"\n className=\"ed-table-delete\"\n onClick={() => { setOpen(false); editor.deleteTable(); }}\n >\n Excluir tabela\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n\nconst PICKER_MAX_ROWS = 8;\nconst PICKER_MAX_COLS = 10;\n\ninterface TableSizePickerProps {\n onPick: (rows: number, cols: number) => void;\n}\n\nfunction TableSizePicker({ onPick }: TableSizePickerProps): JSX.Element {\n const [hover, setHover] = useState<{ r: number; c: number } | null>(null);\n const label = hover ? `${hover.r + 1} × ${hover.c + 1}` : \"Inserir tabela\";\n return (\n <div className=\"ed-table-picker\">\n <div className=\"ed-table-picker-label\">{label}</div>\n <div\n className=\"ed-table-picker-grid\"\n style={{\n gridTemplateColumns: `repeat(${PICKER_MAX_COLS}, 18px)`,\n gridTemplateRows: `repeat(${PICKER_MAX_ROWS}, 18px)`,\n }}\n onMouseLeave={() => setHover(null)}\n >\n {Array.from({ length: PICKER_MAX_ROWS }, (_, r) =>\n Array.from({ length: PICKER_MAX_COLS }, (_, c) => {\n const filled = hover != null && r <= hover.r && c <= hover.c;\n return (\n <button\n key={`${r}-${c}`}\n type=\"button\"\n className={`ed-table-picker-cell${filled ? \" filled\" : \"\"}`}\n onMouseEnter={() => setHover({ r, c })}\n onMouseDown={(e) => e.preventDefault()}\n onClick={(e) => {\n e.preventDefault();\n onPick(r + 1, c + 1);\n }}\n aria-label={`${r + 1} × ${c + 1}`}\n />\n );\n }),\n )}\n </div>\n </div>\n );\n}\n\nfunction blockSelectValue(\n type: BlockType | \"mixed\",\n level: unknown,\n): string {\n if (type === \"mixed\") return \"\";\n if (type === \"heading\") {\n if (typeof level === \"number\" && level >= 1 && level <= 6) return `h${level}`;\n return \"h1\";\n }\n return type;\n}\n\nfunction Group({ children }: { children: ReactNode }): JSX.Element {\n return <div className=\"ed-toolbar-group\">{children}</div>;\n}\n\ninterface MarkButtonProps {\n title: string;\n pressed: boolean;\n onClick: (e: MouseEvent) => void;\n children: ReactNode;\n}\n\nfunction MarkButton({ title, pressed, onClick, children }: MarkButtonProps): JSX.Element {\n return (\n <button\n type=\"button\"\n className=\"ed-toolbar-btn\"\n aria-pressed={pressed}\n title={title}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n"],"mappings":"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","names":["import_react","import_core","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_core","import_react","import_core","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","_","import_react","currentPage","import_react","import_react","import_core","yText","cmdToggleMark","cmdSetMark","cmdRemoveMark","cmdSetBlockType","cmdSetBlockAttr","cmdToggleList","cmdIndentList","cmdDedentList","cmdSplitListItem","cmdInsertTable","cmdDeleteTable","cmdInsertRow","cmdDeleteRow","cmdInsertColumn","cmdDeleteColumn","cmdMoveNextCell","cmdMovePrevCell","cmdMergeRight","cmdMergeDown","cmdSplitCell","cmdSetColumnWidth","cmdMergeSelection","cmdInsertImage","cmdSetImageAttrs","import_jsx_runtime","selectedEmbed","clampListLevel","import_react","import_jsx_runtime","selectedEmbed","_"]}
|