1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-04-22 14:21:54 +02:00

adding forced-layout-example (#954)

This commit is contained in:
Ryan Yurkanin 2017-07-31 21:19:45 -04:00 committed by Ian Storm Taylor
parent f8b103d75e
commit af84cf2511
6 changed files with 150 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -7,6 +7,7 @@ This directory contains a set of examples that give you an idea for how you migh
- [**Plain text**](./plain-text) — showing the most basic case: a glorified `<textarea>`.
- [**Rich text**](./rich-text) — showing the features you'd expect from a basic editor.
- [**Forced Layout**](./forced-layout) - showing how to use schema rules to enforce document structure
- [**Auto-markdown**](./auto-markdown) — showing how to add key handlers for Markdown-like shortcuts.
- [**Links**](./links) — showing how wrap text in inline nodes with associated data.
- [**Images**](./images) — showing how to use void (text-less) nodes to add images.

View File

@ -0,0 +1,8 @@
# Forced Layout Example
![](../../docs/images/forced-layout-example.png)
This example shows you how you can use Rules in your schema to enforce a document structure. The basic example enforces having one title block that is always at the top, and at least one paragraph block underneath it.
Check out the [Examples readme](..) to see how to run it!

View File

@ -0,0 +1,107 @@
import { Editor, Raw, Block } from '../..'
import React from 'react'
import initialState from './state.json'
/**
* The Forced Layout example.
*
* @type {Component}
*/
class ForcedLayout extends React.Component {
/**
* Deserialize the initial editor state.
*
* @type {Object}
*/
state = {
state: Raw.deserialize(initialState, { terse: true }),
schema: {
nodes: {
'title': props => <h1 {...props.attrs}>{props.children}</h1>,
'paragraph': props => <p {...props.attrs}>{props.children}</p>
},
rules: [
/* Rule that always makes the first block a title, normalizes by inserting one if no children, or setting the top to be a title */
{
match: node => node.kind === 'document',
validate: document => !document.nodes.size || document.nodes.first().type !== 'title' ? document.nodes : null,
normalize: (transform, document, nodes) => {
if (!nodes.size) {
const title = Block.create({ type: 'title', data: {}})
return transform.insertNodeByKey(document.key, 0, title)
}
return transform.setNodeByKey(nodes.first().key, 'title')
}
},
/* Rule that only allows for one title, normalizes by making titles paragraphs */
{
match: node => node.kind === 'document',
validate: (document) => {
const invalidChildren = document.nodes.filter((child, index) => child.type === 'title' && index !== 0)
return invalidChildren.size ? invalidChildren : null
},
normalize: (transform, document, invalidChildren) => {
let updatedTransform = transform
invalidChildren.forEach((child) => {
updatedTransform = transform.setNodeByKey(child.key, 'paragraph')
})
return updatedTransform
}
},
/* Rule that forces at least one paragraph, normalizes by inserting an empty paragraph */
{
match: node => node.kind === 'document',
validate: document => document.nodes.size < 2 ? true : null,
normalize: (transform, document) => {
const paragraph = Block.create({ type: 'paragraph', data: {}})
return transform.insertNodeByKey(document.key, 1, paragraph)
}
}
]
}
};
/**
* On change.
*
* @param {State} state
*/
onChange = (state) => {
this.setState({ state })
}
/**
* Render the editor.
*
* @return {Component} component
*/
render = () => {
return (
<Editor
state={this.state.state}
schema={this.state.schema}
onChange={this.onChange}
/>
)
}
}
/**
* Export.
*/
export default ForcedLayout

View File

@ -0,0 +1,32 @@
{
"nodes": [
{
"kind": "block",
"type": "title",
"nodes": [
{
"kind": "text",
"ranges": [
{
"text": "This example shows how to enforce your layout with rules."
}
]
}
]
},
{
"kind": "block",
"type": "paragraph",
"nodes": [
{
"kind": "text",
"ranges": [
{
"text": "This document will always have one title at the top, and at least one paragraph"
}
]
}
]
}
]
}

View File

@ -8,6 +8,7 @@ import CodeHighlighting from './code-highlighting'
import Embeds from './embeds'
import Emojis from './emojis'
import FocusBlur from './focus-blur'
import ForcedLayout from './forced-layout'
import HoveringMenu from './hovering-menu'
import Iframes from './iframes'
import Images from './images'
@ -59,6 +60,7 @@ const EXAMPLES = [
['Plugins', Plugins, '/plugins'],
['Iframes', Iframes, '/iframes'],
['Focus & Blur', FocusBlur, '/focus-blur'],
['Forced Layout', ForcedLayout, '/forced-layout'],
['DEV:Large', DevLargeDocument, '/dev-large', true],
['DEV:Plain', DevPerformancePlain, '/dev-performance-plain', true],