1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-03-06 13:59:47 +01:00
Ian Storm Taylor 7a71de387c
Add controller (#2221)
* fold Stack into Editor

* switch Change objects to be tied to editors, not values

* introduce controller

* add the "commands" concept

* convert history into commands on `value.data`

* add the ability to not normalize on editor creation/setting

* convert schema to a mutable constructor

* add editor.command method

* convert plugin handlers to receive `next`

* switch commands to use the onCommand middleware

* add queries support, convert schema to queries

* split out browser plugin

* remove noop util

* fixes

* fixes

* start fixing tests, refactor hyperscript to be more literal

* fix slate-html-serializer tests

* fix schema tests with hyperscript

* fix text model tests with hyperscript

* fix more tests

* get all tests passing

* fix lint

* undo decorations example update

* update examples

* small changes to the api to make it nicer

* update docs

* update commands/queries plugin logic

* change normalizeNode and validateNode to be middleware

* fix decoration removal

* rename commands tests

* add useful errors to existing APIs

* update changelogs

* cleanup

* fixes

* update docs

* add editor docs
2018-10-09 14:03:27 -07:00

176 lines
5.9 KiB
Markdown

# Plugins
Plugins can be attached to an editor to alter its behavior in different ways. Each editor has a "stack" of plugins, which has a specific order, which it runs through when certain hooks are triggered.
Plugins are plain JavaScript objects, containing a set of middleware functions that run for each hook they choose to implement.
## Hooks
In addition to the [core plugin hooks](../slate/plugins.md), when using `slate-react` there are additional browser-specific event handling hooks, and React-specific rendering hooks available to plugins.
```js
{
decorateNode: Function,
onBeforeInput: Function,
onBlur: Function,
onCopy: Function,
onCut: Function,
onDrop: Function,
onFocus: Function,
onKeyDown: Function,
onKeyUp: Function,
onPaste: Function,
onSelect: Function,
renderEditor: Function,
renderMark: Function,
renderNode: Function,
renderPlaceholder: Function,
shouldNodeComponentUpdate: Function,
}
```
The event hooks have a signature of `(event, change, next)`—the `event` is a React object that you are used to from React's event handlers.
The rendering hooks are just like render props common to other React API's, and receive `(props, editor, next)`. For more information, see the [Rendering](./rendering.md) reference.
### `decorateNode`
`Function decorateNode(node: Node, next: Function) => Array<Decoration>|Void`
The `decorateNode` hook takes a `node` and returns an array of decorations with marks to be applied to the node when it is rendered.
### `onBeforeInput`
`Function onBeforeInput(event: Event, change: Change, next: Function) => Boolean`
This handler is called right before a string of text is inserted into the `contenteditable` element.
Make sure to `event.preventDefault()` if you do not want the default insertion behavior to occur!
### `onBlur`
`Function onBlur(event: Event, change: Change, next: Function) => Boolean`
This handler is called when the editor's `contenteditable` element is blurred.
### `onFocus`
`Function onFocus(event: Event, change: Change, next: Function) => Boolean`
This handler is called when the editor's `contenteditable` element is focused.
### `onCopy`
`Function onCopy(event: Event, change: Change, next: Function) => Boolean`
This handler is called when there is a copy event in the editor's `contenteditable` element.
### `onCut`
`Function onCut(event: Event, change: Change, next: Function) => Boolean`
This handler is equivalent to the `onCopy` handler.
### `onDrop`
`Function onDrop(event: Event, change: Change, next: Function) => Boolean`
This handler is called when the user drops content into the `contenteditable` element. The event is already prevented by default, so you must define a value change to have any affect occur.
### `onKeyDown`
`Function onKeyDown(event: Event, change: Change, next: Function) => Boolean`
This handler is called when any key is pressed in the `contenteditable` element, before any action is taken.
Make sure to `event.preventDefault()` if you do not want the default insertion behavior to occur!
### `onKeyUp`
`Function onKeyUp(event: Event, change: Change, next: Function) => Boolean`
This handler is called when any key is released in the `contenteditable` element.
### `onPaste`
`Function onPaste(event: Event, change: Change, next: Function) => Boolean`
This handler is called when the user pastes content into the `contenteditable` element. The event is already prevented by default, so you must define a value change to have any affect occur.
### `onSelect`
`Function onSelect(event: Event, change: Change, next: Function) => Boolean`
This handler is called whenever the native DOM selection changes.
> 🤖 This is **not** Slate's internal selection representation. If you want to get notified when Slate's `value.selection` changes, use the [`onChange`](../slate-react/editor.md#onchange) property of the `<Editor>`. This handler is instead meant to give you lower-level access to the DOM selection handling, which **is not always triggered** as you'd expect.
### `renderEditor`
`Function renderEditor(props: Object, editor: Editor) => ReactNode|Void`
The `renderEditor` property allows you to define higher-order-component-like behavior. It is passed all of the properties of the editor, including `props.children`. You can then choose to wrap the existing `children` in any custom elements or proxy the properties however you choose. This can be useful for rendering toolbars, styling the editor, rendering validation, etc. Remember that the `renderEditor` function has to render `props.children` for editor's content to render.
### `renderMark`
`Function renderMark(props: Object, next: Function) => ReactNode|Void`
Render a `Mark` with `props`. The `props` object contains:
```js
{
attributes: Object,
children: ReactNode,
editor: Editor,
mark: Mark,
marks: Set<Mark>,
node: Node,
offset: Number,
text: String,
}
```
You must spread the `props.attributes` onto the top-level DOM node you use to render the mark.
### `renderNode`
`Function renderNode(props: Object, next: Function) => ReactNode|Void`
Render a `Node` with `props`. The `props` object contains:
```js
{
attributes: Object,
children: ReactNode,
editor: Editor,
isFocused: Boolean,
isSelected: BOolean,
node: Node,
parent: Node,
readOnly: Boolean,
}
```
You must spread the `props.attributes` onto the top-level DOM node you use to render the node.
### `renderPlaceholder`
`Function renderPlaceholder(props: Object, next: Function) => ReactNode|Void`
Render the placeholder that is shown when the editor has no `value`. The `props` object contains:
```js
{
editor: Editor,
readOnly: Boolean,
}
```
The `placeholder` prop that was passed to the editor can be found at `editor.props.placeholder`.
### `shouldNodeComponentUpdate`
`Function shouldNodeComponentUpdate(previousProps: Object, props: Object, next: Function) => Boolean|Void`
If this function returns `true`, it can force updating the node's component where otherwise it wouldn't for performance.