1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-11 17:53:59 +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:
jasonphillips
2022-03-24 19:31:35 -05:00
committed by GitHub
parent 43ca2b56c8
commit 2a8d86f1a4
3 changed files with 85 additions and 3 deletions

View File

@@ -0,0 +1,5 @@
---
'slate-react': patch
---
Fix decorations applied across nested elements

View File

@@ -5,7 +5,6 @@ import ElementComponent from '../components/element'
import TextComponent from '../components/text'
import { ReactEditor } from '..'
import { useSlateStatic } from './use-slate-static'
import { useDecorate } from './use-decorate'
import { NODE_TO_INDEX, NODE_TO_PARENT } from '../utils/weak-maps'
import {
RenderElementProps,
@@ -34,7 +33,6 @@ const useChildren = (props: {
renderLeaf,
selection,
} = props
const decorate = useDecorate()
const editor = useSlateStatic()
const path = ReactEditor.findPath(editor, node)
const children = []
@@ -50,7 +48,11 @@ const useChildren = (props: {
const range = Editor.range(editor, p)
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)) {
children.push(

View File

@@ -6,7 +6,9 @@ import {
withReact,
DefaultEditable,
RenderElementProps,
RenderLeafProps,
DefaultElement,
DefaultLeaf,
} from '../src'
describe('slate-react', () => {
@@ -96,6 +98,79 @@ describe('slate-react', () => {
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' },
}),
],
])
)
})
})
})
})