Skip to content

Commit d6f0b4c

Browse files
committed
Changed keyboard handler to use BlockNote APIs
1 parent d274b80 commit d6f0b4c

File tree

1 file changed

+82
-53
lines changed

1 file changed

+82
-53
lines changed

packages/core/src/blocks/Table/block.ts

Lines changed: 82 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { createBlockNoteExtension } from "../../editor/BlockNoteExtension.js";
66
import {
77
BlockConfig,
88
createBlockSpecFromTiptapNode,
9+
TableContent,
910
} from "../../schema/index.js";
1011
import { mergeCSSClasses } from "../../util/browser.js";
1112
import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers.js";
@@ -265,59 +266,6 @@ const TiptapTableParagraph = Node.create({
265266
group: "tableContent",
266267
content: "inline*",
267268

268-
addKeyboardShortcuts() {
269-
return {
270-
// If the table is empty while all cells are selected, deletes the table.
271-
Backspace: ({ editor }) => {
272-
if (!(editor.state.selection instanceof CellSelection)) {
273-
return false;
274-
}
275-
276-
const anchorCellColIndex = editor.state.selection.$anchorCell.index();
277-
const anchorCellRowIndex = editor.state.selection.$anchorCell.index(-1);
278-
const headCellColIndex = editor.state.selection.$headCell.index();
279-
const headCellRowIndex = editor.state.selection.$headCell.index(-1);
280-
281-
const minColIndex = Math.min(anchorCellColIndex, headCellColIndex);
282-
const maxColIndex = Math.max(anchorCellColIndex, headCellColIndex);
283-
const minRowIndex = Math.min(anchorCellRowIndex, headCellRowIndex);
284-
const maxRowIndex = Math.max(anchorCellRowIndex, headCellRowIndex);
285-
286-
const posBeforeTable = editor.state.selection.$anchorCell.before(-1);
287-
const tableNode = editor.state.doc.resolve(posBeforeTable).nodeAfter!;
288-
289-
const tableMap = TableMap.get(tableNode);
290-
291-
if (
292-
minColIndex !== 0 ||
293-
maxColIndex !== tableMap.width - 1 ||
294-
minRowIndex !== 0 ||
295-
maxRowIndex !== tableMap.height - 1
296-
) {
297-
return false;
298-
}
299-
300-
for (
301-
let cellIndex = 0;
302-
cellIndex < tableMap.height * tableMap.width;
303-
cellIndex++
304-
) {
305-
const posBeforeCell = posBeforeTable + tableMap.map[cellIndex] + 1;
306-
const cellNode = editor.state.doc.resolve(posBeforeCell).nodeAfter!;
307-
308-
if (cellNode.firstChild && cellNode.firstChild?.content.size > 0) {
309-
return false;
310-
}
311-
}
312-
313-
return editor.commands.deleteRange({
314-
from: posBeforeTable,
315-
to: posBeforeTable + tableNode.nodeSize,
316-
});
317-
},
318-
};
319-
},
320-
321269
parseHTML() {
322270
return [
323271
{
@@ -447,6 +395,87 @@ export const createTableBlockSpec = () =>
447395
TiptapTableRow,
448396
],
449397
}),
398+
// Extension for keyboard shortcut which deletes the table if it's empty
399+
// and all cells are selected. Uses a separate extension as it needs
400+
// priority over keyboard handlers in the `TableExtension`'s
401+
// `tableEditing` plugin.
402+
createBlockNoteExtension({
403+
key: "table-keyboard-delete",
404+
keyboardShortcuts: {
405+
Backspace: ({ editor }) => {
406+
if (!(editor.prosemirrorState.selection instanceof CellSelection)) {
407+
return false;
408+
}
409+
410+
const block = editor.getTextCursorPosition().block;
411+
const content = block.content as TableContent<any, any>;
412+
413+
const rows = content.rows.length;
414+
let cols = 0;
415+
416+
for (let rowIndex = 0; rowIndex < content.rows.length; rowIndex++) {
417+
for (
418+
let cellIndex = 0;
419+
cellIndex < content.rows[rowIndex].cells.length;
420+
cellIndex++
421+
) {
422+
const cell = content.rows[rowIndex].cells[cellIndex];
423+
424+
// Counts number of columns in table from first row.
425+
if (rowIndex === 0) {
426+
const colSpan =
427+
"type" in cell && cell.props.colspan
428+
? cell.props.colspan
429+
: 1;
430+
cols += colSpan;
431+
}
432+
433+
// Returns `false` if any cell isn't empty.
434+
if (
435+
("type" in cell && cell.content.length > 0) ||
436+
(!("type" in cell) && cell.length > 0)
437+
) {
438+
return false;
439+
}
440+
}
441+
}
442+
443+
// Need to use ProseMirror API to check if selection spans table.
444+
const anchorCellColIndex =
445+
editor.prosemirrorState.selection.$anchorCell.index();
446+
const anchorCellRowIndex =
447+
editor.prosemirrorState.selection.$anchorCell.index(-1);
448+
const headCellColIndex =
449+
editor.prosemirrorState.selection.$headCell.index();
450+
const headCellRowIndex =
451+
editor.prosemirrorState.selection.$headCell.index(-1);
452+
453+
const minColIndex = Math.min(anchorCellColIndex, headCellColIndex);
454+
const maxColIndex = Math.max(anchorCellColIndex, headCellColIndex);
455+
const minRowIndex = Math.min(anchorCellRowIndex, headCellRowIndex);
456+
const maxRowIndex = Math.max(anchorCellRowIndex, headCellRowIndex);
457+
458+
if (
459+
minColIndex !== 0 ||
460+
maxColIndex !== cols - 1 ||
461+
minRowIndex !== 0 ||
462+
maxRowIndex !== rows - 1
463+
) {
464+
return false;
465+
}
466+
467+
const selectionBlock =
468+
editor.getPrevBlock(block) || editor.getNextBlock(block);
469+
if (selectionBlock) {
470+
editor.setTextCursorPosition(block);
471+
}
472+
473+
editor.removeBlocks([block]);
474+
475+
return true;
476+
},
477+
},
478+
}),
450479
],
451480
);
452481

0 commit comments

Comments
 (0)