mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-17 12:41:44 +02:00
update walkthroughs, docs and changelog
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
# Core Plugin
|
# Core Plugin
|
||||||
|
|
||||||
Slate's editor is very unopinionated. The only logic it handles by default is logic associated with the `contenteditable` functionality itself—managing text, selections, etc. That logic in contained in a single plugin, called the "core" plugin.
|
Slate's editor is very unopinionated. The only logic it handles by default is logic associated with the `contenteditable` functionality itself—managing text, selections, etc. That logic in contained in two plugin, called the "core" plugins. One runs before all other plugins, and one runs after.
|
||||||
|
|
||||||
|
|
||||||
## Default Behavior
|
## Default Behavior
|
||||||
@@ -64,7 +64,7 @@ However, sometimes you might want to disable the logic of the core plugin withou
|
|||||||
A noop `onBeforeInput` handler looks like:
|
A noop `onBeforeInput` handler looks like:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function onBeforeInput(event, data, state) {
|
function onBeforeInput(event, state) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
return state
|
return state
|
||||||
}
|
}
|
@@ -38,125 +38,65 @@ export default function MySlatePlugin(options) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
All of the event handler properties are passed the same React `event` object you are used to from React's event handlers. They are also passed a `data` object with Slate-specific information relating to the event, the current `change` of the editor, and the `editor` instance itself.
|
All of the event handler properties are passed the same React `event` object you are used to from React's event handlers. They are also passed a `change` object representing any changes that have resulted from the event, and the `editor` instance itself.
|
||||||
|
|
||||||
Each event handler can choose to return a new `change` object, in which case the editor's state will be updated. If nothing is returned, the editor will simply continue resolving the plugin stack.
|
Each event handler can choose to call methods on the `change` object, in which case the editor's state will be updated.
|
||||||
|
|
||||||
|
If the return value of a plugin handler is `null`, the editor will simply continue resolving the plugin stack. However, if you return a non-null value, the editor will break out of the loop.
|
||||||
|
|
||||||
### `onBeforeInput`
|
### `onBeforeInput`
|
||||||
`Function onBeforeInput(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onBeforeInput(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
This handler is called right before a string of text is inserted into the `contenteditable` element.
|
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! If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
Make sure to `event.preventDefault()` if you do not want the default insertion behavior to occur!
|
||||||
|
|
||||||
### `onBlur`
|
### `onBlur`
|
||||||
`Function onBlur(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onBlur(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
This handler is called when the editor's `contenteditable` element is blurred. If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
This handler is called when the editor's `contenteditable` element is blurred.
|
||||||
|
|
||||||
### `onFocus`
|
### `onFocus`
|
||||||
`Function onFocus(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onFocus(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
This handler is called when the editor's `contenteditable` element is focused. If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
This handler is called when the editor's `contenteditable` element is focused.
|
||||||
|
|
||||||
### `onCopy`
|
### `onCopy`
|
||||||
`Function onCopy(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onCopy(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
This handler is called when there is a copy event in the editor's `contenteditable` element.
|
This handler is called when there is a copy event in the editor's `contenteditable` element.
|
||||||
|
|
||||||
The `data` object contains a `type` string and associated data for that type. Right now the only type supported is `"fragment"`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
type: 'fragment',
|
|
||||||
fragment: Document
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
|
||||||
|
|
||||||
### `onCut`
|
### `onCut`
|
||||||
`Function onCut(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onCut(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
This handler is equivalent to the `onCopy` handler. If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
This handler is equivalent to the `onCopy` handler.
|
||||||
|
|
||||||
### `onDrop`
|
### `onDrop`
|
||||||
`Function onDrop(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onDrop(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
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 state change to have any affect occur.
|
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 state change to have any affect occur.
|
||||||
|
|
||||||
The `data` object is a convenience object created to standardize the drop metadata across browsers. Every data object has a `type` property, which can be one of `text`, `html` or `files`, and a `target` property which is a [`Range`](../slate/range.md) indicating where the drop occurred. Depending on the type, its structure will be:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
target: Range,
|
|
||||||
text: String
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
type: 'html',
|
|
||||||
target: Range,
|
|
||||||
text: String,
|
|
||||||
html: String
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
type: 'files',
|
|
||||||
target: Range,
|
|
||||||
files: FileList
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
|
||||||
|
|
||||||
### `onKeyDown`
|
### `onKeyDown`
|
||||||
`Function onKeyDown(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onKeyDown(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
This handler is called when any key is pressed in the `contenteditable` element, before any action is taken.
|
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! If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
Make sure to `event.preventDefault()` if you do not want the default insertion behavior to occur!
|
||||||
|
|
||||||
### `onKeyUp`
|
### `onKeyUp`
|
||||||
`Function onKeyUp(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onKeyUp(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
This handler is called when any key is released in the `contenteditable` element.
|
This handler is called when any key is released in the `contenteditable` element.
|
||||||
|
|
||||||
### `onPaste`
|
### `onPaste`
|
||||||
`Function onPaste(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onPaste(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
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 state change to have any affect occur.
|
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 state change to have any affect occur.
|
||||||
|
|
||||||
The `data` object is a convenience object created to standardize the paste metadata across browsers. Every data object has a `type` property, which can be one of `text`, `html` or `files`. Depending on the type, it's structure will be:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
text: String
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
type: 'html',
|
|
||||||
text: String,
|
|
||||||
html: String
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
type: 'files',
|
|
||||||
files: FileList
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
|
||||||
|
|
||||||
### `onSelect`
|
### `onSelect`
|
||||||
`Function onSelect(event: Event, data: Object, change: Change, editor: Editor) => Change || Void`
|
`Function onSelect(event: Event, change: Change, editor: Editor) => Change || Void`
|
||||||
|
|
||||||
This handler is called whenever the native DOM selection changes.
|
This handler is called whenever the native DOM selection changes.
|
||||||
|
|
||||||
The `data` object contains a [`Range`](../slate/range.md) object representing the new selection.
|
|
||||||
|
|
||||||
If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
|
||||||
|
|
||||||
_Note: This is **not** Slate's internal selection representation (although it mirrors it). If you want to get notified when Slate's 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._
|
_Note: This is **not** Slate's internal selection representation (although it mirrors it). If you want to get notified when Slate's 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._
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@ simulator
|
|||||||
.beforeInput({ data: 'l' })
|
.beforeInput({ data: 'l' })
|
||||||
.beforeInput({ data: 'o' })
|
.beforeInput({ data: 'o' })
|
||||||
.beforeInput({ data: '!' })
|
.beforeInput({ data: '!' })
|
||||||
.keyDown({}, { key: 'enter' })
|
.keyDown({ key: 'Enter' })
|
||||||
|
|
||||||
const nextState = simulator.state
|
const nextState = simulator.state
|
||||||
```
|
```
|
||||||
@@ -34,42 +34,42 @@ const nextState = simulator.state
|
|||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
### `beforeInput`
|
### `beforeInput`
|
||||||
`beforeInput(event: Object, data: Object) => Simulator`
|
`beforeInput(event: Object) => Simulator`
|
||||||
|
|
||||||
Simulator a `beforeinput` event with an `event` object and `data` object.
|
Simulator a `beforeinput` event with an `event` object.
|
||||||
|
|
||||||
### `blur`
|
### `blur`
|
||||||
`blur(event: Object, data: Object) => Simulator`
|
`blur(event: Object) => Simulator`
|
||||||
|
|
||||||
Simulator a `blur` event with an `event` object and `data` object.
|
Simulator a `blur` event with an `event` object.
|
||||||
|
|
||||||
### `copy`
|
### `copy`
|
||||||
`copy(event: Object, data: Object) => Simulator`
|
`copy(event: Object) => Simulator`
|
||||||
|
|
||||||
Simulator a `copy` event with an `event` object and `data` object.
|
Simulator a `copy` event with an `event` object.
|
||||||
|
|
||||||
### `cut`
|
### `cut`
|
||||||
`cut(event: Object, data: Object) => Simulator`
|
`cut(event: Object) => Simulator`
|
||||||
|
|
||||||
Simulator a `cut` event with an `event` object and `data` object.
|
Simulator a `cut` event with an `event` object.
|
||||||
|
|
||||||
### `drop`
|
### `drop`
|
||||||
`drop(event: Object, data: Object) => Simulator`
|
`drop(event: Object) => Simulator`
|
||||||
|
|
||||||
Simulator a `drop` event with an `event` object and `data` object.
|
Simulator a `drop` event with an `event` object.
|
||||||
|
|
||||||
### `focus`
|
### `focus`
|
||||||
`focus(event: Object, data: Object) => Simulator`
|
`focus(event: Object) => Simulator`
|
||||||
|
|
||||||
Simulator a `focus` event with an `event` object and `data` object.
|
Simulator a `focus` event with an `event` object.
|
||||||
|
|
||||||
### `keyDown`
|
### `keyDown`
|
||||||
`keyDown(event: Object, data: Object) => Simulator`
|
`keyDown(event: Object) => Simulator`
|
||||||
|
|
||||||
Simulator a `keyDown` event with an `event` object and `data` object.
|
Simulator a `keyDown` event with an `event` object.
|
||||||
|
|
||||||
### `select`
|
### `select`
|
||||||
`select(event: Object, data: Object) => Simulator`
|
`select(event: Object) => Simulator`
|
||||||
|
|
||||||
Simulator a `select` event with an `event` object and `data` object.
|
Simulator a `select` event with an `event` object.
|
||||||
|
|
||||||
|
@@ -50,7 +50,7 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Define a new handler which prints the key that was pressed.
|
// Define a new handler which prints the key that was pressed.
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
console.log(event.key)
|
console.log(event.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
// Return with no changes if it's not the "&" key.
|
// Return with no changes if it's not the "&" key.
|
||||||
if (event.key != '&') return
|
if (event.key != '&') return
|
||||||
|
|
||||||
|
@@ -27,7 +27,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
if (event.key != '`' || !event.metaKey) return
|
if (event.key != '`' || !event.metaKey) return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
const isCode = change.state.blocks.some(block => block.type == 'code')
|
const isCode = change.state.blocks.some(block => block.type == 'code')
|
||||||
@@ -68,7 +68,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
if (!event.metaKey) return
|
if (!event.metaKey) return
|
||||||
|
|
||||||
// Decide what to do based on the key code...
|
// Decide what to do based on the key code...
|
||||||
@@ -144,7 +144,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
if (!event.metaKey) return
|
if (!event.metaKey) return
|
||||||
|
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
|
@@ -22,7 +22,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
if (event.key != '&') return
|
if (event.key != '&') return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
change.insertText('and');
|
change.insertText('and');
|
||||||
@@ -84,7 +84,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
if (event.key != '&') return
|
if (event.key != '&') return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
change.insertText('and')
|
change.insertText('and')
|
||||||
@@ -128,7 +128,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
// Return with no changes if it's not the "`" key with cmd/ctrl pressed.
|
// Return with no changes if it's not the "`" key with cmd/ctrl pressed.
|
||||||
if (event.key != '`' || !event.metaKey) return
|
if (event.key != '`' || !event.metaKey) return
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
if (event.key != '`' || !event.metaKey) return
|
if (event.key != '`' || !event.metaKey) return
|
||||||
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@@ -29,7 +29,7 @@ class App extends React.Component {
|
|||||||
this.setState({ state })
|
this.setState({ state })
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown = (event, data, change) => {
|
onKeyDown = (event, change) => {
|
||||||
if (event.key != 'b' || !event.metaKey) return
|
if (event.key != 'b' || !event.metaKey) return
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
change.toggleMark('bold')
|
change.toggleMark('bold')
|
||||||
@@ -71,7 +71,7 @@ function MarkHotkey(options) {
|
|||||||
|
|
||||||
// Return our "plugin" object, containing the `onKeyDown` handler.
|
// Return our "plugin" object, containing the `onKeyDown` handler.
|
||||||
return {
|
return {
|
||||||
onKeyDown(event, data, change) {
|
onKeyDown(event, change) {
|
||||||
// Check that the key pressed matches our `key` option.
|
// Check that the key pressed matches our `key` option.
|
||||||
if (!event.metaKey || event.key != key) return
|
if (!event.metaKey || event.key != key) return
|
||||||
|
|
||||||
|
@@ -7,6 +7,22 @@ This document maintains a list of changes to the `slate-react` package with each
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### `0.6.0` — October 16, 2017
|
||||||
|
|
||||||
|
###### BREAKING
|
||||||
|
|
||||||
|
- **The `data` argument to event handlers has been removed.** Previously event handlers had a signature of `(event, data, change, editor)`, but now they have a signature of just `(event, change, editor)`. This leads to simpler internal Slate logic, and less complex relationship dependencies between plugins. All of the information inside the old `data` argument can be accessed via the similar properties on the `event` argument, or via the `getEventRange`, `getEventTransfer` and `setEventTransfer` helpers.
|
||||||
|
|
||||||
|
###### NEW
|
||||||
|
|
||||||
|
- **Added a new `setEventTransfer` helper.** This is useful if you're working with `onDrop` or `onPaste` event and you want to set custom data in the event, to retrieve later or for others to consume. It takes a data `type` and a `value` to set the type do.
|
||||||
|
|
||||||
|
- **Event handlers now have access to new events.** The `onClick`, `onCompositionEnd`, `onCompositionStart`, `onDragEnd`, `onDragEnter`, `onDragExit`, `onDragLeave`, `onDragOver`, `onDragStart`, and `onInput` events are all now newly exposed. Your plugin logic can use them to solve some more advanced use cases, and even override the internal Slate logic when necessary. 99% of use cases won't require them still, but they can be useful to have when needed.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
### `0.5.0` — October 15, 2017
|
### `0.5.0` — October 15, 2017
|
||||||
|
|
||||||
###### DEPRECATED
|
###### DEPRECATED
|
||||||
|
Reference in New Issue
Block a user