Refactor actions using builtin editor methods
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -235,70 +235,33 @@ export function TableCellMenu({ editor }: TableCellMenuProps) {
|
||||
setMenuOpen(false);
|
||||
};
|
||||
|
||||
const hasSpannedCell = (): boolean => {
|
||||
const { selection } = editor.state;
|
||||
|
||||
if (selection instanceof CellSelection) {
|
||||
let found = false;
|
||||
selection.forEachCell((node) => {
|
||||
if (node.attrs.colspan > 1 || node.attrs.rowspan > 1) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
const $pos = editor.state.doc.resolve(selection.from);
|
||||
const cell = cellAround($pos);
|
||||
if (!cell) return false;
|
||||
const cellNode = editor.state.doc.nodeAt(cell.pos);
|
||||
if (!cellNode) return false;
|
||||
return cellNode.attrs.colspan > 1 || cellNode.attrs.rowspan > 1;
|
||||
};
|
||||
|
||||
const handleSplitCell = () => {
|
||||
editor.chain().focus().splitCell().run();
|
||||
setMenuOpen(false);
|
||||
};
|
||||
|
||||
const handleClearContents = () => {
|
||||
const { state, dispatch } = editor.view;
|
||||
const { selection, schema } = state;
|
||||
const { tr } = state;
|
||||
let cursorTarget: number | null = null;
|
||||
const { state } = editor.view;
|
||||
|
||||
if (selection instanceof CellSelection) {
|
||||
selection.forEachCell((node, pos) => {
|
||||
const start = pos + 1;
|
||||
const end = pos + node.nodeSize - 1;
|
||||
if (cursorTarget === null) {
|
||||
cursorTarget = tr.mapping.map(start) + 1;
|
||||
}
|
||||
tr.replaceWith(
|
||||
tr.mapping.map(start),
|
||||
tr.mapping.map(end),
|
||||
schema.nodes.paragraph.create(),
|
||||
);
|
||||
});
|
||||
if (state.selection instanceof CellSelection) {
|
||||
editor.commands.deleteSelection();
|
||||
} else {
|
||||
const $pos = state.doc.resolve(selection.from);
|
||||
const { dispatch } = editor.view;
|
||||
const { tr, schema } = state;
|
||||
const $pos = state.doc.resolve(state.selection.from);
|
||||
const cell = cellAround($pos);
|
||||
if (cell) {
|
||||
const cellNode = state.doc.nodeAt(cell.pos);
|
||||
if (cellNode) {
|
||||
const start = cell.pos + 1;
|
||||
const end = cell.pos + cellNode.nodeSize - 1;
|
||||
cursorTarget = start + 1;
|
||||
tr.replaceWith(start, end, schema.nodes.paragraph.create());
|
||||
tr.setSelection(TextSelection.create(tr.doc, start + 1));
|
||||
dispatch(tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cursorTarget !== null) {
|
||||
tr.setSelection(TextSelection.create(tr.doc, cursorTarget));
|
||||
}
|
||||
|
||||
dispatch(tr);
|
||||
setMenuOpen(false);
|
||||
};
|
||||
|
||||
@@ -340,11 +303,13 @@ export function TableCellMenu({ editor }: TableCellMenuProps) {
|
||||
onMouseDown={e => e.preventDefault()}
|
||||
className={menu()}
|
||||
>
|
||||
<MenuButton onClick={handleMergeCells}>
|
||||
<IntersectIcon size={16} weight="bold" />
|
||||
Merge cells
|
||||
</MenuButton>
|
||||
{hasSpannedCell() && (
|
||||
{editor.can().mergeCells() && (
|
||||
<MenuButton onClick={handleMergeCells}>
|
||||
<IntersectIcon size={16} weight="bold" />
|
||||
Merge cells
|
||||
</MenuButton>
|
||||
)}
|
||||
{editor.can().splitCell() && (
|
||||
<MenuButton onClick={handleSplitCell}>
|
||||
<SplitHorizontalIcon size={16} weight="bold" />
|
||||
Split cells
|
||||
|
||||
@@ -450,19 +450,17 @@ export function TableColumnMenu({ editor }: TableColumnMenuProps) {
|
||||
if (!table) return;
|
||||
|
||||
const map = TableMap.get(table);
|
||||
const { tr, schema } = editor.state;
|
||||
const targetType = isHeaderColumn()
|
||||
? schema.nodes.tableCell
|
||||
: schema.nodes.tableHeader;
|
||||
const cellPos = map.positionAt(0, 0, table) + tableStart;
|
||||
|
||||
for (let row = 0; row < map.height; row++) {
|
||||
const cellPos = map.map[row * map.width] + tableStart;
|
||||
const cellNode = editor.state.doc.nodeAt(cellPos);
|
||||
if (!cellNode) continue;
|
||||
tr.setNodeMarkup(cellPos, targetType, cellNode.attrs);
|
||||
}
|
||||
|
||||
editor.view.dispatch(tr);
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.command(({ tr }) => {
|
||||
tr.setSelection(TextSelection.create(tr.doc, cellPos + 1));
|
||||
return true;
|
||||
})
|
||||
.toggleHeaderColumn()
|
||||
.run();
|
||||
} catch {
|
||||
// table may have changed
|
||||
}
|
||||
@@ -503,26 +501,26 @@ export function TableColumnMenu({ editor }: TableColumnMenuProps) {
|
||||
const { colIndex, tableStart } = currentCol;
|
||||
|
||||
try {
|
||||
const tableNodePos = tableStart - 1;
|
||||
const table = editor.state.doc.nodeAt(tableNodePos);
|
||||
const table = editor.state.doc.nodeAt(tableStart - 1);
|
||||
if (!table) return;
|
||||
|
||||
const rows: PMNode[] = [];
|
||||
table.forEach((row) => {
|
||||
const cells: PMNode[] = [];
|
||||
row.forEach((cell, _offset, i) => {
|
||||
cells.push(cell);
|
||||
if (i === colIndex) {
|
||||
cells.push(cell.copy(cell.content));
|
||||
}
|
||||
});
|
||||
rows.push(row.type.create(row.attrs, cells));
|
||||
});
|
||||
const map = TableMap.get(table);
|
||||
|
||||
const newTable = table.type.create(table.attrs, rows);
|
||||
const { tr } = editor.state;
|
||||
tr.replaceWith(tableNodePos, tableNodePos + table.nodeSize, newTable);
|
||||
editor.view.dispatch(tr);
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.command(({ tr }) => {
|
||||
for (let row = map.height - 1; row >= 0; row--) {
|
||||
const cellOffset = map.map[row * map.width + colIndex];
|
||||
const cell = table.nodeAt(cellOffset);
|
||||
if (!cell) continue;
|
||||
|
||||
const insertPos = cellOffset + tableStart + cell.nodeSize;
|
||||
tr.insert(insertPos, cell);
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.run();
|
||||
} catch {
|
||||
// table may have changed
|
||||
}
|
||||
@@ -593,25 +591,17 @@ export function TableColumnMenu({ editor }: TableColumnMenuProps) {
|
||||
if (!table) return;
|
||||
|
||||
const map = TableMap.get(table);
|
||||
const { tr } = editor.state;
|
||||
const { schema } = editor.state;
|
||||
const firstCellPos = map.map[colIndex] + tableStart;
|
||||
const lastCellPos
|
||||
= map.map[(map.height - 1) * map.width + colIndex] + tableStart;
|
||||
|
||||
for (let row = 0; row < map.height; row++) {
|
||||
const cellPos = map.map[row * map.width + colIndex] + tableStart;
|
||||
const cellNode = editor.state.doc.nodeAt(cellPos);
|
||||
if (!cellNode) continue;
|
||||
const $anchor = editor.state.doc.resolve(firstCellPos);
|
||||
const $head = editor.state.doc.resolve(lastCellPos);
|
||||
|
||||
const start = cellPos + 1;
|
||||
const end = cellPos + cellNode.nodeSize - 1;
|
||||
|
||||
tr.replaceWith(
|
||||
tr.mapping.map(start),
|
||||
tr.mapping.map(end),
|
||||
schema.nodes.paragraph.create(),
|
||||
);
|
||||
}
|
||||
|
||||
editor.view.dispatch(tr);
|
||||
editor.view.dispatch(
|
||||
editor.state.tr.setSelection(new CellSelection($anchor, $head)),
|
||||
);
|
||||
editor.commands.deleteSelection();
|
||||
} catch {
|
||||
// table may have changed
|
||||
}
|
||||
|
||||
@@ -446,19 +446,17 @@ export function TableRowMenu({ editor }: TableRowMenuProps) {
|
||||
if (!table) return;
|
||||
|
||||
const map = TableMap.get(table);
|
||||
const { tr, schema } = editor.state;
|
||||
const targetType = isHeaderRow()
|
||||
? schema.nodes.tableCell
|
||||
: schema.nodes.tableHeader;
|
||||
const cellPos = map.positionAt(0, 0, table) + tableStart;
|
||||
|
||||
for (let col = 0; col < map.width; col++) {
|
||||
const cellPos = map.map[col] + tableStart;
|
||||
const cellNode = editor.state.doc.nodeAt(cellPos);
|
||||
if (!cellNode) continue;
|
||||
tr.setNodeMarkup(cellPos, targetType, cellNode.attrs);
|
||||
}
|
||||
|
||||
editor.view.dispatch(tr);
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.command(({ tr }) => {
|
||||
tr.setSelection(TextSelection.create(tr.doc, cellPos + 1));
|
||||
return true;
|
||||
})
|
||||
.toggleHeaderRow()
|
||||
.run();
|
||||
} catch {
|
||||
// table may have changed
|
||||
}
|
||||
@@ -499,22 +497,24 @@ export function TableRowMenu({ editor }: TableRowMenuProps) {
|
||||
const { rowIndex, tableStart } = currentRow;
|
||||
|
||||
try {
|
||||
const tableNodePos = tableStart - 1;
|
||||
const table = editor.state.doc.nodeAt(tableNodePos);
|
||||
const table = editor.state.doc.nodeAt(tableStart - 1);
|
||||
if (!table) return;
|
||||
|
||||
const rows: PMNode[] = [];
|
||||
table.forEach((row, _offset, i) => {
|
||||
rows.push(row);
|
||||
if (i === rowIndex) {
|
||||
rows.push(row.copy(row.content));
|
||||
}
|
||||
});
|
||||
const rowNode = table.child(rowIndex);
|
||||
|
||||
const newTable = table.type.create(table.attrs, rows);
|
||||
const { tr } = editor.state;
|
||||
tr.replaceWith(tableNodePos, tableNodePos + table.nodeSize, newTable);
|
||||
editor.view.dispatch(tr);
|
||||
let insertPos = tableStart;
|
||||
for (let i = 0; i <= rowIndex; i++) {
|
||||
insertPos += table.child(i).nodeSize;
|
||||
}
|
||||
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.command(({ tr }) => {
|
||||
tr.insert(insertPos, rowNode);
|
||||
return true;
|
||||
})
|
||||
.run();
|
||||
} catch {
|
||||
// table may have changed
|
||||
}
|
||||
@@ -585,25 +585,17 @@ export function TableRowMenu({ editor }: TableRowMenuProps) {
|
||||
if (!table) return;
|
||||
|
||||
const map = TableMap.get(table);
|
||||
const { tr } = editor.state;
|
||||
const { schema } = editor.state;
|
||||
const firstCellPos = map.map[rowIndex * map.width] + tableStart;
|
||||
const lastCellPos
|
||||
= map.map[rowIndex * map.width + (map.width - 1)] + tableStart;
|
||||
|
||||
for (let col = 0; col < map.width; col++) {
|
||||
const cellPos = map.map[rowIndex * map.width + col] + tableStart;
|
||||
const cellNode = editor.state.doc.nodeAt(cellPos);
|
||||
if (!cellNode) continue;
|
||||
const $anchor = editor.state.doc.resolve(firstCellPos);
|
||||
const $head = editor.state.doc.resolve(lastCellPos);
|
||||
|
||||
const start = cellPos + 1;
|
||||
const end = cellPos + cellNode.nodeSize - 1;
|
||||
|
||||
tr.replaceWith(
|
||||
tr.mapping.map(start),
|
||||
tr.mapping.map(end),
|
||||
schema.nodes.paragraph.create(),
|
||||
);
|
||||
}
|
||||
|
||||
editor.view.dispatch(tr);
|
||||
editor.view.dispatch(
|
||||
editor.state.tr.setSelection(new CellSelection($anchor, $head)),
|
||||
);
|
||||
editor.commands.deleteSelection();
|
||||
} catch {
|
||||
// table may have changed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user