Skip to content

Commit

Permalink
Make drop and dragend event handlers global (#5664)
Browse files Browse the repository at this point in the history
  • Loading branch information
12joan committed Jun 23, 2024
1 parent ab3570d commit 0016f98
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/grumpy-icons-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'slate-react': patch
---

Fix: `state.isDraggingInternally` is stale if a drop handler outside the editor causes the dragged DOM element to unmount
30 changes: 17 additions & 13 deletions packages/slate-react/src/components/editable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -822,26 +822,37 @@ export const Editable = (props: EditableProps) => {
]
)

// Attach a native DOM event handler for `selectionchange`, because React's
// built-in `onSelect` handler doesn't fire for all selection changes. It's a
// leaky polyfill that only fires on keypresses or clicks. Instead, we want to
// fire for any change to the selection inside the editor. (2019/11/04)
// https://github.com/facebook/react/issues/5785
useIsomorphicLayoutEffect(() => {
const window = ReactEditor.getWindow(editor)

// Attach a native DOM event handler for `selectionchange`, because React's
// built-in `onSelect` handler doesn't fire for all selection changes. It's
// a leaky polyfill that only fires on keypresses or clicks. Instead, we
// want to fire for any change to the selection inside the editor.
// (2019/11/04) https://github.com/facebook/react/issues/5785
window.document.addEventListener(
'selectionchange',
scheduleOnDOMSelectionChange
)

// Listen for dragend and drop globally. In Firefox, if a drop handler
// initiates an operation that causes the originally dragged element to
// unmount, that element will not emit a dragend event. (2024/06/21)
const stoppedDragging = () => {
state.isDraggingInternally = false
}
window.document.addEventListener('dragend', stoppedDragging)
window.document.addEventListener('drop', stoppedDragging)

return () => {
window.document.removeEventListener(
'selectionchange',
scheduleOnDOMSelectionChange
)
window.document.removeEventListener('dragend', stoppedDragging)
window.document.removeEventListener('drop', stoppedDragging)
}
}, [scheduleOnDOMSelectionChange])
}, [scheduleOnDOMSelectionChange, state])

const decorations = decorate([editor, []])

Expand Down Expand Up @@ -1378,8 +1389,6 @@ export const Editable = (props: EditableProps) => {
ReactEditor.focus(editor)
}
}

state.isDraggingInternally = false
},
[readOnly, editor, attributes.onDrop, state]
)}
Expand All @@ -1393,11 +1402,6 @@ export const Editable = (props: EditableProps) => {
) {
attributes.onDragEnd(event)
}

// When dropping on a different droppable element than the current editor,
// `onDrop` is not called. So we need to clean up in `onDragEnd` instead.
// Note: `onDragEnd` is only called when `onDrop` is not called
state.isDraggingInternally = false
},
[readOnly, state, attributes, editor]
)}
Expand Down
2 changes: 1 addition & 1 deletion packages/slate-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ export { ReactEditor } from './plugin/react-editor'
export { withReact } from './plugin/with-react'

// Utils
export { NODE_TO_INDEX, NODE_TO_PARENT } from "./utils/weak-maps"
export { NODE_TO_INDEX, NODE_TO_PARENT } from './utils/weak-maps'

0 comments on commit 0016f98

Please sign in to comment.