mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-13 18:53:59 +02:00
Fix crash when a void node deletes itself on click (#4616)
* Fix crash when a void node deletes itself on click Fixes https://github.com/ianstormtaylor/slate/issues/4240 * Add 'image delete' feature to example My immediate motivation is to demonstrate the bug that this fixes. But this is also a very common editor feature, and I think it's valuable to show how to achieve it. * add changeset * fix:eslint * revert changes to mentions.tsx
This commit is contained in:
5
.changeset/curly-ghosts-look.md
Normal file
5
.changeset/curly-ghosts-look.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'slate-react': patch
|
||||
---
|
||||
|
||||
Fixed crash on self-deleting void node
|
@@ -706,19 +706,29 @@ export const Editable = (props: EditableProps) => {
|
||||
) {
|
||||
const node = ReactEditor.toSlateNode(editor, event.target)
|
||||
const path = ReactEditor.findPath(editor, node)
|
||||
const start = Editor.start(editor, path)
|
||||
const end = Editor.end(editor, path)
|
||||
|
||||
const startVoid = Editor.void(editor, { at: start })
|
||||
const endVoid = Editor.void(editor, { at: end })
|
||||
// At this time, the Slate document may be arbitrarily different,
|
||||
// because onClick handlers can change the document before we get here.
|
||||
// Therefore we must check that this path actually exists,
|
||||
// and that it still refers to the same node.
|
||||
if (Editor.hasPath(editor, path)) {
|
||||
const lookupNode = Node.get(editor, path)
|
||||
if (lookupNode === node) {
|
||||
const start = Editor.start(editor, path)
|
||||
const end = Editor.end(editor, path)
|
||||
|
||||
if (
|
||||
startVoid &&
|
||||
endVoid &&
|
||||
Path.equals(startVoid[1], endVoid[1])
|
||||
) {
|
||||
const range = Editor.range(editor, start)
|
||||
Transforms.select(editor, range)
|
||||
const startVoid = Editor.void(editor, { at: start })
|
||||
const endVoid = Editor.void(editor, { at: end })
|
||||
|
||||
if (
|
||||
startVoid &&
|
||||
endVoid &&
|
||||
Path.equals(startVoid[1], endVoid[1])
|
||||
) {
|
||||
const range = Editor.range(editor, start)
|
||||
Transforms.select(editor, range)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@@ -9,6 +9,7 @@ import {
|
||||
useSelected,
|
||||
useFocused,
|
||||
withReact,
|
||||
ReactEditor,
|
||||
} from 'slate-react'
|
||||
import { withHistory } from 'slate-history'
|
||||
import { css } from 'emotion'
|
||||
@@ -89,12 +90,20 @@ const Element = props => {
|
||||
}
|
||||
|
||||
const Image = ({ attributes, children, element }) => {
|
||||
const editor = useSlateStatic()
|
||||
const path = ReactEditor.findPath(editor, element)
|
||||
|
||||
const selected = useSelected()
|
||||
const focused = useFocused()
|
||||
return (
|
||||
<div {...attributes}>
|
||||
{children}
|
||||
<div contentEditable={false}>
|
||||
<div
|
||||
contentEditable={false}
|
||||
className={css`
|
||||
position: relative;
|
||||
`}
|
||||
>
|
||||
<img
|
||||
src={element.url}
|
||||
className={css`
|
||||
@@ -104,6 +113,19 @@ const Image = ({ attributes, children, element }) => {
|
||||
box-shadow: ${selected && focused ? '0 0 0 3px #B4D5FF' : 'none'};
|
||||
`}
|
||||
/>
|
||||
<Button
|
||||
active
|
||||
onClick={() => Transforms.removeNodes(editor, { at: path })}
|
||||
className={css`
|
||||
display: ${selected && focused ? 'inline' : 'none'};
|
||||
position: absolute;
|
||||
top: 0.5em;
|
||||
left: 0.5em;
|
||||
background-color: white;
|
||||
`}
|
||||
>
|
||||
<Icon>delete</Icon>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -159,6 +181,20 @@ const initialValue: Descendant[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
children: [
|
||||
{
|
||||
text:
|
||||
'You can delete images with the cross in the top left. Try deleting this sheep:',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'image',
|
||||
url: 'https://source.unsplash.com/zOwZKwZOZq8',
|
||||
children: [{ text: '' }],
|
||||
},
|
||||
]
|
||||
|
||||
export default ImagesExample
|
||||
|
Reference in New Issue
Block a user