Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reset state.isDraggingInternally using global event handlers #5664

Merged
merged 1 commit into from
Jun 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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'
Loading