1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-11 01:33:58 +02:00

add read-only mode, closes #108 #106

This commit is contained in:
Ian Storm Taylor
2016-07-17 15:57:27 -07:00
parent 6140386f2e
commit c489eee418
6 changed files with 89 additions and 3 deletions

View File

@@ -11,6 +11,7 @@ The top-level React component that renders the Slate editor itself.
- [`className`](#classname) - [`className`](#classname)
- [`onChange`](#onchange) - [`onChange`](#onchange)
- [`plugins`](#plugins) - [`plugins`](#plugins)
- [`readOnly`](#readonly)
- [`state`](#state) - [`state`](#state)
- [`style`](#style) - [`style`](#style)
- [Placeholder Properties](#placeholder-properties) - [Placeholder Properties](#placeholder-properties)
@@ -36,6 +37,7 @@ The top-level React component that renders the Slate editor itself.
className={string} className={string}
onChange={Function} onChange={Function}
plugins={Array} plugins={Array}
readOnly={Boolean}
state={State} state={State}
style={Object} style={Object}
/> />
@@ -56,6 +58,11 @@ A change handler that will be called with the newly-changed editor `state`. You
An array of [`Plugins`](../plugins) that define the editor's behavior. An array of [`Plugins`](../plugins) that define the editor's behavior.
### `readOnly`
`Boolean`
Whether the editor should be in "read-only" mode, where all of the rendering is the same, but the user is prevented from editing the editor's content.
### `state` ### `state`
`State` `State`

View File

@@ -14,6 +14,7 @@ import Images from './images'
import Links from './links' import Links from './links'
import PasteHtml from './paste-html' import PasteHtml from './paste-html'
import PlainText from './plain-text' import PlainText from './plain-text'
import ReadOnly from './read-only'
import RichText from './rich-text' import RichText from './rich-text'
import Tables from './tables' import Tables from './tables'
@@ -66,6 +67,7 @@ class App extends React.Component {
{this.renderTab('Tables', 'tables')} {this.renderTab('Tables', 'tables')}
{this.renderTab('Code Highlighting', 'code-highlighting')} {this.renderTab('Code Highlighting', 'code-highlighting')}
{this.renderTab('Paste HTML', 'paste-html')} {this.renderTab('Paste HTML', 'paste-html')}
{this.renderTab('Read Only', 'read-only')}
</div> </div>
) )
} }
@@ -116,6 +118,7 @@ const router = (
<Route path="links" component={Links} /> <Route path="links" component={Links} />
<Route path="paste-html" component={PasteHtml} /> <Route path="paste-html" component={PasteHtml} />
<Route path="plain-text" component={PlainText} /> <Route path="plain-text" component={PlainText} />
<Route path="read-only" component={ReadOnly} />
<Route path="rich-text" component={RichText} /> <Route path="rich-text" component={RichText} />
<Route path="tables" component={Tables} /> <Route path="tables" component={Tables} />
</Route> </Route>

View File

@@ -0,0 +1,8 @@
# Plain Text Example
![](../../docs/images/plain-text-example.png)
This is the most basic Slate example. It's basically a glorified `<textarea>`. But it gives you a sense for the absolute basics of Slate.
Check out the [Examples readme](..) to see how to run it!

View File

@@ -0,0 +1,56 @@
import { Editor, Plain } from '../..'
import React from 'react'
/**
* The read-only example.
*
* @type {Component}
*/
class ReadOnly extends React.Component {
/**
* Deserialize the initial editor state.
*
* @type {Object}
*/
state = {
state: Plain.deserialize('This is read-only text. You should not be able to edit it, which is useful for scenarios where you want to render via Slate, without giving the user editing persmissions.')
};
/**
* On change.
*
* @param {State} state
*/
onChange = (state) => {
this.setState({ state })
}
/**
* Render the editor.
*
* @return {Component} component
*/
render = () => {
return (
<Editor
readOnly
placeholder={'Enter some text...'}
state={this.state.state}
onChange={this.onChange}
/>
)
}
}
/**
* Export.
*/
export default ReadOnly

View File

@@ -33,6 +33,7 @@ class Content extends React.Component {
onKeyDown: React.PropTypes.func, onKeyDown: React.PropTypes.func,
onPaste: React.PropTypes.func, onPaste: React.PropTypes.func,
onSelect: React.PropTypes.func, onSelect: React.PropTypes.func,
readOnly: React.PropTypes.bool,
renderMark: React.PropTypes.func.isRequired, renderMark: React.PropTypes.func.isRequired,
renderNode: React.PropTypes.func.isRequired, renderNode: React.PropTypes.func.isRequired,
state: React.PropTypes.object.isRequired, state: React.PropTypes.object.isRequired,
@@ -44,6 +45,7 @@ class Content extends React.Component {
*/ */
static defaultProps = { static defaultProps = {
readOnly: false,
style: {} style: {}
}; };
@@ -98,6 +100,7 @@ class Content extends React.Component {
*/ */
onBeforeInput = (e) => { onBeforeInput = (e) => {
if (this.props.readOnly) return
this.props.onBeforeInput(e) this.props.onBeforeInput(e)
} }
@@ -108,6 +111,7 @@ class Content extends React.Component {
*/ */
onBlur = (e) => { onBlur = (e) => {
if (this.props.readOnly) return
if (this.tmp.isCopying) return if (this.tmp.isCopying) return
let { state } = this.props let { state } = this.props
@@ -146,6 +150,7 @@ class Content extends React.Component {
*/ */
onCut = (e) => { onCut = (e) => {
if (this.props.readOnly) return
this.onCutCopy(e) this.onCutCopy(e)
// Once the cut has successfully executed, delete the current selection. // Once the cut has successfully executed, delete the current selection.
@@ -216,6 +221,7 @@ class Content extends React.Component {
*/ */
onKeyDown = (e) => { onKeyDown = (e) => {
if (this.props.readOnly) return
const key = keycode(e.which) const key = keycode(e.which)
if ( if (
@@ -240,6 +246,7 @@ class Content extends React.Component {
*/ */
onPaste = (e) => { onPaste = (e) => {
if (this.props.readOnly) return
e.preventDefault() e.preventDefault()
const data = e.clipboardData const data = e.clipboardData
const paste = {} const paste = {}
@@ -298,6 +305,7 @@ class Content extends React.Component {
*/ */
onSelect = (e) => { onSelect = (e) => {
if (this.props.readOnly) return
if (this.tmp.isRendering) return if (this.tmp.isRendering) return
if (this.tmp.isCopying) return if (this.tmp.isCopying) return
@@ -337,7 +345,7 @@ class Content extends React.Component {
*/ */
render = () => { render = () => {
const { className, state } = this.props const { className, readOnly, state } = this.props
const { document } = state const { document } = state
const children = document.nodes const children = document.nodes
.map(node => this.renderNode(node)) .map(node => this.renderNode(node))
@@ -353,7 +361,8 @@ class Content extends React.Component {
return ( return (
<div <div
className={className} className={className}
contentEditable suppressContentEditableWarning contentEditable={!readOnly}
suppressContentEditableWarning
style={style} style={style}
onBeforeInput={this.onBeforeInput} onBeforeInput={this.onBeforeInput}
onBlur={this.onBlur} onBlur={this.onBlur}

View File

@@ -24,6 +24,7 @@ class Editor extends React.Component {
placeholderClassName: React.PropTypes.string, placeholderClassName: React.PropTypes.string,
placeholderStyle: React.PropTypes.object, placeholderStyle: React.PropTypes.object,
plugins: React.PropTypes.array, plugins: React.PropTypes.array,
readOnly: React.PropTypes.bool,
renderDecorations: React.PropTypes.func, renderDecorations: React.PropTypes.func,
renderMark: React.PropTypes.func, renderMark: React.PropTypes.func,
renderNode: React.PropTypes.func, renderNode: React.PropTypes.func,
@@ -32,7 +33,8 @@ class Editor extends React.Component {
}; };
static defaultProps = { static defaultProps = {
plugins: [] plugins: [],
readOnly: false
}; };
/** /**
@@ -175,6 +177,7 @@ class Editor extends React.Component {
editor={this} editor={this}
state={this.state.state} state={this.state.state}
onChange={this.onChange} onChange={this.onChange}
readOnly={this.props.readOnly}
renderMark={this.renderMark} renderMark={this.renderMark}
renderNode={this.renderNode} renderNode={this.renderNode}
onPaste={this.onPaste} onPaste={this.onPaste}