@portabletext/editor 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/lib/index.d.mts +911 -0
- package/lib/index.d.ts +911 -0
- package/lib/index.esm.js +4896 -0
- package/lib/index.esm.js.map +1 -0
- package/lib/index.js +4874 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +4896 -0
- package/lib/index.mjs.map +1 -0
- package/package.json +119 -0
- package/src/editor/Editable.tsx +683 -0
- package/src/editor/PortableTextEditor.tsx +308 -0
- package/src/editor/__tests__/PortableTextEditor.test.tsx +386 -0
- package/src/editor/__tests__/PortableTextEditorTester.tsx +116 -0
- package/src/editor/__tests__/RangeDecorations.test.tsx +115 -0
- package/src/editor/__tests__/handleClick.test.tsx +218 -0
- package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +389 -0
- package/src/editor/__tests__/utils.ts +39 -0
- package/src/editor/components/DraggableBlock.tsx +287 -0
- package/src/editor/components/Element.tsx +279 -0
- package/src/editor/components/Leaf.tsx +288 -0
- package/src/editor/components/SlateContainer.tsx +81 -0
- package/src/editor/components/Synchronizer.tsx +190 -0
- package/src/editor/hooks/usePortableTextEditor.ts +23 -0
- package/src/editor/hooks/usePortableTextEditorKeyGenerator.ts +24 -0
- package/src/editor/hooks/usePortableTextEditorSelection.ts +22 -0
- package/src/editor/hooks/usePortableTextEditorValue.ts +16 -0
- package/src/editor/hooks/usePortableTextReadOnly.ts +20 -0
- package/src/editor/hooks/useSyncValue.test.tsx +125 -0
- package/src/editor/hooks/useSyncValue.ts +372 -0
- package/src/editor/nodes/DefaultAnnotation.tsx +16 -0
- package/src/editor/nodes/DefaultObject.tsx +15 -0
- package/src/editor/nodes/index.ts +189 -0
- package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +244 -0
- package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +142 -0
- package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +346 -0
- package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +162 -0
- package/src/editor/plugins/__tests__/withHotkeys.test.tsx +212 -0
- package/src/editor/plugins/__tests__/withInsertBreak.test.tsx +204 -0
- package/src/editor/plugins/__tests__/withPlaceholderBlock.test.tsx +133 -0
- package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +65 -0
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +1377 -0
- package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +91 -0
- package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +115 -0
- package/src/editor/plugins/createWithEditableAPI.ts +573 -0
- package/src/editor/plugins/createWithHotKeys.ts +304 -0
- package/src/editor/plugins/createWithInsertBreak.ts +45 -0
- package/src/editor/plugins/createWithInsertData.ts +359 -0
- package/src/editor/plugins/createWithMaxBlocks.ts +24 -0
- package/src/editor/plugins/createWithObjectKeys.ts +63 -0
- package/src/editor/plugins/createWithPatches.ts +274 -0
- package/src/editor/plugins/createWithPlaceholderBlock.ts +36 -0
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +91 -0
- package/src/editor/plugins/createWithPortableTextLists.ts +160 -0
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +441 -0
- package/src/editor/plugins/createWithPortableTextSelections.ts +65 -0
- package/src/editor/plugins/createWithSchemaTypes.ts +76 -0
- package/src/editor/plugins/createWithUndoRedo.ts +494 -0
- package/src/editor/plugins/createWithUtils.ts +81 -0
- package/src/editor/plugins/index.ts +155 -0
- package/src/index.ts +11 -0
- package/src/patch/PatchEvent.ts +33 -0
- package/src/patch/applyPatch.ts +29 -0
- package/src/patch/array.ts +89 -0
- package/src/patch/arrayInsert.ts +27 -0
- package/src/patch/object.ts +39 -0
- package/src/patch/patches.ts +53 -0
- package/src/patch/primitive.ts +43 -0
- package/src/patch/string.ts +51 -0
- package/src/types/editor.ts +576 -0
- package/src/types/options.ts +17 -0
- package/src/types/patch.ts +65 -0
- package/src/types/slate.ts +25 -0
- package/src/utils/__tests__/dmpToOperations.test.ts +181 -0
- package/src/utils/__tests__/operationToPatches.test.ts +421 -0
- package/src/utils/__tests__/patchToOperations.test.ts +293 -0
- package/src/utils/__tests__/ranges.test.ts +18 -0
- package/src/utils/__tests__/valueNormalization.test.tsx +62 -0
- package/src/utils/__tests__/values.test.ts +253 -0
- package/src/utils/applyPatch.ts +407 -0
- package/src/utils/bufferUntil.ts +15 -0
- package/src/utils/debug.ts +12 -0
- package/src/utils/getPortableTextMemberSchemaTypes.ts +100 -0
- package/src/utils/operationToPatches.ts +357 -0
- package/src/utils/patches.ts +36 -0
- package/src/utils/paths.ts +60 -0
- package/src/utils/ranges.ts +77 -0
- package/src/utils/schema.ts +8 -0
- package/src/utils/selection.ts +65 -0
- package/src/utils/ucs2Indices.ts +67 -0
- package/src/utils/validateValue.ts +394 -0
- package/src/utils/values.ts +208 -0
- package/src/utils/weakMaps.ts +24 -0
- package/src/utils/withChanges.ts +25 -0
- package/src/utils/withPreserveKeys.ts +14 -0
- package/src/utils/withoutPatching.ts +14 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {jest} from '@jest/globals'
|
|
2
|
+
import {Schema} from '@sanity/schema'
|
|
3
|
+
import {defineArrayMember, defineField} from '@sanity/types'
|
|
4
|
+
import {type ForwardedRef, forwardRef, useCallback, useEffect, useMemo} from 'react'
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
PortableTextEditable,
|
|
8
|
+
type PortableTextEditableProps,
|
|
9
|
+
PortableTextEditor,
|
|
10
|
+
type PortableTextEditorProps,
|
|
11
|
+
} from '../../index'
|
|
12
|
+
|
|
13
|
+
const imageType = defineField({
|
|
14
|
+
type: 'image',
|
|
15
|
+
name: 'blockImage',
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const someObject = defineField({
|
|
19
|
+
type: 'object',
|
|
20
|
+
name: 'someObject',
|
|
21
|
+
fields: [{type: 'string', name: 'color'}],
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const blockType = defineField({
|
|
25
|
+
type: 'block',
|
|
26
|
+
name: 'myTestBlockType',
|
|
27
|
+
styles: [
|
|
28
|
+
{title: 'Normal', value: 'normal'},
|
|
29
|
+
{title: 'H1', value: 'h1'},
|
|
30
|
+
{title: 'H2', value: 'h2'},
|
|
31
|
+
{title: 'H3', value: 'h3'},
|
|
32
|
+
{title: 'H4', value: 'h4'},
|
|
33
|
+
{title: 'H5', value: 'h5'},
|
|
34
|
+
{title: 'H6', value: 'h6'},
|
|
35
|
+
{title: 'Quote', value: 'blockquote'},
|
|
36
|
+
],
|
|
37
|
+
of: [someObject, imageType],
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const portableTextType = defineArrayMember({
|
|
41
|
+
type: 'array',
|
|
42
|
+
name: 'body',
|
|
43
|
+
of: [blockType, someObject],
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const colorAndLink = defineArrayMember({
|
|
47
|
+
type: 'array',
|
|
48
|
+
name: 'colorAndLink',
|
|
49
|
+
of: [
|
|
50
|
+
{
|
|
51
|
+
...blockType,
|
|
52
|
+
marks: {
|
|
53
|
+
annotations: [
|
|
54
|
+
{
|
|
55
|
+
name: 'link',
|
|
56
|
+
type: 'object',
|
|
57
|
+
fields: [{type: 'string', name: 'color'}],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'color',
|
|
61
|
+
type: 'object',
|
|
62
|
+
fields: [{type: 'string', name: 'color'}],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const schema = Schema.compile({
|
|
71
|
+
name: 'test',
|
|
72
|
+
types: [portableTextType, colorAndLink],
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
let key = 0
|
|
76
|
+
|
|
77
|
+
export const PortableTextEditorTester = forwardRef(function PortableTextEditorTester(
|
|
78
|
+
props: Partial<Omit<PortableTextEditorProps, 'type' | 'onChange' | 'value'>> & {
|
|
79
|
+
onChange?: PortableTextEditorProps['onChange']
|
|
80
|
+
rangeDecorations?: PortableTextEditableProps['rangeDecorations']
|
|
81
|
+
renderPlaceholder?: PortableTextEditableProps['renderPlaceholder']
|
|
82
|
+
schemaType: PortableTextEditorProps['schemaType']
|
|
83
|
+
selection?: PortableTextEditableProps['selection']
|
|
84
|
+
value?: PortableTextEditorProps['value']
|
|
85
|
+
},
|
|
86
|
+
ref: ForwardedRef<PortableTextEditor>,
|
|
87
|
+
) {
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
key = 0
|
|
90
|
+
}, [])
|
|
91
|
+
const _keyGenerator = useCallback(() => {
|
|
92
|
+
key++
|
|
93
|
+
return `${key}`
|
|
94
|
+
}, [])
|
|
95
|
+
const onChange = useMemo(() => props.onChange || jest.fn(), [props.onChange])
|
|
96
|
+
return (
|
|
97
|
+
<PortableTextEditor
|
|
98
|
+
schemaType={props.schemaType}
|
|
99
|
+
onChange={onChange}
|
|
100
|
+
value={props.value || undefined}
|
|
101
|
+
keyGenerator={_keyGenerator}
|
|
102
|
+
ref={ref}
|
|
103
|
+
>
|
|
104
|
+
<PortableTextEditable
|
|
105
|
+
selection={props.selection || undefined}
|
|
106
|
+
rangeDecorations={props.rangeDecorations}
|
|
107
|
+
renderPlaceholder={props.renderPlaceholder}
|
|
108
|
+
aria-describedby="desc_foo"
|
|
109
|
+
/>
|
|
110
|
+
</PortableTextEditor>
|
|
111
|
+
)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
export const schemaType = schema.get('body')
|
|
115
|
+
|
|
116
|
+
export const schemaTypeWithColorAndLink = schema.get('colorAndLink')
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {describe, expect, it, jest} from '@jest/globals'
|
|
2
|
+
/* eslint-disable no-irregular-whitespace */
|
|
3
|
+
import {type PortableTextBlock} from '@sanity/types'
|
|
4
|
+
import {render, waitFor} from '@testing-library/react'
|
|
5
|
+
import {createRef, type ReactNode, type RefObject} from 'react'
|
|
6
|
+
|
|
7
|
+
import {type RangeDecoration} from '../..'
|
|
8
|
+
import {type PortableTextEditor} from '../PortableTextEditor'
|
|
9
|
+
import {PortableTextEditorTester, schemaType} from './PortableTextEditorTester'
|
|
10
|
+
|
|
11
|
+
const helloBlock: PortableTextBlock = {
|
|
12
|
+
_key: '123',
|
|
13
|
+
_type: 'myTestBlockType',
|
|
14
|
+
markDefs: [],
|
|
15
|
+
children: [{_key: '567', _type: 'span', text: 'Hello', marks: []}],
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let rangeDecorationIteration = 0
|
|
19
|
+
|
|
20
|
+
const RangeDecorationTestComponent = ({children}: {children?: ReactNode}) => {
|
|
21
|
+
rangeDecorationIteration++
|
|
22
|
+
return <span data-testid="range-decoration">{children}</span>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('RangeDecorations', () => {
|
|
26
|
+
it.only('only render range decorations as necessary', async () => {
|
|
27
|
+
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
28
|
+
const onChange = jest.fn()
|
|
29
|
+
const value = [helloBlock]
|
|
30
|
+
let rangeDecorations: RangeDecoration[] = [
|
|
31
|
+
{
|
|
32
|
+
component: RangeDecorationTestComponent,
|
|
33
|
+
selection: {
|
|
34
|
+
anchor: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 0},
|
|
35
|
+
focus: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
]
|
|
39
|
+
const {rerender} = render(
|
|
40
|
+
<PortableTextEditorTester
|
|
41
|
+
onChange={onChange}
|
|
42
|
+
rangeDecorations={rangeDecorations}
|
|
43
|
+
ref={editorRef}
|
|
44
|
+
schemaType={schemaType}
|
|
45
|
+
value={value}
|
|
46
|
+
/>,
|
|
47
|
+
)
|
|
48
|
+
await waitFor(() => {
|
|
49
|
+
expect([rangeDecorationIteration, 'initial']).toEqual([0, 'initial'])
|
|
50
|
+
})
|
|
51
|
+
// Re-render with the same range decorations
|
|
52
|
+
rerender(
|
|
53
|
+
<PortableTextEditorTester
|
|
54
|
+
onChange={onChange}
|
|
55
|
+
rangeDecorations={rangeDecorations}
|
|
56
|
+
ref={editorRef}
|
|
57
|
+
schemaType={schemaType}
|
|
58
|
+
value={value}
|
|
59
|
+
/>,
|
|
60
|
+
)
|
|
61
|
+
await waitFor(() => {
|
|
62
|
+
expect([rangeDecorationIteration, 'initial']).toEqual([0, 'initial'])
|
|
63
|
+
})
|
|
64
|
+
// Update the range decorations, a new object with identical values
|
|
65
|
+
rangeDecorations = [
|
|
66
|
+
{
|
|
67
|
+
component: RangeDecorationTestComponent,
|
|
68
|
+
selection: {
|
|
69
|
+
anchor: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 0},
|
|
70
|
+
focus: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
]
|
|
74
|
+
rerender(
|
|
75
|
+
<PortableTextEditorTester
|
|
76
|
+
onChange={onChange}
|
|
77
|
+
rangeDecorations={rangeDecorations}
|
|
78
|
+
ref={editorRef}
|
|
79
|
+
schemaType={schemaType}
|
|
80
|
+
value={value}
|
|
81
|
+
/>,
|
|
82
|
+
)
|
|
83
|
+
await waitFor(() => {
|
|
84
|
+
expect([rangeDecorationIteration, 'updated-with-equal-values']).toEqual([
|
|
85
|
+
0,
|
|
86
|
+
'updated-with-equal-values',
|
|
87
|
+
])
|
|
88
|
+
})
|
|
89
|
+
// Update the range decorations with a new offset
|
|
90
|
+
rangeDecorations = [
|
|
91
|
+
{
|
|
92
|
+
component: RangeDecorationTestComponent,
|
|
93
|
+
selection: {
|
|
94
|
+
anchor: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
95
|
+
focus: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 4},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
]
|
|
99
|
+
rerender(
|
|
100
|
+
<PortableTextEditorTester
|
|
101
|
+
onChange={onChange}
|
|
102
|
+
rangeDecorations={rangeDecorations}
|
|
103
|
+
ref={editorRef}
|
|
104
|
+
schemaType={schemaType}
|
|
105
|
+
value={value}
|
|
106
|
+
/>,
|
|
107
|
+
)
|
|
108
|
+
await waitFor(() => {
|
|
109
|
+
expect([rangeDecorationIteration, 'updated-with-different']).toEqual([
|
|
110
|
+
1,
|
|
111
|
+
'updated-with-different',
|
|
112
|
+
])
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
})
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import {describe, expect, it, jest} from '@jest/globals'
|
|
2
|
+
import {fireEvent, render, waitFor} from '@testing-library/react'
|
|
3
|
+
import {createRef, type RefObject} from 'react'
|
|
4
|
+
|
|
5
|
+
import {PortableTextEditor} from '../PortableTextEditor'
|
|
6
|
+
import {PortableTextEditorTester, schemaType} from './PortableTextEditorTester'
|
|
7
|
+
import {getEditableElement} from './utils'
|
|
8
|
+
|
|
9
|
+
describe('adds empty text block if its needed', () => {
|
|
10
|
+
const newBlock = {
|
|
11
|
+
_type: 'myTestBlockType',
|
|
12
|
+
_key: '3',
|
|
13
|
+
style: 'normal',
|
|
14
|
+
markDefs: [],
|
|
15
|
+
children: [
|
|
16
|
+
{
|
|
17
|
+
_type: 'span',
|
|
18
|
+
_key: '2',
|
|
19
|
+
text: '',
|
|
20
|
+
marks: [],
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
}
|
|
24
|
+
it('adds a new block at the bottom, when clicking on the portable text editor, because the only block is void and user is focused on that one', async () => {
|
|
25
|
+
const initialValue = [
|
|
26
|
+
{
|
|
27
|
+
_key: 'b',
|
|
28
|
+
_type: 'someObject',
|
|
29
|
+
},
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
const initialSelection = {
|
|
33
|
+
focus: {path: [{_key: 'b'}], offset: 0},
|
|
34
|
+
anchor: {path: [{_key: 'b'}], offset: 0},
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
38
|
+
const onChange = jest.fn()
|
|
39
|
+
const component = render(
|
|
40
|
+
<PortableTextEditorTester
|
|
41
|
+
onChange={onChange}
|
|
42
|
+
ref={editorRef}
|
|
43
|
+
schemaType={schemaType}
|
|
44
|
+
value={initialValue}
|
|
45
|
+
/>,
|
|
46
|
+
)
|
|
47
|
+
const element = await getEditableElement(component)
|
|
48
|
+
|
|
49
|
+
const editor = editorRef.current
|
|
50
|
+
const inlineType = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
|
|
51
|
+
await waitFor(async () => {
|
|
52
|
+
if (editor && inlineType && element) {
|
|
53
|
+
PortableTextEditor.focus(editor)
|
|
54
|
+
PortableTextEditor.select(editor, initialSelection)
|
|
55
|
+
fireEvent.click(element)
|
|
56
|
+
expect(PortableTextEditor.getValue(editor)).toEqual([initialValue[0], newBlock])
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
it('should not add blocks if the last element is a text block', async () => {
|
|
61
|
+
const initialValue = [
|
|
62
|
+
{
|
|
63
|
+
_key: 'b',
|
|
64
|
+
_type: 'someObject',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
_type: 'myTestBlockType',
|
|
68
|
+
_key: '3',
|
|
69
|
+
style: 'normal',
|
|
70
|
+
markDefs: [],
|
|
71
|
+
children: [
|
|
72
|
+
{
|
|
73
|
+
_type: 'span',
|
|
74
|
+
_key: '2',
|
|
75
|
+
text: '',
|
|
76
|
+
marks: [],
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
const initialSelection = {
|
|
83
|
+
focus: {path: [{_key: 'b'}], offset: 0},
|
|
84
|
+
anchor: {path: [{_key: 'b'}], offset: 0},
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
88
|
+
const onChange = jest.fn()
|
|
89
|
+
const component = render(
|
|
90
|
+
<PortableTextEditorTester
|
|
91
|
+
onChange={onChange}
|
|
92
|
+
ref={editorRef}
|
|
93
|
+
schemaType={schemaType}
|
|
94
|
+
value={initialValue}
|
|
95
|
+
/>,
|
|
96
|
+
)
|
|
97
|
+
const element = await getEditableElement(component)
|
|
98
|
+
|
|
99
|
+
const editor = editorRef.current
|
|
100
|
+
const inlineType = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
|
|
101
|
+
await waitFor(async () => {
|
|
102
|
+
if (editor && inlineType && element) {
|
|
103
|
+
PortableTextEditor.focus(editor)
|
|
104
|
+
PortableTextEditor.select(editor, initialSelection)
|
|
105
|
+
fireEvent.click(element)
|
|
106
|
+
expect(PortableTextEditor.getValue(editor)).toEqual(initialValue)
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
it('should not add blocks if the last element is void, but its not focused on that one', async () => {
|
|
111
|
+
const initialValue = [
|
|
112
|
+
{
|
|
113
|
+
_key: 'a',
|
|
114
|
+
_type: 'someObject',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
_type: 'myTestBlockType',
|
|
118
|
+
_key: 'b',
|
|
119
|
+
style: 'normal',
|
|
120
|
+
markDefs: [],
|
|
121
|
+
children: [
|
|
122
|
+
{
|
|
123
|
+
_type: 'span',
|
|
124
|
+
_key: 'b1',
|
|
125
|
+
text: '',
|
|
126
|
+
marks: [],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
_key: 'c',
|
|
132
|
+
_type: 'someObject',
|
|
133
|
+
},
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
const initialSelection = {
|
|
137
|
+
focus: {path: [{_key: 'b'}, 'children', {_key: 'b1'}], offset: 2},
|
|
138
|
+
anchor: {path: [{_key: 'b'}, 'children', {_key: 'b1'}], offset: 2},
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
142
|
+
const onChange = jest.fn()
|
|
143
|
+
const component = render(
|
|
144
|
+
<PortableTextEditorTester
|
|
145
|
+
onChange={onChange}
|
|
146
|
+
ref={editorRef}
|
|
147
|
+
schemaType={schemaType}
|
|
148
|
+
value={initialValue}
|
|
149
|
+
/>,
|
|
150
|
+
)
|
|
151
|
+
const element = await getEditableElement(component)
|
|
152
|
+
|
|
153
|
+
const editor = editorRef.current
|
|
154
|
+
const inlineType = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
|
|
155
|
+
await waitFor(async () => {
|
|
156
|
+
if (editor && inlineType && element) {
|
|
157
|
+
PortableTextEditor.focus(editor)
|
|
158
|
+
PortableTextEditor.select(editor, initialSelection)
|
|
159
|
+
fireEvent.click(element)
|
|
160
|
+
expect(PortableTextEditor.getValue(editor)).toEqual(initialValue)
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
it('should not add blocks if the last element is void, and its focused on that one when clicking', async () => {
|
|
165
|
+
const initialValue = [
|
|
166
|
+
{
|
|
167
|
+
_key: 'a',
|
|
168
|
+
_type: 'someObject',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
_type: 'myTestBlockType',
|
|
172
|
+
_key: 'b',
|
|
173
|
+
style: 'normal',
|
|
174
|
+
markDefs: [],
|
|
175
|
+
children: [
|
|
176
|
+
{
|
|
177
|
+
_type: 'span',
|
|
178
|
+
_key: 'b1',
|
|
179
|
+
text: '',
|
|
180
|
+
marks: [],
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
_key: 'c',
|
|
186
|
+
_type: 'someObject',
|
|
187
|
+
},
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
const initialSelection = {
|
|
191
|
+
focus: {path: [{_key: 'c'}], offset: 0},
|
|
192
|
+
anchor: {path: [{_key: 'c'}], offset: 0},
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
196
|
+
const onChange = jest.fn()
|
|
197
|
+
const component = render(
|
|
198
|
+
<PortableTextEditorTester
|
|
199
|
+
onChange={onChange}
|
|
200
|
+
ref={editorRef}
|
|
201
|
+
schemaType={schemaType}
|
|
202
|
+
value={initialValue}
|
|
203
|
+
/>,
|
|
204
|
+
)
|
|
205
|
+
const element = await getEditableElement(component)
|
|
206
|
+
|
|
207
|
+
const editor = editorRef.current
|
|
208
|
+
const inlineType = editor?.schemaTypes.inlineObjects.find((t) => t.name === 'someObject')
|
|
209
|
+
await waitFor(async () => {
|
|
210
|
+
if (editor && inlineType && element) {
|
|
211
|
+
PortableTextEditor.focus(editor)
|
|
212
|
+
PortableTextEditor.select(editor, initialSelection)
|
|
213
|
+
fireEvent.click(element)
|
|
214
|
+
expect(PortableTextEditor.getValue(editor)).toEqual(initialValue.concat(newBlock))
|
|
215
|
+
}
|
|
216
|
+
})
|
|
217
|
+
})
|
|
218
|
+
})
|