1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-20 06:01:24 +02:00

clean up examples

This commit is contained in:
Ian Storm Taylor
2016-07-13 16:19:49 -07:00
parent 9793b11140
commit ab12518a4b
8 changed files with 298 additions and 126 deletions

View File

@@ -5,7 +5,7 @@ import keycode from 'keycode'
import initialState from './state.json' import initialState from './state.json'
/** /**
* Node renderers. * Define a set of node renderers.
* *
* @type {Object} * @type {Object}
*/ */

View File

@@ -6,7 +6,7 @@ import keycode from 'keycode'
import initialState from './state.json' import initialState from './state.json'
/** /**
* Node renderers. * Define a set of node renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -16,7 +16,7 @@ const NODES = {
} }
/** /**
* Mark renderers. * Define a set of mark renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -34,22 +34,42 @@ const MARKS = {
} }
/** /**
* Example. * The code highlighting example.
* *
* @type {Component} * @type {Component}
*/ */
class CodeHighlighting extends React.Component { class CodeHighlighting extends React.Component {
/**
* Deserialize the raw initial state.
*
* @type {Object}
*/
state = { state = {
state: Raw.deserialize(initialState) state: Raw.deserialize(initialState)
}; };
/**
* On change, save the new state.
*
* @param {State} state
*/
onChange = (state) => { onChange = (state) => {
this.setState({ state }) this.setState({ state })
} }
onKeyDown = (e, state, editor) => { /**
* On key down inside code blocks, insert soft new lines.
*
* @param {Event} e
* @param {State} state
* @return {State}
*/
onKeyDown = (e, state) => {
const key = keycode(e.which) const key = keycode(e.which)
if (key != 'enter') return if (key != 'enter') return
const { startBlock } = state const { startBlock } = state
@@ -62,6 +82,12 @@ class CodeHighlighting extends React.Component {
return transform.apply() return transform.apply()
} }
/**
* Render.
*
* @return {Component}
*/
render = () => { render = () => {
return ( return (
<div className="editor"> <div className="editor">
@@ -77,15 +103,36 @@ class CodeHighlighting extends React.Component {
) )
} }
/**
* Return a node renderer for a Slate `node`.
*
* @param {Node} node
* @return {Component or Void}
*/
renderNode = (node) => { renderNode = (node) => {
return NODES[node.type] return NODES[node.type]
} }
/**
* Return a mark renderer for a Slate `mark`.
*
* @param {Mark} mark
* @return {Object or Void}
*/
renderMark = (mark) => { renderMark = (mark) => {
return MARKS[mark.type] || {} return MARKS[mark.type] || {}
} }
renderDecorations = (text, state, editor) => { /**
* Render decorations on `text` nodes inside code blocks.
*
* @param {Text} text
* @return {Characters}
*/
renderDecorations = (text, state) => {
const { document } = state const { document } = state
const block = document.getClosestBlock(text) const block = document.getClosestBlock(text)
if (block.type != 'code') return text.characters if (block.type != 'code') return text.characters

View File

@@ -6,7 +6,7 @@ import position from 'selection-position'
import initialState from './state.json' import initialState from './state.json'
/** /**
* Mark renderers. * Define a set of mark renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -30,17 +30,27 @@ const MARKS = {
} }
/** /**
* The rich text example. * The hovering menu example.
* *
* @type {Component} * @type {Component}
*/ */
class HoveringMenu extends React.Component { class HoveringMenu extends React.Component {
/**
* Deserialize the raw initial state.
*
* @type {Object}
*/
state = { state = {
state: Raw.deserialize(initialState) state: Raw.deserialize(initialState)
}; };
/**
* On update, update the menu.
*/
componentDidMount = () => { componentDidMount = () => {
this.updateMenu() this.updateMenu()
} }
@@ -49,6 +59,64 @@ class HoveringMenu extends React.Component {
this.updateMenu() this.updateMenu()
} }
/**
* Check if the current selection has a mark with `type` in it.
*
* @param {String} type
* @return {Boolean}
*/
hasMark = (type) => {
const { state } = this.state
return state.marks.some(mark => mark.type == type)
}
/**
* On change, save the new state.
*
* @param {State} state
*/
onChange = (state) => {
this.setState({ state })
}
/**
* When a mark button is clicked, toggle the current mark.
*
* @param {Event} e
* @param {String} type
*/
onClickMark = (e, type) => {
e.preventDefault()
const isActive = this.hasMark(type)
let { state } = this.state
state = state
.transform()
[isActive ? 'unmark' : 'mark'](type)
.apply()
this.setState({ state })
}
/**
* When the portal opens, cache the menu element.
*
* @param {Element} portal
*/
onOpen = (portal) => {
this.setState({ menu: portal.firstChild })
}
/**
* Render.
*
* @return {Element}
*/
render = () => { render = () => {
return ( return (
<div> <div>
@@ -58,6 +126,12 @@ class HoveringMenu extends React.Component {
) )
} }
/**
* Render the hovering menu.
*
* @return {Element}
*/
renderMenu = () => { renderMenu = () => {
const { state } = this.state const { state } = this.state
const isOpen = state.isExpanded && state.isFocused const isOpen = state.isExpanded && state.isFocused
@@ -73,6 +147,14 @@ class HoveringMenu extends React.Component {
) )
} }
/**
* Render a mark-toggling toolbar button.
*
* @param {String} type
* @param {String} icon
* @return {Element}
*/
renderMarkButton = (type, icon) => { renderMarkButton = (type, icon) => {
const isActive = this.hasMark(type) const isActive = this.hasMark(type)
const onMouseDown = e => this.onClickMark(e, type) const onMouseDown = e => this.onClickMark(e, type)
@@ -84,6 +166,12 @@ class HoveringMenu extends React.Component {
) )
} }
/**
* Render the Slate editor.
*
* @return {Element}
*/
renderEditor = () => { renderEditor = () => {
return ( return (
<div className="editor"> <div className="editor">
@@ -96,10 +184,21 @@ class HoveringMenu extends React.Component {
) )
} }
/**
* Return a mark renderer for a Slate `mark`.
*
* @param {Mark} mark
* @return {Object or Void}
*/
renderMark = (mark) => { renderMark = (mark) => {
return MARKS[mark.type] return MARKS[mark.type]
} }
/**
* Update the menu's absolute position.
*/
updateMenu = () => { updateMenu = () => {
const { menu, state } = this.state const { menu, state } = this.state
if (!menu) return if (!menu) return
@@ -115,32 +214,6 @@ class HoveringMenu extends React.Component {
menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px` menu.style.left = `${rect.left + window.scrollX - menu.offsetWidth / 2 + rect.width / 2}px`
} }
hasMark = (type) => {
const { state } = this.state
return state.marks.some(mark => mark.type == type)
}
onChange = (state) => {
this.setState({ state })
}
onClickMark = (e, type) => {
e.preventDefault()
const isActive = this.hasMark(type)
let { state } = this.state
state = state
.transform()
[isActive ? 'unmark' : 'mark'](type)
.apply()
this.setState({ state })
}
onOpen = (el) => {
this.setState({ menu: el.firstChild })
}
} }
/** /**

View File

@@ -6,7 +6,7 @@ import initialState from './state.json'
import { Map } from 'immutable' import { Map } from 'immutable'
/** /**
* Node renderers. * Define a set of node renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -29,6 +29,12 @@ const NODES = {
class Images extends React.Component { class Images extends React.Component {
/**
* Deserialize the raw initial state.
*
* @type {Object}
*/
state = { state = {
state: Raw.deserialize(initialState) state: Raw.deserialize(initialState)
}; };

View File

@@ -6,7 +6,7 @@ import initialState from './state.json'
import { Map } from 'immutable' import { Map } from 'immutable'
/** /**
* Node renderers. * Define a set of node renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -28,6 +28,12 @@ const NODES = {
class Links extends React.Component { class Links extends React.Component {
/**
* Deserialize the raw initial state.
*
* @type {Object}
*/
state = { state = {
state: Raw.deserialize(initialState) state: Raw.deserialize(initialState)
}; };

View File

@@ -4,7 +4,7 @@ import React from 'react'
import initialState from './state.json' import initialState from './state.json'
/** /**
* Node renderers. * Define a set of node renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -29,7 +29,7 @@ const NODES = {
} }
/** /**
* Mark renderers. * Define a set of mark renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -157,17 +157,58 @@ const RULES = [
const serializer = new Html(RULES) const serializer = new Html(RULES)
/** /**
* The rich text example. * The pasting html example.
* *
* @type {Component} * @type {Component}
*/ */
class PasteHtml extends React.Component { class PasteHtml extends React.Component {
/**
* Deserialize the raw initial state.
*
* @type {Object}
*/
state = { state = {
state: Raw.deserialize(initialState) state: Raw.deserialize(initialState)
}; };
/**
* On change, save the new state.
*
* @param {State} state
*/
onChange = (state) => {
this.setState({ state })
}
/**
* On paste, deserialize the HTML and then insert the fragment.
*
* @param {Event} e
* @param {Object} paste
* @param {State} state
*/
onPaste = (e, paste, state) => {
if (paste.type != 'html') return
const { html } = paste
const { document } = serializer.deserialize(html)
return state
.transform()
.insertFragment(document)
.apply()
}
/**
* Render.
*
* @return {Component}
*/
render = () => { render = () => {
return ( return (
<div className="editor"> <div className="editor">
@@ -182,29 +223,28 @@ class PasteHtml extends React.Component {
) )
} }
/**
* Return a node renderer for a Slate `node`.
*
* @param {Node} node
* @return {Component or Void}
*/
renderNode = (node) => { renderNode = (node) => {
return NODES[node.type] return NODES[node.type]
} }
/**
* Return a mark renderer for a Slate `mark`.
*
* @param {Mark} mark
* @return {Object or Void}
*/
renderMark = (mark) => { renderMark = (mark) => {
return MARKS[mark.type] return MARKS[mark.type]
} }
onChange = (state) => {
this.setState({ state })
}
onPaste = (e, paste, state, editor) => {
if (paste.type != 'html') return
const { html } = paste
const { document } = serializer.deserialize(html)
return state
.transform()
.insertFragment(document)
.apply()
}
} }
/** /**

View File

@@ -5,7 +5,7 @@ import initialState from './state.json'
import keycode from 'keycode' import keycode from 'keycode'
/** /**
* Defin a set of node renderers. * Define a set of node renderers.
* *
* @type {Object} * @type {Object}
*/ */

View File

@@ -5,7 +5,7 @@ import initialState from './state.json'
import keycode from 'keycode' import keycode from 'keycode'
/** /**
* Node renderers. * Define a set of node renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -17,7 +17,7 @@ const NODES = {
} }
/** /**
* Mark renderers. * Define a set of mark renderers.
* *
* @type {Object} * @type {Object}
*/ */
@@ -46,75 +46,6 @@ class Tables extends React.Component {
state: Raw.deserialize(initialState) state: Raw.deserialize(initialState)
}; };
/**
* Render the example.
*
* @return {Component} component
*/
render = () => {
return (
<div className="editor">
<Editor
state={this.state.state}
renderNode={this.renderNode}
renderMark={this.renderMark}
onKeyDown={this.onKeyDown}
onChange={this.onChange}
/>
</div>
)
}
/**
* Render a `node`.
*
* @param {Node} node
* @return {Element}
*/
renderNode = (node) => {
return NODES[node.type]
}
/**
* Render a `mark`.
*
* @param {Mark} mark
* @return {Element}
*/
renderMark = (mark) => {
return MARKS[mark.type]
}
/**
* On change.
*
* @param {State} state
*/
onChange = (state) => {
this.setState({ state })
}
/**
* On key down, check for our specific key shortcuts.
*
* @param {Event} e
* @param {State} state
* @return {State or Null} state
*/
onKeyDown = (e, state) => {
if (state.startBlock.type != 'table-cell') return
switch (keycode(e.which)) {
case 'backspace': return this.onBackspace(e, state)
case 'delete': return this.onDelete(e, state)
case 'enter': return this.onEnter(e, state)
}
}
/** /**
* On backspace, do nothing if at the start of a table cell. * On backspace, do nothing if at the start of a table cell.
* *
@@ -129,6 +60,16 @@ class Tables extends React.Component {
return state return state
} }
/**
* On change.
*
* @param {State} state
*/
onChange = (state) => {
this.setState({ state })
}
/** /**
* On delete, do nothing if at the end of a table cell. * On delete, do nothing if at the end of a table cell.
* *
@@ -156,6 +97,65 @@ class Tables extends React.Component {
return state return state
} }
/**
* On key down, check for our specific key shortcuts.
*
* @param {Event} e
* @param {State} state
* @return {State or Null} state
*/
onKeyDown = (e, state) => {
if (state.startBlock.type != 'table-cell') return
switch (keycode(e.which)) {
case 'backspace': return this.onBackspace(e, state)
case 'delete': return this.onDelete(e, state)
case 'enter': return this.onEnter(e, state)
}
}
/**
* Render the example.
*
* @return {Component} component
*/
render = () => {
return (
<div className="editor">
<Editor
state={this.state.state}
renderNode={this.renderNode}
renderMark={this.renderMark}
onKeyDown={this.onKeyDown}
onChange={this.onChange}
/>
</div>
)
}
/**
* Return a node renderer for a Slate `node`.
*
* @param {Node} node
* @return {Component or Void}
*/
renderNode = (node) => {
return NODES[node.type]
}
/**
* Return a mark renderer for a Slate `mark`.
*
* @param {Mark} mark
* @return {Object or Void}
*/
renderMark = (mark) => {
return MARKS[mark.type]
}
} }
/** /**