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

Allow control of Slate's event handler execution in custom event handler API #4299

Merged
5 changes: 5 additions & 0 deletions .changeset/chilly-gifts-dance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'slate-react': minor
---

Allow custom event handlers on Editable component to return boolean flag to specify whether the event can be treated as being handled
38 changes: 38 additions & 0 deletions docs/libraries/slate-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,44 @@ React components for rendering Slate editors

The main Slate editor.

#### Event Handling

By default, the `Editable` component comes with a set of event handlers that realize typical rich-text editing behavior (e.g., among others `Editable` implements its own `onCopy`, `onPaste`, `onDrop`, and `onKeyDown`). In some cases you may want to extend or overwrite Slate's default behavior, which can be done by passing your own event handler to the `Editable` component.
georgberecz marked this conversation as resolved.
Show resolved Hide resolved

Your custom event handler can control whether or not Slate will execute its own event handler after yours depending on the return value of your event handler as described below.
georgberecz marked this conversation as resolved.
Show resolved Hide resolved

```javascript
const onClick = useCallback(event => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we remove the useCallback from here and below? It's not specifically relevant to what is being explained

// Implement custom event logic...

// When no value is returned, Slate will execute its own event handler if neither
// isDefaultPrevented or isPropagationStopped was set on the event
}, []);

const onDrop = useCallback(event => {
// Implement custom event logic...

// No matter the state of the event, treat it as being handled by returning true here
// -> Slate will skip its own event handler
return true;
}, []);

const onDragStart = useCallback(event => {
// Implement custom event logic...

// No matter the status of the event, treat event as *not* being handled by returning false
// -> Slate will exectue its own event handler afterward
return false;
}, []);

<Editable
onClick={onClick}
onDrop={onDrop}
onDragStart={onDragStart
{/*...*/}
/>
```

### `DefaultElement(props: RenderElementProps)`

The default element renderer.
Expand Down
10 changes: 8 additions & 2 deletions packages/slate-react/src/components/editable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1191,13 +1191,19 @@ export const isEventHandled = <
EventType extends React.SyntheticEvent<unknown, unknown>
>(
event: EventType,
handler?: (event: EventType) => void
handler?: (event: EventType) => void | boolean
) => {
if (!handler) {
return false
}
// The custom event handler may return a boolean to specify whether the event
// shall be treated as being handled or not.
const shouldTreatEventAsHandled = handler(event)

handler(event)
if (shouldTreatEventAsHandled != null) {
return shouldTreatEventAsHandled
}

return event.isDefaultPrevented() || event.isPropagationStopped()
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the isDOMEventHandled method be updated as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, very good point! I initially thought it shouldn't, but after having another look at the code I feel like it actually should behave the same way to stay consistent and not confuse people. I will adjust it.

Expand Down