Skip to content

Commit

Permalink
Allow control of Slate's event handler execution in custom event hand…
Browse files Browse the repository at this point in the history
…ler API (#4299)

Co-authored-by: Georg Berecz <gberecz@palantir.com>
Co-authored-by: Claudéric Demers <clauderic.d@gmail.com>
  • Loading branch information
3 people authored Jun 1, 2021
1 parent dfc0396 commit 2c17e2b
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 4 deletions.
49 changes: 49 additions & 0 deletions .changeset/override-event-handlers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
'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.

By default, the `Editable` component comes with a set of event handlers that handle typical rich-text editing behaviors (for example, it implements its own `onCopy`, `onPaste`, `onDrop`, and `onKeyDown` handlers).

In some cases you may want to extend or override Slate's default behavior, which can be done by passing your own event handler(s) to the `Editable` component.

Your custom event handler can control whether or not Slate should execute its own event handling for a given event after your handler runs depending on the return value of your event handler as described below.

```jsx
import {Editable} from 'slate-react';

function MyEditor() {
const onClick = event => {
// Implement custom event logic...

// When no value is returned, Slate will execute its own event handler when
// neither isDefaultPrevented nor isPropagationStopped was set on the event
};

const onDrop = 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 = 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;
};

return (
<Editable
onClick={onClick}
onDrop={onDrop}
onDragStart={onDragStart}
{/*...*/}
/>
)
}
```
46 changes: 46 additions & 0 deletions docs/libraries/slate-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,52 @@ 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 handle typical rich-text editing behaviors (for example, it implements its own `onCopy`, `onPaste`, `onDrop`, and `onKeyDown` handlers).

In some cases you may want to extend or override Slate's default behavior, which can be done by passing your own event handler(s) to the `Editable` component.

Your custom event handler can control whether or not Slate should execute its own event handling for a given event after your handler runs depending on the return value of your event handler as described below.

```jsx
import {Editable} from 'slate-react';

function MyEditor() {
const onClick = event => {
// Implement custom event logic...

// When no value is returned, Slate will execute its own event handler when
// neither isDefaultPrevented nor isPropagationStopped was set on the event
};

const onDrop = 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 = 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;
};

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

### `DefaultElement(props: RenderElementProps)`

The default element renderer.
Expand Down
21 changes: 17 additions & 4 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)

if (shouldTreatEventAsHandled != null) {
return shouldTreatEventAsHandled
}

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

Expand All @@ -1207,12 +1213,19 @@ export const isEventHandled = <

export const isDOMEventHandled = <E extends Event>(
event: E,
handler?: (event: E) => void
handler?: (event: E) => void | boolean
) => {
if (!handler) {
return false
}

handler(event)
// 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)

if (shouldTreatEventAsHandled != null) {
return shouldTreatEventAsHandled
}

return event.defaultPrevented
}

0 comments on commit 2c17e2b

Please sign in to comment.