1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-21 06:31:28 +02:00

fix void leaf selection handling

This commit is contained in:
Ian Storm Taylor
2016-08-01 18:26:27 -07:00
parent 1780bb0c75
commit 789c4b3002
4 changed files with 36 additions and 37 deletions

View File

@@ -17,7 +17,9 @@ Transform methods can either operate on the [`Document`](./document.md), the [`S
- [`deleteBackward`](#deletebackward) - [`deleteBackward`](#deletebackward)
- [`deleteForward`](#deleteforward) - [`deleteForward`](#deleteforward)
- [`delete`](#delete) - [`delete`](#delete)
- [`insertBlock`](#insertblock)
- [`insertFragment`](#insertfragment) - [`insertFragment`](#insertfragment)
- [`insertInline`](#insertinline)
- [`insertText`](#inserttext) - [`insertText`](#inserttext)
- [`addMark`](#addmark) - [`addMark`](#addmark)
- [`setBlock`](#setblock) - [`setBlock`](#setblock)
@@ -50,7 +52,9 @@ Transform methods can either operate on the [`Document`](./document.md), the [`S
- [`deleteAtRange`](#deleteatrange) - [`deleteAtRange`](#deleteatrange)
- [`deleteBackwardAtRange`](#deletebackwardatrange) - [`deleteBackwardAtRange`](#deletebackwardatrange)
- [`deleteForwardAtRange`](#deleteforwardatrange) - [`deleteForwardAtRange`](#deleteforwardatrange)
- [`insertBlockAtRange`](#insertblockatrange)
- [`insertFragmentAtRange`](#insertfragmentatrange) - [`insertFragmentAtRange`](#insertfragmentatrange)
- [`insertInlineAtRange`](#insertinlineatrange)
- [`insertTextAtRange`](#inserttextatrange) - [`insertTextAtRange`](#inserttextatrange)
- [`addMarkAtRange`](#addmarkatrange) - [`addMarkAtRange`](#addmarkatrange)
- [`setBlockAtRange`](#setblockatrange) - [`setBlockAtRange`](#setblockatrange)

View File

@@ -202,41 +202,9 @@ class Images extends React.Component {
*/ */
insertImage = (state, src) => { insertImage = (state, src) => {
if (state.isExpanded) { return state
state = state
.transform() .transform()
.delete() .insertBlock({
.apply()
}
const { anchorBlock, selection } = state
let transform = state.transform()
if (anchorBlock.type == 'image') {
transform = transform.splitBlock()
}
else if (anchorBlock.text != '') {
if (selection.isAtEndOf(anchorBlock)) {
transform = transform.splitBlock()
}
else if (selection.isAtStartOf(anchorBlock)) {
transform = transform
.splitBlock()
.collapseToStartOfPreviousBlock()
}
else {
transform = transform
.splitBlock()
.splitBlock()
.collapseToStartOfPreviousBlock()
}
}
return transform
.setBlock({
type: 'image', type: 'image',
isVoid: true, isVoid: true,
data: { src } data: { src }

View File

@@ -28,6 +28,7 @@ class Leaf extends React.Component {
static propTypes = { static propTypes = {
index: React.PropTypes.number.isRequired, index: React.PropTypes.number.isRequired,
isVoid: React.PropTypes.bool,
marks: React.PropTypes.object.isRequired, marks: React.PropTypes.object.isRequired,
node: React.PropTypes.object.isRequired, node: React.PropTypes.object.isRequired,
ranges: React.PropTypes.object.isRequired, ranges: React.PropTypes.object.isRequired,
@@ -36,6 +37,16 @@ class Leaf extends React.Component {
text: React.PropTypes.string.isRequired text: React.PropTypes.string.isRequired
}; };
/**
* Default properties.
*
* @type {Object}
*/
static defaultProps = {
isVoid: false
};
/** /**
* Constructor. * Constructor.
* *
@@ -85,6 +96,10 @@ class Leaf extends React.Component {
return state.selection.hasEdgeBetween(node, start, end) return state.selection.hasEdgeBetween(node, start, end)
} }
/**
* When the DOM updates, try updating the selection.
*/
componentDidMount() { componentDidMount() {
this.updateSelection() this.updateSelection()
} }
@@ -93,14 +108,18 @@ class Leaf extends React.Component {
this.updateSelection() this.updateSelection()
} }
/**
* Update the DOM selection if it's inside the leaf.
*/
updateSelection() { updateSelection() {
const { state, ranges } = this.props const { state, ranges, isVoid } = this.props
const { selection } = state const { selection } = state
// If the selection is blurred we have nothing to do. // If the selection is blurred we have nothing to do.
if (selection.isBlurred) return if (selection.isBlurred) return
const { anchorOffset, focusOffset } = selection let { anchorOffset, focusOffset } = selection
const { node, index } = this.props const { node, index } = this.props
const { start, end } = OffsetKey.findBounds(index, ranges) const { start, end } = OffsetKey.findBounds(index, ranges)
@@ -109,6 +128,13 @@ class Leaf extends React.Component {
const hasFocus = selection.hasFocusBetween(node, start, end) const hasFocus = selection.hasFocusBetween(node, start, end)
if (!hasAnchor && !hasFocus) return if (!hasAnchor && !hasFocus) return
// If the leaf is a void leaf, ensure that it has no width. This is due to
// void nodes always rendering an empty leaf, for browser compatibility.
if (isVoid) {
anchorOffset = 0
focusOffset = 0
}
// We have a selection to render, so prepare a few things... // We have a selection to render, so prepare a few things...
const native = window.getSelection() const native = window.getSelection()
const el = findDeepestNode(ReactDOM.findDOMNode(this)) const el = findDeepestNode(ReactDOM.findDOMNode(this))

View File

@@ -164,6 +164,7 @@ class Void extends React.Component {
return ( return (
<Leaf <Leaf
isVoid
renderMark={noop} renderMark={noop}
key={offsetKey} key={offsetKey}
state={state} state={state}