diff --git a/.changeset/fair-forks-hope.md b/.changeset/fair-forks-hope.md new file mode 100644 index 000000000..4e28b6896 --- /dev/null +++ b/.changeset/fair-forks-hope.md @@ -0,0 +1,8 @@ +--- +'slate': minor +'slate-react': minor +--- + +A different behavior for inserting a soft break with shift+enter is quite common in rich text editors. Right now you have to do this in onKeyDown which is not so nice. This adds a separate insertSoftBreak method on the editor instance that gets called when a soft break is inserted. This maintains the current default behavior for backwards compatibility (it just splits the block). But at least you can easily overwrite it now. + +If you rely on overwriting editor.insertBreak for extra behavior for soft breaks this might be a breaking change for you and you should overwrite editor.insertSoftBreak instead. diff --git a/docs/api/nodes/editor.md b/docs/api/nodes/editor.md index 1290617ad..8d76d8f43 100644 --- a/docs/api/nodes/editor.md +++ b/docs/api/nodes/editor.md @@ -460,6 +460,10 @@ Insert a fragment at the current selection. If the selection is currently expand Insert a block break at the current selection. If the selection is currently expanded, delete it first. +#### `insertSoftBreak() => void` + +Insert a soft break at the current selection. If the selection is currently expanded, delete it first. + #### `insertNode(node: Node) => void` Insert a node at the current selection. If the selection is currently expanded, delete it first. diff --git a/docs/concepts/07-editor.md b/docs/concepts/07-editor.md index 8816958d1..1a2eb5c53 100644 --- a/docs/concepts/07-editor.md +++ b/docs/concepts/07-editor.md @@ -21,6 +21,7 @@ interface Editor { deleteForward: (unit: 'character' | 'word' | 'line' | 'block') => void deleteFragment: () => void insertBreak: () => void + insertSoftBreak: () => void insertFragment: (fragment: Node[]) => void insertNode: (node: Node) => void insertText: (text: string) => void diff --git a/packages/slate-react/src/components/editable.tsx b/packages/slate-react/src/components/editable.tsx index 04850253b..65f92eef8 100644 --- a/packages/slate-react/src/components/editable.tsx +++ b/packages/slate-react/src/components/editable.tsx @@ -472,6 +472,9 @@ export const Editable = (props: EditableProps) => { } case 'insertLineBreak': + Editor.insertSoftBreak(editor) + break + case 'insertParagraph': { Editor.insertBreak(editor) break @@ -1178,6 +1181,12 @@ export const Editable = (props: EditableProps) => { return } + if (Hotkeys.isSoftBreak(nativeEvent)) { + event.preventDefault() + Editor.insertSoftBreak(editor) + return + } + if (Hotkeys.isSplitBlock(nativeEvent)) { event.preventDefault() Editor.insertBreak(editor) diff --git a/packages/slate-react/src/utils/hotkeys.ts b/packages/slate-react/src/utils/hotkeys.ts index 33937d40d..65de16d68 100644 --- a/packages/slate-react/src/utils/hotkeys.ts +++ b/packages/slate-react/src/utils/hotkeys.ts @@ -17,7 +17,8 @@ const HOTKEYS = { extendBackward: 'shift+left', extendForward: 'shift+right', italic: 'mod+i', - splitBlock: 'shift?+enter', + insertSoftBreak: 'shift+enter', + splitBlock: 'enter', undo: 'mod+z', } @@ -89,6 +90,7 @@ export default { isMoveWordBackward: create('moveWordBackward'), isMoveWordForward: create('moveWordForward'), isRedo: create('redo'), + isSoftBreak: create('insertSoftBreak'), isSplitBlock: create('splitBlock'), isTransposeCharacter: create('transposeCharacter'), isUndo: create('undo'), diff --git a/packages/slate/src/create-editor.ts b/packages/slate/src/create-editor.ts index b1a903b5e..7fc54974f 100644 --- a/packages/slate/src/create-editor.ts +++ b/packages/slate/src/create-editor.ts @@ -158,6 +158,10 @@ export const createEditor = (): Editor => { Transforms.splitNodes(editor, { always: true }) }, + insertSoftBreak: () => { + Transforms.splitNodes(editor, { always: true }) + }, + insertFragment: (fragment: Node[]) => { Transforms.insertFragment(editor, fragment) }, diff --git a/packages/slate/src/interfaces/editor.ts b/packages/slate/src/interfaces/editor.ts index f1a8fe3db..b8618ebab 100644 --- a/packages/slate/src/interfaces/editor.ts +++ b/packages/slate/src/interfaces/editor.ts @@ -62,6 +62,7 @@ export interface BaseEditor { deleteFragment: (direction?: 'forward' | 'backward') => void getFragment: () => Descendant[] insertBreak: () => void + insertSoftBreak: () => void insertFragment: (fragment: Node[]) => void insertNode: (node: Node) => void insertText: (text: string) => void @@ -126,6 +127,7 @@ export interface EditorInterface { hasPath: (editor: Editor, path: Path) => boolean hasTexts: (editor: Editor, element: Element) => boolean insertBreak: (editor: Editor) => void + insertSoftBreak: (editor: Editor) => void insertFragment: (editor: Editor, fragment: Node[]) => void insertNode: (editor: Editor, node: Node) => void insertText: (editor: Editor, text: string) => void @@ -527,6 +529,16 @@ export const Editor: EditorInterface = { editor.insertBreak() }, + /** + * Insert a soft break at the current selection. + * + * If the selection is currently expanded, it will be deleted first. + */ + + insertSoftBreak(editor: Editor): void { + editor.insertSoftBreak() + }, + /** * Insert a fragment at the current selection. * @@ -582,6 +594,7 @@ export const Editor: EditorInterface = { typeof value.deleteForward === 'function' && typeof value.deleteFragment === 'function' && typeof value.insertBreak === 'function' && + typeof value.insertSoftBreak === 'function' && typeof value.insertFragment === 'function' && typeof value.insertNode === 'function' && typeof value.insertText === 'function' && diff --git a/packages/slate/test/interfaces/Element/isElement/editor.tsx b/packages/slate/test/interfaces/Element/isElement/editor.tsx index 190477d47..1c091056e 100644 --- a/packages/slate/test/interfaces/Element/isElement/editor.tsx +++ b/packages/slate/test/interfaces/Element/isElement/editor.tsx @@ -11,6 +11,7 @@ export const input = { deleteForward() {}, deleteFragment() {}, insertBreak() {}, + insertSoftBreak() {}, insertFragment() {}, insertNode() {}, insertText() {}, diff --git a/packages/slate/test/interfaces/Element/isElementList/full-editor.tsx b/packages/slate/test/interfaces/Element/isElementList/full-editor.tsx index 1ecc89b3f..747463aba 100644 --- a/packages/slate/test/interfaces/Element/isElementList/full-editor.tsx +++ b/packages/slate/test/interfaces/Element/isElementList/full-editor.tsx @@ -12,6 +12,7 @@ export const input = [ deleteForward() {}, deleteFragment() {}, insertBreak() {}, + insertSoftBreak() {}, insertFragment() {}, insertNode() {}, insertText() {},