Skip to content

Commit 84ade80

Browse files
fix: Hard break keyboard shortcut not working in custom blocks (#1554)
* Replaced TipTap hard break extension with our own * Removed `setHardBreak` command and dependency * Added hard break shortcut configuration to API * Fixed lint * Small cleanup
1 parent 5558a51 commit 84ade80

File tree

7 files changed

+72
-20
lines changed

7 files changed

+72
-20
lines changed

package-lock.json

Lines changed: 0 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@
7575
"@tiptap/extension-collaboration": "^2.11.5",
7676
"@tiptap/extension-collaboration-cursor": "^2.11.5",
7777
"@tiptap/extension-gapcursor": "^2.11.5",
78-
"@tiptap/extension-hard-break": "^2.11.5",
7978
"@tiptap/extension-history": "^2.11.5",
8079
"@tiptap/extension-horizontal-rule": "^2.11.5",
8180
"@tiptap/extension-italic": "^2.11.5",

packages/core/src/blocks/TableBlockContent/TableExtension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const TableExtension = Extension.create({
3131
this.editor.state.selection.$head.parent.type.name ===
3232
"tableParagraph"
3333
) {
34-
this.editor.commands.setHardBreak();
34+
this.editor.commands.insertContent({ type: "hardBreak" });
3535

3636
return true;
3737
}

packages/core/src/editor/BlockNoteExtensions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { AnyExtension, Extension, extensions } from "@tiptap/core";
22
import { Gapcursor } from "@tiptap/extension-gapcursor";
3-
import { HardBreak } from "@tiptap/extension-hard-break";
43
import { History } from "@tiptap/extension-history";
54
import { Link } from "@tiptap/extension-link";
65
import { Text } from "@tiptap/extension-text";
@@ -17,6 +16,7 @@ import { CommentsPlugin } from "../extensions/Comments/CommentsPlugin.js";
1716
import type { ThreadStore } from "../comments/index.js";
1817
import { FilePanelProsemirrorPlugin } from "../extensions/FilePanel/FilePanelPlugin.js";
1918
import { FormattingToolbarProsemirrorPlugin } from "../extensions/FormattingToolbar/FormattingToolbarPlugin.js";
19+
import { HardBreak } from "../extensions/HardBreak/HardBreak.js";
2020
import { KeyboardShortcutsExtension } from "../extensions/KeyboardShortcuts/KeyboardShortcutsExtension.js";
2121
import { LinkToolbarProsemirrorPlugin } from "../extensions/LinkToolbar/LinkToolbarPlugin.js";
2222
import {
@@ -179,7 +179,7 @@ const getTipTapExtensions = <
179179
types: ["blockContainer", "columnList", "column"],
180180
setIdAttribute: opts.setIdAttribute,
181181
}),
182-
HardBreak.extend({ priority: 10 }),
182+
HardBreak,
183183
// Comments,
184184

185185
// basics:
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Stripped down version of the TipTap HardBreak extension:
2+
// https://github.com/ueberdosis/tiptap/blob/f3258d9ee5fb7979102fe63434f6ea4120507311/packages/extension-hard-break/src/hard-break.ts#L80
3+
// Changes:
4+
// - Removed options
5+
// - Removed keyboard shortcuts & moved them to the `KeyboardShortcutsExtension`
6+
// - Removed `setHardBreak` command (added a simpler version in the Shift+Enter
7+
// handler in `KeyboardShortcutsExtension`).
8+
// - Added priority
9+
import { mergeAttributes, Node } from "@tiptap/core";
10+
11+
export const HardBreak = Node.create({
12+
name: "hardBreak",
13+
14+
inline: true,
15+
16+
group: "inline",
17+
18+
selectable: false,
19+
20+
linebreakReplacement: true,
21+
22+
priority: 10,
23+
24+
parseHTML() {
25+
return [{ tag: "br" }];
26+
},
27+
28+
renderHTML({ HTMLAttributes }) {
29+
return ["br", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
30+
},
31+
32+
renderText() {
33+
return "\n";
34+
},
35+
});

packages/core/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,8 @@ export const KeyboardShortcutsExtension = Extension.create<{
437437
}),
438438
]);
439439

440-
const handleEnter = () =>
441-
this.editor.commands.first(({ commands }) => [
440+
const handleEnter = (withShift = false) => {
441+
return this.editor.commands.first(({ commands }) => [
442442
// Removes a level of nesting if the block is empty & indented, while the selection is also empty & at the start
443443
// of the block.
444444
() =>
@@ -467,6 +467,34 @@ export const KeyboardShortcutsExtension = Extension.create<{
467467
return commands.liftListItem("blockContainer");
468468
}
469469

470+
return false;
471+
}),
472+
// Creates a hard break if block is configured to do so.
473+
() =>
474+
commands.command(({ state }) => {
475+
const blockInfo = getBlockInfoFromSelection(state);
476+
477+
const blockHardBreakShortcut: "shift+enter" | "enter" | "none" =
478+
this.options.editor.schema.blockSchema[blockInfo.blockNoteType]
479+
.hardBreakShortcut ?? "shift+enter";
480+
481+
if (blockHardBreakShortcut === "none") {
482+
return false;
483+
}
484+
485+
if (
486+
// If shortcut is not configured, or is configured as "shift+enter",
487+
// create a hard break for shift+enter, but not for enter.
488+
(blockHardBreakShortcut === "shift+enter" && withShift) ||
489+
// If shortcut is configured as "enter", create a hard break for
490+
// both enter and shift+enter.
491+
blockHardBreakShortcut === "enter"
492+
) {
493+
return commands.insertContent({
494+
type: "hardBreak",
495+
});
496+
}
497+
470498
return false;
471499
}),
472500
// Creates a new block and moves the selection to it if the current one is empty, while the selection is also
@@ -538,11 +566,13 @@ export const KeyboardShortcutsExtension = Extension.create<{
538566
return false;
539567
}),
540568
]);
569+
};
541570

542571
return {
543572
Backspace: handleBackspace,
544573
Delete: handleDelete,
545-
Enter: handleEnter,
574+
Enter: () => handleEnter(),
575+
"Shift-Enter": () => handleEnter(true),
546576
// Always returning true for tab key presses ensures they're not captured by the browser. Otherwise, they blur the
547577
// editor since the browser will try to use tab for keyboard navigation.
548578
Tab: () => {

packages/core/src/schema/blocks/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export type BlockConfig =
6363
content: "inline" | "none" | "table";
6464
isSelectable?: boolean;
6565
isFileBlock?: false;
66+
hardBreakShortcut?: "shift+enter" | "enter" | "none";
6667
}
6768
| FileBlockConfig;
6869

0 commit comments

Comments
 (0)