mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-04-16 11:22:15 +02:00
rename plugin.render to renderPortal, and add plugin.render
This commit is contained in:
parent
fa4f9dff6c
commit
2a5d3ee556
11
History.md
11
History.md
@ -4,6 +4,17 @@ This document maintains a list of changes to Slate with each new version. Until
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.18.0` — March 2, 2017
|
||||
|
||||
###### BREAKING CHANGES
|
||||
|
||||
- **The `plugin.render` property is now called `plugin.renderPortal`.** This is to make way for the new `plugin.render` property that offers HOC-like behavior, so that plugins can augment the editor however they choose.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
### `0.17.0` — February 27, 2017
|
||||
|
||||
###### DEPRECATION CHANGES
|
||||
|
@ -43,6 +43,10 @@ When the user pastes content into the editor, the core plugin handles all pastes
|
||||
|
||||
When the user makes a new selection in the DOM, the core plugin updates that selection in Slate's internal data model, re-rendering if it needs to.
|
||||
|
||||
### `render`
|
||||
|
||||
Renders all of the default contents of the editor!
|
||||
|
||||
### `schema`
|
||||
|
||||
The core plugin defines a schema that enforces a few constraints on the content and defines default block and inline node renderer components—wrapping in a `<div>` and `<span>`, respectively. Each of these components contains `shouldComponentUpdate` logic that prevents unnecessary re-renders.
|
||||
|
@ -20,6 +20,8 @@ When the editor needs to resolve a plugin-related handler, it will loop through
|
||||
- [Other Properties](#other-properties)
|
||||
- [`onChange`](#onchange)
|
||||
- [`onBeforeChange`](#onbeforechange)
|
||||
- [`render`](#render)
|
||||
- [`renderPortal`](#renderportal)
|
||||
- [`schema`](#schema)
|
||||
|
||||
|
||||
@ -181,7 +183,7 @@ The `data` object is a convenience object created to standardize the paste metad
|
||||
If no other plugin handles this event, it will be handled by the [Core plugin](./core.md).
|
||||
|
||||
### `onSelect`
|
||||
`Function onSelect(event: Event, data: Object, state: State, editor: Editor => State || Void`
|
||||
`Function onSelect(event: Event, data: Object, state: State, editor: Editor) => State || Void`
|
||||
|
||||
This handler is called whenever the native DOM selection changes.
|
||||
|
||||
@ -216,6 +218,16 @@ The `onBeforeChange` handler isn't a native browser event handler. Instead, it i
|
||||
|
||||
Like `onChange`, `onBeforeChange` is cummulative.
|
||||
|
||||
### `render`
|
||||
`Function render(props: Object, state: State, editor: Editor) => Object || Void`
|
||||
|
||||
The `render` 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.
|
||||
|
||||
### `renderPortal`
|
||||
`Function renderPortal(state: State, editor: Editor) => Object || Void`
|
||||
|
||||
The `renderPortal` property allows you to define extra elements that will render outside of the editor, in a separate [portal](). This is useful for rendering hovering menus, or other cases where you don't need to render inside the editor, but want to add elements to the DOM.
|
||||
|
||||
### `schema`
|
||||
`Object`
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
|
||||
import Content from './content'
|
||||
import Debug from 'debug'
|
||||
import Portal from 'react-portal'
|
||||
import React from 'react'
|
||||
@ -47,23 +46,6 @@ const PLUGINS_PROPS = [
|
||||
'schema',
|
||||
]
|
||||
|
||||
/**
|
||||
* Pass-through properties of the editor.
|
||||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
|
||||
const PASS_THROUGH_PROPS = [
|
||||
'autoCorrect',
|
||||
'autoFocus',
|
||||
'className',
|
||||
'readOnly',
|
||||
'role',
|
||||
'spellCheck',
|
||||
'style',
|
||||
'tabIndex',
|
||||
]
|
||||
|
||||
/**
|
||||
* Editor.
|
||||
*
|
||||
@ -258,32 +240,14 @@ class Editor extends React.Component {
|
||||
render = () => {
|
||||
const { props, state } = this
|
||||
const { stack } = state
|
||||
const handlers = {}
|
||||
const passes = {}
|
||||
const children = stack.render(state.state, this)
|
||||
|
||||
for (const property of EVENT_HANDLERS) {
|
||||
handlers[property] = this[property]
|
||||
}
|
||||
|
||||
for (const property of PASS_THROUGH_PROPS) {
|
||||
passes[property] = this.props[property]
|
||||
}
|
||||
const children = stack
|
||||
.renderPortal(state.state, this)
|
||||
.map((child, i) => <Portal key={i} isOpened>{child}</Portal>)
|
||||
|
||||
debug('render', { props, state })
|
||||
|
||||
return (
|
||||
<Content
|
||||
{...handlers}
|
||||
{...passes}
|
||||
editor={this}
|
||||
onChange={this.onChange}
|
||||
schema={this.getSchema()}
|
||||
state={this.getState()}
|
||||
>
|
||||
{children.map((child, i) => <Portal key={i} isOpened>{child}</Portal>)}
|
||||
</Content>
|
||||
)
|
||||
const tree = stack.render(state.state, this, { ...props, children })
|
||||
return tree
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,16 +41,6 @@ const STATE_ACCUMULATOR_METHODS = [
|
||||
'onChange',
|
||||
]
|
||||
|
||||
/**
|
||||
* Methods that accumulate an array.
|
||||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
|
||||
const ARRAY_ACCUMULATOR_METHODS = [
|
||||
'render'
|
||||
]
|
||||
|
||||
/**
|
||||
* Default properties.
|
||||
*
|
||||
@ -95,6 +85,53 @@ class Stack extends new Record(DEFAULTS) {
|
||||
return 'stack'
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke `render` on all of the plugins in reverse, building up a tree of
|
||||
* higher-order components.
|
||||
*
|
||||
* @param {State} state
|
||||
* @param {Editor} editor
|
||||
* @param {Object} children
|
||||
* @param {Object} props
|
||||
* @return {Component}
|
||||
*/
|
||||
|
||||
render = (state, editor, props) => {
|
||||
debug('render')
|
||||
const plugins = this.plugins.slice().reverse()
|
||||
let children
|
||||
|
||||
for (const plugin of plugins) {
|
||||
if (!plugin.render) continue
|
||||
children = plugin.render(props, state, editor)
|
||||
props.children = children
|
||||
}
|
||||
|
||||
return children
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke `renderPortal` on all of the plugins, building a list of portals.
|
||||
*
|
||||
* @param {State} state
|
||||
* @param {Editor} editor
|
||||
* @return {Array}
|
||||
*/
|
||||
|
||||
renderPortal = (state, editor) => {
|
||||
debug('renderPortal')
|
||||
const portals = []
|
||||
|
||||
for (const plugin of this.plugins) {
|
||||
if (!plugin.renderPortal) continue
|
||||
const portal = plugin.renderPortal(state, editor)
|
||||
if (portal == null) continue
|
||||
portals.push(portal)
|
||||
}
|
||||
|
||||
return portals
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,31 +188,6 @@ for (const method of STATE_ACCUMULATOR_METHODS) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix in the array accumulator methods.
|
||||
*
|
||||
* @param {State} state
|
||||
* @param {Editor} editor
|
||||
* @param {Mixed} ...args
|
||||
* @return {Array}
|
||||
*/
|
||||
|
||||
for (const method of ARRAY_ACCUMULATOR_METHODS) {
|
||||
Stack.prototype[method] = function (state, editor, ...args) {
|
||||
debug(method)
|
||||
const array = []
|
||||
|
||||
for (const plugin of this.plugins) {
|
||||
if (!plugin[method]) continue
|
||||
const next = plugin[method](...args, state, editor)
|
||||
if (next == null) continue
|
||||
array.push(next)
|
||||
}
|
||||
|
||||
return array
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a `value` is a state object.
|
||||
*
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
import Base64 from '../serializers/base-64'
|
||||
import Content from '../components/content'
|
||||
import Character from '../models/character'
|
||||
import Debug from 'debug'
|
||||
import Placeholder from '../components/placeholder'
|
||||
@ -814,6 +815,43 @@ function Plugin(options = {}) {
|
||||
.apply()
|
||||
}
|
||||
|
||||
/**
|
||||
* Render.
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {State} state
|
||||
* @param {Editor} editor
|
||||
* @return {Object}
|
||||
*/
|
||||
|
||||
function render(props, state, editor) {
|
||||
return (
|
||||
<Content
|
||||
autoCorrect={props.autoCorrect}
|
||||
autoFocus={props.autoFocus}
|
||||
className={props.className}
|
||||
children={props.children}
|
||||
editor={editor}
|
||||
onBeforeInput={editor.onBeforeInput}
|
||||
onBlur={editor.onBlur}
|
||||
onChange={editor.onChange}
|
||||
onCopy={editor.onCopy}
|
||||
onCut={editor.onCut}
|
||||
onDrop={editor.onDrop}
|
||||
onKeyDown={editor.onKeyDown}
|
||||
onPaste={editor.onPaste}
|
||||
onSelect={editor.onSelect}
|
||||
readOnly={props.readOnly}
|
||||
role={props.role}
|
||||
schema={editor.getSchema()}
|
||||
spellCheck={props.spellCheck}
|
||||
state={state}
|
||||
style={props.style}
|
||||
tabIndex={props.tabIndex}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A default schema rule to render block nodes.
|
||||
*
|
||||
@ -892,6 +930,7 @@ function Plugin(options = {}) {
|
||||
onKeyDown,
|
||||
onPaste,
|
||||
onSelect,
|
||||
render,
|
||||
schema,
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user