mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-12 10:14:02 +02:00
Fix child element decorations (#4910)
* fix slate-react handling of nested element decorations * chore: add changeset * changes from review
This commit is contained in:
5
.changeset/poor-hats-design.md
Normal file
5
.changeset/poor-hats-design.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'slate-react': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix decorations applied across nested elements
|
@@ -5,7 +5,6 @@ import ElementComponent from '../components/element'
|
|||||||
import TextComponent from '../components/text'
|
import TextComponent from '../components/text'
|
||||||
import { ReactEditor } from '..'
|
import { ReactEditor } from '..'
|
||||||
import { useSlateStatic } from './use-slate-static'
|
import { useSlateStatic } from './use-slate-static'
|
||||||
import { useDecorate } from './use-decorate'
|
|
||||||
import { NODE_TO_INDEX, NODE_TO_PARENT } from '../utils/weak-maps'
|
import { NODE_TO_INDEX, NODE_TO_PARENT } from '../utils/weak-maps'
|
||||||
import {
|
import {
|
||||||
RenderElementProps,
|
RenderElementProps,
|
||||||
@@ -34,7 +33,6 @@ const useChildren = (props: {
|
|||||||
renderLeaf,
|
renderLeaf,
|
||||||
selection,
|
selection,
|
||||||
} = props
|
} = props
|
||||||
const decorate = useDecorate()
|
|
||||||
const editor = useSlateStatic()
|
const editor = useSlateStatic()
|
||||||
const path = ReactEditor.findPath(editor, node)
|
const path = ReactEditor.findPath(editor, node)
|
||||||
const children = []
|
const children = []
|
||||||
@@ -50,7 +48,11 @@ const useChildren = (props: {
|
|||||||
const range = Editor.range(editor, p)
|
const range = Editor.range(editor, p)
|
||||||
const sel = selection && Range.intersection(range, selection)
|
const sel = selection && Range.intersection(range, selection)
|
||||||
|
|
||||||
const ds = decorations.filter(dec => Range.intersection(dec, range))
|
const ds = decorations.reduce<Range[]>((acc, dec) => {
|
||||||
|
const intersection = Range.intersection(dec, range)
|
||||||
|
if (intersection) acc.push(intersection)
|
||||||
|
return acc
|
||||||
|
}, [])
|
||||||
|
|
||||||
if (Element.isElement(n)) {
|
if (Element.isElement(n)) {
|
||||||
children.push(
|
children.push(
|
||||||
|
@@ -6,7 +6,9 @@ import {
|
|||||||
withReact,
|
withReact,
|
||||||
DefaultEditable,
|
DefaultEditable,
|
||||||
RenderElementProps,
|
RenderElementProps,
|
||||||
|
RenderLeafProps,
|
||||||
DefaultElement,
|
DefaultElement,
|
||||||
|
DefaultLeaf,
|
||||||
} from '../src'
|
} from '../src'
|
||||||
|
|
||||||
describe('slate-react', () => {
|
describe('slate-react', () => {
|
||||||
@@ -96,6 +98,79 @@ describe('slate-react', () => {
|
|||||||
|
|
||||||
expect(renderElement).toHaveBeenCalledTimes(3)
|
expect(renderElement).toHaveBeenCalledTimes(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should pass the intersecting part of decorations to nested elements', () => {
|
||||||
|
const editor = withReact(createEditor())
|
||||||
|
|
||||||
|
const value = [
|
||||||
|
{
|
||||||
|
type: 'parent',
|
||||||
|
children: [
|
||||||
|
{ type: 'block', children: [{ text: 'foo', highlight: false }] },
|
||||||
|
{ type: 'block', children: [{ text: 'bar', highlight: false }] },
|
||||||
|
{ type: 'block', children: [{ text: 'baz', highlight: false }] },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const decorate = jest.fn<Range[], [NodeEntry]>(([node]) => {
|
||||||
|
if (node !== value[0]) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
anchor: { path: [0, 1, 0], offset: 1 },
|
||||||
|
focus: { path: [0, 2, 0], offset: 2 },
|
||||||
|
highlight: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const renderLeaf = jest.fn<JSX.Element, [RenderLeafProps]>(DefaultLeaf)
|
||||||
|
const onChange = jest.fn<void, []>()
|
||||||
|
let el: ReactTestRenderer
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
el = create(
|
||||||
|
<Slate editor={editor} value={value} onChange={onChange}>
|
||||||
|
<DefaultEditable decorate={decorate} renderLeaf={renderLeaf} />
|
||||||
|
</Slate>,
|
||||||
|
{ createNodeMock }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 4 renders, for foo,b,ar,ba,z
|
||||||
|
expect(renderLeaf).toHaveBeenCalledTimes(5)
|
||||||
|
expect(renderLeaf.mock.calls).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
[
|
||||||
|
expect.objectContaining({
|
||||||
|
leaf: { highlight: false, text: 'foo' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
expect.objectContaining({
|
||||||
|
leaf: { highlight: false, text: 'b' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
expect.objectContaining({
|
||||||
|
leaf: { highlight: true, text: 'ar' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
expect.objectContaining({
|
||||||
|
leaf: { highlight: true, text: 'ba' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
expect.objectContaining({
|
||||||
|
leaf: { highlight: false, text: 'z' },
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
])
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user