diff --git a/.changeset/override-event-handlers.md b/.changeset/override-event-handlers.md new file mode 100644 index 0000000000..3910d89e60 --- /dev/null +++ b/.changeset/override-event-handlers.md @@ -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 ( + + ) +} +``` diff --git a/docs/libraries/slate-react.md b/docs/libraries/slate-react.md index 11f11c0cdf..88bde11f58 100644 --- a/docs/libraries/slate-react.md +++ b/docs/libraries/slate-react.md @@ -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 ( + + ) +} +``` + ### `DefaultElement(props: RenderElementProps)` The default element renderer. diff --git a/packages/slate-react/src/components/editable.tsx b/packages/slate-react/src/components/editable.tsx index 7c0582ee28..7cb987aa2e 100644 --- a/packages/slate-react/src/components/editable.tsx +++ b/packages/slate-react/src/components/editable.tsx @@ -1191,13 +1191,19 @@ export const isEventHandled = < EventType extends React.SyntheticEvent >( 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() } @@ -1207,12 +1213,19 @@ export const isEventHandled = < export const isDOMEventHandled = ( 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 }