mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-13 10:44:02 +02:00
add embeds example, fix to not let events propagate out of voids
This commit is contained in:
9
examples/embeds/Readme.md
Normal file
9
examples/embeds/Readme.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
# Images Example
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This example shows you how you can use "void" nodes to render content that has no text in it, like images.
|
||||||
|
|
||||||
|
Check out the [Examples readme](..) to see how to run it!
|
||||||
|
|
81
examples/embeds/index.js
Normal file
81
examples/embeds/index.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
import { Editor, Raw } from '../..'
|
||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
import Video from './video'
|
||||||
|
import initialState from './state.json'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a set of node renderers.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const NODES = {
|
||||||
|
video: Video
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The images example.
|
||||||
|
*
|
||||||
|
* @type {Component}
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Embeds extends React.Component {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize the raw initial state.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
state = {
|
||||||
|
state: Raw.deserialize(initialState, { terse: true })
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On change.
|
||||||
|
*
|
||||||
|
* @param {State} state
|
||||||
|
*/
|
||||||
|
|
||||||
|
onChange = (state) => {
|
||||||
|
this.setState({ state })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the app.
|
||||||
|
*
|
||||||
|
* @return {Element} element
|
||||||
|
*/
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
return (
|
||||||
|
<div className="editor">
|
||||||
|
<Editor
|
||||||
|
state={this.state.state}
|
||||||
|
renderNode={this.renderNode}
|
||||||
|
onChange={this.onChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a `node`.
|
||||||
|
*
|
||||||
|
* @param {Node} node
|
||||||
|
* @return {Element}
|
||||||
|
*/
|
||||||
|
|
||||||
|
renderNode = (node) => {
|
||||||
|
return NODES[node.type]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default Embeds
|
32
examples/embeds/state.json
Normal file
32
examples/embeds/state.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"kind": "block",
|
||||||
|
"type": "paragraph",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"kind": "text",
|
||||||
|
"text": "In addition to simple image nodes, you can actually create complex embedded nodes. For example, this one contains an input element that lets you change the video being rendered!"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "block",
|
||||||
|
"type": "video",
|
||||||
|
"isVoid": true,
|
||||||
|
"data": {
|
||||||
|
"video": "https://www.youtube.com/embed/FaHEusBG20c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "block",
|
||||||
|
"type": "paragraph",
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"kind": "text",
|
||||||
|
"text": "Try it out! If you want another good video URL to try, go with: https://www.youtube.com/embed/6Ejga4kJUts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
122
examples/embeds/video.js
Normal file
122
examples/embeds/video.js
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { Void } from '../..'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An video embed component.
|
||||||
|
*
|
||||||
|
* @type {Component}
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Video extends React.Component {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the input text changes, update the `video` data on the node.
|
||||||
|
*
|
||||||
|
* @param {Event} e
|
||||||
|
*/
|
||||||
|
|
||||||
|
onChange = (e) => {
|
||||||
|
const video = e.target.value
|
||||||
|
const { node, state, editor } = this.props
|
||||||
|
const properties = {
|
||||||
|
data: { video }
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = state
|
||||||
|
.transform()
|
||||||
|
.setNodeByKey(node.key, properties)
|
||||||
|
.apply()
|
||||||
|
|
||||||
|
editor.onChange(next)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When clicks happen in the input, stop propagation so that the void node
|
||||||
|
* itself isn't focused, since that would unfocus the input.
|
||||||
|
*
|
||||||
|
* @type {Event} e
|
||||||
|
*/
|
||||||
|
|
||||||
|
onClick = (e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render.
|
||||||
|
*
|
||||||
|
* @return {Element}
|
||||||
|
*/
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
return (
|
||||||
|
<Void {...this.props}>
|
||||||
|
{this.renderVideo()}
|
||||||
|
{this.renderInput()}
|
||||||
|
</Void>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the Youtube iframe, responsively.
|
||||||
|
*
|
||||||
|
* @return {Element}
|
||||||
|
*/
|
||||||
|
|
||||||
|
renderVideo = () => {
|
||||||
|
const video = this.props.node.data.get('video')
|
||||||
|
const wrapperStyle = {
|
||||||
|
position: 'relative',
|
||||||
|
paddingBottom: '66.66%',
|
||||||
|
paddingTop: '25px',
|
||||||
|
height: '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
const iframeStyle = {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '0px',
|
||||||
|
left: '0px',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%'
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={wrapperStyle}>
|
||||||
|
<iframe
|
||||||
|
id="ytplayer"
|
||||||
|
type="text/html"
|
||||||
|
width="640"
|
||||||
|
height="390"
|
||||||
|
src={video}
|
||||||
|
frameBorder="0"
|
||||||
|
style={iframeStyle}
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the video URL input.
|
||||||
|
*
|
||||||
|
* @return {Element}
|
||||||
|
*/
|
||||||
|
|
||||||
|
renderInput = () => {
|
||||||
|
const video = this.props.node.data.get('video')
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
value={video}
|
||||||
|
onChange={this.onChange}
|
||||||
|
onClick={this.onClick}
|
||||||
|
style={{ marginTop: '5px' }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default Video
|
@@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
html {
|
html,
|
||||||
|
input,
|
||||||
|
textarea {
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: 'Roboto', sans-serif;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
background: #eee;
|
background: #eee;
|
||||||
@@ -41,6 +43,19 @@ td {
|
|||||||
border: 2px solid #ddd;
|
border: 2px solid #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-size: .85em;
|
||||||
|
width: 100%;
|
||||||
|
padding: .5em;
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
outline: 0;
|
||||||
|
border-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Icons.
|
* Icons.
|
||||||
*/
|
*/
|
||||||
|
@@ -9,6 +9,7 @@ import { Router, Route, Link, IndexRedirect, hashHistory } from 'react-router'
|
|||||||
|
|
||||||
import AutoMarkdown from './auto-markdown'
|
import AutoMarkdown from './auto-markdown'
|
||||||
import CodeHighlighting from './code-highlighting'
|
import CodeHighlighting from './code-highlighting'
|
||||||
|
import Embeds from './embeds'
|
||||||
import HoveringMenu from './hovering-menu'
|
import HoveringMenu from './hovering-menu'
|
||||||
import Images from './images'
|
import Images from './images'
|
||||||
import Links from './links'
|
import Links from './links'
|
||||||
@@ -67,6 +68,7 @@ class App extends React.Component {
|
|||||||
{this.renderTab('Hovering Menu', 'hovering-menu')}
|
{this.renderTab('Hovering Menu', 'hovering-menu')}
|
||||||
{this.renderTab('Links', 'links')}
|
{this.renderTab('Links', 'links')}
|
||||||
{this.renderTab('Images', 'images')}
|
{this.renderTab('Images', 'images')}
|
||||||
|
{this.renderTab('Embeds', 'embeds')}
|
||||||
{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')}
|
||||||
@@ -117,6 +119,7 @@ const router = (
|
|||||||
<IndexRedirect to="rich-text" />
|
<IndexRedirect to="rich-text" />
|
||||||
<Route path="auto-markdown" component={AutoMarkdown} />
|
<Route path="auto-markdown" component={AutoMarkdown} />
|
||||||
<Route path="code-highlighting" component={CodeHighlighting} />
|
<Route path="code-highlighting" component={CodeHighlighting} />
|
||||||
|
<Route path="embeds" component={Embeds} />
|
||||||
<Route path="hovering-menu" component={HoveringMenu} />
|
<Route path="hovering-menu" component={HoveringMenu} />
|
||||||
<Route path="images" component={Images} />
|
<Route path="images" component={Images} />
|
||||||
<Route path="links" component={Links} />
|
<Route path="links" component={Links} />
|
||||||
|
@@ -27,6 +27,10 @@
|
|||||||
</blockquote>
|
</blockquote>
|
||||||
<p></p>
|
<p></p>
|
||||||
<p></p>
|
<p></p>
|
||||||
|
<div contenteditable="false">
|
||||||
|
<div contenteditable>
|
||||||
|
<input value="test" />
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
<li>one</li>
|
<li>one</li>
|
||||||
<li>two</li>
|
<li>two</li>
|
||||||
|
@@ -155,6 +155,7 @@ class Content extends React.Component {
|
|||||||
|
|
||||||
onBeforeInput = (e) => {
|
onBeforeInput = (e) => {
|
||||||
if (this.props.readOnly) return
|
if (this.props.readOnly) return
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
const data = {}
|
const data = {}
|
||||||
this.props.onBeforeInput(e, data)
|
this.props.onBeforeInput(e, data)
|
||||||
@@ -169,6 +170,7 @@ class Content extends React.Component {
|
|||||||
onBlur = (e) => {
|
onBlur = (e) => {
|
||||||
if (this.props.readOnly) return
|
if (this.props.readOnly) return
|
||||||
if (this.tmp.isCopying) return
|
if (this.tmp.isCopying) return
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
const data = {}
|
const data = {}
|
||||||
this.props.onBlur(e, data)
|
this.props.onBlur(e, data)
|
||||||
@@ -191,6 +193,8 @@ class Content extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
onCompositionStart = (e) => {
|
onCompositionStart = (e) => {
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
this.tmp.isComposing = true
|
this.tmp.isComposing = true
|
||||||
this.tmp.compositions++
|
this.tmp.compositions++
|
||||||
}
|
}
|
||||||
@@ -204,6 +208,8 @@ class Content extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
onCompositionEnd = (e) => {
|
onCompositionEnd = (e) => {
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
this.forces++
|
this.forces++
|
||||||
const count = this.tmp.compositions
|
const count = this.tmp.compositions
|
||||||
|
|
||||||
@@ -223,6 +229,8 @@ class Content extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
onCopy = (e) => {
|
onCopy = (e) => {
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
this.tmp.isCopying = true
|
this.tmp.isCopying = true
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
this.tmp.isCopying = false
|
this.tmp.isCopying = false
|
||||||
@@ -243,6 +251,7 @@ class Content extends React.Component {
|
|||||||
|
|
||||||
onCut = (e) => {
|
onCut = (e) => {
|
||||||
if (this.props.readOnly) return
|
if (this.props.readOnly) return
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
this.tmp.isCopying = true
|
this.tmp.isCopying = true
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
@@ -263,6 +272,8 @@ class Content extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
onDragEnd = (e) => {
|
onDragEnd = (e) => {
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
this.tmp.isDragging = false
|
this.tmp.isDragging = false
|
||||||
this.tmp.isInternalDrag = null
|
this.tmp.isInternalDrag = null
|
||||||
}
|
}
|
||||||
@@ -274,6 +285,8 @@ class Content extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
onDragOver = (e) => {
|
onDragOver = (e) => {
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
const data = e.nativeEvent.dataTransfer
|
const data = e.nativeEvent.dataTransfer
|
||||||
// COMPAT: In Firefox, `types` is array-like. (2016/06/21)
|
// COMPAT: In Firefox, `types` is array-like. (2016/06/21)
|
||||||
const types = Array.from(data.types)
|
const types = Array.from(data.types)
|
||||||
@@ -295,6 +308,8 @@ class Content extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
onDragStart = (e) => {
|
onDragStart = (e) => {
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
this.tmp.isDragging = true
|
this.tmp.isDragging = true
|
||||||
this.tmp.isInternalDrag = true
|
this.tmp.isInternalDrag = true
|
||||||
const data = e.nativeEvent.dataTransfer
|
const data = e.nativeEvent.dataTransfer
|
||||||
@@ -318,6 +333,8 @@ class Content extends React.Component {
|
|||||||
|
|
||||||
onDrop = (e) => {
|
onDrop = (e) => {
|
||||||
if (this.props.readOnly) return
|
if (this.props.readOnly) return
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
const { state, renderDecorations } = this.props
|
const { state, renderDecorations } = this.props
|
||||||
@@ -403,6 +420,8 @@ class Content extends React.Component {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
onInput = (e) => {
|
onInput = (e) => {
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
let { state, renderDecorations } = this.props
|
let { state, renderDecorations } = this.props
|
||||||
const { selection } = state
|
const { selection } = state
|
||||||
const native = window.getSelection()
|
const native = window.getSelection()
|
||||||
@@ -454,6 +473,8 @@ class Content extends React.Component {
|
|||||||
|
|
||||||
onKeyDown = (e) => {
|
onKeyDown = (e) => {
|
||||||
if (this.props.readOnly) return
|
if (this.props.readOnly) return
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
const key = keycode(e.which)
|
const key = keycode(e.which)
|
||||||
const data = {}
|
const data = {}
|
||||||
|
|
||||||
@@ -505,6 +526,8 @@ class Content extends React.Component {
|
|||||||
|
|
||||||
onPaste = (e) => {
|
onPaste = (e) => {
|
||||||
if (this.props.readOnly) return
|
if (this.props.readOnly) return
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
const { clipboardData } = e
|
const { clipboardData } = e
|
||||||
@@ -557,6 +580,7 @@ class Content extends React.Component {
|
|||||||
if (this.tmp.isRendering) return
|
if (this.tmp.isRendering) return
|
||||||
if (this.tmp.isCopying) return
|
if (this.tmp.isCopying) return
|
||||||
if (this.tmp.isComposing) return
|
if (this.tmp.isComposing) return
|
||||||
|
if (isNonEditable(e)) return
|
||||||
|
|
||||||
const { state, renderDecorations } = this.props
|
const { state, renderDecorations } = this.props
|
||||||
let { document, selection } = state
|
let { document, selection } = state
|
||||||
@@ -695,6 +719,21 @@ class Content extends React.Component {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an `event` is being fired from inside a non-contentediable child
|
||||||
|
* element, in which case we'll want to ignore it.
|
||||||
|
*
|
||||||
|
* @param {Event} event
|
||||||
|
* @return {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isNonEditable(event) {
|
||||||
|
const { target, currentTarget } = event
|
||||||
|
const nonEditable = target.closest('[contenteditable="false"]:not([data-void="true"])')
|
||||||
|
const isContained = currentTarget.contains(nonEditable)
|
||||||
|
return isContained
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export.
|
* Export.
|
||||||
*/
|
*/
|
||||||
|
@@ -55,6 +55,7 @@ class Leaf extends React.Component {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.isBlurred) return false
|
||||||
const { start, end } = OffsetKey.findBounds(index, props.ranges)
|
const { start, end } = OffsetKey.findBounds(index, props.ranges)
|
||||||
return selection.hasEdgeBetween(node, start, end)
|
return selection.hasEdgeBetween(node, start, end)
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,7 @@ class Node extends React.Component {
|
|||||||
shouldComponentUpdate = (props) => {
|
shouldComponentUpdate = (props) => {
|
||||||
return (
|
return (
|
||||||
props.node != this.props.node ||
|
props.node != this.props.node ||
|
||||||
props.state.selection.hasEdgeIn(props.node)
|
(props.state.isFocused && props.state.selection.hasEdgeIn(props.node))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ class Text extends React.Component {
|
|||||||
shouldComponentUpdate(props, state) {
|
shouldComponentUpdate(props, state) {
|
||||||
return (
|
return (
|
||||||
props.node != this.props.node ||
|
props.node != this.props.node ||
|
||||||
props.state.selection.hasEdgeIn(props.node)
|
(props.state.isFocused && props.state.selection.hasEdgeIn(props.node))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -47,7 +47,7 @@ class Void extends React.Component {
|
|||||||
shouldComponentUpdate = (props, state) => {
|
shouldComponentUpdate = (props, state) => {
|
||||||
return (
|
return (
|
||||||
props.node != this.props.node ||
|
props.node != this.props.node ||
|
||||||
props.state.selection.hasEdgeIn(props.node)
|
(props.state.isFocused && props.state.selection.hasEdgeIn(props.node))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,11 @@ class Void extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tag contentEditable={false} onClick={this.onClick}>
|
<Tag
|
||||||
|
contentEditable={false}
|
||||||
|
data-void="true"
|
||||||
|
onClick={this.onClick}
|
||||||
|
>
|
||||||
<Tag
|
<Tag
|
||||||
contentEditable
|
contentEditable
|
||||||
suppressContentEditableWarning
|
suppressContentEditableWarning
|
||||||
@@ -94,7 +98,7 @@ class Void extends React.Component {
|
|||||||
style={styles}
|
style={styles}
|
||||||
>
|
>
|
||||||
{this.renderSpacer()}
|
{this.renderSpacer()}
|
||||||
<Tag contentEditable={false} onClick={this.onClick}>{children}</Tag>
|
<Tag contentEditable={false}>{children}</Tag>
|
||||||
</Tag>
|
</Tag>
|
||||||
</Tag>
|
</Tag>
|
||||||
)
|
)
|
||||||
|
@@ -365,6 +365,7 @@ function Plugin(options = {}) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function onKeyDownBackspace(e, data, state) {
|
function onKeyDownBackspace(e, data, state) {
|
||||||
|
|
||||||
// If expanded, delete regularly.
|
// If expanded, delete regularly.
|
||||||
if (state.isExpanded) {
|
if (state.isExpanded) {
|
||||||
return state
|
return state
|
||||||
@@ -406,6 +407,7 @@ function Plugin(options = {}) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function onKeyDownDelete(e, data, state) {
|
function onKeyDownDelete(e, data, state) {
|
||||||
|
|
||||||
// If expanded, delete regularly.
|
// If expanded, delete regularly.
|
||||||
if (state.isExpanded) {
|
if (state.isExpanded) {
|
||||||
return state
|
return state
|
||||||
|
Reference in New Issue
Block a user