Skip to content

Commit c720a63

Browse files
fix: Key inputs in blocks without content (#730)
* Added temp fix for Enter inputs on blocks without content * Updated fix to handle more edge cases
1 parent 5e1861b commit c720a63

File tree

2 files changed

+44
-13
lines changed

2 files changed

+44
-13
lines changed

packages/core/src/editor/BlockNoteExtensions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export const getBlockNoteExtensions = <
6868
UniqueID.configure({
6969
types: ["blockContainer"],
7070
}),
71-
HardBreak,
71+
HardBreak.extend({ priority: 10 }),
7272
// Comments,
7373

7474
// basics:

packages/core/src/extensions/NonEditableBlocks/NonEditableBlockPlugin.ts

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,58 @@
1-
import { Plugin, PluginKey } from "prosemirror-state";
1+
import { Plugin, PluginKey, TextSelection } from "prosemirror-state";
22

33
const PLUGIN_KEY = new PluginKey("non-editable-block");
4-
// Prevent typing for blocks without inline content, as this would otherwise
5-
// convert them into paragraph blocks.
4+
// By default, typing with a node selection active will cause ProseMirror to
5+
// replace the node with one that contains editable content. This plugin blocks
6+
// this behaviour without also blocking things like keyboard shortcuts:
7+
//
8+
// - Lets through key presses that do not include alphanumeric characters. This
9+
// includes things like backspace/delete/home/end/etc.
10+
// - Lets through any key presses that include ctrl/meta keys. These will be
11+
// shortcuts of some kind like ctrl+C/mod+C.
12+
// - Special case for Enter key which creates a new paragraph block below and
13+
// sets the selection to it. This is just to bring the UX closer to Notion
14+
//
15+
// While a more elegant solution would probably process transactions instead of
16+
// keystrokes, this brings us most of the way to Notion's UX without much added
17+
// complexity.
618
export const NonEditableBlockPlugin = () => {
719
return new Plugin({
820
key: PLUGIN_KEY,
921
props: {
1022
handleKeyDown: (view, event) => {
1123
// Checks for node selection
1224
if ("node" in view.state.selection) {
13-
// Checks if key input will insert a character - we want to block this
14-
// as it will convert the block into a paragraph.
15-
if (
16-
event.key.length === 1 &&
17-
!event.ctrlKey &&
18-
!event.altKey &&
19-
!event.metaKey &&
20-
!event.shiftKey
21-
) {
25+
// Checks if key press uses ctrl/meta modifier
26+
if (event.ctrlKey || event.metaKey) {
27+
return false;
28+
}
29+
// Checks if key press is alphanumeric
30+
if (event.key.length === 1) {
2231
event.preventDefault();
32+
33+
return true;
34+
}
35+
// Checks if key press is Enter
36+
if (event.key === "Enter") {
37+
const tr = view.state.tr;
38+
view.dispatch(
39+
tr
40+
.insert(
41+
view.state.tr.selection.$to.after(),
42+
view.state.schema.nodes["paragraph"].create()
43+
)
44+
.setSelection(
45+
new TextSelection(
46+
tr.doc.resolve(view.state.tr.selection.$to.after() + 1)
47+
)
48+
)
49+
);
50+
51+
return true;
2352
}
2453
}
54+
55+
return false;
2556
},
2657
},
2758
});

0 commit comments

Comments
 (0)