-
-
Notifications
You must be signed in to change notification settings - Fork 621
feat: Shortcut to delete empty table while cells are selected #2052
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,12 @@ | ||
import { Node, mergeAttributes } from "@tiptap/core"; | ||
import { DOMParser, Fragment, Node as PMNode, Schema } from "prosemirror-model"; | ||
import { TableView } from "prosemirror-tables"; | ||
import { CellSelection, TableMap, TableView } from "prosemirror-tables"; | ||
import { NodeView } from "prosemirror-view"; | ||
import { createBlockNoteExtension } from "../../editor/BlockNoteExtension.js"; | ||
import { | ||
BlockConfig, | ||
createBlockSpecFromTiptapNode, | ||
TableContent, | ||
} from "../../schema/index.js"; | ||
import { mergeCSSClasses } from "../../util/browser.js"; | ||
import { createDefaultBlockDOMOutputSpec } from "../defaultBlockHelpers.js"; | ||
|
@@ -394,6 +395,87 @@ export const createTableBlockSpec = () => | |
TiptapTableRow, | ||
], | ||
}), | ||
// Extension for keyboard shortcut which deletes the table if it's empty | ||
// and all cells are selected. Uses a separate extension as it needs | ||
// priority over keyboard handlers in the `TableExtension`'s | ||
// `tableEditing` plugin. | ||
createBlockNoteExtension({ | ||
key: "table-keyboard-delete", | ||
keyboardShortcuts: { | ||
Backspace: ({ editor }) => { | ||
if (!(editor.prosemirrorState.selection instanceof CellSelection)) { | ||
return false; | ||
} | ||
|
||
const block = editor.getTextCursorPosition().block; | ||
const content = block.content as TableContent<any, any>; | ||
|
||
const rows = content.rows.length; | ||
let cols = 0; | ||
|
||
for (let rowIndex = 0; rowIndex < content.rows.length; rowIndex++) { | ||
for ( | ||
let cellIndex = 0; | ||
cellIndex < content.rows[rowIndex].cells.length; | ||
cellIndex++ | ||
) { | ||
const cell = content.rows[rowIndex].cells[cellIndex]; | ||
|
||
// Counts number of columns in table from first row. | ||
if (rowIndex === 0) { | ||
const colSpan = | ||
"type" in cell && cell.props.colspan | ||
? cell.props.colspan | ||
: 1; | ||
cols += colSpan; | ||
} | ||
|
||
// Returns `false` if any cell isn't empty. | ||
if ( | ||
("type" in cell && cell.content.length > 0) || | ||
(!("type" in cell) && cell.length > 0) | ||
) { | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
// Need to use ProseMirror API to check if selection spans table. | ||
const anchorCellColIndex = | ||
editor.prosemirrorState.selection.$anchorCell.index(); | ||
const anchorCellRowIndex = | ||
editor.prosemirrorState.selection.$anchorCell.index(-1); | ||
const headCellColIndex = | ||
editor.prosemirrorState.selection.$headCell.index(); | ||
const headCellRowIndex = | ||
editor.prosemirrorState.selection.$headCell.index(-1); | ||
|
||
const minColIndex = Math.min(anchorCellColIndex, headCellColIndex); | ||
const maxColIndex = Math.max(anchorCellColIndex, headCellColIndex); | ||
const minRowIndex = Math.min(anchorCellRowIndex, headCellRowIndex); | ||
const maxRowIndex = Math.max(anchorCellRowIndex, headCellRowIndex); | ||
|
||
if ( | ||
minColIndex !== 0 || | ||
maxColIndex !== cols - 1 || | ||
minRowIndex !== 0 || | ||
maxRowIndex !== rows - 1 | ||
) { | ||
return false; | ||
} | ||
|
||
|
||
const selectionBlock = | ||
editor.getPrevBlock(block) || editor.getNextBlock(block); | ||
if (selectionBlock) { | ||
editor.setTextCursorPosition(block); | ||
} | ||
|
||
editor.removeBlocks([block]); | ||
matthewlipski marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
return true; | ||
}, | ||
}, | ||
}), | ||
], | ||
); | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.