diff --git a/examples/auto-markdown/index.js b/examples/auto-markdown/index.js index 4d2996c48..e68b7efef 100644 --- a/examples/auto-markdown/index.js +++ b/examples/auto-markdown/index.js @@ -5,7 +5,7 @@ import keycode from 'keycode' import initialState from './state.json' /** - * Node renderers. + * Define a set of node renderers. * * @type {Object} */ diff --git a/examples/code-highlighting/index.js b/examples/code-highlighting/index.js index a9be58351..8fafe2ba0 100644 --- a/examples/code-highlighting/index.js +++ b/examples/code-highlighting/index.js @@ -6,7 +6,7 @@ import keycode from 'keycode' import initialState from './state.json' /** - * Node renderers. + * Define a set of node renderers. * * @type {Object} */ @@ -16,7 +16,7 @@ const NODES = { } /** - * Mark renderers. + * Define a set of mark renderers. * * @type {Object} */ @@ -34,22 +34,42 @@ const MARKS = { } /** - * Example. + * The code highlighting example. * * @type {Component} */ class CodeHighlighting extends React.Component { + /** + * Deserialize the raw initial state. + * + * @type {Object} + */ + state = { state: Raw.deserialize(initialState) }; + /** + * On change, save the new state. + * + * @param {State} state + */ + onChange = (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) if (key != 'enter') return const { startBlock } = state @@ -62,6 +82,12 @@ class CodeHighlighting extends React.Component { return transform.apply() } + /** + * Render. + * + * @return {Component} + */ + render = () => { return (
@@ -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) => { 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] || {} } - renderDecorations = (text, state, editor) => { + /** + * Render decorations on `text` nodes inside code blocks. + * + * @param {Text} text + * @return {Characters} + */ + + renderDecorations = (text, state) => { const { document } = state const block = document.getClosestBlock(text) if (block.type != 'code') return text.characters diff --git a/examples/hovering-menu/index.js b/examples/hovering-menu/index.js index 5f333837d..a7df79657 100644 --- a/examples/hovering-menu/index.js +++ b/examples/hovering-menu/index.js @@ -6,7 +6,7 @@ import position from 'selection-position' import initialState from './state.json' /** - * Mark renderers. + * Define a set of mark renderers. * * @type {Object} */ @@ -30,17 +30,27 @@ const MARKS = { } /** - * The rich text example. + * The hovering menu example. * * @type {Component} */ class HoveringMenu extends React.Component { + /** + * Deserialize the raw initial state. + * + * @type {Object} + */ + state = { state: Raw.deserialize(initialState) }; + /** + * On update, update the menu. + */ + componentDidMount = () => { this.updateMenu() } @@ -49,6 +59,64 @@ class HoveringMenu extends React.Component { 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 = () => { return (
@@ -58,6 +126,12 @@ class HoveringMenu extends React.Component { ) } + /** + * Render the hovering menu. + * + * @return {Element} + */ + renderMenu = () => { const { state } = this.state 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) => { const isActive = this.hasMark(type) const onMouseDown = e => this.onClickMark(e, type) @@ -84,6 +166,12 @@ class HoveringMenu extends React.Component { ) } + /** + * Render the Slate editor. + * + * @return {Element} + */ + renderEditor = () => { return (
@@ -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) => { return MARKS[mark.type] } + /** + * Update the menu's absolute position. + */ + updateMenu = () => { const { menu, state } = this.state 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` } - 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 }) - } - } /** diff --git a/examples/images/index.js b/examples/images/index.js index f3834bdf2..a62ef5019 100644 --- a/examples/images/index.js +++ b/examples/images/index.js @@ -6,7 +6,7 @@ import initialState from './state.json' import { Map } from 'immutable' /** - * Node renderers. + * Define a set of node renderers. * * @type {Object} */ @@ -29,6 +29,12 @@ const NODES = { class Images extends React.Component { + /** + * Deserialize the raw initial state. + * + * @type {Object} + */ + state = { state: Raw.deserialize(initialState) }; diff --git a/examples/links/index.js b/examples/links/index.js index 13e335793..ae15aae07 100644 --- a/examples/links/index.js +++ b/examples/links/index.js @@ -6,7 +6,7 @@ import initialState from './state.json' import { Map } from 'immutable' /** - * Node renderers. + * Define a set of node renderers. * * @type {Object} */ @@ -28,6 +28,12 @@ const NODES = { class Links extends React.Component { + /** + * Deserialize the raw initial state. + * + * @type {Object} + */ + state = { state: Raw.deserialize(initialState) }; diff --git a/examples/paste-html/index.js b/examples/paste-html/index.js index e487f7fff..1fd20fca5 100644 --- a/examples/paste-html/index.js +++ b/examples/paste-html/index.js @@ -4,7 +4,7 @@ import React from 'react' import initialState from './state.json' /** - * Node renderers. + * Define a set of node renderers. * * @type {Object} */ @@ -29,7 +29,7 @@ const NODES = { } /** - * Mark renderers. + * Define a set of mark renderers. * * @type {Object} */ @@ -157,17 +157,58 @@ const RULES = [ const serializer = new Html(RULES) /** - * The rich text example. + * The pasting html example. * * @type {Component} */ class PasteHtml extends React.Component { + /** + * Deserialize the raw initial state. + * + * @type {Object} + */ + state = { 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 = () => { return (
@@ -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) => { 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] } - 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() - } - } /** diff --git a/examples/rich-text/index.js b/examples/rich-text/index.js index 74128a8c4..cf4f4a165 100644 --- a/examples/rich-text/index.js +++ b/examples/rich-text/index.js @@ -5,7 +5,7 @@ import initialState from './state.json' import keycode from 'keycode' /** - * Defin a set of node renderers. + * Define a set of node renderers. * * @type {Object} */ diff --git a/examples/tables/index.js b/examples/tables/index.js index 6e0056e47..2c8a27b41 100644 --- a/examples/tables/index.js +++ b/examples/tables/index.js @@ -5,7 +5,7 @@ import initialState from './state.json' import keycode from 'keycode' /** - * Node renderers. + * Define a set of node renderers. * * @type {Object} */ @@ -17,7 +17,7 @@ const NODES = { } /** - * Mark renderers. + * Define a set of mark renderers. * * @type {Object} */ @@ -46,75 +46,6 @@ class Tables extends React.Component { state: Raw.deserialize(initialState) }; - /** - * Render the example. - * - * @return {Component} component - */ - - render = () => { - return ( -
- -
- ) - } - - /** - * 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. * @@ -129,6 +60,16 @@ class Tables extends React.Component { return state } + /** + * On change. + * + * @param {State} state + */ + + onChange = (state) => { + this.setState({ state }) + } + /** * On delete, do nothing if at the end of a table cell. * @@ -156,6 +97,65 @@ class Tables extends React.Component { 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 ( +
+ +
+ ) + } + + /** + * 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] + } + } /**