1
0
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:
Samy Pessé
2018-07-04 01:07:38 +02:00
committed by Ian Storm Taylor
parent 37418643e2
commit 0ceefea2e7
12 changed files with 279 additions and 25 deletions

View File

@@ -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}

View File

@@ -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}

View File

@@ -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}

View File

@@ -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">&#x200B;</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">&#x200B;</span>
</span>
</span>
</div>
<div contenteditable="false">
<img class="" src="https://example.com/image2.png">
</div>
</div>
</div>
`.trim()

View File

@@ -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">&#x200B;</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">&#x200B;</span>
</span>
</span>
</div>
<div contenteditable="false">
<img class="" src="https://example.com/image2.png">
</div>
</div>
</div>
`.trim()

View File

@@ -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">&#x200B;</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">&#x200B;</span>
</span>
</span>
</div>
<div contenteditable="false">
<img class="" src="https://example.com/image2.png">
</div>
</div>
</div>
`.trim()