@notectl/core 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/chunks/{ToolbarPlugin-D5VqeBPT.mjs → ToolbarPlugin-sJTiZr-S.mjs} +2 -2
- package/dist/chunks/ToolbarPlugin-sJTiZr-S.mjs.map +1 -0
- package/dist/chunks/index-QvKiO9_4.mjs +538 -0
- package/dist/chunks/index-QvKiO9_4.mjs.map +1 -0
- package/dist/editor/EditorDOM.d.ts.map +1 -1
- package/dist/editor/NotectlEditor.d.ts +5 -1
- package/dist/editor/NotectlEditor.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/notectl-core.mjs +1846 -1712
- package/dist/notectl-core.mjs.map +1 -1
- package/dist/notectl-core.umd.js +1050 -966
- package/dist/notectl-core.umd.js.map +1 -1
- package/dist/plugins/PluginManager.d.ts +3 -1
- package/dist/plugins/PluginManager.d.ts.map +1 -1
- package/dist/plugins/code-block/CodeBlockCommands.d.ts +5 -0
- package/dist/plugins/code-block/CodeBlockCommands.d.ts.map +1 -0
- package/dist/plugins/code-block/CodeBlockKeyboardHandlers.d.ts +10 -0
- package/dist/plugins/code-block/CodeBlockKeyboardHandlers.d.ts.map +1 -0
- package/dist/plugins/code-block/CodeBlockNodeView.d.ts +1 -1
- package/dist/plugins/code-block/CodeBlockNodeView.d.ts.map +1 -1
- package/dist/plugins/code-block/CodeBlockPlugin.d.ts +3 -111
- package/dist/plugins/code-block/CodeBlockPlugin.d.ts.map +1 -1
- package/dist/plugins/code-block/CodeBlockService.d.ts +5 -0
- package/dist/plugins/code-block/CodeBlockService.d.ts.map +1 -0
- package/dist/plugins/code-block/CodeBlockTypes.d.ts +69 -0
- package/dist/plugins/code-block/CodeBlockTypes.d.ts.map +1 -0
- package/dist/plugins/code-block.mjs +1 -1
- package/dist/plugins/font-size/FontSizeOperations.d.ts +22 -0
- package/dist/plugins/font-size/FontSizeOperations.d.ts.map +1 -0
- package/dist/plugins/font-size/FontSizePlugin.d.ts +1 -10
- package/dist/plugins/font-size/FontSizePlugin.d.ts.map +1 -1
- package/dist/plugins/font-size/FontSizePopup.d.ts +9 -0
- package/dist/plugins/font-size/FontSizePopup.d.ts.map +1 -0
- package/dist/plugins/font-size.mjs +146 -162
- package/dist/plugins/font-size.mjs.map +1 -1
- package/dist/plugins/font.mjs +1 -1
- package/dist/plugins/heading.mjs +1 -1
- package/dist/plugins/image/ImageNodeView.d.ts.map +1 -1
- package/dist/plugins/image.mjs +1 -1
- package/dist/plugins/image.mjs.map +1 -1
- package/dist/plugins/print/PrintContentPreparer.d.ts +12 -0
- package/dist/plugins/print/PrintContentPreparer.d.ts.map +1 -0
- package/dist/plugins/print/PrintPlugin.d.ts +12 -0
- package/dist/plugins/print/PrintPlugin.d.ts.map +1 -0
- package/dist/plugins/print/PrintServiceImpl.d.ts +7 -0
- package/dist/plugins/print/PrintServiceImpl.d.ts.map +1 -0
- package/dist/plugins/print/PrintStyleCollector.d.ts +10 -0
- package/dist/plugins/print/PrintStyleCollector.d.ts.map +1 -0
- package/dist/plugins/print/PrintTypes.d.ts +56 -0
- package/dist/plugins/print/PrintTypes.d.ts.map +1 -0
- package/dist/plugins/table/TableControls.d.ts.map +1 -1
- package/dist/plugins/table/TableControlsDOM.d.ts.map +1 -1
- package/dist/plugins/table.mjs +13 -13
- package/dist/plugins/table.mjs.map +1 -1
- package/dist/plugins/toolbar/ToolbarPlugin.d.ts.map +1 -1
- package/dist/plugins/toolbar.mjs +1 -1
- package/dist/view/Reconciler.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunks/ToolbarPlugin-D5VqeBPT.mjs.map +0 -1
- package/dist/chunks/index-CPPb-Jah.mjs +0 -569
- package/dist/chunks/index-CPPb-Jah.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.mjs","sources":["../../src/plugins/table/TableHelpers.ts","../../src/plugins/table/TableCommands.ts","../../src/plugins/table/TableNavigation.ts","../../src/plugins/table/TableControlsDOM.ts","../../src/plugins/table/TableControlsLayout.ts","../../src/plugins/table/TableControls.ts","../../src/plugins/table/TableSelection.ts","../../src/plugins/table/TablePlugin.ts","../../src/editor/styles/table.ts","../../src/plugins/table/TableNodeViews.ts"],"sourcesContent":["/**\n * Utility functions for table operations: creating table structures,\n * finding table context, and navigating cells.\n */\n\nimport {\n\ttype BlockNode,\n\ttype ChildNode,\n\tcreateBlockNode,\n\tcreateTextNode,\n\tgenerateBlockId,\n\tgetBlockChildren,\n} from '../../model/Document.js';\nimport type { BlockId, NodeTypeName } from '../../model/TypeBrands.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\n\n/** Context information about a cell within a table. */\nexport interface TableContext {\n\treadonly tableId: BlockId;\n\treadonly tableIndex: number;\n\treadonly rowId: BlockId;\n\treadonly rowIndex: number;\n\treadonly cellId: BlockId;\n\treadonly colIndex: number;\n\treadonly totalRows: number;\n\treadonly totalCols: number;\n}\n\n/** Creates a table BlockNode structure with the given dimensions. */\nexport function createTable(rows: number, cols: number): BlockNode {\n\tconst tableId: BlockId = generateBlockId();\n\tconst rowNodes: ChildNode[] = [];\n\n\tfor (let r = 0; r < rows; r++) {\n\t\tconst cellNodes: ChildNode[] = [];\n\t\tfor (let c = 0; c < cols; c++) {\n\t\t\tcellNodes.push(createTableCell());\n\t\t}\n\t\trowNodes.push(\n\t\t\tcreateBlockNode(nodeType('table_row') as NodeTypeName, cellNodes, generateBlockId()),\n\t\t);\n\t}\n\n\treturn createBlockNode(nodeType('table') as NodeTypeName, rowNodes, tableId);\n}\n\n/** Creates a single table row with the given number of cells. */\nexport function createTableRow(cols: number): BlockNode {\n\tconst cellNodes: ChildNode[] = [];\n\tfor (let c = 0; c < cols; c++) {\n\t\tcellNodes.push(createTableCell());\n\t}\n\treturn createBlockNode(nodeType('table_row') as NodeTypeName, cellNodes, generateBlockId());\n}\n\n/** Creates a single empty table cell containing a paragraph. */\nexport function createTableCell(): BlockNode {\n\tconst paragraph: BlockNode = createBlockNode(\n\t\tnodeType('paragraph') as NodeTypeName,\n\t\t[createTextNode('')],\n\t\tgenerateBlockId(),\n\t);\n\treturn createBlockNode(nodeType('table_cell') as NodeTypeName, [paragraph], generateBlockId());\n}\n\n/**\n * Finds table context for a given block ID.\n * Returns null if the block is not inside a table.\n */\nexport function findTableContext(state: EditorState, blockId: BlockId): TableContext | null {\n\tconst path = state.getNodePath(blockId);\n\tif (!path) return null;\n\n\t// Collect table, row, and cell in a single pass\n\tlet tableId: BlockId | null = null;\n\tlet tableNode: BlockNode | null = null;\n\tlet rowId: BlockId | null = null;\n\tlet cellId: BlockId | null = null;\n\n\tfor (const id of path) {\n\t\tconst node = state.getBlock(id as BlockId);\n\t\tif (!node) continue;\n\t\tif (node.type === 'table') {\n\t\t\ttableId = id as BlockId;\n\t\t\ttableNode = node;\n\t\t} else if (node.type === 'table_row') {\n\t\t\trowId = id as BlockId;\n\t\t} else if (node.type === 'table_cell') {\n\t\t\tcellId = id as BlockId;\n\t\t}\n\t}\n\n\t// If the block itself is a cell\n\tconst block = state.getBlock(blockId);\n\tif (block?.type === 'table_cell') {\n\t\tcellId = blockId;\n\t}\n\n\tif (!tableId || !tableNode || !cellId || !rowId) return null;\n\n\t// Find table index in document\n\tconst tableIndex: number = state.doc.children.findIndex((b) => b.id === tableId);\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(tableNode);\n\tconst rowIndex: number = rows.findIndex((r) => r.id === rowId);\n\tif (rowIndex === -1) return null;\n\n\tconst rowNode: BlockNode | undefined = rows[rowIndex];\n\tif (!rowNode) return null;\n\tconst cells: readonly BlockNode[] = getBlockChildren(rowNode);\n\tconst colIndex: number = cells.findIndex((c) => c.id === cellId);\n\tif (colIndex === -1) return null;\n\n\tconst totalCols: number = cells.length;\n\tconst totalRows: number = rows.length;\n\n\treturn {\n\t\ttableId,\n\t\ttableIndex,\n\t\trowId,\n\t\trowIndex,\n\t\tcellId,\n\t\tcolIndex,\n\t\ttotalRows,\n\t\ttotalCols,\n\t};\n}\n\n/**\n * Gets the cell BlockId at the given row and column indices.\n * Returns null if out of bounds.\n */\nexport function getCellAt(\n\tstate: EditorState,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): BlockId | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tconst row: BlockNode | undefined = rows[rowIndex];\n\tif (!row) return null;\n\n\tconst cells: readonly BlockNode[] = getBlockChildren(row);\n\tconst cell: BlockNode | undefined = cells[colIndex];\n\treturn cell?.id ?? null;\n}\n\n/** Returns all cell IDs in a table in row-major order. */\nexport function getAllCellIds(state: EditorState, tableId: BlockId): readonly BlockId[] {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return [];\n\n\tconst result: BlockId[] = [];\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tfor (const row of rows) {\n\t\tconst cells: readonly BlockNode[] = getBlockChildren(row);\n\t\tfor (const cell of cells) {\n\t\t\tresult.push(cell.id);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** Returns the first leaf-block ID inside a table cell (e.g. the paragraph). */\nexport function getFirstLeafInCell(state: EditorState, cellId: BlockId): BlockId {\n\tconst cell: BlockNode | undefined = state.getBlock(cellId);\n\tif (!cell) return cellId;\n\tconst blockChildren: readonly BlockNode[] = getBlockChildren(cell);\n\tconst first: BlockNode | undefined = blockChildren[0];\n\tif (!first) return cellId;\n\tlet current: BlockNode = first;\n\twhile (true) {\n\t\tconst children: readonly BlockNode[] = getBlockChildren(current);\n\t\tconst next: BlockNode | undefined = children[0];\n\t\tif (!next) return current.id;\n\t\tcurrent = next;\n\t}\n}\n\n/** Returns the last leaf-block ID inside a table cell. */\nexport function getLastLeafInCell(state: EditorState, cellId: BlockId): BlockId {\n\tconst cell: BlockNode | undefined = state.getBlock(cellId);\n\tif (!cell) return cellId;\n\tconst blockChildren: readonly BlockNode[] = getBlockChildren(cell);\n\tconst last: BlockNode | undefined = blockChildren[blockChildren.length - 1];\n\tif (!last) return cellId;\n\tlet current: BlockNode = last;\n\twhile (true) {\n\t\tconst children: readonly BlockNode[] = getBlockChildren(current);\n\t\tconst next: BlockNode | undefined = children[children.length - 1];\n\t\tif (!next) return current.id;\n\t\tcurrent = next;\n\t}\n}\n\n/** Checks whether a block is inside a table. */\nexport function isInsideTable(state: EditorState, blockId: BlockId): boolean {\n\tconst path = state.getNodePath(blockId);\n\tif (!path) return false;\n\n\tfor (const id of path) {\n\t\tconst node = state.getBlock(id as BlockId);\n\t\tif (node?.type === 'table') return true;\n\t}\n\treturn false;\n}\n","/**\n * Table commands: insert table, add/remove rows and columns, delete table.\n * All commands are registered via PluginContext and operate through transactions.\n *\n * Shared transaction builders (`build*Transaction`) are pure functions that take\n * EditorState + explicit indices and return a Transaction or null. They are used\n * by both commands (via PluginContext) and controls (via getState/dispatch).\n */\n\nimport { createBlockNode, getBlockChildren } from '../../model/Document.js';\nimport {\n\tcreateCollapsedSelection,\n\tcreateNodeSelection,\n\tisNodeSelection,\n} from '../../model/Selection.js';\nimport type { BlockId, NodeTypeName } from '../../model/TypeBrands.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { PluginContext } from '../Plugin.js';\nimport {\n\ttype TableContext,\n\tcreateTable,\n\tcreateTableCell,\n\tcreateTableRow,\n\tfindTableContext,\n\tgetCellAt,\n\tgetFirstLeafInCell,\n} from './TableHelpers.js';\n\n// --- Shared Transaction Builders ---\n\n/** Builds a transaction that inserts a new row at the given index. */\nexport function buildInsertRowTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n\trowIndex: number,\n): Transaction | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows = getBlockChildren(table);\n\tconst numCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\tif (numCols === 0) return null;\n\n\tconst newRow = createTableRow(numCols);\n\tconst tr = state.transaction('command').insertNode([tableId], rowIndex, newRow);\n\n\tconst firstCell = getBlockChildren(newRow)[0];\n\tconst firstLeaf = firstCell ? getBlockChildren(firstCell)[0] : undefined;\n\tif (firstLeaf) {\n\t\ttr.setSelection(createCollapsedSelection(firstLeaf.id, 0));\n\t} else if (firstCell) {\n\t\ttr.setSelection(createCollapsedSelection(firstCell.id, 0));\n\t}\n\n\treturn tr.build();\n}\n\n/** Builds a transaction that inserts a new column at the given index. */\nexport function buildInsertColumnTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n\tcolIndex: number,\n): Transaction | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows = getBlockChildren(table);\n\tconst tr = state.transaction('command');\n\n\tfor (const row of rows) {\n\t\tconst newCell = createTableCell();\n\t\ttr.insertNode([tableId, row.id], colIndex, newCell);\n\t}\n\n\ttr.setSelection(state.selection);\n\treturn tr.build();\n}\n\n/**\n * Builds a transaction that deletes the row at the given index.\n * If it's the last row, delegates to `createDeleteTableTransaction`.\n * @param preferredCol Column index to place the cursor in after deletion (default 0).\n */\nexport function buildDeleteRowTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n\trowIndex: number,\n\tpreferredCol = 0,\n): Transaction | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows = getBlockChildren(table);\n\tif (rows.length <= 1) {\n\t\treturn createDeleteTableTransaction(state, tableId);\n\t}\n\n\tconst tr = state.transaction('command').removeNode([tableId], rowIndex);\n\n\tconst targetRow: number = rowIndex > 0 ? rowIndex - 1 : 1;\n\tconst cellId: BlockId | null = getCellAt(state, tableId, targetRow, preferredCol);\n\tif (cellId) {\n\t\tconst leafId: BlockId = getFirstLeafInCell(state, cellId);\n\t\ttr.setSelection(createCollapsedSelection(leafId, 0));\n\t}\n\n\treturn tr.build();\n}\n\n/**\n * Builds a transaction that deletes the column at the given index.\n * If it's the last column, delegates to `createDeleteTableTransaction`.\n * @param preferredRow Row index to place the cursor in after deletion (default 0).\n */\nexport function buildDeleteColumnTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n\tcolIndex: number,\n\tpreferredRow = 0,\n): Transaction | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows = getBlockChildren(table);\n\tconst numCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\n\tif (numCols <= 1) {\n\t\treturn createDeleteTableTransaction(state, tableId);\n\t}\n\n\tconst tr = state.transaction('command');\n\n\tfor (let r: number = rows.length - 1; r >= 0; r--) {\n\t\tconst row = rows[r];\n\t\tif (!row) continue;\n\t\ttr.removeNode([tableId, row.id], colIndex);\n\t}\n\n\tconst targetCol: number = colIndex > 0 ? colIndex - 1 : 1;\n\tconst cellId: BlockId | null = getCellAt(state, tableId, preferredRow, targetCol);\n\tif (cellId) {\n\t\tconst leafId: BlockId = getFirstLeafInCell(state, cellId);\n\t\ttr.setSelection(createCollapsedSelection(leafId, 0));\n\t}\n\n\treturn tr.build();\n}\n\n/**\n * Creates a transaction that removes the given root-level table node.\n * Cursor placement prefers the next root block, then previous.\n */\nexport function createDeleteTableTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n): Transaction | null {\n\tconst tableIndex: number = state.doc.children.findIndex((block) => block.id === tableId);\n\tif (tableIndex === -1) return null;\n\n\tconst tr = state.transaction('command').removeNode([], tableIndex);\n\n\tconst nextRoot = state.doc.children[tableIndex + 1];\n\tif (nextRoot) {\n\t\ttr.setSelection(createCollapsedSelection(nextRoot.id, 0));\n\t\treturn tr.build();\n\t}\n\n\tconst prevRoot = state.doc.children[tableIndex - 1];\n\tif (prevRoot) {\n\t\ttr.setSelection(createCollapsedSelection(prevRoot.id, 0));\n\t}\n\n\treturn tr.build();\n}\n\n// --- Commands ---\n\ninterface TableDeletionTarget {\n\treadonly tableId: BlockId;\n}\n\n/**\n * Inserts a table with the given dimensions at the current cursor position.\n * Adds a paragraph after the table for cursor escape.\n * Moves cursor into the first cell.\n */\nexport function insertTable(context: PluginContext, rows: number, cols: number): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\tif (isNodeSelection(sel)) return false;\n\n\tconst currentBlockId: BlockId = sel.anchor.blockId;\n\n\t// Find which root-level block contains the current selection\n\tlet rootIndex = -1;\n\tfor (let i = 0; i < state.doc.children.length; i++) {\n\t\tconst rootBlock = state.doc.children[i];\n\t\tif (!rootBlock) continue;\n\t\tif (rootBlock.id === currentBlockId) {\n\t\t\trootIndex = i;\n\t\t\tbreak;\n\t\t}\n\t\t// Check if current block is nested inside this root block\n\t\tconst path = state.getNodePath(currentBlockId);\n\t\tif (path && path[0] === rootBlock.id) {\n\t\t\trootIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (rootIndex === -1) rootIndex = state.doc.children.length - 1;\n\n\tconst tableNode = createTable(rows, cols);\n\tconst paragraphAfter = createBlockNode(nodeType('paragraph') as NodeTypeName);\n\n\t// Insert table after current block, then paragraph after table\n\tconst insertIndex: number = rootIndex + 1;\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.insertNode([], insertIndex, tableNode)\n\t\t.insertNode([], insertIndex + 1, paragraphAfter);\n\n\t// Set cursor in first paragraph inside first cell\n\tconst firstRow = getBlockChildren(tableNode)[0];\n\tconst firstCell = firstRow ? getBlockChildren(firstRow)[0] : undefined;\n\tconst firstParagraph = firstCell ? getBlockChildren(firstCell)[0] : undefined;\n\n\tif (firstParagraph) {\n\t\ttr.setSelection(createCollapsedSelection(firstParagraph.id, 0));\n\t} else if (firstCell) {\n\t\ttr.setSelection(createCollapsedSelection(firstCell.id, 0));\n\t}\n\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/** Adds a row above the current row. */\nexport function addRowAbove(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = buildInsertRowTransaction(state, tableCtx.tableId, tableCtx.rowIndex);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Adds a row below the current row. */\nexport function addRowBelow(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = buildInsertRowTransaction(state, tableCtx.tableId, tableCtx.rowIndex + 1);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Adds a column to the left of the current column. */\nexport function addColumnLeft(context: PluginContext): boolean {\n\treturn addColumn(context, 'left');\n}\n\n/** Adds a column to the right of the current column. */\nexport function addColumnRight(context: PluginContext): boolean {\n\treturn addColumn(context, 'right');\n}\n\nfunction addColumn(context: PluginContext, side: 'left' | 'right'): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst insertColIndex: number = side === 'left' ? tableCtx.colIndex : tableCtx.colIndex + 1;\n\tconst tr = buildInsertColumnTransaction(state, tableCtx.tableId, insertColIndex);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Deletes the current row. If it's the last row, deletes the entire table. */\nexport function deleteRow(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = buildDeleteRowTransaction(\n\t\tstate,\n\t\ttableCtx.tableId,\n\t\ttableCtx.rowIndex,\n\t\ttableCtx.colIndex,\n\t);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Deletes the current column. If it's the last column, deletes the entire table. */\nexport function deleteColumn(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = buildDeleteColumnTransaction(\n\t\tstate,\n\t\ttableCtx.tableId,\n\t\ttableCtx.colIndex,\n\t\ttableCtx.rowIndex,\n\t);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Deletes the entire table and moves cursor to surrounding block. */\nexport function deleteTable(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst target = resolveTableDeletionTarget(state);\n\tif (!target) return false;\n\n\tconst tr = createDeleteTableTransaction(state, target.tableId);\n\tif (!tr) return false;\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Selects the surrounding table as a node object. */\nexport function selectTable(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\n\tif (isNodeSelection(sel)) {\n\t\tconst selectedNode = state.getBlock(sel.nodeId);\n\t\treturn selectedNode?.type === 'table';\n\t}\n\n\tconst tableCtx: TableContext | null = findTableContext(state, sel.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst path = state.getNodePath(tableCtx.tableId);\n\tif (!path) return false;\n\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.setSelection(createNodeSelection(tableCtx.tableId, path))\n\t\t.build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Registers all table commands on the given plugin context. */\nexport function registerTableCommands(context: PluginContext): void {\n\tcontext.registerCommand('insertTable', () => insertTable(context, 3, 3));\n\tcontext.registerCommand('addRowAbove', () => addRowAbove(context));\n\tcontext.registerCommand('addRowBelow', () => addRowBelow(context));\n\tcontext.registerCommand('addColumnLeft', () => addColumnLeft(context));\n\tcontext.registerCommand('addColumnRight', () => addColumnRight(context));\n\tcontext.registerCommand('deleteRow', () => deleteRow(context));\n\tcontext.registerCommand('deleteColumn', () => deleteColumn(context));\n\tcontext.registerCommand('selectTable', () => selectTable(context));\n\tcontext.registerCommand('deleteTable', () => deleteTable(context));\n}\n\nfunction resolveTableDeletionTarget(\n\tstate: ReturnType<PluginContext['getState']>,\n): TableDeletionTarget | null {\n\tif (isNodeSelection(state.selection)) {\n\t\tconst selectedNode = state.getBlock(state.selection.nodeId);\n\t\tif (selectedNode?.type !== 'table') return null;\n\t\treturn { tableId: selectedNode.id };\n\t}\n\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return null;\n\n\treturn { tableId: tableCtx.tableId };\n}\n","/**\n * Keyboard navigation handlers for table cells.\n * Handles Tab, Shift-Tab, arrow keys, Enter, Backspace, Delete, and Escape.\n */\n\nimport type { Keymap } from '../../input/Keymap.js';\nimport { getBlockLength } from '../../model/Document.js';\nimport {\n\ttype Selection,\n\tcreateCollapsedSelection,\n\tcreateNodeSelection,\n\tisCollapsed,\n\tisNodeSelection,\n} from '../../model/Selection.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { addRowBelow } from './TableCommands.js';\nimport {\n\ttype TableContext,\n\tfindTableContext,\n\tgetCellAt,\n\tgetFirstLeafInCell,\n\tgetLastLeafInCell,\n} from './TableHelpers.js';\n\n/** Registers all table navigation keymaps. */\nexport function registerTableKeymaps(context: PluginContext): void {\n\tconst keymap: Keymap = {\n\t\tTab: () => handleTab(context),\n\t\t'Shift-Tab': () => handleShiftTab(context),\n\t\tEnter: () => handleEnter(context),\n\t\tBackspace: () => handleBackspace(context),\n\t\tDelete: () => handleDelete(context),\n\t\tArrowDown: () => handleArrowDown(context),\n\t\tArrowUp: () => handleArrowUp(context),\n\t\tArrowRight: () => handleArrowRight(context),\n\t\tArrowLeft: () => handleArrowLeft(context),\n\t\tEscape: () => handleEscape(context),\n\t};\n\n\tcontext.registerKeymap(keymap);\n}\n\n/**\n * Guards against NodeSelection and resolves TableContext.\n * Passes the narrowed text Selection to the handler, avoiding re-narrowing.\n * Returns false (not handled) if the cursor is not inside a table.\n */\nfunction withTableContext(\n\tcontext: PluginContext,\n\thandler: (state: EditorState, sel: Selection, tableCtx: TableContext) => boolean,\n): boolean {\n\tconst state: EditorState = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst sel: Selection = state.selection;\n\tconst tableCtx: TableContext | null = findTableContext(state, sel.anchor.blockId);\n\tif (!tableCtx) return false;\n\treturn handler(state, sel, tableCtx);\n}\n\n/** Tab: move to next cell. At end of table, add a new row. */\nfunction handleTab(context: PluginContext): boolean {\n\treturn withTableContext(context, (_state, _sel, tableCtx) => {\n\t\tif (tableCtx.colIndex < tableCtx.totalCols - 1) {\n\t\t\treturn moveToCellAndSelect(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex,\n\t\t\t\ttableCtx.colIndex + 1,\n\t\t\t);\n\t\t}\n\n\t\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, 0);\n\t\t}\n\n\t\taddRowBelow(context);\n\t\treturn true;\n\t});\n}\n\n/** Shift-Tab: move to previous cell. At start of table, stay put. */\nfunction handleShiftTab(context: PluginContext): boolean {\n\treturn withTableContext(context, (_state, _sel, tableCtx) => {\n\t\tif (tableCtx.colIndex > 0) {\n\t\t\treturn moveToCellAndSelect(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex,\n\t\t\t\ttableCtx.colIndex - 1,\n\t\t\t);\n\t\t}\n\n\t\tif (tableCtx.rowIndex > 0) {\n\t\t\treturn moveToCellAndSelect(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex - 1,\n\t\t\t\ttableCtx.totalCols - 1,\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t});\n}\n\n/** Enter: move to same column in next row (spreadsheet behavior). */\nfunction handleEnter(context: PluginContext): boolean {\n\tconst state: EditorState = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\n\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t// Only intercept Enter for paragraphs inside table cells.\n\t// Other block types (list_item, heading, etc.) are handled by their plugins.\n\tif (block && block.type !== 'paragraph') return false;\n\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, tableCtx.colIndex);\n\t}\n\n\t// On last row — block to prevent splitBlock\n\treturn true;\n}\n\n/** Backspace at deletion-boundary: select table node (first step of 2-step delete). */\nfunction handleBackspace(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tif (!isCollapsed(sel)) return false;\n\t\tif (sel.anchor.offset !== 0) return false;\n\n\t\tconst isAtDeletionBoundary: boolean = tableCtx.rowIndex === 0 && tableCtx.colIndex === 0;\n\t\tif (!isAtDeletionBoundary) return false;\n\n\t\tconst firstLeaf: BlockId = getFirstLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== firstLeaf) return false;\n\n\t\treturn selectTableNode(context, tableCtx.tableId);\n\t});\n}\n\n/** Delete at deletion-boundary: select table node (first step of 2-step delete). */\nfunction handleDelete(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tif (!isCollapsed(sel)) return false;\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tconst blockLen: number = getBlockLength(block);\n\t\tif (sel.anchor.offset !== blockLen) return false;\n\n\t\tconst isAtDeletionBoundary: boolean =\n\t\t\ttableCtx.rowIndex === tableCtx.totalRows - 1 && tableCtx.colIndex === tableCtx.totalCols - 1;\n\t\tif (!isAtDeletionBoundary) return false;\n\n\t\tconst lastLeaf: BlockId = getLastLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== lastLeaf) return false;\n\n\t\treturn selectTableNode(context, tableCtx.tableId);\n\t});\n}\n\n/** ArrowDown: move to same column in next row. */\nfunction handleArrowDown(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tconst lastLeaf: BlockId = getLastLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== lastLeaf) return false;\n\n\t\tif (tableCtx.rowIndex >= tableCtx.totalRows - 1) {\n\t\t\treturn handleEscape(context);\n\t\t}\n\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, tableCtx.colIndex);\n\t});\n}\n\n/** ArrowUp: move to same column in previous row. */\nfunction handleArrowUp(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tconst firstLeaf: BlockId = getFirstLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== firstLeaf) return false;\n\n\t\tif (tableCtx.rowIndex <= 0) return false;\n\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex - 1, tableCtx.colIndex);\n\t});\n}\n\n/** ArrowRight at cell end: move to next cell. */\nfunction handleArrowRight(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tif (!isCollapsed(sel)) return false;\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tconst blockLen: number = getBlockLength(block);\n\t\tif (sel.anchor.offset !== blockLen) return false;\n\n\t\tconst lastLeaf: BlockId = getLastLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== lastLeaf) return false;\n\n\t\tif (tableCtx.colIndex < tableCtx.totalCols - 1) {\n\t\t\treturn moveToCellAndSelect(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex,\n\t\t\t\ttableCtx.colIndex + 1,\n\t\t\t);\n\t\t}\n\n\t\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, 0);\n\t\t}\n\n\t\treturn true;\n\t});\n}\n\n/** ArrowLeft at cell start: move to previous cell. */\nfunction handleArrowLeft(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tif (!isCollapsed(sel)) return false;\n\t\tif (sel.anchor.offset !== 0) return false;\n\n\t\tconst firstLeaf: BlockId = getFirstLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== firstLeaf) return false;\n\n\t\tif (tableCtx.colIndex > 0) {\n\t\t\treturn moveToCellAtEnd(context, tableCtx.tableId, tableCtx.rowIndex, tableCtx.colIndex - 1);\n\t\t}\n\n\t\tif (tableCtx.rowIndex > 0) {\n\t\t\treturn moveToCellAtEnd(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex - 1,\n\t\t\t\ttableCtx.totalCols - 1,\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t});\n}\n\n/** Escape: move cursor to the paragraph after the table. */\nfunction handleEscape(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, _sel, tableCtx) => {\n\t\tconst nextIndex: number = tableCtx.tableIndex + 1;\n\t\tif (nextIndex >= state.doc.children.length) return false;\n\n\t\tconst nextBlock = state.doc.children[nextIndex];\n\t\tif (!nextBlock) return false;\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setSelection(createCollapsedSelection(nextBlock.id, 0))\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t});\n}\n\n// --- Cell navigation helpers ---\n\n/** Moves cursor to the start of a cell (first leaf block inside). */\nfunction moveToCellAndSelect(\n\tcontext: PluginContext,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): boolean {\n\tconst state: EditorState = context.getState();\n\tconst cellId: BlockId | null = getCellAt(state, tableId, rowIndex, colIndex);\n\tif (!cellId) return false;\n\n\tconst leafId: BlockId = getFirstLeafInCell(state, cellId);\n\tconst tr = state.transaction('command').setSelection(createCollapsedSelection(leafId, 0)).build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Moves cursor to the end of a cell (last leaf block inside, for ArrowLeft). */\nfunction moveToCellAtEnd(\n\tcontext: PluginContext,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): boolean {\n\tconst state: EditorState = context.getState();\n\tconst cellId: BlockId | null = getCellAt(state, tableId, rowIndex, colIndex);\n\tif (!cellId) return false;\n\n\tconst leafId: BlockId = getLastLeafInCell(state, cellId);\n\tconst leaf = state.getBlock(leafId);\n\tif (!leaf) return false;\n\n\tconst leafLen: number = getBlockLength(leaf);\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.setSelection(createCollapsedSelection(leafId, leafLen))\n\t\t.build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Switches current selection to a table NodeSelection. */\nfunction selectTableNode(context: PluginContext, tableId: BlockId): boolean {\n\tconst state: EditorState = context.getState();\n\tconst path = state.getNodePath(tableId);\n\tif (!path) return false;\n\n\tconst tr = state.transaction('input').setSelection(createNodeSelection(tableId, path)).build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n","/**\n * Pure DOM factory functions for table controls.\n * No state logic — only element creation and CSS class assignment.\n */\n\n// --- SVG Icons ---\n\nexport const PLUS_SVG: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" ' +\n\t'viewBox=\"0 0 12 12\" fill=\"none\">' +\n\t'<path d=\"M6 1v10M1 6h10\" stroke=\"currentColor\" ' +\n\t'stroke-width=\"1.8\" stroke-linecap=\"round\"/></svg>';\n\nexport const DELETE_SVG: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" ' +\n\t'viewBox=\"0 0 10 10\" fill=\"none\">' +\n\t'<path d=\"M2 2l6 6M8 2l-6 6\" stroke=\"currentColor\" ' +\n\t'stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>';\n\nexport const TABLE_DELETE_SVG: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" ' +\n\t'viewBox=\"0 0 24 24\" fill=\"none\">' +\n\t'<path d=\"M9 3h6m-9 4h12M10 11v6m4-6v6m-9 3h14l-1-13H6L5 20z\" ' +\n\t'stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" ' +\n\t'stroke-linejoin=\"round\"/></svg>';\n\n// --- DOM Factories ---\n\n/** Creates a button with standard table-control setup (mousedown prevention, ARIA). */\nexport function createButton(\n\tclassName: string,\n\tinnerHTML: string,\n\ttitle: string,\n): HTMLButtonElement {\n\tconst btn: HTMLButtonElement = document.createElement('button');\n\tbtn.className = className;\n\tbtn.innerHTML = innerHTML;\n\tbtn.title = title;\n\tbtn.type = 'button';\n\tbtn.setAttribute('aria-label', title);\n\tbtn.setAttribute('contenteditable', 'false');\n\tbtn.addEventListener('mousedown', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t});\n\treturn btn;\n}\n\n/** Builds the insert-line element (horizontal or vertical) with a plus-icon button. */\nexport function buildInsertLine(orientation: 'horizontal' | 'vertical'): HTMLDivElement {\n\tconst line: HTMLDivElement = document.createElement('div');\n\tline.className = `ntbl-insert-line ntbl-insert-line--${orientation}`;\n\tline.setAttribute('contenteditable', 'false');\n\n\tconst title: string = orientation === 'horizontal' ? 'Insert row' : 'Insert column';\n\tconst btn: HTMLButtonElement = createButton('ntbl-insert-btn', PLUS_SVG, title);\n\tline.appendChild(btn);\n\n\treturn line;\n}\n\n/** Builds a zone-button for adding rows or columns at the table edge. */\nexport function buildAddButton(className: string, title: string): HTMLButtonElement {\n\tconst btn: HTMLButtonElement = document.createElement('button');\n\tbtn.className = `ntbl-add-zone ${className}`;\n\tbtn.type = 'button';\n\tbtn.setAttribute('contenteditable', 'false');\n\tbtn.setAttribute('aria-label', title);\n\tbtn.title = title;\n\n\tconst icon: HTMLSpanElement = document.createElement('span');\n\ticon.className = 'ntbl-add-icon';\n\ticon.innerHTML = PLUS_SVG;\n\tbtn.appendChild(icon);\n\n\tbtn.addEventListener('mousedown', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t});\n\n\treturn btn;\n}\n\n/** Builds a handle-bar container (for column or row handles). */\nexport function buildHandleBar(className: string): HTMLDivElement {\n\tconst bar: HTMLDivElement = document.createElement('div');\n\tbar.className = className;\n\tbar.setAttribute('contenteditable', 'false');\n\treturn bar;\n}\n\n/** Builds a single column or row handle with a delete button. */\nexport function buildHandle(\n\tclassName: string,\n\tindex: number,\n\tdeleteLabel: string,\n\tonDelete: (idx: number) => void,\n): HTMLDivElement {\n\tconst handle: HTMLDivElement = document.createElement('div');\n\thandle.className = `ntbl-handle ${className}`;\n\thandle.dataset.index = String(index);\n\n\tconst deleteBtn: HTMLButtonElement = createButton('ntbl-handle-delete', DELETE_SVG, deleteLabel);\n\tdeleteBtn.addEventListener('click', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tonDelete(index);\n\t});\n\thandle.appendChild(deleteBtn);\n\n\treturn handle;\n}\n","/**\n * Measurement and positioning logic for table controls.\n * All functions are pure (take numeric/DOM inputs, return structured results).\n */\n\n// --- Types ---\n\nexport interface BorderInfo {\n\treadonly position: number;\n\treadonly index: number;\n}\n\nexport interface NearestBorderResult {\n\treadonly type: 'row' | 'col' | 'none';\n\treadonly border: BorderInfo | null;\n}\n\n// --- Constants ---\n\nexport const BORDER_THRESHOLD: number = 10;\n\n// --- Offset ---\n\n/** Returns the table's offset relative to the container (walks offsetParent chain). */\nexport function getTableOffset(\n\ttableEl: HTMLElement,\n\tcontainer: HTMLElement,\n): { top: number; left: number } {\n\tlet top = 0;\n\tlet left = 0;\n\tlet el: HTMLElement | null = tableEl;\n\twhile (el && el !== container) {\n\t\ttop += el.offsetTop;\n\t\tleft += el.offsetLeft;\n\t\tel = el.offsetParent as HTMLElement | null;\n\t}\n\treturn { top, left };\n}\n\n// --- Border Measurement ---\n\n/** Measures the Y-positions of inter-row borders (between adjacent <tr> elements). */\nexport function measureRowBorders(tableEl: HTMLTableElement): BorderInfo[] {\n\tconst trs: NodeListOf<HTMLTableRowElement> = tableEl.querySelectorAll(':scope > tbody > tr');\n\tconst tableTop: number = tableEl.offsetTop;\n\tconst borders: BorderInfo[] = [];\n\n\tfor (let i = 1; i < trs.length; i++) {\n\t\tconst tr: HTMLTableRowElement | undefined = trs[i];\n\t\tif (!tr) continue;\n\t\tborders.push({\n\t\t\tposition: tr.offsetTop - tableTop,\n\t\t\tindex: i,\n\t\t});\n\t}\n\n\treturn borders;\n}\n\n/** Measures the X-positions of inter-column borders (evenly spaced). */\nexport function measureColBorders(tableWidth: number, numCols: number): BorderInfo[] {\n\tif (numCols <= 1) return [];\n\n\tconst colWidth: number = tableWidth / numCols;\n\tconst borders: BorderInfo[] = [];\n\n\tfor (let i = 1; i < numCols; i++) {\n\t\tborders.push({\n\t\t\tposition: Math.round(colWidth * i),\n\t\t\tindex: i,\n\t\t});\n\t}\n\n\treturn borders;\n}\n\n// --- Positioning ---\n\n/** Positions column handles evenly across the table width. */\nexport function positionColHandles(\n\tcolBar: HTMLDivElement,\n\ttableWidth: number,\n\tnumCols: number,\n): void {\n\tconst handles: HTMLCollection = colBar.children;\n\tif (handles.length === 0) return;\n\n\tconst colWidth: number = tableWidth / numCols;\n\n\tfor (let i = 0; i < handles.length; i++) {\n\t\tconst h = handles[i] as HTMLElement;\n\t\th.style.left = `${Math.round(colWidth * i)}px`;\n\t\th.style.width = `${Math.round(colWidth)}px`;\n\t}\n\n\tcolBar.style.width = `${tableWidth}px`;\n}\n\n/** Positions row handles to match actual <tr> offsets and heights. */\nexport function positionRowHandles(rowBar: HTMLDivElement, tableEl: HTMLTableElement): void {\n\tconst handles: HTMLCollection = rowBar.children;\n\tif (handles.length === 0) return;\n\n\tconst trs: NodeListOf<HTMLTableRowElement> = tableEl.querySelectorAll(':scope > tbody > tr');\n\tconst tableTop: number = tableEl.offsetTop;\n\tlet totalHeight = 0;\n\n\tfor (let i = 0; i < handles.length; i++) {\n\t\tconst h = handles[i] as HTMLElement;\n\t\tconst tr: HTMLTableRowElement | undefined = trs[i];\n\t\tif (tr) {\n\t\t\tconst top: number = tr.offsetTop - tableTop;\n\t\t\tconst height: number = tr.offsetHeight;\n\t\t\th.style.top = `${top}px`;\n\t\t\th.style.height = `${height}px`;\n\t\t\ttotalHeight = top + height;\n\t\t}\n\t}\n\n\trowBar.style.height = `${totalHeight}px`;\n}\n\n/** Positions add-row and add-column buttons at the table edges. */\nexport function positionAddButtons(\n\taddRowZone: HTMLElement,\n\taddColZone: HTMLElement,\n\ttableEl: HTMLElement,\n\tcontainer: HTMLElement,\n): void {\n\tconst offset = getTableOffset(tableEl, container);\n\tconst tableHeight: number = tableEl.offsetHeight;\n\tconst tableWidth: number = tableEl.offsetWidth;\n\n\taddRowZone.style.width = `${tableWidth}px`;\n\taddRowZone.style.left = `${offset.left}px`;\n\n\taddColZone.style.height = `${tableHeight}px`;\n\taddColZone.style.top = `${offset.top}px`;\n}\n\n// --- Border Detection ---\n\n/**\n * Finds the nearest row or column border to the given mouse position.\n * Returns which border is closest (within threshold), preferring the nearer one.\n */\nexport function findNearestBorder(\n\tx: number,\n\ty: number,\n\trowBorders: readonly BorderInfo[],\n\tcolBorders: readonly BorderInfo[],\n): NearestBorderResult {\n\tlet nearestRowDist: number = Number.POSITIVE_INFINITY;\n\tlet nearestRowBorder: BorderInfo | null = null;\n\n\tfor (const border of rowBorders) {\n\t\tconst dist: number = Math.abs(y - border.position);\n\t\tif (dist < nearestRowDist && dist < BORDER_THRESHOLD) {\n\t\t\tnearestRowDist = dist;\n\t\t\tnearestRowBorder = border;\n\t\t}\n\t}\n\n\tlet nearestColDist: number = Number.POSITIVE_INFINITY;\n\tlet nearestColBorder: BorderInfo | null = null;\n\n\tfor (const border of colBorders) {\n\t\tconst dist: number = Math.abs(x - border.position);\n\t\tif (dist < nearestColDist && dist < BORDER_THRESHOLD) {\n\t\t\tnearestColDist = dist;\n\t\t\tnearestColBorder = border;\n\t\t}\n\t}\n\n\tif (nearestRowBorder && (!nearestColBorder || nearestRowDist <= nearestColDist)) {\n\t\treturn { type: 'row', border: nearestRowBorder };\n\t}\n\n\tif (nearestColBorder) {\n\t\treturn { type: 'col', border: nearestColBorder };\n\t}\n\n\treturn { type: 'none', border: null };\n}\n","/**\n * Interactive table controls orchestrator.\n * Wires DOM elements (from TableControlsDOM) with layout logic (from TableControlsLayout)\n * and shared transaction builders (from TableCommands) to produce the interactive overlay.\n */\n\nimport type { BlockNode } from '../../model/Document.js';\nimport { getBlockChildren } from '../../model/Document.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport {\n\tbuildDeleteColumnTransaction,\n\tbuildDeleteRowTransaction,\n\tbuildInsertColumnTransaction,\n\tbuildInsertRowTransaction,\n\tcreateDeleteTableTransaction,\n} from './TableCommands.js';\nimport {\n\tTABLE_DELETE_SVG,\n\tbuildAddButton,\n\tbuildHandle,\n\tbuildHandleBar,\n\tbuildInsertLine,\n\tcreateButton,\n} from './TableControlsDOM.js';\nimport {\n\tBORDER_THRESHOLD,\n\ttype BorderInfo,\n\tfindNearestBorder,\n\tgetTableOffset,\n\tmeasureColBorders,\n\tmeasureRowBorders,\n\tpositionAddButtons,\n\tpositionColHandles,\n\tpositionRowHandles,\n} from './TableControlsLayout.js';\n\n// --- Types ---\n\nexport interface TableControlsHandle {\n\tupdate(node: BlockNode): void;\n\tdestroy(): void;\n}\n\n// --- Class ---\n\nclass TableControls implements TableControlsHandle {\n\tprivate tableId: BlockId;\n\tprivate numRows: number;\n\tprivate numCols: number;\n\tprivate activeRowIndex = -1;\n\tprivate activeColIndex = -1;\n\n\tprivate readonly colBar: HTMLDivElement;\n\tprivate readonly rowBar: HTMLDivElement;\n\tprivate readonly insertLineH: HTMLDivElement;\n\tprivate readonly insertLineV: HTMLDivElement;\n\tprivate readonly addRowZone: HTMLButtonElement;\n\tprivate readonly addColZone: HTMLButtonElement;\n\tprivate readonly deleteTableBtn: HTMLButtonElement;\n\tprivate readonly observer: ResizeObserver;\n\n\tprivate readonly container: HTMLElement;\n\tprivate readonly tableEl: HTMLTableElement;\n\tprivate readonly getState: () => EditorState;\n\tprivate readonly dispatchFn: (tr: Transaction) => void;\n\n\tprivate readonly onMouseMove = (e: MouseEvent): void => {\n\t\tconst tableRect: DOMRect = this.tableEl.getBoundingClientRect();\n\t\tconst x: number = e.clientX - tableRect.left;\n\t\tconst y: number = e.clientY - tableRect.top;\n\n\t\tconst inTable: boolean =\n\t\t\tx >= -BORDER_THRESHOLD &&\n\t\t\tx <= tableRect.width + BORDER_THRESHOLD &&\n\t\t\ty >= -BORDER_THRESHOLD &&\n\t\t\ty <= tableRect.height + BORDER_THRESHOLD;\n\n\t\tif (!inTable) {\n\t\t\tthis.hideInsertLines();\n\t\t\treturn;\n\t\t}\n\n\t\tconst rowBorders: BorderInfo[] = measureRowBorders(this.tableEl);\n\t\tconst colBorders: BorderInfo[] = measureColBorders(this.tableEl.offsetWidth, this.numCols);\n\t\tconst result = findNearestBorder(x, y, rowBorders, colBorders);\n\n\t\tif (result.type === 'row' && result.border) {\n\t\t\tthis.showHorizontalLine(result.border);\n\t\t\tthis.hideVerticalLine();\n\t\t} else if (result.type === 'col' && result.border) {\n\t\t\tthis.showVerticalLine(result.border);\n\t\t\tthis.hideHorizontalLine();\n\t\t} else {\n\t\t\tthis.hideInsertLines();\n\t\t}\n\t};\n\n\tprivate readonly onMouseLeave = (): void => {\n\t\tthis.hideInsertLines();\n\t};\n\n\tconstructor(\n\t\tcontainer: HTMLElement,\n\t\ttableEl: HTMLTableElement,\n\t\tinitialNode: BlockNode,\n\t\tgetState: () => EditorState,\n\t\tdispatch: (tr: Transaction) => void,\n\t) {\n\t\tthis.container = container;\n\t\tthis.tableEl = tableEl;\n\t\tthis.getState = getState;\n\t\tthis.dispatchFn = dispatch;\n\n\t\tthis.tableId = initialNode.id;\n\t\tthis.numRows = getBlockChildren(initialNode).length;\n\t\tthis.numCols = this.countCols(initialNode);\n\n\t\t// Create DOM elements\n\t\tthis.colBar = buildHandleBar('ntbl-col-bar');\n\t\tthis.rowBar = buildHandleBar('ntbl-row-bar');\n\t\tthis.insertLineH = buildInsertLine('horizontal');\n\t\tthis.insertLineV = buildInsertLine('vertical');\n\t\tthis.addRowZone = buildAddButton('ntbl-add-row', 'Add row');\n\t\tthis.addColZone = buildAddButton('ntbl-add-col', 'Add column');\n\t\tthis.deleteTableBtn = createButton('ntbl-delete-table-btn', TABLE_DELETE_SVG, 'Delete table');\n\n\t\tcontainer.append(\n\t\t\tthis.colBar,\n\t\t\tthis.rowBar,\n\t\t\tthis.insertLineH,\n\t\t\tthis.insertLineV,\n\t\t\tthis.addRowZone,\n\t\t\tthis.addColZone,\n\t\t\tthis.deleteTableBtn,\n\t\t);\n\n\t\tthis.rebuildColHandles();\n\t\tthis.rebuildRowHandles();\n\t\tthis.bindEventListeners();\n\n\t\tthis.observer = new ResizeObserver(() => {\n\t\t\tthis.positionControls();\n\t\t});\n\t\tthis.observer.observe(tableEl);\n\t\trequestAnimationFrame(() => this.positionControls());\n\t}\n\n\tupdate(node: BlockNode): void {\n\t\tthis.tableId = node.id;\n\t\tconst newRows: number = getBlockChildren(node).length;\n\t\tconst newCols: number = this.countCols(node);\n\n\t\tif (newRows !== this.numRows || newCols !== this.numCols) {\n\t\t\tthis.numRows = newRows;\n\t\t\tthis.numCols = newCols;\n\t\t\tthis.rebuildColHandles();\n\t\t\tthis.rebuildRowHandles();\n\t\t}\n\n\t\trequestAnimationFrame(() => this.positionControls());\n\t}\n\n\tdestroy(): void {\n\t\tthis.observer.disconnect();\n\t\tthis.container.removeEventListener('mousemove', this.onMouseMove);\n\t\tthis.container.removeEventListener('mouseleave', this.onMouseLeave);\n\t\tthis.colBar.remove();\n\t\tthis.rowBar.remove();\n\t\tthis.insertLineH.remove();\n\t\tthis.insertLineV.remove();\n\t\tthis.addRowZone.remove();\n\t\tthis.addColZone.remove();\n\t\tthis.deleteTableBtn.remove();\n\t}\n\n\tprivate bindEventListeners(): void {\n\t\tconst insertBtnH = this.insertLineH.querySelector('.ntbl-insert-btn') as HTMLButtonElement;\n\t\tconst insertBtnV = this.insertLineV.querySelector('.ntbl-insert-btn') as HTMLButtonElement;\n\n\t\tinsertBtnH.addEventListener('click', () => {\n\t\t\tif (this.activeRowIndex >= 0) {\n\t\t\t\tthis.dispatchTransaction(\n\t\t\t\t\tbuildInsertRowTransaction(this.getState(), this.tableId, this.activeRowIndex),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tinsertBtnV.addEventListener('click', () => {\n\t\t\tif (this.activeColIndex >= 0) {\n\t\t\t\tthis.dispatchTransaction(\n\t\t\t\t\tbuildInsertColumnTransaction(this.getState(), this.tableId, this.activeColIndex),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tthis.addRowZone.addEventListener('click', () => {\n\t\t\tthis.dispatchTransaction(\n\t\t\t\tbuildInsertRowTransaction(this.getState(), this.tableId, this.numRows),\n\t\t\t);\n\t\t});\n\n\t\tthis.addColZone.addEventListener('click', () => {\n\t\t\tthis.dispatchTransaction(\n\t\t\t\tbuildInsertColumnTransaction(this.getState(), this.tableId, this.numCols),\n\t\t\t);\n\t\t});\n\n\t\tthis.deleteTableBtn.addEventListener('click', () => {\n\t\t\tthis.dispatchTransaction(createDeleteTableTransaction(this.getState(), this.tableId));\n\t\t});\n\n\t\tthis.container.addEventListener('mousemove', this.onMouseMove);\n\t\tthis.container.addEventListener('mouseleave', this.onMouseLeave);\n\t}\n\n\tprivate dispatchTransaction(tr: Transaction | null): void {\n\t\tif (tr) this.dispatchFn(tr);\n\t}\n\n\tprivate countCols(node: BlockNode): number {\n\t\tconst rows = getBlockChildren(node);\n\t\treturn rows[0] ? getBlockChildren(rows[0]).length : 0;\n\t}\n\n\tprivate positionControls(): void {\n\t\tpositionColHandles(this.colBar, this.tableEl.offsetWidth, this.numCols);\n\t\tpositionRowHandles(this.rowBar, this.tableEl);\n\t\tpositionAddButtons(this.addRowZone, this.addColZone, this.tableEl, this.container);\n\t}\n\n\tprivate showHorizontalLine(border: BorderInfo): void {\n\t\tthis.activeRowIndex = border.index;\n\t\tconst offset = getTableOffset(this.tableEl, this.container);\n\t\tthis.insertLineH.style.top = `${offset.top + border.position - 1}px`;\n\t\tthis.insertLineH.style.left = `${offset.left}px`;\n\t\tthis.insertLineH.style.width = `${this.tableEl.offsetWidth}px`;\n\t\tthis.insertLineH.classList.add('ntbl-insert-line--visible');\n\t}\n\n\tprivate showVerticalLine(border: BorderInfo): void {\n\t\tthis.activeColIndex = border.index;\n\t\tconst offset = getTableOffset(this.tableEl, this.container);\n\t\tthis.insertLineV.style.left = `${offset.left + border.position - 1}px`;\n\t\tthis.insertLineV.style.top = `${offset.top}px`;\n\t\tthis.insertLineV.style.height = `${this.tableEl.offsetHeight}px`;\n\t\tthis.insertLineV.classList.add('ntbl-insert-line--visible');\n\t}\n\n\tprivate hideInsertLines(): void {\n\t\tthis.hideHorizontalLine();\n\t\tthis.hideVerticalLine();\n\t}\n\n\tprivate hideHorizontalLine(): void {\n\t\tthis.insertLineH.classList.remove('ntbl-insert-line--visible');\n\t\tthis.activeRowIndex = -1;\n\t}\n\n\tprivate hideVerticalLine(): void {\n\t\tthis.insertLineV.classList.remove('ntbl-insert-line--visible');\n\t\tthis.activeColIndex = -1;\n\t}\n\n\tprivate rebuildColHandles(): void {\n\t\tthis.colBar.innerHTML = '';\n\t\tfor (let i = 0; i < this.numCols; i++) {\n\t\t\tconst handle: HTMLDivElement = buildHandle(\n\t\t\t\t'ntbl-col-handle',\n\t\t\t\ti,\n\t\t\t\t'Delete column',\n\t\t\t\t(idx: number) => {\n\t\t\t\t\tthis.dispatchTransaction(\n\t\t\t\t\t\tbuildDeleteColumnTransaction(this.getState(), this.tableId, idx),\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.colBar.appendChild(handle);\n\t\t}\n\t}\n\n\tprivate rebuildRowHandles(): void {\n\t\tthis.rowBar.innerHTML = '';\n\t\tfor (let i = 0; i < this.numRows; i++) {\n\t\t\tconst handle: HTMLDivElement = buildHandle(\n\t\t\t\t'ntbl-row-handle',\n\t\t\t\ti,\n\t\t\t\t'Delete row',\n\t\t\t\t(idx: number) => {\n\t\t\t\t\tthis.dispatchTransaction(buildDeleteRowTransaction(this.getState(), this.tableId, idx));\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.rowBar.appendChild(handle);\n\t\t}\n\t}\n}\n\n// --- Factory ---\n\n/** Creates table controls for the given table element. */\nexport function createTableControls(\n\tcontainer: HTMLElement,\n\ttableEl: HTMLTableElement,\n\tinitialNode: BlockNode,\n\tgetState: () => EditorState,\n\tdispatch: (tr: Transaction) => void,\n): TableControlsHandle {\n\treturn new TableControls(container, tableEl, initialNode, getState, dispatch);\n}\n","/**\n * Multi-cell selection service for tables.\n * Tracks selected cell range and provides IDs for bulk formatting.\n */\n\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport { ServiceKey } from '../Plugin.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { findTableContext, getCellAt } from './TableHelpers.js';\n\n/** Rectangular range of cells within a table. */\nexport interface CellRange {\n\treadonly tableId: BlockId;\n\treadonly fromRow: number;\n\treadonly fromCol: number;\n\treadonly toRow: number;\n\treadonly toCol: number;\n}\n\n/** Service for managing multi-cell selection. */\nexport interface TableSelectionService {\n\tgetSelectedRange(): CellRange | null;\n\tsetSelectedRange(range: CellRange | null): void;\n\tgetSelectedCellIds(): readonly BlockId[];\n\tisSelected(cellId: BlockId): boolean;\n}\n\nexport const TableSelectionServiceKey = new ServiceKey<TableSelectionService>('tableSelection');\n\n/** Creates and registers the TableSelectionService. */\nexport function createTableSelectionService(context: PluginContext): TableSelectionService {\n\tlet selectedRange: CellRange | null = null;\n\tlet cachedCellIds: readonly BlockId[] = [];\n\tlet cachedCellIdSet: Set<BlockId> = new Set();\n\n\tfunction updateCache(): void {\n\t\tif (!selectedRange) {\n\t\t\tcachedCellIds = [];\n\t\t\tcachedCellIdSet = new Set();\n\t\t\treturn;\n\t\t}\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst ids: BlockId[] = [];\n\n\t\tconst minRow: number = Math.min(selectedRange.fromRow, selectedRange.toRow);\n\t\tconst maxRow: number = Math.max(selectedRange.fromRow, selectedRange.toRow);\n\t\tconst minCol: number = Math.min(selectedRange.fromCol, selectedRange.toCol);\n\t\tconst maxCol: number = Math.max(selectedRange.fromCol, selectedRange.toCol);\n\n\t\tfor (let r = minRow; r <= maxRow; r++) {\n\t\t\tfor (let c = minCol; c <= maxCol; c++) {\n\t\t\t\tconst cellId: BlockId | null = getCellAt(state, selectedRange.tableId, r, c);\n\t\t\t\tif (cellId) ids.push(cellId);\n\t\t\t}\n\t\t}\n\n\t\tcachedCellIds = ids;\n\t\tcachedCellIdSet = new Set(ids);\n\t}\n\n\tconst service: TableSelectionService = {\n\t\tgetSelectedRange(): CellRange | null {\n\t\t\treturn selectedRange;\n\t\t},\n\n\t\tsetSelectedRange(range: CellRange | null): void {\n\t\t\tselectedRange = range;\n\t\t\tupdateCache();\n\t\t\tupdateCellHighlights(context, cachedCellIdSet);\n\t\t},\n\n\t\tgetSelectedCellIds(): readonly BlockId[] {\n\t\t\treturn cachedCellIds;\n\t\t},\n\n\t\tisSelected(cellId: BlockId): boolean {\n\t\t\treturn cachedCellIdSet.has(cellId);\n\t\t},\n\t};\n\n\tcontext.registerService(TableSelectionServiceKey, service);\n\treturn service;\n}\n\n/** Updates CSS class on selected cells for visual highlighting. */\nfunction updateCellHighlights(context: PluginContext, selectedIds: Set<BlockId>): void {\n\tconst container: HTMLElement = context.getContainer();\n\tconst cells: NodeListOf<Element> = container.querySelectorAll('td[data-block-id]');\n\n\tfor (const cell of cells) {\n\t\tconst cellId = cell.getAttribute('data-block-id') as BlockId;\n\t\tif (selectedIds.has(cellId)) {\n\t\t\tcell.classList.add('notectl-table-cell--selected');\n\t\t} else {\n\t\t\tcell.classList.remove('notectl-table-cell--selected');\n\t\t}\n\t}\n}\n\n/**\n * Installs mouse handlers for multi-cell selection on the editor container.\n * Returns a cleanup function.\n */\nexport function installMouseSelection(\n\tcontext: PluginContext,\n\tservice: TableSelectionService,\n): () => void {\n\tconst container: HTMLElement = context.getContainer();\n\tlet anchorCell: { tableId: BlockId; row: number; col: number } | null = null;\n\tlet isDragging = false;\n\n\tfunction handleMouseDown(e: MouseEvent): void {\n\t\tconst target = e.target as HTMLElement;\n\t\tconst cellEl: HTMLElement | null = target.closest('td[data-block-id]');\n\t\tif (!cellEl) {\n\t\t\tservice.setSelectedRange(null);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!e.shiftKey) {\n\t\t\t// Clear any existing multi-cell selection before starting a new anchor\n\t\t\tservice.setSelectedRange(null);\n\t\t\t// Start new selection anchor\n\t\t\tconst state: EditorState = context.getState();\n\t\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\t\tconst tableCtx = findTableContext(state, cellId);\n\t\t\tif (!tableCtx) return;\n\n\t\t\tanchorCell = {\n\t\t\t\ttableId: tableCtx.tableId,\n\t\t\t\trow: tableCtx.rowIndex,\n\t\t\t\tcol: tableCtx.colIndex,\n\t\t\t};\n\t\t\tisDragging = true;\n\t\t\t// Don't set range yet — wait for mousemove to avoid interfering with clicks\n\t\t} else if (anchorCell) {\n\t\t\t// Shift-click: extend selection\n\t\t\tconst state: EditorState = context.getState();\n\t\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\t\tconst tableCtx = findTableContext(state, cellId);\n\t\t\tif (!tableCtx || tableCtx.tableId !== anchorCell.tableId) return;\n\n\t\t\te.preventDefault();\n\t\t\tservice.setSelectedRange({\n\t\t\t\ttableId: anchorCell.tableId,\n\t\t\t\tfromRow: anchorCell.row,\n\t\t\t\tfromCol: anchorCell.col,\n\t\t\t\ttoRow: tableCtx.rowIndex,\n\t\t\t\ttoCol: tableCtx.colIndex,\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction handleMouseMove(e: MouseEvent): void {\n\t\tif (!isDragging || !anchorCell) return;\n\n\t\tconst target = e.target as HTMLElement;\n\t\tconst cellEl: HTMLElement | null = target.closest('td[data-block-id]');\n\t\tif (!cellEl) return;\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\tconst tableCtx = findTableContext(state, cellId);\n\t\tif (!tableCtx || tableCtx.tableId !== anchorCell.tableId) return;\n\n\t\t// Only set range if we've moved to a different cell\n\t\tif (tableCtx.rowIndex !== anchorCell.row || tableCtx.colIndex !== anchorCell.col) {\n\t\t\te.preventDefault();\n\t\t\tservice.setSelectedRange({\n\t\t\t\ttableId: anchorCell.tableId,\n\t\t\t\tfromRow: anchorCell.row,\n\t\t\t\tfromCol: anchorCell.col,\n\t\t\t\ttoRow: tableCtx.rowIndex,\n\t\t\t\ttoCol: tableCtx.colIndex,\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction handleMouseUp(): void {\n\t\tisDragging = false;\n\t}\n\n\tcontainer.addEventListener('mousedown', handleMouseDown);\n\tcontainer.addEventListener('mousemove', handleMouseMove);\n\tdocument.addEventListener('mouseup', handleMouseUp);\n\n\treturn () => {\n\t\tcontainer.removeEventListener('mousedown', handleMouseDown);\n\t\tcontainer.removeEventListener('mousemove', handleMouseMove);\n\t\tdocument.removeEventListener('mouseup', handleMouseUp);\n\t};\n}\n","/**\n * TablePlugin: registers table, table_row, and table_cell node types\n * with NodeSpecs, NodeViews, commands, keyboard navigation, toolbar\n * grid picker, multi-cell selection, and context menu.\n */\n\nimport { TABLE_CSS } from '../../editor/styles/table.js';\nimport { isNodeSelection } from '../../model/Selection.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { insertTable, registerTableCommands } from './TableCommands.js';\nimport { isInsideTable } from './TableHelpers.js';\nimport { registerTableKeymaps } from './TableNavigation.js';\nimport {\n\tcreateTableCellNodeViewFactory,\n\tcreateTableNodeViewFactory,\n\tcreateTableRowNodeViewFactory,\n} from './TableNodeViews.js';\nimport {\n\ttype TableSelectionService,\n\tcreateTableSelectionService,\n\tinstallMouseSelection,\n} from './TableSelection.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\ttable: Record<string, never>;\n\t\ttable_row: Record<string, never>;\n\t\ttable_cell: { colspan?: number; rowspan?: number };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface TableConfig {\n\t/** Maximum rows in grid picker. Defaults to 8. */\n\treadonly maxPickerRows?: number;\n\t/** Maximum columns in grid picker. Defaults to 8. */\n\treadonly maxPickerCols?: number;\n\t/** When true, a separator is rendered after the table toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: TableConfig = {\n\tmaxPickerRows: 8,\n\tmaxPickerCols: 8,\n};\n\n// --- SVG Icon ---\n\nconst TABLE_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">' +\n\t'<path d=\"M3 3h18v18H3V3zm2 2v4h6V5H5zm8 0v4h6V5h-6zm-8 6v4h6v-4H5z' +\n\t'm8 0v4h6v-4h-6zm-8 6v4h6v-4H5zm8 0v4h6v-4h-6z\"/></svg>';\n\n// --- Plugin ---\n\nexport class TablePlugin implements Plugin {\n\treadonly id = 'table';\n\treadonly name = 'Table';\n\treadonly priority = 40;\n\n\tprivate readonly config: TableConfig;\n\tprivate selectionService: TableSelectionService | null = null;\n\tprivate cleanupMouseSelection: (() => void) | null = null;\n\tprivate context: PluginContext | null = null;\n\n\tconstructor(config?: Partial<TableConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tcontext.registerStyleSheet(TABLE_CSS);\n\t\tthis.context = context;\n\n\t\tthis.registerNodeSpecs(context);\n\t\tthis.registerNodeViews(context);\n\t\tregisterTableCommands(context);\n\t\tregisterTableKeymaps(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.selectionService = createTableSelectionService(context);\n\t}\n\n\tonReady(): void {\n\t\tif (this.context && this.selectionService) {\n\t\t\tthis.cleanupMouseSelection = installMouseSelection(this.context, this.selectionService);\n\t\t}\n\t}\n\n\tdestroy(): void {\n\t\tthis.cleanupMouseSelection?.();\n\t\tthis.cleanupMouseSelection = null;\n\t\tthis.selectionService = null;\n\t\tthis.context = null;\n\t}\n\n\tonStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void {\n\t\t// Clear multi-cell selection when cursor moves outside table\n\t\tif (this.selectionService?.getSelectedRange()) {\n\t\t\tconst sel = newState.selection;\n\t\t\tif (isNodeSelection(sel) || !isInsideTable(newState, sel.anchor.blockId)) {\n\t\t\t\tthis.selectionService.setSelectedRange(null);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate registerNodeSpecs(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['table_row'], min: 1 },\n\t\t\tisolating: true,\n\t\t\tselectable: true,\n\t\t\ttoDOM(node) {\n\t\t\t\tconst wrapper: HTMLDivElement = document.createElement('div');\n\t\t\t\twrapper.className = 'notectl-table-wrapper';\n\t\t\t\twrapper.setAttribute('data-block-id', node.id);\n\t\t\t\treturn wrapper;\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table_row',\n\t\t\tgroup: 'table_content',\n\t\t\tcontent: { allow: ['table_cell'], min: 1 },\n\t\t\ttoDOM(node) {\n\t\t\t\tconst tr: HTMLTableRowElement = document.createElement('tr');\n\t\t\t\ttr.setAttribute('data-block-id', node.id);\n\t\t\t\ttr.setAttribute('role', 'row');\n\t\t\t\treturn tr;\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table_cell',\n\t\t\tgroup: 'table_content',\n\t\t\tcontent: {\n\t\t\t\tallow: ['paragraph', 'list_item', 'heading', 'blockquote', 'image', 'horizontal_rule'],\n\t\t\t},\n\t\t\tisolating: true,\n\t\t\ttoDOM(node) {\n\t\t\t\tconst td: HTMLTableCellElement = document.createElement('td');\n\t\t\t\ttd.setAttribute('data-block-id', node.id);\n\t\t\t\ttd.setAttribute('role', 'cell');\n\t\t\t\treturn td;\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerNodeViews(context: PluginContext): void {\n\t\tconst registry = context.getSchemaRegistry();\n\n\t\tcontext.registerNodeView('table', createTableNodeViewFactory(registry));\n\t\tcontext.registerNodeView('table_row', createTableRowNodeViewFactory(registry));\n\t\tcontext.registerNodeView('table_cell', createTableCellNodeViewFactory(registry));\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst maxRows: number = this.config.maxPickerRows ?? 8;\n\t\tconst maxCols: number = this.config.maxPickerCols ?? 8;\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'table',\n\t\t\tgroup: 'insert',\n\t\t\ticon: TABLE_ICON,\n\t\t\tlabel: 'Insert Table',\n\t\t\ttooltip: 'Insert Table',\n\t\t\tcommand: 'insertTable',\n\t\t\tpriority: 80,\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\tpopupType: 'gridPicker',\n\t\t\tpopupConfig: {\n\t\t\t\tmaxRows,\n\t\t\t\tmaxCols,\n\t\t\t\tonSelect: (rows: number, cols: number) => {\n\t\t\t\t\tinsertTable(context, rows, cols);\n\t\t\t\t},\n\t\t\t},\n\t\t\tisActive: (state: EditorState) => {\n\t\t\t\tif (isNodeSelection(state.selection)) return false;\n\t\t\t\treturn isInsideTable(state, state.selection.anchor.blockId);\n\t\t\t},\n\t\t});\n\t}\n}\n","/** Table styles — table layout, selection, context menu, controls, insert lines. */\nexport const TABLE_CSS = `\n/* Table */\n.notectl-table-wrapper {\n\tmargin: 8px 0;\n\toverflow-x: auto;\n\tposition: relative;\n}\n\n.notectl-table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n\ttable-layout: fixed;\n}\n\n.notectl-table td {\n\tborder: 1px solid var(--notectl-border);\n\tpadding: 8px 12px;\n\tmin-width: 60px;\n\tvertical-align: top;\n\tmin-height: 1.6em;\n}\n\n.notectl-table td:focus-within {\n\toutline: 2px solid var(--notectl-primary);\n\toutline-offset: -2px;\n}\n\n.notectl-table-cell--selected {\n\tbackground: var(--notectl-primary-muted);\n}\n\n/* Table Context Menu */\n.notectl-table-context-menu {\n\tposition: fixed;\n\tbackground: var(--notectl-surface-overlay);\n\tborder: 1px solid var(--notectl-border);\n\tborder-radius: 6px;\n\tbox-shadow: 0 4px 12px var(--notectl-shadow);\n\tpadding: 4px 0;\n\tmin-width: 180px;\n\tz-index: 10000;\n}\n\n.notectl-table-context-menu button {\n\tdisplay: block;\n\twidth: 100%;\n\tpadding: 8px 12px;\n\ttext-align: left;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: var(--notectl-fg);\n\tfont-family: inherit;\n}\n\n.notectl-table-context-menu button:hover {\n\tbackground: var(--notectl-hover-bg);\n}\n\n.notectl-table-context-menu hr {\n\tborder: none;\n\tborder-top: 1px solid var(--notectl-border);\n\tmargin: 4px 0;\n}\n\n/* === Table Controls === */\n\n/* Outer container for table + controls */\n.ntbl-container {\n\tposition: relative;\n\tmargin: 8px 0;\n\tpadding: 24px 0 0 24px;\n}\n\n.ntbl-container .notectl-table-wrapper {\n\tmargin: 0;\n}\n\n.ntbl-container.notectl-table--selected .notectl-table-wrapper {\n\toutline: 2px solid var(--notectl-primary-fg);\n\toutline-offset: 2px;\n\tborder-radius: 6px;\n}\n\n/* --- Column Handle Bar --- */\n.ntbl-col-bar {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 24px;\n\theight: 20px;\n\tdisplay: flex;\n\topacity: 0;\n\ttransition: opacity 0.2s ease;\n\tz-index: 3;\n\tpointer-events: none;\n}\n\n.ntbl-container:hover .ntbl-col-bar,\n.ntbl-container:focus-within .ntbl-col-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n.ntbl-container.notectl-table--selected .ntbl-col-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n/* --- Row Handle Bar --- */\n.ntbl-row-bar {\n\tposition: absolute;\n\ttop: 24px;\n\tleft: 0;\n\twidth: 20px;\n\tdisplay: flex;\n\tflex-direction: column;\n\topacity: 0;\n\ttransition: opacity 0.2s ease;\n\tz-index: 3;\n\tpointer-events: none;\n}\n\n.ntbl-container:hover .ntbl-row-bar,\n.ntbl-container:focus-within .ntbl-row-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n.ntbl-container.notectl-table--selected .ntbl-row-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n/* --- Handle (shared base) --- */\n.ntbl-handle {\n\tposition: absolute;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcursor: pointer;\n\ttransition: background 0.15s ease;\n\tborder-radius: 3px;\n}\n\n.ntbl-col-handle {\n\theight: 100%;\n\tbackground: var(--notectl-hover-bg);\n\tborder-radius: 4px 4px 0 0;\n}\n\n.ntbl-col-handle:hover {\n\tbackground: var(--notectl-border);\n}\n\n.ntbl-row-handle {\n\twidth: 100%;\n\tbackground: var(--notectl-hover-bg);\n\tborder-radius: 4px 0 0 4px;\n}\n\n.ntbl-row-handle:hover {\n\tbackground: var(--notectl-border);\n}\n\n/* --- Handle Delete Button --- */\n.ntbl-handle-delete {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\theight: 16px;\n\tborder: none;\n\tbackground: transparent;\n\tcolor: var(--notectl-fg-muted);\n\tcursor: pointer;\n\tborder-radius: 3px;\n\tpadding: 0;\n\topacity: 0;\n\ttransform: scale(0.7);\n\ttransition: opacity 0.15s, transform 0.15s,\n\t\tbackground 0.15s, color 0.15s;\n}\n\n.ntbl-handle:hover .ntbl-handle-delete,\n.ntbl-handle:focus-within .ntbl-handle-delete {\n\topacity: 1;\n\ttransform: scale(1);\n}\n\n.ntbl-handle-delete:hover,\n.ntbl-handle-delete:focus-visible {\n\tbackground: var(--notectl-danger-muted);\n\tcolor: var(--notectl-danger);\n}\n\n.ntbl-handle-delete:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n/* --- Insert Lines --- */\n.ntbl-insert-line {\n\tposition: absolute;\n\tpointer-events: none;\n\topacity: 0;\n\ttransition: opacity 0.15s ease;\n\tz-index: 6;\n}\n\n.ntbl-insert-line--visible {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n.ntbl-insert-line--horizontal {\n\theight: 2px;\n\tbackground: linear-gradient(\n\t\t90deg,\n\t\ttransparent,\n\t\tvar(--notectl-primary) 8%,\n\t\tvar(--notectl-primary) 92%,\n\t\ttransparent\n\t);\n\tbox-shadow: 0 0 6px var(--notectl-focus-ring);\n}\n\n.ntbl-insert-line--vertical {\n\twidth: 2px;\n\tbackground: linear-gradient(\n\t\t180deg,\n\t\ttransparent,\n\t\tvar(--notectl-primary) 8%,\n\t\tvar(--notectl-primary) 92%,\n\t\ttransparent\n\t);\n\tbox-shadow: 0 0 6px var(--notectl-focus-ring);\n}\n\n/* --- Insert Button on Line --- */\n.ntbl-insert-btn {\n\tposition: absolute;\n\twidth: 20px;\n\theight: 20px;\n\tborder-radius: 50%;\n\tbackground: var(--notectl-bg);\n\tborder: 2px solid var(--notectl-primary);\n\tcolor: var(--notectl-primary);\n\tcursor: pointer;\n\tpointer-events: all;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: 0;\n\tbox-shadow: 0 2px 8px var(--notectl-focus-ring);\n\ttransition: background 0.15s, color 0.15s,\n\t\ttransform 0.15s, box-shadow 0.15s;\n}\n\n.ntbl-insert-line--horizontal .ntbl-insert-btn {\n\tleft: 50%;\n\ttop: -9px;\n\ttransform: translateX(-50%);\n}\n\n.ntbl-insert-line--vertical .ntbl-insert-btn {\n\ttop: 50%;\n\tleft: -9px;\n\ttransform: translateY(-50%);\n}\n\n.ntbl-insert-btn:hover,\n.ntbl-insert-btn:focus-visible {\n\tbackground: var(--notectl-primary);\n\tcolor: var(--notectl-bg);\n\tbox-shadow: 0 2px 12px var(--notectl-focus-ring);\n}\n\n.ntbl-insert-btn:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n.ntbl-insert-line--horizontal .ntbl-insert-btn:hover {\n\ttransform: translateX(-50%) scale(1.2);\n}\n\n.ntbl-insert-line--vertical .ntbl-insert-btn:hover {\n\ttransform: translateY(-50%) scale(1.2);\n}\n\n/* --- Add Row / Add Column Zones --- */\n.ntbl-add-zone {\n\tposition: absolute;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcursor: pointer;\n\tuser-select: none;\n\topacity: 0;\n\ttransition: opacity 0.2s ease, background 0.2s ease,\n\t\tborder-color 0.2s ease;\n}\n\n.ntbl-container:hover .ntbl-add-zone,\n.ntbl-container:focus-within .ntbl-add-zone {\n\topacity: 1;\n}\n\n.ntbl-container.notectl-table--selected .ntbl-add-zone {\n\topacity: 1;\n}\n\n.ntbl-delete-table-btn {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 20px;\n\theight: 20px;\n\tborder: 1px solid var(--notectl-danger);\n\tborder-radius: 4px;\n\tbackground: var(--notectl-bg);\n\tcolor: var(--notectl-danger);\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\topacity: 0;\n\ttransition: opacity 0.2s ease, background 0.15s, border-color 0.15s;\n\tz-index: 7;\n}\n\n.ntbl-container:hover .ntbl-delete-table-btn,\n.ntbl-container:focus-within .ntbl-delete-table-btn,\n.ntbl-container.notectl-table--selected .ntbl-delete-table-btn {\n\topacity: 1;\n}\n\n.ntbl-delete-table-btn:hover,\n.ntbl-delete-table-btn:focus-visible {\n\tbackground: var(--notectl-danger-muted);\n\tborder-color: var(--notectl-danger);\n}\n\n.ntbl-delete-table-btn:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n.ntbl-add-row {\n\tbottom: 0;\n\theight: 24px;\n\tborder: 1px dashed var(--notectl-border);\n\tborder-radius: 0 0 6px 6px;\n\tborder-top: none;\n\tcolor: var(--notectl-fg-muted);\n\ttransform: translateY(100%);\n}\n\n.ntbl-add-row:hover,\n.ntbl-add-row:focus-visible {\n\tbackground: var(--notectl-primary-muted);\n\tborder-color: var(--notectl-primary);\n\tcolor: var(--notectl-primary);\n}\n\n.ntbl-add-row:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n.ntbl-add-col {\n\tright: 0;\n\ttop: 24px;\n\twidth: 24px;\n\tborder: 1px dashed var(--notectl-border);\n\tborder-radius: 0 6px 6px 0;\n\tborder-left: none;\n\tcolor: var(--notectl-fg-muted);\n\ttransform: translateX(100%);\n}\n\n.ntbl-add-col:hover,\n.ntbl-add-col:focus-visible {\n\tbackground: var(--notectl-primary-muted);\n\tborder-color: var(--notectl-primary);\n\tcolor: var(--notectl-primary);\n}\n\n.ntbl-add-col:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n.ntbl-add-icon {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\ttransition: transform 0.2s ease;\n}\n\n.ntbl-add-zone:hover .ntbl-add-icon {\n\ttransform: scale(1.15);\n}\n`;\n","/**\n * NodeViewFactories for table, table_row, and table_cell.\n * Provides custom DOM rendering with proper HTML table elements and ARIA.\n * The table NodeView includes interactive controls for row/column management.\n */\n\nimport type { BlockNode } from '../../model/Document.js';\nimport { getBlockChildren } from '../../model/Document.js';\nimport type { SchemaRegistry } from '../../model/SchemaRegistry.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { NodeView, NodeViewFactory } from '../../view/NodeView.js';\nimport { type TableControlsHandle, createTableControls } from './TableControls.js';\n\n/**\n * Creates a NodeViewFactory for the table node type.\n * Renders as outer container with controls + table + tbody.\n */\nexport function createTableNodeViewFactory(_registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\tgetState: () => EditorState,\n\t\tdispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\t// Outer container: holds controls + wrapper\n\t\tconst container: HTMLDivElement = document.createElement('div');\n\t\tcontainer.className = 'ntbl-container';\n\t\tcontainer.setAttribute('data-block-id', node.id);\n\t\tcontainer.setAttribute('data-selectable', 'true');\n\n\t\t// Table wrapper: provides overflow scrolling\n\t\tconst wrapper: HTMLDivElement = document.createElement('div');\n\t\twrapper.className = 'notectl-table-wrapper';\n\n\t\tconst table: HTMLTableElement = document.createElement('table');\n\t\ttable.className = 'notectl-table';\n\t\ttable.setAttribute('role', 'table');\n\n\t\tconst rows: readonly BlockNode[] = getBlockChildren(node);\n\t\tconst totalRows: number = rows.length;\n\t\tconst totalCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\t\ttable.setAttribute('aria-label', `Table with ${totalRows} rows and ${totalCols} columns`);\n\n\t\tconst tbody: HTMLTableSectionElement = document.createElement('tbody');\n\t\ttable.appendChild(tbody);\n\t\twrapper.appendChild(table);\n\t\tcontainer.appendChild(wrapper);\n\n\t\t// Live region for screen reader announcements\n\t\tconst liveRegion: HTMLDivElement = document.createElement('div');\n\t\tliveRegion.className = 'notectl-sr-only';\n\t\tliveRegion.setAttribute('aria-live', 'polite');\n\t\tliveRegion.setAttribute('aria-atomic', 'true');\n\t\tcontainer.appendChild(liveRegion);\n\n\t\t// Initialize interactive controls\n\t\tconst controls: TableControlsHandle = createTableControls(\n\t\t\tcontainer,\n\t\t\ttable,\n\t\t\tnode,\n\t\t\tgetState,\n\t\t\tdispatch,\n\t\t);\n\n\t\treturn {\n\t\t\tdom: container,\n\t\t\tcontentDOM: tbody,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table') return false;\n\t\t\t\tcontainer.setAttribute('data-block-id', updatedNode.id);\n\t\t\t\tcontainer.setAttribute('data-selectable', 'true');\n\t\t\t\tconst updatedRows: readonly BlockNode[] = getBlockChildren(updatedNode);\n\t\t\t\tconst newTotalRows: number = updatedRows.length;\n\t\t\t\tconst newTotalCols: number = updatedRows[0] ? getBlockChildren(updatedRows[0]).length : 0;\n\t\t\t\ttable.setAttribute(\n\t\t\t\t\t'aria-label',\n\t\t\t\t\t`Table with ${newTotalRows} rows and ${newTotalCols} columns`,\n\t\t\t\t);\n\n\t\t\t\t// Update controls to reflect new structure\n\t\t\t\tcontrols.update(updatedNode);\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\tcontrols.destroy();\n\t\t\t},\n\t\t\tselectNode(): void {\n\t\t\t\tcontainer.classList.add('notectl-table--selected');\n\t\t\t},\n\t\t\tdeselectNode(): void {\n\t\t\t\tcontainer.classList.remove('notectl-table--selected');\n\t\t\t},\n\t\t};\n\t};\n}\n\n/**\n * Creates a NodeViewFactory for the table_row node type.\n * Renders as `<tr role=\"row\">`.\n */\nexport function createTableRowNodeViewFactory(_registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\t_getState: () => EditorState,\n\t\t_dispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\tconst tr: HTMLTableRowElement = document.createElement('tr');\n\t\ttr.setAttribute('data-block-id', node.id);\n\t\ttr.setAttribute('role', 'row');\n\n\t\treturn {\n\t\t\tdom: tr,\n\t\t\tcontentDOM: tr,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table_row') return false;\n\t\t\t\ttr.setAttribute('data-block-id', updatedNode.id);\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\t// No cleanup needed\n\t\t\t},\n\t\t};\n\t};\n}\n\n/**\n * Creates a NodeViewFactory for the table_cell node type.\n * Renders as `<td role=\"cell\">` with text content rendered inside.\n */\nexport function createTableCellNodeViewFactory(_registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\t_getState: () => EditorState,\n\t\t_dispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\tconst td: HTMLTableCellElement = document.createElement('td');\n\t\ttd.setAttribute('data-block-id', node.id);\n\t\ttd.setAttribute('role', 'cell');\n\n\t\tconst colspan: number = (node.attrs?.colspan as number | undefined) ?? 1;\n\t\tconst rowspan: number = (node.attrs?.rowspan as number | undefined) ?? 1;\n\t\tif (colspan > 1) td.colSpan = colspan;\n\t\tif (rowspan > 1) td.rowSpan = rowspan;\n\n\t\t// Apply alignment from AlignmentPlugin's patched attribute\n\t\tconst align: string | undefined = node.attrs?.align as string | undefined;\n\t\tif (align && align !== 'left') {\n\t\t\ttd.style.textAlign = align;\n\t\t}\n\n\t\treturn {\n\t\t\tdom: td,\n\t\t\tcontentDOM: td,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table_cell') return false;\n\t\t\t\ttd.setAttribute('data-block-id', updatedNode.id);\n\n\t\t\t\tconst newColspan: number = (updatedNode.attrs?.colspan as number | undefined) ?? 1;\n\t\t\t\tconst newRowspan: number = (updatedNode.attrs?.rowspan as number | undefined) ?? 1;\n\t\t\t\tif (newColspan > 1) {\n\t\t\t\t\ttd.colSpan = newColspan;\n\t\t\t\t} else {\n\t\t\t\t\ttd.removeAttribute('colspan');\n\t\t\t\t}\n\t\t\t\tif (newRowspan > 1) {\n\t\t\t\t\ttd.rowSpan = newRowspan;\n\t\t\t\t} else {\n\t\t\t\t\ttd.removeAttribute('rowspan');\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\t// No cleanup needed\n\t\t\t},\n\t\t};\n\t};\n}\n"],"names":["createTableCell","paragraph","createBlockNode","nodeType","createTextNode","generateBlockId","findTableContext","state","blockId","path","getNodePath","tableId","tableNode","rowId","cellId","id","node","getBlock","type","block","tableIndex","doc","children","findIndex","b","rows","getBlockChildren","rowIndex","r","rowNode","cells","colIndex","c","totalCols","length","totalRows","getCellAt","table","row","cell","getFirstLeafInCell","first","current","next","getLastLeafInCell","blockChildren","last","isInsideTable","buildInsertRowTransaction","numCols","newRow","cols","cellNodes","push","tr","transaction","insertNode","firstCell","firstLeaf","setSelection","createCollapsedSelection","build","buildInsertColumnTransaction","newCell","selection","buildDeleteRowTransaction","preferredCol","createDeleteTableTransaction","removeNode","leafId","buildDeleteColumnTransaction","preferredRow","nextRoot","prevRoot","insertTable","context","getState","sel","isNodeSelection","currentBlockId","anchor","rootIndex","i","rootBlock","rowNodes","paragraphAfter","insertIndex","firstRow","firstParagraph","dispatch","addRowBelow","tableCtx","addColumn","side","insertColIndex","registerTableCommands","registerCommand","selectedNode","nodeId","createNodeSelection","target","withTableContext","handler","handleEscape","_sel","nextIndex","nextBlock","moveToCellAndSelect","moveToCellAtEnd","leaf","leafLen","getBlockLength","selectTableNode","PLUS_SVG","createButton","className","innerHTML","title","btn","document","createElement","setAttribute","addEventListener","e","preventDefault","stopPropagation","buildInsertLine","orientation","line","appendChild","buildAddButton","icon","buildHandleBar","bar","buildHandle","index","deleteLabel","onDelete","handle","dataset","String","deleteBtn","getTableOffset","tableEl","container","top","left","el","offsetTop","offsetLeft","offsetParent","TableControls","numRows","activeRowIndex","activeColIndex","colBar","rowBar","insertLineH","insertLineV","addRowZone","addColZone","deleteTableBtn","observer","dispatchFn","onMouseMove","tableRect","this","getBoundingClientRect","x","clientX","y","clientY","width","height","hideInsertLines","result","rowBorders","colBorders","nearestRowDist","Number","POSITIVE_INFINITY","nearestRowBorder","border","dist","Math","abs","position","nearestColDist","nearestColBorder","trs","querySelectorAll","tableTop","borders","tableWidth","colWidth","round","offsetWidth","showHorizontalLine","hideVerticalLine","showVerticalLine","hideHorizontalLine","onMouseLeave","initialNode","countCols","append","rebuildColHandles","rebuildRowHandles","bindEventListeners","ResizeObserver","positionControls","observe","requestAnimationFrame","newRows","newCols","destroy","disconnect","removeEventListener","remove","insertBtnH","querySelector","insertBtnV","dispatchTransaction","handles","h","style","totalHeight","offsetHeight","offset","tableHeight","classList","add","idx","TableSelectionServiceKey","ServiceKey","DEFAULT_CONFIG","maxPickerRows","maxPickerCols","TablePlugin","name","priority","config","selectionService","cleanupMouseSelection","registerStyleSheet","registerNodeSpecs","registerNodeViews","keymap","Tab","_state","Enter","Backspace","isCollapsed","Delete","blockLen","lastLeaf","ArrowDown","ArrowUp","ArrowRight","ArrowLeft","Escape","registerKeymap","registerToolbarItem","selectedRange","cachedCellIds","cachedCellIdSet","Set","service","getSelectedRange","range","ids","minRow","min","fromRow","toRow","maxRow","max","minCol","fromCol","toCol","maxCol","updateCache","selectedIds","getContainer","getAttribute","has","getSelectedCellIds","isSelected","registerService","onReady","anchorCell","isDragging","handleMouseDown","cellEl","closest","shiftKey","setSelectedRange","col","handleMouseMove","handleMouseUp","_oldState","newState","_tr","registerNodeSpec","group","content","allow","isolating","selectable","wrapper","td","getSchemaRegistry","registerNodeView","tbody","liveRegion","controls","dom","contentDOM","updatedNode","updatedRows","newTotalRows","newTotalCols","update","selectNode","deselectNode","_getState","_dispatch","colspan","attrs","rowspan","colSpan","rowSpan","align","textAlign","newColspan","newRowspan","removeAttribute","maxRows","maxCols","label","tooltip","command","separatorAfter","popupType","popupConfig","onSelect","isActive"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table.mjs","sources":["../../src/plugins/table/TableHelpers.ts","../../src/plugins/table/TableCommands.ts","../../src/plugins/table/TableNavigation.ts","../../src/plugins/table/TableControlsDOM.ts","../../src/plugins/table/TableControlsLayout.ts","../../src/plugins/table/TableControls.ts","../../src/plugins/table/TableSelection.ts","../../src/plugins/table/TablePlugin.ts","../../src/editor/styles/table.ts","../../src/plugins/table/TableNodeViews.ts"],"sourcesContent":["/**\n * Utility functions for table operations: creating table structures,\n * finding table context, and navigating cells.\n */\n\nimport {\n\ttype BlockNode,\n\ttype ChildNode,\n\tcreateBlockNode,\n\tcreateTextNode,\n\tgenerateBlockId,\n\tgetBlockChildren,\n} from '../../model/Document.js';\nimport type { BlockId, NodeTypeName } from '../../model/TypeBrands.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\n\n/** Context information about a cell within a table. */\nexport interface TableContext {\n\treadonly tableId: BlockId;\n\treadonly tableIndex: number;\n\treadonly rowId: BlockId;\n\treadonly rowIndex: number;\n\treadonly cellId: BlockId;\n\treadonly colIndex: number;\n\treadonly totalRows: number;\n\treadonly totalCols: number;\n}\n\n/** Creates a table BlockNode structure with the given dimensions. */\nexport function createTable(rows: number, cols: number): BlockNode {\n\tconst tableId: BlockId = generateBlockId();\n\tconst rowNodes: ChildNode[] = [];\n\n\tfor (let r = 0; r < rows; r++) {\n\t\tconst cellNodes: ChildNode[] = [];\n\t\tfor (let c = 0; c < cols; c++) {\n\t\t\tcellNodes.push(createTableCell());\n\t\t}\n\t\trowNodes.push(\n\t\t\tcreateBlockNode(nodeType('table_row') as NodeTypeName, cellNodes, generateBlockId()),\n\t\t);\n\t}\n\n\treturn createBlockNode(nodeType('table') as NodeTypeName, rowNodes, tableId);\n}\n\n/** Creates a single table row with the given number of cells. */\nexport function createTableRow(cols: number): BlockNode {\n\tconst cellNodes: ChildNode[] = [];\n\tfor (let c = 0; c < cols; c++) {\n\t\tcellNodes.push(createTableCell());\n\t}\n\treturn createBlockNode(nodeType('table_row') as NodeTypeName, cellNodes, generateBlockId());\n}\n\n/** Creates a single empty table cell containing a paragraph. */\nexport function createTableCell(): BlockNode {\n\tconst paragraph: BlockNode = createBlockNode(\n\t\tnodeType('paragraph') as NodeTypeName,\n\t\t[createTextNode('')],\n\t\tgenerateBlockId(),\n\t);\n\treturn createBlockNode(nodeType('table_cell') as NodeTypeName, [paragraph], generateBlockId());\n}\n\n/**\n * Finds table context for a given block ID.\n * Returns null if the block is not inside a table.\n */\nexport function findTableContext(state: EditorState, blockId: BlockId): TableContext | null {\n\tconst path = state.getNodePath(blockId);\n\tif (!path) return null;\n\n\t// Collect table, row, and cell in a single pass\n\tlet tableId: BlockId | null = null;\n\tlet tableNode: BlockNode | null = null;\n\tlet rowId: BlockId | null = null;\n\tlet cellId: BlockId | null = null;\n\n\tfor (const id of path) {\n\t\tconst node = state.getBlock(id as BlockId);\n\t\tif (!node) continue;\n\t\tif (node.type === 'table') {\n\t\t\ttableId = id as BlockId;\n\t\t\ttableNode = node;\n\t\t} else if (node.type === 'table_row') {\n\t\t\trowId = id as BlockId;\n\t\t} else if (node.type === 'table_cell') {\n\t\t\tcellId = id as BlockId;\n\t\t}\n\t}\n\n\t// If the block itself is a cell\n\tconst block = state.getBlock(blockId);\n\tif (block?.type === 'table_cell') {\n\t\tcellId = blockId;\n\t}\n\n\tif (!tableId || !tableNode || !cellId || !rowId) return null;\n\n\t// Find table index in document\n\tconst tableIndex: number = state.doc.children.findIndex((b) => b.id === tableId);\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(tableNode);\n\tconst rowIndex: number = rows.findIndex((r) => r.id === rowId);\n\tif (rowIndex === -1) return null;\n\n\tconst rowNode: BlockNode | undefined = rows[rowIndex];\n\tif (!rowNode) return null;\n\tconst cells: readonly BlockNode[] = getBlockChildren(rowNode);\n\tconst colIndex: number = cells.findIndex((c) => c.id === cellId);\n\tif (colIndex === -1) return null;\n\n\tconst totalCols: number = cells.length;\n\tconst totalRows: number = rows.length;\n\n\treturn {\n\t\ttableId,\n\t\ttableIndex,\n\t\trowId,\n\t\trowIndex,\n\t\tcellId,\n\t\tcolIndex,\n\t\ttotalRows,\n\t\ttotalCols,\n\t};\n}\n\n/**\n * Gets the cell BlockId at the given row and column indices.\n * Returns null if out of bounds.\n */\nexport function getCellAt(\n\tstate: EditorState,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): BlockId | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tconst row: BlockNode | undefined = rows[rowIndex];\n\tif (!row) return null;\n\n\tconst cells: readonly BlockNode[] = getBlockChildren(row);\n\tconst cell: BlockNode | undefined = cells[colIndex];\n\treturn cell?.id ?? null;\n}\n\n/** Returns all cell IDs in a table in row-major order. */\nexport function getAllCellIds(state: EditorState, tableId: BlockId): readonly BlockId[] {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return [];\n\n\tconst result: BlockId[] = [];\n\tconst rows: readonly BlockNode[] = getBlockChildren(table);\n\tfor (const row of rows) {\n\t\tconst cells: readonly BlockNode[] = getBlockChildren(row);\n\t\tfor (const cell of cells) {\n\t\t\tresult.push(cell.id);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** Returns the first leaf-block ID inside a table cell (e.g. the paragraph). */\nexport function getFirstLeafInCell(state: EditorState, cellId: BlockId): BlockId {\n\tconst cell: BlockNode | undefined = state.getBlock(cellId);\n\tif (!cell) return cellId;\n\tconst blockChildren: readonly BlockNode[] = getBlockChildren(cell);\n\tconst first: BlockNode | undefined = blockChildren[0];\n\tif (!first) return cellId;\n\tlet current: BlockNode = first;\n\twhile (true) {\n\t\tconst children: readonly BlockNode[] = getBlockChildren(current);\n\t\tconst next: BlockNode | undefined = children[0];\n\t\tif (!next) return current.id;\n\t\tcurrent = next;\n\t}\n}\n\n/** Returns the last leaf-block ID inside a table cell. */\nexport function getLastLeafInCell(state: EditorState, cellId: BlockId): BlockId {\n\tconst cell: BlockNode | undefined = state.getBlock(cellId);\n\tif (!cell) return cellId;\n\tconst blockChildren: readonly BlockNode[] = getBlockChildren(cell);\n\tconst last: BlockNode | undefined = blockChildren[blockChildren.length - 1];\n\tif (!last) return cellId;\n\tlet current: BlockNode = last;\n\twhile (true) {\n\t\tconst children: readonly BlockNode[] = getBlockChildren(current);\n\t\tconst next: BlockNode | undefined = children[children.length - 1];\n\t\tif (!next) return current.id;\n\t\tcurrent = next;\n\t}\n}\n\n/** Checks whether a block is inside a table. */\nexport function isInsideTable(state: EditorState, blockId: BlockId): boolean {\n\tconst path = state.getNodePath(blockId);\n\tif (!path) return false;\n\n\tfor (const id of path) {\n\t\tconst node = state.getBlock(id as BlockId);\n\t\tif (node?.type === 'table') return true;\n\t}\n\treturn false;\n}\n","/**\n * Table commands: insert table, add/remove rows and columns, delete table.\n * All commands are registered via PluginContext and operate through transactions.\n *\n * Shared transaction builders (`build*Transaction`) are pure functions that take\n * EditorState + explicit indices and return a Transaction or null. They are used\n * by both commands (via PluginContext) and controls (via getState/dispatch).\n */\n\nimport { createBlockNode, getBlockChildren } from '../../model/Document.js';\nimport {\n\tcreateCollapsedSelection,\n\tcreateNodeSelection,\n\tisNodeSelection,\n} from '../../model/Selection.js';\nimport type { BlockId, NodeTypeName } from '../../model/TypeBrands.js';\nimport { nodeType } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { PluginContext } from '../Plugin.js';\nimport {\n\ttype TableContext,\n\tcreateTable,\n\tcreateTableCell,\n\tcreateTableRow,\n\tfindTableContext,\n\tgetCellAt,\n\tgetFirstLeafInCell,\n} from './TableHelpers.js';\n\n// --- Shared Transaction Builders ---\n\n/** Builds a transaction that inserts a new row at the given index. */\nexport function buildInsertRowTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n\trowIndex: number,\n): Transaction | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows = getBlockChildren(table);\n\tconst numCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\tif (numCols === 0) return null;\n\n\tconst newRow = createTableRow(numCols);\n\tconst tr = state.transaction('command').insertNode([tableId], rowIndex, newRow);\n\n\tconst firstCell = getBlockChildren(newRow)[0];\n\tconst firstLeaf = firstCell ? getBlockChildren(firstCell)[0] : undefined;\n\tif (firstLeaf) {\n\t\ttr.setSelection(createCollapsedSelection(firstLeaf.id, 0));\n\t} else if (firstCell) {\n\t\ttr.setSelection(createCollapsedSelection(firstCell.id, 0));\n\t}\n\n\treturn tr.build();\n}\n\n/** Builds a transaction that inserts a new column at the given index. */\nexport function buildInsertColumnTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n\tcolIndex: number,\n): Transaction | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows = getBlockChildren(table);\n\tconst tr = state.transaction('command');\n\n\tfor (const row of rows) {\n\t\tconst newCell = createTableCell();\n\t\ttr.insertNode([tableId, row.id], colIndex, newCell);\n\t}\n\n\ttr.setSelection(state.selection);\n\treturn tr.build();\n}\n\n/**\n * Builds a transaction that deletes the row at the given index.\n * If it's the last row, delegates to `createDeleteTableTransaction`.\n * @param preferredCol Column index to place the cursor in after deletion (default 0).\n */\nexport function buildDeleteRowTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n\trowIndex: number,\n\tpreferredCol = 0,\n): Transaction | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows = getBlockChildren(table);\n\tif (rows.length <= 1) {\n\t\treturn createDeleteTableTransaction(state, tableId);\n\t}\n\n\tconst tr = state.transaction('command').removeNode([tableId], rowIndex);\n\n\tconst targetRow: number = rowIndex > 0 ? rowIndex - 1 : 1;\n\tconst cellId: BlockId | null = getCellAt(state, tableId, targetRow, preferredCol);\n\tif (cellId) {\n\t\tconst leafId: BlockId = getFirstLeafInCell(state, cellId);\n\t\ttr.setSelection(createCollapsedSelection(leafId, 0));\n\t}\n\n\treturn tr.build();\n}\n\n/**\n * Builds a transaction that deletes the column at the given index.\n * If it's the last column, delegates to `createDeleteTableTransaction`.\n * @param preferredRow Row index to place the cursor in after deletion (default 0).\n */\nexport function buildDeleteColumnTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n\tcolIndex: number,\n\tpreferredRow = 0,\n): Transaction | null {\n\tconst table = state.getBlock(tableId);\n\tif (!table) return null;\n\n\tconst rows = getBlockChildren(table);\n\tconst numCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\n\tif (numCols <= 1) {\n\t\treturn createDeleteTableTransaction(state, tableId);\n\t}\n\n\tconst tr = state.transaction('command');\n\n\tfor (let r: number = rows.length - 1; r >= 0; r--) {\n\t\tconst row = rows[r];\n\t\tif (!row) continue;\n\t\ttr.removeNode([tableId, row.id], colIndex);\n\t}\n\n\tconst targetCol: number = colIndex > 0 ? colIndex - 1 : 1;\n\tconst cellId: BlockId | null = getCellAt(state, tableId, preferredRow, targetCol);\n\tif (cellId) {\n\t\tconst leafId: BlockId = getFirstLeafInCell(state, cellId);\n\t\ttr.setSelection(createCollapsedSelection(leafId, 0));\n\t}\n\n\treturn tr.build();\n}\n\n/**\n * Creates a transaction that removes the given root-level table node.\n * Cursor placement prefers the next root block, then previous.\n */\nexport function createDeleteTableTransaction(\n\tstate: EditorState,\n\ttableId: BlockId,\n): Transaction | null {\n\tconst tableIndex: number = state.doc.children.findIndex((block) => block.id === tableId);\n\tif (tableIndex === -1) return null;\n\n\tconst tr = state.transaction('command').removeNode([], tableIndex);\n\n\tconst nextRoot = state.doc.children[tableIndex + 1];\n\tif (nextRoot) {\n\t\ttr.setSelection(createCollapsedSelection(nextRoot.id, 0));\n\t\treturn tr.build();\n\t}\n\n\tconst prevRoot = state.doc.children[tableIndex - 1];\n\tif (prevRoot) {\n\t\ttr.setSelection(createCollapsedSelection(prevRoot.id, 0));\n\t}\n\n\treturn tr.build();\n}\n\n// --- Commands ---\n\ninterface TableDeletionTarget {\n\treadonly tableId: BlockId;\n}\n\n/**\n * Inserts a table with the given dimensions at the current cursor position.\n * Adds a paragraph after the table for cursor escape.\n * Moves cursor into the first cell.\n */\nexport function insertTable(context: PluginContext, rows: number, cols: number): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\tif (isNodeSelection(sel)) return false;\n\n\tconst currentBlockId: BlockId = sel.anchor.blockId;\n\n\t// Find which root-level block contains the current selection\n\tlet rootIndex = -1;\n\tfor (let i = 0; i < state.doc.children.length; i++) {\n\t\tconst rootBlock = state.doc.children[i];\n\t\tif (!rootBlock) continue;\n\t\tif (rootBlock.id === currentBlockId) {\n\t\t\trootIndex = i;\n\t\t\tbreak;\n\t\t}\n\t\t// Check if current block is nested inside this root block\n\t\tconst path = state.getNodePath(currentBlockId);\n\t\tif (path && path[0] === rootBlock.id) {\n\t\t\trootIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (rootIndex === -1) rootIndex = state.doc.children.length - 1;\n\n\tconst tableNode = createTable(rows, cols);\n\tconst paragraphAfter = createBlockNode(nodeType('paragraph') as NodeTypeName);\n\n\t// Insert table after current block, then paragraph after table\n\tconst insertIndex: number = rootIndex + 1;\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.insertNode([], insertIndex, tableNode)\n\t\t.insertNode([], insertIndex + 1, paragraphAfter);\n\n\t// Set cursor in first paragraph inside first cell\n\tconst firstRow = getBlockChildren(tableNode)[0];\n\tconst firstCell = firstRow ? getBlockChildren(firstRow)[0] : undefined;\n\tconst firstParagraph = firstCell ? getBlockChildren(firstCell)[0] : undefined;\n\n\tif (firstParagraph) {\n\t\ttr.setSelection(createCollapsedSelection(firstParagraph.id, 0));\n\t} else if (firstCell) {\n\t\ttr.setSelection(createCollapsedSelection(firstCell.id, 0));\n\t}\n\n\tcontext.dispatch(tr.build());\n\treturn true;\n}\n\n/** Adds a row above the current row. */\nexport function addRowAbove(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = buildInsertRowTransaction(state, tableCtx.tableId, tableCtx.rowIndex);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Adds a row below the current row. */\nexport function addRowBelow(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = buildInsertRowTransaction(state, tableCtx.tableId, tableCtx.rowIndex + 1);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Adds a column to the left of the current column. */\nexport function addColumnLeft(context: PluginContext): boolean {\n\treturn addColumn(context, 'left');\n}\n\n/** Adds a column to the right of the current column. */\nexport function addColumnRight(context: PluginContext): boolean {\n\treturn addColumn(context, 'right');\n}\n\nfunction addColumn(context: PluginContext, side: 'left' | 'right'): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst insertColIndex: number = side === 'left' ? tableCtx.colIndex : tableCtx.colIndex + 1;\n\tconst tr = buildInsertColumnTransaction(state, tableCtx.tableId, insertColIndex);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Deletes the current row. If it's the last row, deletes the entire table. */\nexport function deleteRow(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = buildDeleteRowTransaction(\n\t\tstate,\n\t\ttableCtx.tableId,\n\t\ttableCtx.rowIndex,\n\t\ttableCtx.colIndex,\n\t);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Deletes the current column. If it's the last column, deletes the entire table. */\nexport function deleteColumn(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst tr = buildDeleteColumnTransaction(\n\t\tstate,\n\t\ttableCtx.tableId,\n\t\ttableCtx.colIndex,\n\t\ttableCtx.rowIndex,\n\t);\n\tif (!tr) return false;\n\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Deletes the entire table and moves cursor to surrounding block. */\nexport function deleteTable(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst target = resolveTableDeletionTarget(state);\n\tif (!target) return false;\n\n\tconst tr = createDeleteTableTransaction(state, target.tableId);\n\tif (!tr) return false;\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Selects the surrounding table as a node object. */\nexport function selectTable(context: PluginContext): boolean {\n\tconst state = context.getState();\n\tconst sel = state.selection;\n\n\tif (isNodeSelection(sel)) {\n\t\tconst selectedNode = state.getBlock(sel.nodeId);\n\t\treturn selectedNode?.type === 'table';\n\t}\n\n\tconst tableCtx: TableContext | null = findTableContext(state, sel.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tconst path = state.getNodePath(tableCtx.tableId);\n\tif (!path) return false;\n\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.setSelection(createNodeSelection(tableCtx.tableId, path))\n\t\t.build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Registers all table commands on the given plugin context. */\nexport function registerTableCommands(context: PluginContext): void {\n\tcontext.registerCommand('insertTable', () => insertTable(context, 3, 3));\n\tcontext.registerCommand('addRowAbove', () => addRowAbove(context));\n\tcontext.registerCommand('addRowBelow', () => addRowBelow(context));\n\tcontext.registerCommand('addColumnLeft', () => addColumnLeft(context));\n\tcontext.registerCommand('addColumnRight', () => addColumnRight(context));\n\tcontext.registerCommand('deleteRow', () => deleteRow(context));\n\tcontext.registerCommand('deleteColumn', () => deleteColumn(context));\n\tcontext.registerCommand('selectTable', () => selectTable(context));\n\tcontext.registerCommand('deleteTable', () => deleteTable(context));\n}\n\nfunction resolveTableDeletionTarget(\n\tstate: ReturnType<PluginContext['getState']>,\n): TableDeletionTarget | null {\n\tif (isNodeSelection(state.selection)) {\n\t\tconst selectedNode = state.getBlock(state.selection.nodeId);\n\t\tif (selectedNode?.type !== 'table') return null;\n\t\treturn { tableId: selectedNode.id };\n\t}\n\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return null;\n\n\treturn { tableId: tableCtx.tableId };\n}\n","/**\n * Keyboard navigation handlers for table cells.\n * Handles Tab, Shift-Tab, arrow keys, Enter, Backspace, Delete, and Escape.\n */\n\nimport type { Keymap } from '../../input/Keymap.js';\nimport { getBlockLength } from '../../model/Document.js';\nimport {\n\ttype Selection,\n\tcreateCollapsedSelection,\n\tcreateNodeSelection,\n\tisCollapsed,\n\tisNodeSelection,\n} from '../../model/Selection.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { addRowBelow } from './TableCommands.js';\nimport {\n\ttype TableContext,\n\tfindTableContext,\n\tgetCellAt,\n\tgetFirstLeafInCell,\n\tgetLastLeafInCell,\n} from './TableHelpers.js';\n\n/** Registers all table navigation keymaps. */\nexport function registerTableKeymaps(context: PluginContext): void {\n\tconst keymap: Keymap = {\n\t\tTab: () => handleTab(context),\n\t\t'Shift-Tab': () => handleShiftTab(context),\n\t\tEnter: () => handleEnter(context),\n\t\tBackspace: () => handleBackspace(context),\n\t\tDelete: () => handleDelete(context),\n\t\tArrowDown: () => handleArrowDown(context),\n\t\tArrowUp: () => handleArrowUp(context),\n\t\tArrowRight: () => handleArrowRight(context),\n\t\tArrowLeft: () => handleArrowLeft(context),\n\t\tEscape: () => handleEscape(context),\n\t};\n\n\tcontext.registerKeymap(keymap);\n}\n\n/**\n * Guards against NodeSelection and resolves TableContext.\n * Passes the narrowed text Selection to the handler, avoiding re-narrowing.\n * Returns false (not handled) if the cursor is not inside a table.\n */\nfunction withTableContext(\n\tcontext: PluginContext,\n\thandler: (state: EditorState, sel: Selection, tableCtx: TableContext) => boolean,\n): boolean {\n\tconst state: EditorState = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\tconst sel: Selection = state.selection;\n\tconst tableCtx: TableContext | null = findTableContext(state, sel.anchor.blockId);\n\tif (!tableCtx) return false;\n\treturn handler(state, sel, tableCtx);\n}\n\n/** Tab: move to next cell. At end of table, add a new row. */\nfunction handleTab(context: PluginContext): boolean {\n\treturn withTableContext(context, (_state, _sel, tableCtx) => {\n\t\tif (tableCtx.colIndex < tableCtx.totalCols - 1) {\n\t\t\treturn moveToCellAndSelect(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex,\n\t\t\t\ttableCtx.colIndex + 1,\n\t\t\t);\n\t\t}\n\n\t\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, 0);\n\t\t}\n\n\t\taddRowBelow(context);\n\t\treturn true;\n\t});\n}\n\n/** Shift-Tab: move to previous cell. At start of table, stay put. */\nfunction handleShiftTab(context: PluginContext): boolean {\n\treturn withTableContext(context, (_state, _sel, tableCtx) => {\n\t\tif (tableCtx.colIndex > 0) {\n\t\t\treturn moveToCellAndSelect(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex,\n\t\t\t\ttableCtx.colIndex - 1,\n\t\t\t);\n\t\t}\n\n\t\tif (tableCtx.rowIndex > 0) {\n\t\t\treturn moveToCellAndSelect(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex - 1,\n\t\t\t\ttableCtx.totalCols - 1,\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t});\n}\n\n/** Enter: move to same column in next row (spreadsheet behavior). */\nfunction handleEnter(context: PluginContext): boolean {\n\tconst state: EditorState = context.getState();\n\tif (isNodeSelection(state.selection)) return false;\n\n\tconst block = state.getBlock(state.selection.anchor.blockId);\n\t// Only intercept Enter for paragraphs inside table cells.\n\t// Other block types (list_item, heading, etc.) are handled by their plugins.\n\tif (block && block.type !== 'paragraph') return false;\n\n\tconst tableCtx: TableContext | null = findTableContext(state, state.selection.anchor.blockId);\n\tif (!tableCtx) return false;\n\n\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, tableCtx.colIndex);\n\t}\n\n\t// On last row — block to prevent splitBlock\n\treturn true;\n}\n\n/** Backspace at deletion-boundary: select table node (first step of 2-step delete). */\nfunction handleBackspace(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tif (!isCollapsed(sel)) return false;\n\t\tif (sel.anchor.offset !== 0) return false;\n\n\t\tconst isAtDeletionBoundary: boolean = tableCtx.rowIndex === 0 && tableCtx.colIndex === 0;\n\t\tif (!isAtDeletionBoundary) return false;\n\n\t\tconst firstLeaf: BlockId = getFirstLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== firstLeaf) return false;\n\n\t\treturn selectTableNode(context, tableCtx.tableId);\n\t});\n}\n\n/** Delete at deletion-boundary: select table node (first step of 2-step delete). */\nfunction handleDelete(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tif (!isCollapsed(sel)) return false;\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tconst blockLen: number = getBlockLength(block);\n\t\tif (sel.anchor.offset !== blockLen) return false;\n\n\t\tconst isAtDeletionBoundary: boolean =\n\t\t\ttableCtx.rowIndex === tableCtx.totalRows - 1 && tableCtx.colIndex === tableCtx.totalCols - 1;\n\t\tif (!isAtDeletionBoundary) return false;\n\n\t\tconst lastLeaf: BlockId = getLastLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== lastLeaf) return false;\n\n\t\treturn selectTableNode(context, tableCtx.tableId);\n\t});\n}\n\n/** ArrowDown: move to same column in next row. */\nfunction handleArrowDown(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tconst lastLeaf: BlockId = getLastLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== lastLeaf) return false;\n\n\t\tif (tableCtx.rowIndex >= tableCtx.totalRows - 1) {\n\t\t\treturn handleEscape(context);\n\t\t}\n\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, tableCtx.colIndex);\n\t});\n}\n\n/** ArrowUp: move to same column in previous row. */\nfunction handleArrowUp(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tconst firstLeaf: BlockId = getFirstLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== firstLeaf) return false;\n\n\t\tif (tableCtx.rowIndex <= 0) return false;\n\n\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex - 1, tableCtx.colIndex);\n\t});\n}\n\n/** ArrowRight at cell end: move to next cell. */\nfunction handleArrowRight(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tif (!isCollapsed(sel)) return false;\n\n\t\tconst block = state.getBlock(sel.anchor.blockId);\n\t\tif (!block) return false;\n\n\t\tconst blockLen: number = getBlockLength(block);\n\t\tif (sel.anchor.offset !== blockLen) return false;\n\n\t\tconst lastLeaf: BlockId = getLastLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== lastLeaf) return false;\n\n\t\tif (tableCtx.colIndex < tableCtx.totalCols - 1) {\n\t\t\treturn moveToCellAndSelect(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex,\n\t\t\t\ttableCtx.colIndex + 1,\n\t\t\t);\n\t\t}\n\n\t\tif (tableCtx.rowIndex < tableCtx.totalRows - 1) {\n\t\t\treturn moveToCellAndSelect(context, tableCtx.tableId, tableCtx.rowIndex + 1, 0);\n\t\t}\n\n\t\treturn true;\n\t});\n}\n\n/** ArrowLeft at cell start: move to previous cell. */\nfunction handleArrowLeft(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, sel, tableCtx) => {\n\t\tif (!isCollapsed(sel)) return false;\n\t\tif (sel.anchor.offset !== 0) return false;\n\n\t\tconst firstLeaf: BlockId = getFirstLeafInCell(state, tableCtx.cellId);\n\t\tif (sel.anchor.blockId !== firstLeaf) return false;\n\n\t\tif (tableCtx.colIndex > 0) {\n\t\t\treturn moveToCellAtEnd(context, tableCtx.tableId, tableCtx.rowIndex, tableCtx.colIndex - 1);\n\t\t}\n\n\t\tif (tableCtx.rowIndex > 0) {\n\t\t\treturn moveToCellAtEnd(\n\t\t\t\tcontext,\n\t\t\t\ttableCtx.tableId,\n\t\t\t\ttableCtx.rowIndex - 1,\n\t\t\t\ttableCtx.totalCols - 1,\n\t\t\t);\n\t\t}\n\n\t\treturn true;\n\t});\n}\n\n/** Escape: move cursor to the paragraph after the table. */\nfunction handleEscape(context: PluginContext): boolean {\n\treturn withTableContext(context, (state, _sel, tableCtx) => {\n\t\tconst nextIndex: number = tableCtx.tableIndex + 1;\n\t\tif (nextIndex >= state.doc.children.length) return false;\n\n\t\tconst nextBlock = state.doc.children[nextIndex];\n\t\tif (!nextBlock) return false;\n\n\t\tconst tr = state\n\t\t\t.transaction('command')\n\t\t\t.setSelection(createCollapsedSelection(nextBlock.id, 0))\n\t\t\t.build();\n\t\tcontext.dispatch(tr);\n\t\treturn true;\n\t});\n}\n\n// --- Cell navigation helpers ---\n\n/** Moves cursor to the start of a cell (first leaf block inside). */\nfunction moveToCellAndSelect(\n\tcontext: PluginContext,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): boolean {\n\tconst state: EditorState = context.getState();\n\tconst cellId: BlockId | null = getCellAt(state, tableId, rowIndex, colIndex);\n\tif (!cellId) return false;\n\n\tconst leafId: BlockId = getFirstLeafInCell(state, cellId);\n\tconst tr = state.transaction('command').setSelection(createCollapsedSelection(leafId, 0)).build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Moves cursor to the end of a cell (last leaf block inside, for ArrowLeft). */\nfunction moveToCellAtEnd(\n\tcontext: PluginContext,\n\ttableId: BlockId,\n\trowIndex: number,\n\tcolIndex: number,\n): boolean {\n\tconst state: EditorState = context.getState();\n\tconst cellId: BlockId | null = getCellAt(state, tableId, rowIndex, colIndex);\n\tif (!cellId) return false;\n\n\tconst leafId: BlockId = getLastLeafInCell(state, cellId);\n\tconst leaf = state.getBlock(leafId);\n\tif (!leaf) return false;\n\n\tconst leafLen: number = getBlockLength(leaf);\n\tconst tr = state\n\t\t.transaction('command')\n\t\t.setSelection(createCollapsedSelection(leafId, leafLen))\n\t\t.build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n\n/** Switches current selection to a table NodeSelection. */\nfunction selectTableNode(context: PluginContext, tableId: BlockId): boolean {\n\tconst state: EditorState = context.getState();\n\tconst path = state.getNodePath(tableId);\n\tif (!path) return false;\n\n\tconst tr = state.transaction('input').setSelection(createNodeSelection(tableId, path)).build();\n\tcontext.dispatch(tr);\n\treturn true;\n}\n","/**\n * Pure DOM factory functions for table controls.\n * No state logic — only element creation and CSS class assignment.\n */\n\n// --- SVG Icons ---\n\nexport const PLUS_SVG: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" ' +\n\t'viewBox=\"0 0 12 12\" fill=\"none\">' +\n\t'<path d=\"M6 1v10M1 6h10\" stroke=\"currentColor\" ' +\n\t'stroke-width=\"1.8\" stroke-linecap=\"round\"/></svg>';\n\nexport const DELETE_SVG: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"10\" height=\"10\" ' +\n\t'viewBox=\"0 0 10 10\" fill=\"none\">' +\n\t'<path d=\"M2 2l6 6M8 2l-6 6\" stroke=\"currentColor\" ' +\n\t'stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>';\n\nexport const TABLE_DELETE_SVG: string =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" ' +\n\t'viewBox=\"0 0 24 24\" fill=\"none\">' +\n\t'<path d=\"M9 3h6m-9 4h12M10 11v6m4-6v6m-9 3h14l-1-13H6L5 20z\" ' +\n\t'stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" ' +\n\t'stroke-linejoin=\"round\"/></svg>';\n\n// --- DOM Factories ---\n\n/** Creates a button with standard table-control setup (mousedown prevention, ARIA). */\nexport function createButton(\n\tclassName: string,\n\tinnerHTML: string,\n\ttitle: string,\n): HTMLButtonElement {\n\tconst btn: HTMLButtonElement = document.createElement('button');\n\tbtn.className = className;\n\tbtn.innerHTML = innerHTML;\n\tbtn.title = title;\n\tbtn.type = 'button';\n\tbtn.setAttribute('aria-label', title);\n\tbtn.setAttribute('contenteditable', 'false');\n\tbtn.addEventListener('mousedown', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t});\n\treturn btn;\n}\n\n/** Builds the insert-line element (horizontal or vertical) with a plus-icon button. */\nexport function buildInsertLine(orientation: 'horizontal' | 'vertical'): HTMLDivElement {\n\tconst line: HTMLDivElement = document.createElement('div');\n\tline.className = `ntbl-insert-line ntbl-insert-line--${orientation}`;\n\tline.setAttribute('contenteditable', 'false');\n\tline.setAttribute('data-notectl-no-print', '');\n\n\tconst title: string = orientation === 'horizontal' ? 'Insert row' : 'Insert column';\n\tconst btn: HTMLButtonElement = createButton('ntbl-insert-btn', PLUS_SVG, title);\n\tline.appendChild(btn);\n\n\treturn line;\n}\n\n/** Builds a zone-button for adding rows or columns at the table edge. */\nexport function buildAddButton(className: string, title: string): HTMLButtonElement {\n\tconst btn: HTMLButtonElement = document.createElement('button');\n\tbtn.className = `ntbl-add-zone ${className}`;\n\tbtn.type = 'button';\n\tbtn.setAttribute('contenteditable', 'false');\n\tbtn.setAttribute('aria-label', title);\n\tbtn.setAttribute('data-notectl-no-print', '');\n\tbtn.title = title;\n\n\tconst icon: HTMLSpanElement = document.createElement('span');\n\ticon.className = 'ntbl-add-icon';\n\ticon.innerHTML = PLUS_SVG;\n\tbtn.appendChild(icon);\n\n\tbtn.addEventListener('mousedown', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t});\n\n\treturn btn;\n}\n\n/** Builds a handle-bar container (for column or row handles). */\nexport function buildHandleBar(className: string): HTMLDivElement {\n\tconst bar: HTMLDivElement = document.createElement('div');\n\tbar.className = className;\n\tbar.setAttribute('contenteditable', 'false');\n\tbar.setAttribute('data-notectl-no-print', '');\n\treturn bar;\n}\n\n/** Builds a single column or row handle with a delete button. */\nexport function buildHandle(\n\tclassName: string,\n\tindex: number,\n\tdeleteLabel: string,\n\tonDelete: (idx: number) => void,\n): HTMLDivElement {\n\tconst handle: HTMLDivElement = document.createElement('div');\n\thandle.className = `ntbl-handle ${className}`;\n\thandle.dataset.index = String(index);\n\n\tconst deleteBtn: HTMLButtonElement = createButton('ntbl-handle-delete', DELETE_SVG, deleteLabel);\n\tdeleteBtn.addEventListener('click', (e: MouseEvent) => {\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tonDelete(index);\n\t});\n\thandle.appendChild(deleteBtn);\n\n\treturn handle;\n}\n","/**\n * Measurement and positioning logic for table controls.\n * All functions are pure (take numeric/DOM inputs, return structured results).\n */\n\n// --- Types ---\n\nexport interface BorderInfo {\n\treadonly position: number;\n\treadonly index: number;\n}\n\nexport interface NearestBorderResult {\n\treadonly type: 'row' | 'col' | 'none';\n\treadonly border: BorderInfo | null;\n}\n\n// --- Constants ---\n\nexport const BORDER_THRESHOLD: number = 10;\n\n// --- Offset ---\n\n/** Returns the table's offset relative to the container (walks offsetParent chain). */\nexport function getTableOffset(\n\ttableEl: HTMLElement,\n\tcontainer: HTMLElement,\n): { top: number; left: number } {\n\tlet top = 0;\n\tlet left = 0;\n\tlet el: HTMLElement | null = tableEl;\n\twhile (el && el !== container) {\n\t\ttop += el.offsetTop;\n\t\tleft += el.offsetLeft;\n\t\tel = el.offsetParent as HTMLElement | null;\n\t}\n\treturn { top, left };\n}\n\n// --- Border Measurement ---\n\n/** Measures the Y-positions of inter-row borders (between adjacent <tr> elements). */\nexport function measureRowBorders(tableEl: HTMLTableElement): BorderInfo[] {\n\tconst trs: NodeListOf<HTMLTableRowElement> = tableEl.querySelectorAll(':scope > tbody > tr');\n\tconst tableTop: number = tableEl.offsetTop;\n\tconst borders: BorderInfo[] = [];\n\n\tfor (let i = 1; i < trs.length; i++) {\n\t\tconst tr: HTMLTableRowElement | undefined = trs[i];\n\t\tif (!tr) continue;\n\t\tborders.push({\n\t\t\tposition: tr.offsetTop - tableTop,\n\t\t\tindex: i,\n\t\t});\n\t}\n\n\treturn borders;\n}\n\n/** Measures the X-positions of inter-column borders (evenly spaced). */\nexport function measureColBorders(tableWidth: number, numCols: number): BorderInfo[] {\n\tif (numCols <= 1) return [];\n\n\tconst colWidth: number = tableWidth / numCols;\n\tconst borders: BorderInfo[] = [];\n\n\tfor (let i = 1; i < numCols; i++) {\n\t\tborders.push({\n\t\t\tposition: Math.round(colWidth * i),\n\t\t\tindex: i,\n\t\t});\n\t}\n\n\treturn borders;\n}\n\n// --- Positioning ---\n\n/** Positions column handles evenly across the table width. */\nexport function positionColHandles(\n\tcolBar: HTMLDivElement,\n\ttableWidth: number,\n\tnumCols: number,\n): void {\n\tconst handles: HTMLCollection = colBar.children;\n\tif (handles.length === 0) return;\n\n\tconst colWidth: number = tableWidth / numCols;\n\n\tfor (let i = 0; i < handles.length; i++) {\n\t\tconst h = handles[i] as HTMLElement;\n\t\th.style.left = `${Math.round(colWidth * i)}px`;\n\t\th.style.width = `${Math.round(colWidth)}px`;\n\t}\n\n\tcolBar.style.width = `${tableWidth}px`;\n}\n\n/** Positions row handles to match actual <tr> offsets and heights. */\nexport function positionRowHandles(rowBar: HTMLDivElement, tableEl: HTMLTableElement): void {\n\tconst handles: HTMLCollection = rowBar.children;\n\tif (handles.length === 0) return;\n\n\tconst trs: NodeListOf<HTMLTableRowElement> = tableEl.querySelectorAll(':scope > tbody > tr');\n\tconst tableTop: number = tableEl.offsetTop;\n\tlet totalHeight = 0;\n\n\tfor (let i = 0; i < handles.length; i++) {\n\t\tconst h = handles[i] as HTMLElement;\n\t\tconst tr: HTMLTableRowElement | undefined = trs[i];\n\t\tif (tr) {\n\t\t\tconst top: number = tr.offsetTop - tableTop;\n\t\t\tconst height: number = tr.offsetHeight;\n\t\t\th.style.top = `${top}px`;\n\t\t\th.style.height = `${height}px`;\n\t\t\ttotalHeight = top + height;\n\t\t}\n\t}\n\n\trowBar.style.height = `${totalHeight}px`;\n}\n\n/** Positions add-row and add-column buttons at the table edges. */\nexport function positionAddButtons(\n\taddRowZone: HTMLElement,\n\taddColZone: HTMLElement,\n\ttableEl: HTMLElement,\n\tcontainer: HTMLElement,\n): void {\n\tconst offset = getTableOffset(tableEl, container);\n\tconst tableHeight: number = tableEl.offsetHeight;\n\tconst tableWidth: number = tableEl.offsetWidth;\n\n\taddRowZone.style.width = `${tableWidth}px`;\n\taddRowZone.style.left = `${offset.left}px`;\n\n\taddColZone.style.height = `${tableHeight}px`;\n\taddColZone.style.top = `${offset.top}px`;\n}\n\n// --- Border Detection ---\n\n/**\n * Finds the nearest row or column border to the given mouse position.\n * Returns which border is closest (within threshold), preferring the nearer one.\n */\nexport function findNearestBorder(\n\tx: number,\n\ty: number,\n\trowBorders: readonly BorderInfo[],\n\tcolBorders: readonly BorderInfo[],\n): NearestBorderResult {\n\tlet nearestRowDist: number = Number.POSITIVE_INFINITY;\n\tlet nearestRowBorder: BorderInfo | null = null;\n\n\tfor (const border of rowBorders) {\n\t\tconst dist: number = Math.abs(y - border.position);\n\t\tif (dist < nearestRowDist && dist < BORDER_THRESHOLD) {\n\t\t\tnearestRowDist = dist;\n\t\t\tnearestRowBorder = border;\n\t\t}\n\t}\n\n\tlet nearestColDist: number = Number.POSITIVE_INFINITY;\n\tlet nearestColBorder: BorderInfo | null = null;\n\n\tfor (const border of colBorders) {\n\t\tconst dist: number = Math.abs(x - border.position);\n\t\tif (dist < nearestColDist && dist < BORDER_THRESHOLD) {\n\t\t\tnearestColDist = dist;\n\t\t\tnearestColBorder = border;\n\t\t}\n\t}\n\n\tif (nearestRowBorder && (!nearestColBorder || nearestRowDist <= nearestColDist)) {\n\t\treturn { type: 'row', border: nearestRowBorder };\n\t}\n\n\tif (nearestColBorder) {\n\t\treturn { type: 'col', border: nearestColBorder };\n\t}\n\n\treturn { type: 'none', border: null };\n}\n","/**\n * Interactive table controls orchestrator.\n * Wires DOM elements (from TableControlsDOM) with layout logic (from TableControlsLayout)\n * and shared transaction builders (from TableCommands) to produce the interactive overlay.\n */\n\nimport type { BlockNode } from '../../model/Document.js';\nimport { getBlockChildren } from '../../model/Document.js';\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport {\n\tbuildDeleteColumnTransaction,\n\tbuildDeleteRowTransaction,\n\tbuildInsertColumnTransaction,\n\tbuildInsertRowTransaction,\n\tcreateDeleteTableTransaction,\n} from './TableCommands.js';\nimport {\n\tTABLE_DELETE_SVG,\n\tbuildAddButton,\n\tbuildHandle,\n\tbuildHandleBar,\n\tbuildInsertLine,\n\tcreateButton,\n} from './TableControlsDOM.js';\nimport {\n\tBORDER_THRESHOLD,\n\ttype BorderInfo,\n\tfindNearestBorder,\n\tgetTableOffset,\n\tmeasureColBorders,\n\tmeasureRowBorders,\n\tpositionAddButtons,\n\tpositionColHandles,\n\tpositionRowHandles,\n} from './TableControlsLayout.js';\n\n// --- Types ---\n\nexport interface TableControlsHandle {\n\tupdate(node: BlockNode): void;\n\tdestroy(): void;\n}\n\n// --- Class ---\n\nclass TableControls implements TableControlsHandle {\n\tprivate tableId: BlockId;\n\tprivate numRows: number;\n\tprivate numCols: number;\n\tprivate activeRowIndex = -1;\n\tprivate activeColIndex = -1;\n\n\tprivate readonly colBar: HTMLDivElement;\n\tprivate readonly rowBar: HTMLDivElement;\n\tprivate readonly insertLineH: HTMLDivElement;\n\tprivate readonly insertLineV: HTMLDivElement;\n\tprivate readonly addRowZone: HTMLButtonElement;\n\tprivate readonly addColZone: HTMLButtonElement;\n\tprivate readonly deleteTableBtn: HTMLButtonElement;\n\tprivate readonly observer: ResizeObserver;\n\n\tprivate readonly container: HTMLElement;\n\tprivate readonly tableEl: HTMLTableElement;\n\tprivate readonly getState: () => EditorState;\n\tprivate readonly dispatchFn: (tr: Transaction) => void;\n\n\tprivate readonly onMouseMove = (e: MouseEvent): void => {\n\t\tconst tableRect: DOMRect = this.tableEl.getBoundingClientRect();\n\t\tconst x: number = e.clientX - tableRect.left;\n\t\tconst y: number = e.clientY - tableRect.top;\n\n\t\tconst inTable: boolean =\n\t\t\tx >= -BORDER_THRESHOLD &&\n\t\t\tx <= tableRect.width + BORDER_THRESHOLD &&\n\t\t\ty >= -BORDER_THRESHOLD &&\n\t\t\ty <= tableRect.height + BORDER_THRESHOLD;\n\n\t\tif (!inTable) {\n\t\t\tthis.hideInsertLines();\n\t\t\treturn;\n\t\t}\n\n\t\tconst rowBorders: BorderInfo[] = measureRowBorders(this.tableEl);\n\t\tconst colBorders: BorderInfo[] = measureColBorders(this.tableEl.offsetWidth, this.numCols);\n\t\tconst result = findNearestBorder(x, y, rowBorders, colBorders);\n\n\t\tif (result.type === 'row' && result.border) {\n\t\t\tthis.showHorizontalLine(result.border);\n\t\t\tthis.hideVerticalLine();\n\t\t} else if (result.type === 'col' && result.border) {\n\t\t\tthis.showVerticalLine(result.border);\n\t\t\tthis.hideHorizontalLine();\n\t\t} else {\n\t\t\tthis.hideInsertLines();\n\t\t}\n\t};\n\n\tprivate readonly onMouseLeave = (): void => {\n\t\tthis.hideInsertLines();\n\t};\n\n\tconstructor(\n\t\tcontainer: HTMLElement,\n\t\ttableEl: HTMLTableElement,\n\t\tinitialNode: BlockNode,\n\t\tgetState: () => EditorState,\n\t\tdispatch: (tr: Transaction) => void,\n\t) {\n\t\tthis.container = container;\n\t\tthis.tableEl = tableEl;\n\t\tthis.getState = getState;\n\t\tthis.dispatchFn = dispatch;\n\n\t\tthis.tableId = initialNode.id;\n\t\tthis.numRows = getBlockChildren(initialNode).length;\n\t\tthis.numCols = this.countCols(initialNode);\n\n\t\t// Create DOM elements\n\t\tthis.colBar = buildHandleBar('ntbl-col-bar');\n\t\tthis.rowBar = buildHandleBar('ntbl-row-bar');\n\t\tthis.insertLineH = buildInsertLine('horizontal');\n\t\tthis.insertLineV = buildInsertLine('vertical');\n\t\tthis.addRowZone = buildAddButton('ntbl-add-row', 'Add row');\n\t\tthis.addColZone = buildAddButton('ntbl-add-col', 'Add column');\n\t\tthis.deleteTableBtn = createButton('ntbl-delete-table-btn', TABLE_DELETE_SVG, 'Delete table');\n\t\tthis.deleteTableBtn.setAttribute('data-notectl-no-print', '');\n\n\t\tcontainer.append(\n\t\t\tthis.colBar,\n\t\t\tthis.rowBar,\n\t\t\tthis.insertLineH,\n\t\t\tthis.insertLineV,\n\t\t\tthis.addRowZone,\n\t\t\tthis.addColZone,\n\t\t\tthis.deleteTableBtn,\n\t\t);\n\n\t\tthis.rebuildColHandles();\n\t\tthis.rebuildRowHandles();\n\t\tthis.bindEventListeners();\n\n\t\tthis.observer = new ResizeObserver(() => {\n\t\t\tthis.positionControls();\n\t\t});\n\t\tthis.observer.observe(tableEl);\n\t\trequestAnimationFrame(() => this.positionControls());\n\t}\n\n\tupdate(node: BlockNode): void {\n\t\tthis.tableId = node.id;\n\t\tconst newRows: number = getBlockChildren(node).length;\n\t\tconst newCols: number = this.countCols(node);\n\n\t\tif (newRows !== this.numRows || newCols !== this.numCols) {\n\t\t\tthis.numRows = newRows;\n\t\t\tthis.numCols = newCols;\n\t\t\tthis.rebuildColHandles();\n\t\t\tthis.rebuildRowHandles();\n\t\t}\n\n\t\trequestAnimationFrame(() => this.positionControls());\n\t}\n\n\tdestroy(): void {\n\t\tthis.observer.disconnect();\n\t\tthis.container.removeEventListener('mousemove', this.onMouseMove);\n\t\tthis.container.removeEventListener('mouseleave', this.onMouseLeave);\n\t\tthis.colBar.remove();\n\t\tthis.rowBar.remove();\n\t\tthis.insertLineH.remove();\n\t\tthis.insertLineV.remove();\n\t\tthis.addRowZone.remove();\n\t\tthis.addColZone.remove();\n\t\tthis.deleteTableBtn.remove();\n\t}\n\n\tprivate bindEventListeners(): void {\n\t\tconst insertBtnH = this.insertLineH.querySelector('.ntbl-insert-btn') as HTMLButtonElement;\n\t\tconst insertBtnV = this.insertLineV.querySelector('.ntbl-insert-btn') as HTMLButtonElement;\n\n\t\tinsertBtnH.addEventListener('click', () => {\n\t\t\tif (this.activeRowIndex >= 0) {\n\t\t\t\tthis.dispatchTransaction(\n\t\t\t\t\tbuildInsertRowTransaction(this.getState(), this.tableId, this.activeRowIndex),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tinsertBtnV.addEventListener('click', () => {\n\t\t\tif (this.activeColIndex >= 0) {\n\t\t\t\tthis.dispatchTransaction(\n\t\t\t\t\tbuildInsertColumnTransaction(this.getState(), this.tableId, this.activeColIndex),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tthis.addRowZone.addEventListener('click', () => {\n\t\t\tthis.dispatchTransaction(\n\t\t\t\tbuildInsertRowTransaction(this.getState(), this.tableId, this.numRows),\n\t\t\t);\n\t\t});\n\n\t\tthis.addColZone.addEventListener('click', () => {\n\t\t\tthis.dispatchTransaction(\n\t\t\t\tbuildInsertColumnTransaction(this.getState(), this.tableId, this.numCols),\n\t\t\t);\n\t\t});\n\n\t\tthis.deleteTableBtn.addEventListener('click', () => {\n\t\t\tthis.dispatchTransaction(createDeleteTableTransaction(this.getState(), this.tableId));\n\t\t});\n\n\t\tthis.container.addEventListener('mousemove', this.onMouseMove);\n\t\tthis.container.addEventListener('mouseleave', this.onMouseLeave);\n\t}\n\n\tprivate dispatchTransaction(tr: Transaction | null): void {\n\t\tif (tr) this.dispatchFn(tr);\n\t}\n\n\tprivate countCols(node: BlockNode): number {\n\t\tconst rows = getBlockChildren(node);\n\t\treturn rows[0] ? getBlockChildren(rows[0]).length : 0;\n\t}\n\n\tprivate positionControls(): void {\n\t\tpositionColHandles(this.colBar, this.tableEl.offsetWidth, this.numCols);\n\t\tpositionRowHandles(this.rowBar, this.tableEl);\n\t\tpositionAddButtons(this.addRowZone, this.addColZone, this.tableEl, this.container);\n\t}\n\n\tprivate showHorizontalLine(border: BorderInfo): void {\n\t\tthis.activeRowIndex = border.index;\n\t\tconst offset = getTableOffset(this.tableEl, this.container);\n\t\tthis.insertLineH.style.top = `${offset.top + border.position - 1}px`;\n\t\tthis.insertLineH.style.left = `${offset.left}px`;\n\t\tthis.insertLineH.style.width = `${this.tableEl.offsetWidth}px`;\n\t\tthis.insertLineH.classList.add('ntbl-insert-line--visible');\n\t}\n\n\tprivate showVerticalLine(border: BorderInfo): void {\n\t\tthis.activeColIndex = border.index;\n\t\tconst offset = getTableOffset(this.tableEl, this.container);\n\t\tthis.insertLineV.style.left = `${offset.left + border.position - 1}px`;\n\t\tthis.insertLineV.style.top = `${offset.top}px`;\n\t\tthis.insertLineV.style.height = `${this.tableEl.offsetHeight}px`;\n\t\tthis.insertLineV.classList.add('ntbl-insert-line--visible');\n\t}\n\n\tprivate hideInsertLines(): void {\n\t\tthis.hideHorizontalLine();\n\t\tthis.hideVerticalLine();\n\t}\n\n\tprivate hideHorizontalLine(): void {\n\t\tthis.insertLineH.classList.remove('ntbl-insert-line--visible');\n\t\tthis.activeRowIndex = -1;\n\t}\n\n\tprivate hideVerticalLine(): void {\n\t\tthis.insertLineV.classList.remove('ntbl-insert-line--visible');\n\t\tthis.activeColIndex = -1;\n\t}\n\n\tprivate rebuildColHandles(): void {\n\t\tthis.colBar.innerHTML = '';\n\t\tfor (let i = 0; i < this.numCols; i++) {\n\t\t\tconst handle: HTMLDivElement = buildHandle(\n\t\t\t\t'ntbl-col-handle',\n\t\t\t\ti,\n\t\t\t\t'Delete column',\n\t\t\t\t(idx: number) => {\n\t\t\t\t\tthis.dispatchTransaction(\n\t\t\t\t\t\tbuildDeleteColumnTransaction(this.getState(), this.tableId, idx),\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.colBar.appendChild(handle);\n\t\t}\n\t}\n\n\tprivate rebuildRowHandles(): void {\n\t\tthis.rowBar.innerHTML = '';\n\t\tfor (let i = 0; i < this.numRows; i++) {\n\t\t\tconst handle: HTMLDivElement = buildHandle(\n\t\t\t\t'ntbl-row-handle',\n\t\t\t\ti,\n\t\t\t\t'Delete row',\n\t\t\t\t(idx: number) => {\n\t\t\t\t\tthis.dispatchTransaction(buildDeleteRowTransaction(this.getState(), this.tableId, idx));\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.rowBar.appendChild(handle);\n\t\t}\n\t}\n}\n\n// --- Factory ---\n\n/** Creates table controls for the given table element. */\nexport function createTableControls(\n\tcontainer: HTMLElement,\n\ttableEl: HTMLTableElement,\n\tinitialNode: BlockNode,\n\tgetState: () => EditorState,\n\tdispatch: (tr: Transaction) => void,\n): TableControlsHandle {\n\treturn new TableControls(container, tableEl, initialNode, getState, dispatch);\n}\n","/**\n * Multi-cell selection service for tables.\n * Tracks selected cell range and provides IDs for bulk formatting.\n */\n\nimport type { BlockId } from '../../model/TypeBrands.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport { ServiceKey } from '../Plugin.js';\nimport type { PluginContext } from '../Plugin.js';\nimport { findTableContext, getCellAt } from './TableHelpers.js';\n\n/** Rectangular range of cells within a table. */\nexport interface CellRange {\n\treadonly tableId: BlockId;\n\treadonly fromRow: number;\n\treadonly fromCol: number;\n\treadonly toRow: number;\n\treadonly toCol: number;\n}\n\n/** Service for managing multi-cell selection. */\nexport interface TableSelectionService {\n\tgetSelectedRange(): CellRange | null;\n\tsetSelectedRange(range: CellRange | null): void;\n\tgetSelectedCellIds(): readonly BlockId[];\n\tisSelected(cellId: BlockId): boolean;\n}\n\nexport const TableSelectionServiceKey = new ServiceKey<TableSelectionService>('tableSelection');\n\n/** Creates and registers the TableSelectionService. */\nexport function createTableSelectionService(context: PluginContext): TableSelectionService {\n\tlet selectedRange: CellRange | null = null;\n\tlet cachedCellIds: readonly BlockId[] = [];\n\tlet cachedCellIdSet: Set<BlockId> = new Set();\n\n\tfunction updateCache(): void {\n\t\tif (!selectedRange) {\n\t\t\tcachedCellIds = [];\n\t\t\tcachedCellIdSet = new Set();\n\t\t\treturn;\n\t\t}\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst ids: BlockId[] = [];\n\n\t\tconst minRow: number = Math.min(selectedRange.fromRow, selectedRange.toRow);\n\t\tconst maxRow: number = Math.max(selectedRange.fromRow, selectedRange.toRow);\n\t\tconst minCol: number = Math.min(selectedRange.fromCol, selectedRange.toCol);\n\t\tconst maxCol: number = Math.max(selectedRange.fromCol, selectedRange.toCol);\n\n\t\tfor (let r = minRow; r <= maxRow; r++) {\n\t\t\tfor (let c = minCol; c <= maxCol; c++) {\n\t\t\t\tconst cellId: BlockId | null = getCellAt(state, selectedRange.tableId, r, c);\n\t\t\t\tif (cellId) ids.push(cellId);\n\t\t\t}\n\t\t}\n\n\t\tcachedCellIds = ids;\n\t\tcachedCellIdSet = new Set(ids);\n\t}\n\n\tconst service: TableSelectionService = {\n\t\tgetSelectedRange(): CellRange | null {\n\t\t\treturn selectedRange;\n\t\t},\n\n\t\tsetSelectedRange(range: CellRange | null): void {\n\t\t\tselectedRange = range;\n\t\t\tupdateCache();\n\t\t\tupdateCellHighlights(context, cachedCellIdSet);\n\t\t},\n\n\t\tgetSelectedCellIds(): readonly BlockId[] {\n\t\t\treturn cachedCellIds;\n\t\t},\n\n\t\tisSelected(cellId: BlockId): boolean {\n\t\t\treturn cachedCellIdSet.has(cellId);\n\t\t},\n\t};\n\n\tcontext.registerService(TableSelectionServiceKey, service);\n\treturn service;\n}\n\n/** Updates CSS class on selected cells for visual highlighting. */\nfunction updateCellHighlights(context: PluginContext, selectedIds: Set<BlockId>): void {\n\tconst container: HTMLElement = context.getContainer();\n\tconst cells: NodeListOf<Element> = container.querySelectorAll('td[data-block-id]');\n\n\tfor (const cell of cells) {\n\t\tconst cellId = cell.getAttribute('data-block-id') as BlockId;\n\t\tif (selectedIds.has(cellId)) {\n\t\t\tcell.classList.add('notectl-table-cell--selected');\n\t\t} else {\n\t\t\tcell.classList.remove('notectl-table-cell--selected');\n\t\t}\n\t}\n}\n\n/**\n * Installs mouse handlers for multi-cell selection on the editor container.\n * Returns a cleanup function.\n */\nexport function installMouseSelection(\n\tcontext: PluginContext,\n\tservice: TableSelectionService,\n): () => void {\n\tconst container: HTMLElement = context.getContainer();\n\tlet anchorCell: { tableId: BlockId; row: number; col: number } | null = null;\n\tlet isDragging = false;\n\n\tfunction handleMouseDown(e: MouseEvent): void {\n\t\tconst target = e.target as HTMLElement;\n\t\tconst cellEl: HTMLElement | null = target.closest('td[data-block-id]');\n\t\tif (!cellEl) {\n\t\t\tservice.setSelectedRange(null);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!e.shiftKey) {\n\t\t\t// Clear any existing multi-cell selection before starting a new anchor\n\t\t\tservice.setSelectedRange(null);\n\t\t\t// Start new selection anchor\n\t\t\tconst state: EditorState = context.getState();\n\t\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\t\tconst tableCtx = findTableContext(state, cellId);\n\t\t\tif (!tableCtx) return;\n\n\t\t\tanchorCell = {\n\t\t\t\ttableId: tableCtx.tableId,\n\t\t\t\trow: tableCtx.rowIndex,\n\t\t\t\tcol: tableCtx.colIndex,\n\t\t\t};\n\t\t\tisDragging = true;\n\t\t\t// Don't set range yet — wait for mousemove to avoid interfering with clicks\n\t\t} else if (anchorCell) {\n\t\t\t// Shift-click: extend selection\n\t\t\tconst state: EditorState = context.getState();\n\t\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\t\tconst tableCtx = findTableContext(state, cellId);\n\t\t\tif (!tableCtx || tableCtx.tableId !== anchorCell.tableId) return;\n\n\t\t\te.preventDefault();\n\t\t\tservice.setSelectedRange({\n\t\t\t\ttableId: anchorCell.tableId,\n\t\t\t\tfromRow: anchorCell.row,\n\t\t\t\tfromCol: anchorCell.col,\n\t\t\t\ttoRow: tableCtx.rowIndex,\n\t\t\t\ttoCol: tableCtx.colIndex,\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction handleMouseMove(e: MouseEvent): void {\n\t\tif (!isDragging || !anchorCell) return;\n\n\t\tconst target = e.target as HTMLElement;\n\t\tconst cellEl: HTMLElement | null = target.closest('td[data-block-id]');\n\t\tif (!cellEl) return;\n\n\t\tconst state: EditorState = context.getState();\n\t\tconst cellId = cellEl.getAttribute('data-block-id') as BlockId;\n\t\tconst tableCtx = findTableContext(state, cellId);\n\t\tif (!tableCtx || tableCtx.tableId !== anchorCell.tableId) return;\n\n\t\t// Only set range if we've moved to a different cell\n\t\tif (tableCtx.rowIndex !== anchorCell.row || tableCtx.colIndex !== anchorCell.col) {\n\t\t\te.preventDefault();\n\t\t\tservice.setSelectedRange({\n\t\t\t\ttableId: anchorCell.tableId,\n\t\t\t\tfromRow: anchorCell.row,\n\t\t\t\tfromCol: anchorCell.col,\n\t\t\t\ttoRow: tableCtx.rowIndex,\n\t\t\t\ttoCol: tableCtx.colIndex,\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction handleMouseUp(): void {\n\t\tisDragging = false;\n\t}\n\n\tcontainer.addEventListener('mousedown', handleMouseDown);\n\tcontainer.addEventListener('mousemove', handleMouseMove);\n\tdocument.addEventListener('mouseup', handleMouseUp);\n\n\treturn () => {\n\t\tcontainer.removeEventListener('mousedown', handleMouseDown);\n\t\tcontainer.removeEventListener('mousemove', handleMouseMove);\n\t\tdocument.removeEventListener('mouseup', handleMouseUp);\n\t};\n}\n","/**\n * TablePlugin: registers table, table_row, and table_cell node types\n * with NodeSpecs, NodeViews, commands, keyboard navigation, toolbar\n * grid picker, multi-cell selection, and context menu.\n */\n\nimport { TABLE_CSS } from '../../editor/styles/table.js';\nimport { isNodeSelection } from '../../model/Selection.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { Plugin, PluginContext } from '../Plugin.js';\nimport { insertTable, registerTableCommands } from './TableCommands.js';\nimport { isInsideTable } from './TableHelpers.js';\nimport { registerTableKeymaps } from './TableNavigation.js';\nimport {\n\tcreateTableCellNodeViewFactory,\n\tcreateTableNodeViewFactory,\n\tcreateTableRowNodeViewFactory,\n} from './TableNodeViews.js';\nimport {\n\ttype TableSelectionService,\n\tcreateTableSelectionService,\n\tinstallMouseSelection,\n} from './TableSelection.js';\n\n// --- Attribute Registry Augmentation ---\n\ndeclare module '../../model/AttrRegistry.js' {\n\tinterface NodeAttrRegistry {\n\t\ttable: Record<string, never>;\n\t\ttable_row: Record<string, never>;\n\t\ttable_cell: { colspan?: number; rowspan?: number };\n\t}\n}\n\n// --- Configuration ---\n\nexport interface TableConfig {\n\t/** Maximum rows in grid picker. Defaults to 8. */\n\treadonly maxPickerRows?: number;\n\t/** Maximum columns in grid picker. Defaults to 8. */\n\treadonly maxPickerCols?: number;\n\t/** When true, a separator is rendered after the table toolbar item. */\n\treadonly separatorAfter?: boolean;\n}\n\nconst DEFAULT_CONFIG: TableConfig = {\n\tmaxPickerRows: 8,\n\tmaxPickerCols: 8,\n};\n\n// --- SVG Icon ---\n\nconst TABLE_ICON =\n\t'<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">' +\n\t'<path d=\"M3 3h18v18H3V3zm2 2v4h6V5H5zm8 0v4h6V5h-6zm-8 6v4h6v-4H5z' +\n\t'm8 0v4h6v-4h-6zm-8 6v4h6v-4H5zm8 0v4h6v-4h-6z\"/></svg>';\n\n// --- Plugin ---\n\nexport class TablePlugin implements Plugin {\n\treadonly id = 'table';\n\treadonly name = 'Table';\n\treadonly priority = 40;\n\n\tprivate readonly config: TableConfig;\n\tprivate selectionService: TableSelectionService | null = null;\n\tprivate cleanupMouseSelection: (() => void) | null = null;\n\tprivate context: PluginContext | null = null;\n\n\tconstructor(config?: Partial<TableConfig>) {\n\t\tthis.config = { ...DEFAULT_CONFIG, ...config };\n\t}\n\n\tinit(context: PluginContext): void {\n\t\tcontext.registerStyleSheet(TABLE_CSS);\n\t\tthis.context = context;\n\n\t\tthis.registerNodeSpecs(context);\n\t\tthis.registerNodeViews(context);\n\t\tregisterTableCommands(context);\n\t\tregisterTableKeymaps(context);\n\t\tthis.registerToolbarItem(context);\n\t\tthis.selectionService = createTableSelectionService(context);\n\t}\n\n\tonReady(): void {\n\t\tif (this.context && this.selectionService) {\n\t\t\tthis.cleanupMouseSelection = installMouseSelection(this.context, this.selectionService);\n\t\t}\n\t}\n\n\tdestroy(): void {\n\t\tthis.cleanupMouseSelection?.();\n\t\tthis.cleanupMouseSelection = null;\n\t\tthis.selectionService = null;\n\t\tthis.context = null;\n\t}\n\n\tonStateChange(_oldState: EditorState, newState: EditorState, _tr: Transaction): void {\n\t\t// Clear multi-cell selection when cursor moves outside table\n\t\tif (this.selectionService?.getSelectedRange()) {\n\t\t\tconst sel = newState.selection;\n\t\t\tif (isNodeSelection(sel) || !isInsideTable(newState, sel.anchor.blockId)) {\n\t\t\t\tthis.selectionService.setSelectedRange(null);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate registerNodeSpecs(context: PluginContext): void {\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table',\n\t\t\tgroup: 'block',\n\t\t\tcontent: { allow: ['table_row'], min: 1 },\n\t\t\tisolating: true,\n\t\t\tselectable: true,\n\t\t\ttoDOM(node) {\n\t\t\t\tconst wrapper: HTMLDivElement = document.createElement('div');\n\t\t\t\twrapper.className = 'notectl-table-wrapper';\n\t\t\t\twrapper.setAttribute('data-block-id', node.id);\n\t\t\t\treturn wrapper;\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table_row',\n\t\t\tgroup: 'table_content',\n\t\t\tcontent: { allow: ['table_cell'], min: 1 },\n\t\t\ttoDOM(node) {\n\t\t\t\tconst tr: HTMLTableRowElement = document.createElement('tr');\n\t\t\t\ttr.setAttribute('data-block-id', node.id);\n\t\t\t\ttr.setAttribute('role', 'row');\n\t\t\t\treturn tr;\n\t\t\t},\n\t\t});\n\n\t\tcontext.registerNodeSpec({\n\t\t\ttype: 'table_cell',\n\t\t\tgroup: 'table_content',\n\t\t\tcontent: {\n\t\t\t\tallow: ['paragraph', 'list_item', 'heading', 'blockquote', 'image', 'horizontal_rule'],\n\t\t\t},\n\t\t\tisolating: true,\n\t\t\ttoDOM(node) {\n\t\t\t\tconst td: HTMLTableCellElement = document.createElement('td');\n\t\t\t\ttd.setAttribute('data-block-id', node.id);\n\t\t\t\ttd.setAttribute('role', 'cell');\n\t\t\t\treturn td;\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate registerNodeViews(context: PluginContext): void {\n\t\tconst registry = context.getSchemaRegistry();\n\n\t\tcontext.registerNodeView('table', createTableNodeViewFactory(registry));\n\t\tcontext.registerNodeView('table_row', createTableRowNodeViewFactory(registry));\n\t\tcontext.registerNodeView('table_cell', createTableCellNodeViewFactory(registry));\n\t}\n\n\tprivate registerToolbarItem(context: PluginContext): void {\n\t\tconst maxRows: number = this.config.maxPickerRows ?? 8;\n\t\tconst maxCols: number = this.config.maxPickerCols ?? 8;\n\n\t\tcontext.registerToolbarItem({\n\t\t\tid: 'table',\n\t\t\tgroup: 'insert',\n\t\t\ticon: TABLE_ICON,\n\t\t\tlabel: 'Insert Table',\n\t\t\ttooltip: 'Insert Table',\n\t\t\tcommand: 'insertTable',\n\t\t\tpriority: 80,\n\t\t\tseparatorAfter: this.config.separatorAfter,\n\t\t\tpopupType: 'gridPicker',\n\t\t\tpopupConfig: {\n\t\t\t\tmaxRows,\n\t\t\t\tmaxCols,\n\t\t\t\tonSelect: (rows: number, cols: number) => {\n\t\t\t\t\tinsertTable(context, rows, cols);\n\t\t\t\t},\n\t\t\t},\n\t\t\tisActive: (state: EditorState) => {\n\t\t\t\tif (isNodeSelection(state.selection)) return false;\n\t\t\t\treturn isInsideTable(state, state.selection.anchor.blockId);\n\t\t\t},\n\t\t});\n\t}\n}\n","/** Table styles — table layout, selection, context menu, controls, insert lines. */\nexport const TABLE_CSS = `\n/* Table */\n.notectl-table-wrapper {\n\tmargin: 8px 0;\n\toverflow-x: auto;\n\tposition: relative;\n}\n\n.notectl-table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n\ttable-layout: fixed;\n}\n\n.notectl-table td {\n\tborder: 1px solid var(--notectl-border);\n\tpadding: 8px 12px;\n\tmin-width: 60px;\n\tvertical-align: top;\n\tmin-height: 1.6em;\n}\n\n.notectl-table td:focus-within {\n\toutline: 2px solid var(--notectl-primary);\n\toutline-offset: -2px;\n}\n\n.notectl-table-cell--selected {\n\tbackground: var(--notectl-primary-muted);\n}\n\n/* Table Context Menu */\n.notectl-table-context-menu {\n\tposition: fixed;\n\tbackground: var(--notectl-surface-overlay);\n\tborder: 1px solid var(--notectl-border);\n\tborder-radius: 6px;\n\tbox-shadow: 0 4px 12px var(--notectl-shadow);\n\tpadding: 4px 0;\n\tmin-width: 180px;\n\tz-index: 10000;\n}\n\n.notectl-table-context-menu button {\n\tdisplay: block;\n\twidth: 100%;\n\tpadding: 8px 12px;\n\ttext-align: left;\n\tborder: none;\n\tbackground: none;\n\tcursor: pointer;\n\tfont-size: 14px;\n\tcolor: var(--notectl-fg);\n\tfont-family: inherit;\n}\n\n.notectl-table-context-menu button:hover {\n\tbackground: var(--notectl-hover-bg);\n}\n\n.notectl-table-context-menu hr {\n\tborder: none;\n\tborder-top: 1px solid var(--notectl-border);\n\tmargin: 4px 0;\n}\n\n/* === Table Controls === */\n\n/* Outer container for table + controls */\n.ntbl-container {\n\tposition: relative;\n\tmargin: 8px 0;\n\tpadding: 24px 0 0 24px;\n}\n\n.ntbl-container .notectl-table-wrapper {\n\tmargin: 0;\n}\n\n.ntbl-container.notectl-table--selected .notectl-table-wrapper {\n\toutline: 2px solid var(--notectl-primary-fg);\n\toutline-offset: 2px;\n\tborder-radius: 6px;\n}\n\n/* --- Column Handle Bar --- */\n.ntbl-col-bar {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 24px;\n\theight: 20px;\n\tdisplay: flex;\n\topacity: 0;\n\ttransition: opacity 0.2s ease;\n\tz-index: 3;\n\tpointer-events: none;\n}\n\n.ntbl-container:hover .ntbl-col-bar,\n.ntbl-container:focus-within .ntbl-col-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n.ntbl-container.notectl-table--selected .ntbl-col-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n/* --- Row Handle Bar --- */\n.ntbl-row-bar {\n\tposition: absolute;\n\ttop: 24px;\n\tleft: 0;\n\twidth: 20px;\n\tdisplay: flex;\n\tflex-direction: column;\n\topacity: 0;\n\ttransition: opacity 0.2s ease;\n\tz-index: 3;\n\tpointer-events: none;\n}\n\n.ntbl-container:hover .ntbl-row-bar,\n.ntbl-container:focus-within .ntbl-row-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n.ntbl-container.notectl-table--selected .ntbl-row-bar {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n/* --- Handle (shared base) --- */\n.ntbl-handle {\n\tposition: absolute;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcursor: pointer;\n\ttransition: background 0.15s ease;\n\tborder-radius: 3px;\n}\n\n.ntbl-col-handle {\n\theight: 100%;\n\tbackground: var(--notectl-hover-bg);\n\tborder-radius: 4px 4px 0 0;\n}\n\n.ntbl-col-handle:hover {\n\tbackground: var(--notectl-border);\n}\n\n.ntbl-row-handle {\n\twidth: 100%;\n\tbackground: var(--notectl-hover-bg);\n\tborder-radius: 4px 0 0 4px;\n}\n\n.ntbl-row-handle:hover {\n\tbackground: var(--notectl-border);\n}\n\n/* --- Handle Delete Button --- */\n.ntbl-handle-delete {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 16px;\n\theight: 16px;\n\tborder: none;\n\tbackground: transparent;\n\tcolor: var(--notectl-fg-muted);\n\tcursor: pointer;\n\tborder-radius: 3px;\n\tpadding: 0;\n\topacity: 0;\n\ttransform: scale(0.7);\n\ttransition: opacity 0.15s, transform 0.15s,\n\t\tbackground 0.15s, color 0.15s;\n}\n\n.ntbl-handle:hover .ntbl-handle-delete,\n.ntbl-handle:focus-within .ntbl-handle-delete {\n\topacity: 1;\n\ttransform: scale(1);\n}\n\n.ntbl-handle-delete:hover,\n.ntbl-handle-delete:focus-visible {\n\tbackground: var(--notectl-danger-muted);\n\tcolor: var(--notectl-danger);\n}\n\n.ntbl-handle-delete:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n/* --- Insert Lines --- */\n.ntbl-insert-line {\n\tposition: absolute;\n\tpointer-events: none;\n\topacity: 0;\n\ttransition: opacity 0.15s ease;\n\tz-index: 6;\n}\n\n.ntbl-insert-line--visible {\n\topacity: 1;\n\tpointer-events: auto;\n}\n\n.ntbl-insert-line--horizontal {\n\theight: 2px;\n\tbackground: linear-gradient(\n\t\t90deg,\n\t\ttransparent,\n\t\tvar(--notectl-primary) 8%,\n\t\tvar(--notectl-primary) 92%,\n\t\ttransparent\n\t);\n\tbox-shadow: 0 0 6px var(--notectl-focus-ring);\n}\n\n.ntbl-insert-line--vertical {\n\twidth: 2px;\n\tbackground: linear-gradient(\n\t\t180deg,\n\t\ttransparent,\n\t\tvar(--notectl-primary) 8%,\n\t\tvar(--notectl-primary) 92%,\n\t\ttransparent\n\t);\n\tbox-shadow: 0 0 6px var(--notectl-focus-ring);\n}\n\n/* --- Insert Button on Line --- */\n.ntbl-insert-btn {\n\tposition: absolute;\n\twidth: 20px;\n\theight: 20px;\n\tborder-radius: 50%;\n\tbackground: var(--notectl-bg);\n\tborder: 2px solid var(--notectl-primary);\n\tcolor: var(--notectl-primary);\n\tcursor: pointer;\n\tpointer-events: all;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: 0;\n\tbox-shadow: 0 2px 8px var(--notectl-focus-ring);\n\ttransition: background 0.15s, color 0.15s,\n\t\ttransform 0.15s, box-shadow 0.15s;\n}\n\n.ntbl-insert-line--horizontal .ntbl-insert-btn {\n\tleft: 50%;\n\ttop: -9px;\n\ttransform: translateX(-50%);\n}\n\n.ntbl-insert-line--vertical .ntbl-insert-btn {\n\ttop: 50%;\n\tleft: -9px;\n\ttransform: translateY(-50%);\n}\n\n.ntbl-insert-btn:hover,\n.ntbl-insert-btn:focus-visible {\n\tbackground: var(--notectl-primary);\n\tcolor: var(--notectl-bg);\n\tbox-shadow: 0 2px 12px var(--notectl-focus-ring);\n}\n\n.ntbl-insert-btn:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n.ntbl-insert-line--horizontal .ntbl-insert-btn:hover {\n\ttransform: translateX(-50%) scale(1.2);\n}\n\n.ntbl-insert-line--vertical .ntbl-insert-btn:hover {\n\ttransform: translateY(-50%) scale(1.2);\n}\n\n/* --- Add Row / Add Column Zones --- */\n.ntbl-add-zone {\n\tposition: absolute;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcursor: pointer;\n\tuser-select: none;\n\topacity: 0;\n\ttransition: opacity 0.2s ease, background 0.2s ease,\n\t\tborder-color 0.2s ease;\n}\n\n.ntbl-container:hover .ntbl-add-zone,\n.ntbl-container:focus-within .ntbl-add-zone {\n\topacity: 1;\n}\n\n.ntbl-container.notectl-table--selected .ntbl-add-zone {\n\topacity: 1;\n}\n\n.ntbl-delete-table-btn {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 20px;\n\theight: 20px;\n\tborder: 1px solid var(--notectl-danger);\n\tborder-radius: 4px;\n\tbackground: var(--notectl-bg);\n\tcolor: var(--notectl-danger);\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\topacity: 0;\n\ttransition: opacity 0.2s ease, background 0.15s, border-color 0.15s;\n\tz-index: 7;\n}\n\n.ntbl-container:hover .ntbl-delete-table-btn,\n.ntbl-container:focus-within .ntbl-delete-table-btn,\n.ntbl-container.notectl-table--selected .ntbl-delete-table-btn {\n\topacity: 1;\n}\n\n.ntbl-delete-table-btn:hover,\n.ntbl-delete-table-btn:focus-visible {\n\tbackground: var(--notectl-danger-muted);\n\tborder-color: var(--notectl-danger);\n}\n\n.ntbl-delete-table-btn:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n.ntbl-add-row {\n\tbottom: 0;\n\theight: 24px;\n\tborder: 1px dashed var(--notectl-border);\n\tborder-radius: 0 0 6px 6px;\n\tborder-top: none;\n\tcolor: var(--notectl-fg-muted);\n\ttransform: translateY(100%);\n}\n\n.ntbl-add-row:hover,\n.ntbl-add-row:focus-visible {\n\tbackground: var(--notectl-primary-muted);\n\tborder-color: var(--notectl-primary);\n\tcolor: var(--notectl-primary);\n}\n\n.ntbl-add-row:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n.ntbl-add-col {\n\tright: 0;\n\ttop: 24px;\n\twidth: 24px;\n\tborder: 1px dashed var(--notectl-border);\n\tborder-radius: 0 6px 6px 0;\n\tborder-left: none;\n\tcolor: var(--notectl-fg-muted);\n\ttransform: translateX(100%);\n}\n\n.ntbl-add-col:hover,\n.ntbl-add-col:focus-visible {\n\tbackground: var(--notectl-primary-muted);\n\tborder-color: var(--notectl-primary);\n\tcolor: var(--notectl-primary);\n}\n\n.ntbl-add-col:focus-visible {\n\toutline: none;\n\tbox-shadow: 0 0 0 2px var(--notectl-focus-ring);\n}\n\n.ntbl-add-icon {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\ttransition: transform 0.2s ease;\n}\n\n.ntbl-add-zone:hover .ntbl-add-icon {\n\ttransform: scale(1.15);\n}\n`;\n","/**\n * NodeViewFactories for table, table_row, and table_cell.\n * Provides custom DOM rendering with proper HTML table elements and ARIA.\n * The table NodeView includes interactive controls for row/column management.\n */\n\nimport type { BlockNode } from '../../model/Document.js';\nimport { getBlockChildren } from '../../model/Document.js';\nimport type { SchemaRegistry } from '../../model/SchemaRegistry.js';\nimport type { EditorState } from '../../state/EditorState.js';\nimport type { Transaction } from '../../state/Transaction.js';\nimport type { NodeView, NodeViewFactory } from '../../view/NodeView.js';\nimport { type TableControlsHandle, createTableControls } from './TableControls.js';\n\n/**\n * Creates a NodeViewFactory for the table node type.\n * Renders as outer container with controls + table + tbody.\n */\nexport function createTableNodeViewFactory(_registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\tgetState: () => EditorState,\n\t\tdispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\t// Outer container: holds controls + wrapper\n\t\tconst container: HTMLDivElement = document.createElement('div');\n\t\tcontainer.className = 'ntbl-container';\n\t\tcontainer.setAttribute('data-block-id', node.id);\n\t\tcontainer.setAttribute('data-selectable', 'true');\n\n\t\t// Table wrapper: provides overflow scrolling\n\t\tconst wrapper: HTMLDivElement = document.createElement('div');\n\t\twrapper.className = 'notectl-table-wrapper';\n\n\t\tconst table: HTMLTableElement = document.createElement('table');\n\t\ttable.className = 'notectl-table';\n\t\ttable.setAttribute('role', 'table');\n\n\t\tconst rows: readonly BlockNode[] = getBlockChildren(node);\n\t\tconst totalRows: number = rows.length;\n\t\tconst totalCols: number = rows[0] ? getBlockChildren(rows[0]).length : 0;\n\t\ttable.setAttribute('aria-label', `Table with ${totalRows} rows and ${totalCols} columns`);\n\n\t\tconst tbody: HTMLTableSectionElement = document.createElement('tbody');\n\t\ttable.appendChild(tbody);\n\t\twrapper.appendChild(table);\n\t\tcontainer.appendChild(wrapper);\n\n\t\t// Live region for screen reader announcements\n\t\tconst liveRegion: HTMLDivElement = document.createElement('div');\n\t\tliveRegion.className = 'notectl-sr-only';\n\t\tliveRegion.setAttribute('aria-live', 'polite');\n\t\tliveRegion.setAttribute('aria-atomic', 'true');\n\t\tcontainer.appendChild(liveRegion);\n\n\t\t// Initialize interactive controls\n\t\tconst controls: TableControlsHandle = createTableControls(\n\t\t\tcontainer,\n\t\t\ttable,\n\t\t\tnode,\n\t\t\tgetState,\n\t\t\tdispatch,\n\t\t);\n\n\t\treturn {\n\t\t\tdom: container,\n\t\t\tcontentDOM: tbody,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table') return false;\n\t\t\t\tcontainer.setAttribute('data-block-id', updatedNode.id);\n\t\t\t\tcontainer.setAttribute('data-selectable', 'true');\n\t\t\t\tconst updatedRows: readonly BlockNode[] = getBlockChildren(updatedNode);\n\t\t\t\tconst newTotalRows: number = updatedRows.length;\n\t\t\t\tconst newTotalCols: number = updatedRows[0] ? getBlockChildren(updatedRows[0]).length : 0;\n\t\t\t\ttable.setAttribute(\n\t\t\t\t\t'aria-label',\n\t\t\t\t\t`Table with ${newTotalRows} rows and ${newTotalCols} columns`,\n\t\t\t\t);\n\n\t\t\t\t// Update controls to reflect new structure\n\t\t\t\tcontrols.update(updatedNode);\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\tcontrols.destroy();\n\t\t\t},\n\t\t\tselectNode(): void {\n\t\t\t\tcontainer.classList.add('notectl-table--selected');\n\t\t\t},\n\t\t\tdeselectNode(): void {\n\t\t\t\tcontainer.classList.remove('notectl-table--selected');\n\t\t\t},\n\t\t};\n\t};\n}\n\n/**\n * Creates a NodeViewFactory for the table_row node type.\n * Renders as `<tr role=\"row\">`.\n */\nexport function createTableRowNodeViewFactory(_registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\t_getState: () => EditorState,\n\t\t_dispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\tconst tr: HTMLTableRowElement = document.createElement('tr');\n\t\ttr.setAttribute('data-block-id', node.id);\n\t\ttr.setAttribute('role', 'row');\n\n\t\treturn {\n\t\t\tdom: tr,\n\t\t\tcontentDOM: tr,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table_row') return false;\n\t\t\t\ttr.setAttribute('data-block-id', updatedNode.id);\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\t// No cleanup needed\n\t\t\t},\n\t\t};\n\t};\n}\n\n/**\n * Creates a NodeViewFactory for the table_cell node type.\n * Renders as `<td role=\"cell\">` with text content rendered inside.\n */\nexport function createTableCellNodeViewFactory(_registry: SchemaRegistry): NodeViewFactory {\n\treturn (\n\t\tnode: BlockNode,\n\t\t_getState: () => EditorState,\n\t\t_dispatch: (tr: Transaction) => void,\n\t): NodeView => {\n\t\tconst td: HTMLTableCellElement = document.createElement('td');\n\t\ttd.setAttribute('data-block-id', node.id);\n\t\ttd.setAttribute('role', 'cell');\n\n\t\tconst colspan: number = (node.attrs?.colspan as number | undefined) ?? 1;\n\t\tconst rowspan: number = (node.attrs?.rowspan as number | undefined) ?? 1;\n\t\tif (colspan > 1) td.colSpan = colspan;\n\t\tif (rowspan > 1) td.rowSpan = rowspan;\n\n\t\t// Apply alignment from AlignmentPlugin's patched attribute\n\t\tconst align: string | undefined = node.attrs?.align as string | undefined;\n\t\tif (align && align !== 'left') {\n\t\t\ttd.style.textAlign = align;\n\t\t}\n\n\t\treturn {\n\t\t\tdom: td,\n\t\t\tcontentDOM: td,\n\t\t\tupdate(updatedNode: BlockNode): boolean {\n\t\t\t\tif (updatedNode.type !== 'table_cell') return false;\n\t\t\t\ttd.setAttribute('data-block-id', updatedNode.id);\n\n\t\t\t\tconst newColspan: number = (updatedNode.attrs?.colspan as number | undefined) ?? 1;\n\t\t\t\tconst newRowspan: number = (updatedNode.attrs?.rowspan as number | undefined) ?? 1;\n\t\t\t\tif (newColspan > 1) {\n\t\t\t\t\ttd.colSpan = newColspan;\n\t\t\t\t} else {\n\t\t\t\t\ttd.removeAttribute('colspan');\n\t\t\t\t}\n\t\t\t\tif (newRowspan > 1) {\n\t\t\t\t\ttd.rowSpan = newRowspan;\n\t\t\t\t} else {\n\t\t\t\t\ttd.removeAttribute('rowspan');\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\tdestroy(): void {\n\t\t\t\t// No cleanup needed\n\t\t\t},\n\t\t};\n\t};\n}\n"],"names":["createTableCell","paragraph","createBlockNode","nodeType","createTextNode","generateBlockId","findTableContext","state","blockId","path","getNodePath","tableId","tableNode","rowId","cellId","id","node","getBlock","type","block","tableIndex","doc","children","findIndex","b","rows","getBlockChildren","rowIndex","r","rowNode","cells","colIndex","c","totalCols","length","totalRows","getCellAt","table","row","cell","getFirstLeafInCell","first","current","next","getLastLeafInCell","blockChildren","last","isInsideTable","buildInsertRowTransaction","numCols","newRow","cols","cellNodes","push","tr","transaction","insertNode","firstCell","firstLeaf","setSelection","createCollapsedSelection","build","buildInsertColumnTransaction","newCell","selection","buildDeleteRowTransaction","preferredCol","createDeleteTableTransaction","removeNode","leafId","buildDeleteColumnTransaction","preferredRow","nextRoot","prevRoot","insertTable","context","getState","sel","isNodeSelection","currentBlockId","anchor","rootIndex","i","rootBlock","rowNodes","paragraphAfter","insertIndex","firstRow","firstParagraph","dispatch","addRowBelow","tableCtx","addColumn","side","insertColIndex","registerTableCommands","registerCommand","selectedNode","nodeId","createNodeSelection","target","withTableContext","handler","handleEscape","_sel","nextIndex","nextBlock","moveToCellAndSelect","moveToCellAtEnd","leaf","leafLen","getBlockLength","selectTableNode","PLUS_SVG","createButton","className","innerHTML","title","btn","document","createElement","setAttribute","addEventListener","e","preventDefault","stopPropagation","buildInsertLine","orientation","line","appendChild","buildAddButton","icon","buildHandleBar","bar","buildHandle","index","deleteLabel","onDelete","handle","dataset","String","deleteBtn","getTableOffset","tableEl","container","top","left","el","offsetTop","offsetLeft","offsetParent","TableControls","numRows","activeRowIndex","activeColIndex","colBar","rowBar","insertLineH","insertLineV","addRowZone","addColZone","deleteTableBtn","observer","dispatchFn","onMouseMove","tableRect","this","getBoundingClientRect","x","clientX","y","clientY","width","height","hideInsertLines","result","rowBorders","colBorders","nearestRowDist","Number","POSITIVE_INFINITY","nearestRowBorder","border","dist","Math","abs","position","nearestColDist","nearestColBorder","trs","querySelectorAll","tableTop","borders","tableWidth","colWidth","round","offsetWidth","showHorizontalLine","hideVerticalLine","showVerticalLine","hideHorizontalLine","onMouseLeave","initialNode","countCols","append","rebuildColHandles","rebuildRowHandles","bindEventListeners","ResizeObserver","positionControls","observe","requestAnimationFrame","newRows","newCols","destroy","disconnect","removeEventListener","remove","insertBtnH","querySelector","insertBtnV","dispatchTransaction","handles","h","style","totalHeight","offsetHeight","offset","tableHeight","classList","add","idx","TableSelectionServiceKey","ServiceKey","DEFAULT_CONFIG","maxPickerRows","maxPickerCols","TablePlugin","name","priority","config","selectionService","cleanupMouseSelection","registerStyleSheet","registerNodeSpecs","registerNodeViews","keymap","Tab","_state","Enter","Backspace","isCollapsed","Delete","blockLen","lastLeaf","ArrowDown","ArrowUp","ArrowRight","ArrowLeft","Escape","registerKeymap","registerToolbarItem","selectedRange","cachedCellIds","cachedCellIdSet","Set","service","getSelectedRange","range","ids","minRow","min","fromRow","toRow","maxRow","max","minCol","fromCol","toCol","maxCol","updateCache","selectedIds","getContainer","getAttribute","has","getSelectedCellIds","isSelected","registerService","onReady","anchorCell","isDragging","handleMouseDown","cellEl","closest","shiftKey","setSelectedRange","col","handleMouseMove","handleMouseUp","_oldState","newState","_tr","registerNodeSpec","group","content","allow","isolating","selectable","wrapper","td","getSchemaRegistry","registerNodeView","tbody","liveRegion","controls","dom","contentDOM","updatedNode","updatedRows","newTotalRows","newTotalCols","update","selectNode","deselectNode","_getState","_dispatch","colspan","attrs","rowspan","colSpan","rowSpan","align","textAlign","newColspan","newRowspan","removeAttribute","maxRows","maxCols","label","tooltip","command","separatorAfter","popupType","popupConfig","onSelect","isActive"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/toolbar/ToolbarPlugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAcxE,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;CACtD;AAID,MAAM,WAAW,iBAAiB;IACjC,sEAAsE;IACtE,OAAO,IAAI,IAAI,CAAC;IAChB,+CAA+C;IAC/C,UAAU,IAAI,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,iBAAiB,+BAA+C,CAAC;AAS9E,qBAAa,aAAc,YAAW,MAAM;IAC3C,QAAQ,CAAC,EAAE,aAAa;IACxB,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,QAAQ,MAAM;IAEvB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,eAAe,CAAuC;gBAElD,YAAY,CAAC,EAAE,mBAAmB;IAI9C,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAelC,OAAO,IAAI,IAAI;IAIf,OAAO,IAAI,IAAI;IAaf,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI;IAIpF,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAavC,OAAO,CAAC,oBAAoB;
|
|
1
|
+
{"version":3,"file":"ToolbarPlugin.d.ts","sourceRoot":"","sources":["../../../src/plugins/toolbar/ToolbarPlugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAcxE,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;CACtD;AAID,MAAM,WAAW,iBAAiB;IACjC,sEAAsE;IACtE,OAAO,IAAI,IAAI,CAAC;IAChB,+CAA+C;IAC/C,UAAU,IAAI,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,iBAAiB,+BAA+C,CAAC;AAS9E,qBAAa,aAAc,YAAW,MAAM;IAC3C,QAAQ,CAAC,EAAE,aAAa;IACxB,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,QAAQ,MAAM;IAEvB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6B;IAC1D,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,eAAe,CAAuC;gBAElD,YAAY,CAAC,EAAE,mBAAmB;IAI9C,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAelC,OAAO,IAAI,IAAI;IAIf,OAAO,IAAI,IAAI;IAaf,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI;IAIpF,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAavC,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,WAAW;IA6BnB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,cAAc;IAQtB,oEAAoE;IACpE,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,oBAAoB;IAyC5B,4EAA4E;IAC5E,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,mBAAmB;IAmC3B,OAAO,CAAC,qBAAqB;IAwD7B,OAAO,CAAC,YAAY;IAkCpB,OAAO,CAAC,kBAAkB;CAc1B"}
|
package/dist/plugins/toolbar.mjs
CHANGED