mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-16 20:24:01 +02:00
Add prop "isFocused" / "isSelected" for custom nodes (#1950)
* Change the definition of isSelected and add isFocused * Document prop "isFocused" * Add unit tests for isFocused / isSelected * Adapt examples * Lint
This commit is contained in:
committed by
Ian Storm Taylor
parent
37418643e2
commit
0ceefea2e7
@@ -458,7 +458,7 @@ class Content extends React.Component {
|
||||
const { value, stack } = editor
|
||||
const Container = tagName
|
||||
const { document, selection, decorations } = value
|
||||
const indexes = document.getSelectionIndexes(selection, selection.isFocused)
|
||||
const indexes = document.getSelectionIndexes(selection)
|
||||
const decs = document.getDecorations(stack).concat(decorations || [])
|
||||
const childrenDecorations = getChildrenDecorations(document, decs)
|
||||
|
||||
@@ -541,7 +541,7 @@ class Content extends React.Component {
|
||||
renderNode = (child, isSelected, decorations) => {
|
||||
const { editor, readOnly } = this.props
|
||||
const { value } = editor
|
||||
const { document } = value
|
||||
const { document, isFocused } = value
|
||||
|
||||
return (
|
||||
<Node
|
||||
@@ -549,6 +549,7 @@ class Content extends React.Component {
|
||||
editor={editor}
|
||||
decorations={decorations}
|
||||
isSelected={isSelected}
|
||||
isFocused={isFocused && isSelected}
|
||||
key={child.key}
|
||||
node={child}
|
||||
parent={document}
|
||||
|
@@ -34,6 +34,7 @@ class Node extends React.Component {
|
||||
block: SlateTypes.block,
|
||||
decorations: ImmutableTypes.list.isRequired,
|
||||
editor: Types.object.isRequired,
|
||||
isFocused: Types.bool.isRequired,
|
||||
isSelected: Types.bool.isRequired,
|
||||
node: SlateTypes.node.isRequired,
|
||||
parent: SlateTypes.node.isRequired,
|
||||
@@ -103,6 +104,7 @@ class Node extends React.Component {
|
||||
// selection value of some of its children could have been changed and they
|
||||
// need to be rendered again.
|
||||
if (n.isSelected || p.isSelected) return true
|
||||
if (n.isFocused || p.isFocused) return true
|
||||
|
||||
// If the decorations have changed, update.
|
||||
if (!n.decorations.equals(p.decorations)) return true
|
||||
@@ -122,6 +124,7 @@ class Node extends React.Component {
|
||||
const {
|
||||
editor,
|
||||
isSelected,
|
||||
isFocused,
|
||||
node,
|
||||
decorations,
|
||||
parent,
|
||||
@@ -158,6 +161,7 @@ class Node extends React.Component {
|
||||
const props = {
|
||||
key: node.key,
|
||||
editor,
|
||||
isFocused,
|
||||
isSelected,
|
||||
node,
|
||||
parent,
|
||||
@@ -193,7 +197,7 @@ class Node extends React.Component {
|
||||
*/
|
||||
|
||||
renderNode = (child, isSelected, decorations) => {
|
||||
const { block, editor, node, readOnly } = this.props
|
||||
const { block, editor, node, readOnly, isFocused } = this.props
|
||||
const Component = child.object == 'text' ? Text : Node
|
||||
|
||||
return (
|
||||
@@ -202,6 +206,7 @@ class Node extends React.Component {
|
||||
decorations={decorations}
|
||||
editor={editor}
|
||||
isSelected={isSelected}
|
||||
isFocused={isFocused && isSelected}
|
||||
key={child.key}
|
||||
node={child}
|
||||
parent={node}
|
||||
|
@@ -102,21 +102,13 @@ class Void extends React.Component {
|
||||
*/
|
||||
|
||||
renderText = () => {
|
||||
const {
|
||||
block,
|
||||
decorations,
|
||||
isSelected,
|
||||
node,
|
||||
readOnly,
|
||||
editor,
|
||||
} = this.props
|
||||
const { block, decorations, node, readOnly, editor } = this.props
|
||||
const child = node.getFirstText()
|
||||
return (
|
||||
<Text
|
||||
block={node.object == 'block' ? node : block}
|
||||
decorations={decorations}
|
||||
editor={editor}
|
||||
isSelected={isSelected}
|
||||
key={child.key}
|
||||
node={child}
|
||||
parent={node}
|
||||
|
@@ -0,0 +1,83 @@
|
||||
/** @jsx h */
|
||||
|
||||
import React from 'react'
|
||||
import h from '../../helpers/h'
|
||||
|
||||
function Image(props) {
|
||||
return React.createElement('img', {
|
||||
className: props.isFocused ? 'focused' : '',
|
||||
src: props.node.data.get('src'),
|
||||
...props.attributes,
|
||||
})
|
||||
}
|
||||
|
||||
function renderNode(props) {
|
||||
switch (props.node.type) {
|
||||
case 'image':
|
||||
return Image(props)
|
||||
}
|
||||
}
|
||||
|
||||
export const props = {
|
||||
renderNode,
|
||||
}
|
||||
|
||||
export const value = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
<anchor />
|
||||
</paragraph>
|
||||
<image key="a" src="https://example.com/image.png" />
|
||||
<paragraph>
|
||||
<focus />
|
||||
</paragraph>
|
||||
<image key="b" src="https://example.com/image2.png" />
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
.change()
|
||||
.blur().value
|
||||
|
||||
export const output = `
|
||||
<div data-slate-editor="true" contenteditable="true" role="textbox">
|
||||
<div style="position:relative">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="n"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div data-slate-void="true">
|
||||
<div data-slate-spacer="true" style="height:0;color:transparent;outline:none;position:absolute">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="z">​</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div contenteditable="false">
|
||||
<img class="" src="https://example.com/image.png">
|
||||
</div>
|
||||
</div>
|
||||
<div style="position:relative">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="n"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div data-slate-void="true">
|
||||
<div data-slate-spacer="true" style="height:0;color:transparent;outline:none;position:absolute">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="z">​</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div contenteditable="false">
|
||||
<img class="" src="https://example.com/image2.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`.trim()
|
@@ -0,0 +1,81 @@
|
||||
/** @jsx h */
|
||||
|
||||
import React from 'react'
|
||||
import h from '../../helpers/h'
|
||||
|
||||
function Image(props) {
|
||||
return React.createElement('img', {
|
||||
className: props.isFocused ? 'focused' : '',
|
||||
src: props.node.data.get('src'),
|
||||
...props.attributes,
|
||||
})
|
||||
}
|
||||
|
||||
function renderNode(props) {
|
||||
switch (props.node.type) {
|
||||
case 'image':
|
||||
return Image(props)
|
||||
}
|
||||
}
|
||||
|
||||
export const props = {
|
||||
renderNode,
|
||||
}
|
||||
|
||||
export const value = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
<anchor />
|
||||
</paragraph>
|
||||
<image key="a" src="https://example.com/image.png" />
|
||||
<paragraph>
|
||||
<focus />
|
||||
</paragraph>
|
||||
<image key="b" src="https://example.com/image2.png" />
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = `
|
||||
<div data-slate-editor="true" contenteditable="true" role="textbox">
|
||||
<div style="position:relative">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="n"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div data-slate-void="true">
|
||||
<div data-slate-spacer="true" style="height:0;color:transparent;outline:none;position:absolute">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="z">​</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div contenteditable="false">
|
||||
<img class="focused" src="https://example.com/image.png">
|
||||
</div>
|
||||
</div>
|
||||
<div style="position:relative">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="n"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div data-slate-void="true">
|
||||
<div data-slate-spacer="true" style="height:0;color:transparent;outline:none;position:absolute">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="z">​</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div contenteditable="false">
|
||||
<img class="" src="https://example.com/image2.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`.trim()
|
@@ -0,0 +1,81 @@
|
||||
/** @jsx h */
|
||||
|
||||
import React from 'react'
|
||||
import h from '../../helpers/h'
|
||||
|
||||
function Image(props) {
|
||||
return React.createElement('img', {
|
||||
className: props.isSelected ? 'selected' : '',
|
||||
src: props.node.data.get('src'),
|
||||
...props.attributes,
|
||||
})
|
||||
}
|
||||
|
||||
function renderNode(props) {
|
||||
switch (props.node.type) {
|
||||
case 'image':
|
||||
return Image(props)
|
||||
}
|
||||
}
|
||||
|
||||
export const props = {
|
||||
renderNode,
|
||||
}
|
||||
|
||||
export const value = (
|
||||
<value>
|
||||
<document>
|
||||
<paragraph>
|
||||
<anchor />
|
||||
</paragraph>
|
||||
<image key="a" src="https://example.com/image.png" />
|
||||
<paragraph>
|
||||
<focus />
|
||||
</paragraph>
|
||||
<image key="b" src="https://example.com/image2.png" />
|
||||
</document>
|
||||
</value>
|
||||
)
|
||||
|
||||
export const output = `
|
||||
<div data-slate-editor="true" contenteditable="true" role="textbox">
|
||||
<div style="position:relative">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="n"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div data-slate-void="true">
|
||||
<div data-slate-spacer="true" style="height:0;color:transparent;outline:none;position:absolute">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="z">​</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div contenteditable="false">
|
||||
<img class="selected" src="https://example.com/image.png">
|
||||
</div>
|
||||
</div>
|
||||
<div style="position:relative">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="n"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div data-slate-void="true">
|
||||
<div data-slate-spacer="true" style="height:0;color:transparent;outline:none;position:absolute">
|
||||
<span>
|
||||
<span>
|
||||
<span data-slate-zero-width="z">​</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div contenteditable="false">
|
||||
<img class="" src="https://example.com/image2.png">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`.trim()
|
Reference in New Issue
Block a user