@portabletext/editor 1.1.1 → 1.1.2
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/README.md +3 -0
- package/lib/index.d.mts +1667 -0
- package/lib/index.d.ts +1667 -0
- package/lib/index.esm.js +305 -153
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +305 -154
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +305 -153
- package/lib/index.mjs.map +1 -1
- package/package.json +23 -22
- package/src/editor/Editable.tsx +30 -31
- package/src/editor/PortableTextEditor.tsx +23 -6
- package/src/editor/__tests__/PortableTextEditor.test.tsx +9 -9
- package/src/editor/__tests__/PortableTextEditorTester.tsx +2 -5
- package/src/editor/__tests__/RangeDecorations.test.tsx +2 -2
- package/src/editor/__tests__/handleClick.test.tsx +27 -7
- package/src/editor/__tests__/insert-block.test.tsx +4 -4
- package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +7 -7
- package/src/editor/__tests__/self-solving.test.tsx +176 -0
- package/src/editor/components/Leaf.tsx +28 -23
- package/src/editor/components/Synchronizer.tsx +60 -32
- package/src/editor/editor-machine.ts +195 -0
- package/src/editor/hooks/usePortableTextEditorSelection.tsx +11 -13
- package/src/editor/hooks/useSyncValue.test.tsx +9 -9
- package/src/editor/hooks/useSyncValue.ts +14 -13
- package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +1 -1
- package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +28 -28
- package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +17 -17
- package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +8 -8
- package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +5 -5
- package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +2 -2
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +46 -46
- package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +22 -11
- package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +9 -9
- package/src/editor/plugins/createWithInsertData.ts +4 -8
- package/src/editor/plugins/createWithObjectKeys.ts +7 -0
- package/src/editor/plugins/createWithPatches.ts +5 -6
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +10 -2
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +20 -4
- package/src/editor/plugins/createWithPortableTextSelections.ts +4 -5
- package/src/editor/plugins/createWithSchemaTypes.ts +9 -0
- package/src/editor/plugins/index.ts +18 -8
- package/src/index.ts +9 -3
- package/src/utils/__tests__/dmpToOperations.test.ts +1 -1
- package/src/utils/__tests__/operationToPatches.test.ts +61 -61
- package/src/utils/__tests__/patchToOperations.test.ts +39 -39
- package/src/utils/__tests__/ranges.test.ts +1 -1
- package/src/utils/__tests__/valueNormalization.test.tsx +14 -2
- package/src/utils/__tests__/values.test.ts +17 -17
- package/src/utils/validateValue.ts +0 -22
- package/src/editor/__tests__/utils.ts +0 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -47,29 +47,30 @@
|
|
|
47
47
|
"is-hotkey-esm": "^1.0.0",
|
|
48
48
|
"lodash": "^4.17.21",
|
|
49
49
|
"slate": "0.103.0",
|
|
50
|
-
"slate-react": "0.
|
|
50
|
+
"slate-react": "0.110.1",
|
|
51
|
+
"xstate": "^5.18.2"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
|
-
"@
|
|
54
|
-
"@
|
|
55
|
-
"@cucumber/messages": "^26.0.0",
|
|
54
|
+
"@babel/preset-env": "^7.25.4",
|
|
55
|
+
"@babel/preset-react": "^7.24.7",
|
|
56
56
|
"@jest/globals": "^29.7.0",
|
|
57
57
|
"@jest/types": "^29.6.3",
|
|
58
|
-
"@playwright/test": "1.
|
|
58
|
+
"@playwright/test": "1.47.2",
|
|
59
59
|
"@portabletext/toolkit": "^2.0.15",
|
|
60
60
|
"@sanity/block-tools": "^3.55.0",
|
|
61
61
|
"@sanity/diff-match-patch": "^3.1.1",
|
|
62
|
-
"@sanity/pkg-utils": "^6.
|
|
62
|
+
"@sanity/pkg-utils": "^6.11.2",
|
|
63
63
|
"@sanity/schema": "^3.55.0",
|
|
64
64
|
"@sanity/test": "0.0.1-alpha.1",
|
|
65
65
|
"@sanity/types": "^3.55.0",
|
|
66
|
-
"@sanity/ui": "^2.8.
|
|
66
|
+
"@sanity/ui": "^2.8.9",
|
|
67
67
|
"@sanity/util": "^3.55.0",
|
|
68
68
|
"@testing-library/dom": "^10.4.0",
|
|
69
|
-
"@testing-library/
|
|
69
|
+
"@testing-library/jest-dom": "^6.5.0",
|
|
70
|
+
"@testing-library/react": "^16.0.1",
|
|
70
71
|
"@types/debug": "^4.1.5",
|
|
71
72
|
"@types/express": "^4.17.21",
|
|
72
|
-
"@types/express-ws": "^3.0.
|
|
73
|
+
"@types/express-ws": "^3.0.5",
|
|
73
74
|
"@types/lodash": "^4.17.7",
|
|
74
75
|
"@types/node": "^18.19.8",
|
|
75
76
|
"@types/node-ipc": "^9.2.3",
|
|
@@ -81,18 +82,19 @@
|
|
|
81
82
|
"express": "^4.19.2",
|
|
82
83
|
"express-ws": "^5.0.2",
|
|
83
84
|
"jest": "^29.7.0",
|
|
84
|
-
"jest-dev-server": "^10.1.
|
|
85
|
-
"jest-environment-jsdom": "^29.7.0",
|
|
85
|
+
"jest-dev-server": "^10.1.1",
|
|
86
86
|
"jest-environment-node": "^29.7.0",
|
|
87
|
+
"jsdom": "^25.0.1",
|
|
87
88
|
"node-ipc": "npm:@node-ipc/compat@9.2.5",
|
|
88
89
|
"react": "^18.3.1",
|
|
89
90
|
"react-dom": "^18.3.1",
|
|
90
91
|
"rxjs": "^7.8.1",
|
|
91
|
-
"styled-components": "^6.1.
|
|
92
|
+
"styled-components": "^6.1.13",
|
|
92
93
|
"ts-node": "^10.9.2",
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
94
|
+
"typescript": "5.6.2",
|
|
95
|
+
"vite": "^5.4.2",
|
|
96
|
+
"vitest": "^2.1.1",
|
|
97
|
+
"@sanity/gherkin-driver": "^0.0.1"
|
|
96
98
|
},
|
|
97
99
|
"peerDependencies": {
|
|
98
100
|
"@sanity/block-tools": "^3.47.1",
|
|
@@ -100,8 +102,8 @@
|
|
|
100
102
|
"@sanity/types": "^3.47.1",
|
|
101
103
|
"@sanity/util": "^3.47.1",
|
|
102
104
|
"react": "^16.9 || ^17 || ^18",
|
|
103
|
-
"rxjs": "^7",
|
|
104
|
-
"styled-components": "^6.1"
|
|
105
|
+
"rxjs": "^7.8.1",
|
|
106
|
+
"styled-components": "^6.1.13"
|
|
105
107
|
},
|
|
106
108
|
"engines": {
|
|
107
109
|
"node": ">=18"
|
|
@@ -115,11 +117,10 @@
|
|
|
115
117
|
"check:types": "tsc",
|
|
116
118
|
"clean": "del .turbo && del lib && del node_modules",
|
|
117
119
|
"dev": "pkg-utils watch",
|
|
118
|
-
"dev:e2e-server": "cd ./e2e-tests/ && tsx serve",
|
|
119
120
|
"lint:fix": "biome lint --write .",
|
|
120
|
-
"test": "
|
|
121
|
+
"test": "vitest --run",
|
|
122
|
+
"test:watch": "vitest",
|
|
121
123
|
"test:e2e": "jest --config=e2e-tests/e2e.config.ts",
|
|
122
|
-
"test:e2e:watch": "jest --config=e2e-tests/e2e.config.ts --watch"
|
|
123
|
-
"test:watch": "jest --watch"
|
|
124
|
+
"test:e2e:watch": "jest --config=e2e-tests/e2e.config.ts --watch"
|
|
124
125
|
}
|
|
125
126
|
}
|
package/src/editor/Editable.tsx
CHANGED
|
@@ -161,15 +161,15 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
161
161
|
|
|
162
162
|
const rangeDecorationsRef = useRef(rangeDecorations)
|
|
163
163
|
|
|
164
|
-
const {
|
|
164
|
+
const {editorActor, schemaTypes} = portableTextEditor
|
|
165
165
|
const slateEditor = useSlate()
|
|
166
166
|
|
|
167
167
|
const blockTypeName = schemaTypes.block.name
|
|
168
168
|
|
|
169
169
|
// React/UI-specific plugins
|
|
170
170
|
const withInsertData = useMemo(
|
|
171
|
-
() => createWithInsertData(
|
|
172
|
-
[
|
|
171
|
+
() => createWithInsertData(editorActor, schemaTypes, keyGenerator),
|
|
172
|
+
[editorActor, keyGenerator, schemaTypes],
|
|
173
173
|
)
|
|
174
174
|
const withHotKeys = useMemo(
|
|
175
175
|
() => createWithHotkeys(schemaTypes, portableTextEditor, hotkeys),
|
|
@@ -278,13 +278,16 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
278
278
|
// Output selection here in those cases where the editor selection was the same, and there are no set_selection operations made.
|
|
279
279
|
// The selection is usually automatically emitted to change$ by the withPortableTextSelections plugin whenever there is a set_selection operation applied.
|
|
280
280
|
if (!slateEditor.operations.some((o) => o.type === 'set_selection')) {
|
|
281
|
-
|
|
281
|
+
editorActor.send({
|
|
282
|
+
type: 'selection',
|
|
283
|
+
selection: normalizedSelection,
|
|
284
|
+
})
|
|
282
285
|
}
|
|
283
286
|
slateEditor.onChange()
|
|
284
287
|
}
|
|
285
288
|
}
|
|
286
289
|
}
|
|
287
|
-
}, [propsSelection, slateEditor
|
|
290
|
+
}, [editorActor, propsSelection, slateEditor])
|
|
288
291
|
|
|
289
292
|
const syncRangeDecorations = useCallback(
|
|
290
293
|
(operation?: Operation) => {
|
|
@@ -348,28 +351,24 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
348
351
|
[portableTextEditor, rangeDecorations, schemaTypes, slateEditor],
|
|
349
352
|
)
|
|
350
353
|
|
|
351
|
-
//
|
|
354
|
+
// Restore selection from props when the editor has been initialized properly with it's value
|
|
352
355
|
useEffect(() => {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
switch (next.type) {
|
|
356
|
-
case 'ready':
|
|
357
|
-
restoreSelectionFromProps()
|
|
358
|
-
break
|
|
359
|
-
case 'invalidValue':
|
|
360
|
-
setHasInvalidValue(true)
|
|
361
|
-
break
|
|
362
|
-
case 'value':
|
|
363
|
-
setHasInvalidValue(false)
|
|
364
|
-
break
|
|
365
|
-
default:
|
|
366
|
-
}
|
|
356
|
+
const onReady = editorActor.on('ready', () => {
|
|
357
|
+
restoreSelectionFromProps()
|
|
367
358
|
})
|
|
359
|
+
const onInvalidValue = editorActor.on('invalid value', () => {
|
|
360
|
+
setHasInvalidValue(true)
|
|
361
|
+
})
|
|
362
|
+
const onValueChanged = editorActor.on('value changed', () => {
|
|
363
|
+
setHasInvalidValue(false)
|
|
364
|
+
})
|
|
365
|
+
|
|
368
366
|
return () => {
|
|
369
|
-
|
|
370
|
-
|
|
367
|
+
onReady.unsubscribe()
|
|
368
|
+
onInvalidValue.unsubscribe()
|
|
369
|
+
onValueChanged.unsubscribe()
|
|
371
370
|
}
|
|
372
|
-
}, [
|
|
371
|
+
}, [editorActor, restoreSelectionFromProps])
|
|
373
372
|
|
|
374
373
|
// Restore selection from props when it changes
|
|
375
374
|
useEffect(() => {
|
|
@@ -451,7 +450,7 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
451
450
|
slateEditor.insertData(event.clipboardData)
|
|
452
451
|
} else {
|
|
453
452
|
// Resolve it as promise (can be either async promise or sync return value)
|
|
454
|
-
|
|
453
|
+
editorActor.send({type: 'loading'})
|
|
455
454
|
Promise.resolve(onPasteResult)
|
|
456
455
|
.then((result) => {
|
|
457
456
|
debug('Custom paste function from client resolved', result)
|
|
@@ -476,11 +475,11 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
476
475
|
return error
|
|
477
476
|
})
|
|
478
477
|
.finally(() => {
|
|
479
|
-
|
|
478
|
+
editorActor.send({type: 'done loading'})
|
|
480
479
|
})
|
|
481
480
|
}
|
|
482
481
|
},
|
|
483
|
-
[
|
|
482
|
+
[onPaste, portableTextEditor, schemaTypes, slateEditor],
|
|
484
483
|
)
|
|
485
484
|
|
|
486
485
|
const handleOnFocus: FocusEventHandler<HTMLDivElement> = useCallback(
|
|
@@ -495,18 +494,18 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
495
494
|
Transforms.select(slateEditor, Editor.start(slateEditor, []))
|
|
496
495
|
slateEditor.onChange()
|
|
497
496
|
}
|
|
498
|
-
|
|
497
|
+
editorActor.send({type: 'focus', event})
|
|
499
498
|
const newSelection = PortableTextEditor.getSelection(portableTextEditor)
|
|
500
499
|
// If the selection is the same, emit it explicitly here as there is no actual onChange event triggered.
|
|
501
500
|
if (selection === newSelection) {
|
|
502
|
-
|
|
501
|
+
editorActor.send({
|
|
503
502
|
type: 'selection',
|
|
504
503
|
selection,
|
|
505
504
|
})
|
|
506
505
|
}
|
|
507
506
|
}
|
|
508
507
|
},
|
|
509
|
-
[onFocus, portableTextEditor,
|
|
508
|
+
[editorActor, onFocus, portableTextEditor, slateEditor],
|
|
510
509
|
)
|
|
511
510
|
|
|
512
511
|
const handleClick = useCallback(
|
|
@@ -542,10 +541,10 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
542
541
|
onBlur(event)
|
|
543
542
|
}
|
|
544
543
|
if (!event.isPropagationStopped()) {
|
|
545
|
-
|
|
544
|
+
editorActor.send({type: 'blur', event})
|
|
546
545
|
}
|
|
547
546
|
},
|
|
548
|
-
[
|
|
547
|
+
[editorActor, onBlur],
|
|
549
548
|
)
|
|
550
549
|
|
|
551
550
|
const handleOnBeforeInput = useCallback(
|
|
@@ -11,12 +11,14 @@ import type {
|
|
|
11
11
|
} from '@sanity/types'
|
|
12
12
|
import {Component, type MutableRefObject, type PropsWithChildren} from 'react'
|
|
13
13
|
import {Subject} from 'rxjs'
|
|
14
|
+
import {createActor, type Subscription} from 'xstate'
|
|
14
15
|
import type {
|
|
15
16
|
EditableAPI,
|
|
16
17
|
EditableAPIDeleteOptions,
|
|
17
18
|
EditorChange,
|
|
18
19
|
EditorChanges,
|
|
19
20
|
EditorSelection,
|
|
21
|
+
MutationChange,
|
|
20
22
|
PatchObservable,
|
|
21
23
|
PortableTextMemberSchemaTypes,
|
|
22
24
|
} from '../types/editor'
|
|
@@ -25,6 +27,7 @@ import {getPortableTextMemberSchemaTypes} from '../utils/getPortableTextMemberSc
|
|
|
25
27
|
import {compileType} from '../utils/schema'
|
|
26
28
|
import {SlateContainer} from './components/SlateContainer'
|
|
27
29
|
import {Synchronizer} from './components/Synchronizer'
|
|
30
|
+
import {editorMachine, type EditorActor} from './editor-machine'
|
|
28
31
|
import {PortableTextEditorContext} from './hooks/usePortableTextEditor'
|
|
29
32
|
import {
|
|
30
33
|
defaultKeyGenerator,
|
|
@@ -92,6 +95,11 @@ export type PortableTextEditorProps = PropsWithChildren<{
|
|
|
92
95
|
* @public
|
|
93
96
|
*/
|
|
94
97
|
export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
98
|
+
/**
|
|
99
|
+
* @internal
|
|
100
|
+
* Don't use this API directly. It's subject to change.
|
|
101
|
+
*/
|
|
102
|
+
public editorActor: EditorActor
|
|
95
103
|
/**
|
|
96
104
|
* An observable of all the editor changes.
|
|
97
105
|
*/
|
|
@@ -118,7 +126,8 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
118
126
|
)
|
|
119
127
|
}
|
|
120
128
|
|
|
121
|
-
this.
|
|
129
|
+
this.editorActor = createActor(editorMachine)
|
|
130
|
+
this.editorActor.start()
|
|
122
131
|
|
|
123
132
|
this.schemaTypes = getPortableTextMemberSchemaTypes(
|
|
124
133
|
props.schemaType.hasOwnProperty('jsonType')
|
|
@@ -154,8 +163,7 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
154
163
|
}
|
|
155
164
|
|
|
156
165
|
render() {
|
|
157
|
-
const {
|
|
158
|
-
const {change$} = this
|
|
166
|
+
const {value, children, patches$, incomingPatches$} = this.props
|
|
159
167
|
const _patches$ = incomingPatches$ || patches$ // Backward compatibility
|
|
160
168
|
|
|
161
169
|
const maxBlocks =
|
|
@@ -176,11 +184,20 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
176
184
|
<PortableTextEditorKeyGeneratorContext.Provider value={keyGenerator}>
|
|
177
185
|
<PortableTextEditorContext.Provider value={this}>
|
|
178
186
|
<PortableTextEditorReadOnlyContext.Provider value={readOnly}>
|
|
179
|
-
<PortableTextEditorSelectionProvider
|
|
187
|
+
<PortableTextEditorSelectionProvider
|
|
188
|
+
editorActor={this.editorActor}
|
|
189
|
+
>
|
|
180
190
|
<Synchronizer
|
|
181
|
-
|
|
191
|
+
editorActor={this.editorActor}
|
|
182
192
|
getValue={this.getValue}
|
|
183
|
-
onChange={
|
|
193
|
+
onChange={(change) => {
|
|
194
|
+
this.props.onChange(change)
|
|
195
|
+
/**
|
|
196
|
+
* For backwards compatibility, we relay all changes to the
|
|
197
|
+
* `change$` Subject as well.
|
|
198
|
+
*/
|
|
199
|
+
this.change$.next(change)
|
|
200
|
+
}}
|
|
184
201
|
value={value}
|
|
185
202
|
/>
|
|
186
203
|
{children}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {describe, expect, it, jest} from '@jest/globals'
|
|
2
1
|
import type {PortableTextBlock} from '@sanity/types'
|
|
3
2
|
import {render, waitFor} from '@testing-library/react'
|
|
4
3
|
import {createRef, type RefObject} from 'react'
|
|
4
|
+
import {describe, expect, it, vi} from 'vitest'
|
|
5
5
|
import type {EditorSelection} from '../..'
|
|
6
6
|
import {PortableTextEditor} from '../PortableTextEditor'
|
|
7
7
|
import {PortableTextEditorTester, schemaType} from './PortableTextEditorTester'
|
|
@@ -18,7 +18,7 @@ const renderPlaceholder = () => 'Jot something down here'
|
|
|
18
18
|
describe('initialization', () => {
|
|
19
19
|
it('receives initial onChange events and has custom placeholder', async () => {
|
|
20
20
|
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
21
|
-
const onChange =
|
|
21
|
+
const onChange = vi.fn()
|
|
22
22
|
const {container} = render(
|
|
23
23
|
<PortableTextEditorTester
|
|
24
24
|
onChange={onChange}
|
|
@@ -88,7 +88,7 @@ describe('initialization', () => {
|
|
|
88
88
|
})
|
|
89
89
|
it('takes value from props and confirms it by emitting value change event', async () => {
|
|
90
90
|
const initialValue = [helloBlock]
|
|
91
|
-
const onChange =
|
|
91
|
+
const onChange = vi.fn()
|
|
92
92
|
const editorRef = createRef<PortableTextEditor>()
|
|
93
93
|
render(
|
|
94
94
|
<PortableTextEditorTester
|
|
@@ -120,7 +120,7 @@ describe('initialization', () => {
|
|
|
120
120
|
focus: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
121
121
|
backward: false,
|
|
122
122
|
}
|
|
123
|
-
const onChange =
|
|
123
|
+
const onChange = vi.fn()
|
|
124
124
|
render(
|
|
125
125
|
<PortableTextEditorTester
|
|
126
126
|
onChange={onChange}
|
|
@@ -164,7 +164,7 @@ describe('initialization', () => {
|
|
|
164
164
|
focus: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 3},
|
|
165
165
|
backward: false,
|
|
166
166
|
}
|
|
167
|
-
const onChange =
|
|
167
|
+
const onChange = vi.fn()
|
|
168
168
|
const {rerender} = render(
|
|
169
169
|
<PortableTextEditorTester
|
|
170
170
|
onChange={onChange}
|
|
@@ -223,7 +223,7 @@ describe('initialization', () => {
|
|
|
223
223
|
anchor: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
224
224
|
focus: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
225
225
|
}
|
|
226
|
-
const onChange =
|
|
226
|
+
const onChange = vi.fn()
|
|
227
227
|
render(
|
|
228
228
|
<PortableTextEditorTester
|
|
229
229
|
onChange={onChange}
|
|
@@ -266,7 +266,7 @@ describe('initialization', () => {
|
|
|
266
266
|
anchor: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
267
267
|
focus: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
268
268
|
}
|
|
269
|
-
const onChange =
|
|
269
|
+
const onChange = vi.fn()
|
|
270
270
|
let _rerender: any
|
|
271
271
|
await waitFor(() => {
|
|
272
272
|
render(
|
|
@@ -300,7 +300,7 @@ describe('initialization', () => {
|
|
|
300
300
|
expect(onChange).toHaveBeenCalledWith({type: 'value', value})
|
|
301
301
|
})
|
|
302
302
|
value = [{_type: 'banana', _key: '123'}]
|
|
303
|
-
const newOnChange =
|
|
303
|
+
const newOnChange = vi.fn()
|
|
304
304
|
_rerender(
|
|
305
305
|
<PortableTextEditorTester
|
|
306
306
|
onChange={newOnChange}
|
|
@@ -352,7 +352,7 @@ describe('initialization', () => {
|
|
|
352
352
|
anchor: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
353
353
|
focus: {path: [{_key: '123'}, 'children', {_key: '567'}], offset: 2},
|
|
354
354
|
}
|
|
355
|
-
const onChange =
|
|
355
|
+
const onChange = vi.fn()
|
|
356
356
|
render(
|
|
357
357
|
<PortableTextEditorTester
|
|
358
358
|
onChange={onChange}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {jest} from '@jest/globals'
|
|
2
1
|
import {Schema} from '@sanity/schema'
|
|
3
2
|
import {defineArrayMember, defineField} from '@sanity/types'
|
|
4
3
|
import {
|
|
@@ -8,6 +7,7 @@ import {
|
|
|
8
7
|
useMemo,
|
|
9
8
|
type ForwardedRef,
|
|
10
9
|
} from 'react'
|
|
10
|
+
import {vi} from 'vitest'
|
|
11
11
|
import {
|
|
12
12
|
PortableTextEditable,
|
|
13
13
|
PortableTextEditor,
|
|
@@ -100,10 +100,7 @@ export const PortableTextEditorTester = forwardRef(
|
|
|
100
100
|
key++
|
|
101
101
|
return `${key}`
|
|
102
102
|
}, [])
|
|
103
|
-
const onChange = useMemo(
|
|
104
|
-
() => props.onChange || jest.fn(),
|
|
105
|
-
[props.onChange],
|
|
106
|
-
)
|
|
103
|
+
const onChange = useMemo(() => props.onChange || vi.fn(), [props.onChange])
|
|
107
104
|
return (
|
|
108
105
|
<PortableTextEditor
|
|
109
106
|
schemaType={props.schemaType}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {describe, expect, it, jest} from '@jest/globals'
|
|
2
1
|
import type {PortableTextBlock} from '@sanity/types'
|
|
3
2
|
import {render, waitFor} from '@testing-library/react'
|
|
4
3
|
import {createRef, type ReactNode, type RefObject} from 'react'
|
|
4
|
+
import {describe, expect, it, vi} from 'vitest'
|
|
5
5
|
import type {RangeDecoration} from '../..'
|
|
6
6
|
import type {PortableTextEditor} from '../PortableTextEditor'
|
|
7
7
|
import {PortableTextEditorTester, schemaType} from './PortableTextEditorTester'
|
|
@@ -23,7 +23,7 @@ const RangeDecorationTestComponent = ({children}: {children?: ReactNode}) => {
|
|
|
23
23
|
describe('RangeDecorations', () => {
|
|
24
24
|
it('only render range decorations as necessary', async () => {
|
|
25
25
|
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
26
|
-
const onChange =
|
|
26
|
+
const onChange = vi.fn()
|
|
27
27
|
const value = [helloBlock]
|
|
28
28
|
let rangeDecorations: RangeDecoration[] = [
|
|
29
29
|
{
|
|
@@ -1,9 +1,29 @@
|
|
|
1
|
-
import {describe, expect, it, jest} from '@jest/globals'
|
|
2
1
|
import {fireEvent, render, waitFor} from '@testing-library/react'
|
|
3
|
-
import {createRef, type RefObject} from 'react'
|
|
2
|
+
import {act, createRef, type RefObject} from 'react'
|
|
3
|
+
import {describe, expect, it, vi} from 'vitest'
|
|
4
4
|
import {PortableTextEditor} from '../PortableTextEditor'
|
|
5
5
|
import {PortableTextEditorTester, schemaType} from './PortableTextEditorTester'
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
async function getEditableElement(
|
|
8
|
+
component: ReturnType<typeof render>,
|
|
9
|
+
): Promise<Element> {
|
|
10
|
+
await act(async () => component)
|
|
11
|
+
const element = component.container.querySelector(
|
|
12
|
+
'[data-slate-editor="true"]',
|
|
13
|
+
)
|
|
14
|
+
if (!element) {
|
|
15
|
+
throw new Error('Could not find element')
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Manually add this because JSDom doesn't implement this and Slate checks for it
|
|
19
|
+
* internally before doing stuff.
|
|
20
|
+
*
|
|
21
|
+
* https://github.com/jsdom/jsdom/issues/1670
|
|
22
|
+
*/
|
|
23
|
+
// @ts-ignore
|
|
24
|
+
element.isContentEditable = true
|
|
25
|
+
return element
|
|
26
|
+
}
|
|
7
27
|
|
|
8
28
|
describe('adds empty text block if its needed', () => {
|
|
9
29
|
const newBlock = {
|
|
@@ -34,7 +54,7 @@ describe('adds empty text block if its needed', () => {
|
|
|
34
54
|
}
|
|
35
55
|
|
|
36
56
|
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
37
|
-
const onChange =
|
|
57
|
+
const onChange = vi.fn()
|
|
38
58
|
const component = render(
|
|
39
59
|
<PortableTextEditorTester
|
|
40
60
|
onChange={onChange}
|
|
@@ -96,7 +116,7 @@ describe('adds empty text block if its needed', () => {
|
|
|
96
116
|
}
|
|
97
117
|
|
|
98
118
|
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
99
|
-
const onChange =
|
|
119
|
+
const onChange = vi.fn()
|
|
100
120
|
const component = render(
|
|
101
121
|
<PortableTextEditorTester
|
|
102
122
|
onChange={onChange}
|
|
@@ -151,7 +171,7 @@ describe('adds empty text block if its needed', () => {
|
|
|
151
171
|
}
|
|
152
172
|
|
|
153
173
|
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
154
|
-
const onChange =
|
|
174
|
+
const onChange = vi.fn()
|
|
155
175
|
const component = render(
|
|
156
176
|
<PortableTextEditorTester
|
|
157
177
|
onChange={onChange}
|
|
@@ -217,7 +237,7 @@ describe('adds empty text block if its needed', () => {
|
|
|
217
237
|
}
|
|
218
238
|
|
|
219
239
|
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
220
|
-
const onChange =
|
|
240
|
+
const onChange = vi.fn()
|
|
221
241
|
const component = render(
|
|
222
242
|
<PortableTextEditorTester
|
|
223
243
|
onChange={onChange}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {describe, expect, jest, test} from '@jest/globals'
|
|
2
1
|
import {Schema} from '@sanity/schema'
|
|
3
2
|
import type {PortableTextBlock} from '@sanity/types'
|
|
4
3
|
import {render, waitFor} from '@testing-library/react'
|
|
5
4
|
import {createRef, type RefObject} from 'react'
|
|
5
|
+
import {describe, expect, test, vi} from 'vitest'
|
|
6
6
|
import type {EditorChange, EditorSelection} from '../../types/editor'
|
|
7
7
|
import {PortableTextEditable} from '../Editable'
|
|
8
8
|
import {PortableTextEditor} from '../PortableTextEditor'
|
|
@@ -35,7 +35,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
35
35
|
style: 'normal',
|
|
36
36
|
}
|
|
37
37
|
const initialValue: Array<PortableTextBlock> = [emptyTextBlock]
|
|
38
|
-
const onChange: (change: EditorChange) => void =
|
|
38
|
+
const onChange: (change: EditorChange) => void = vi.fn()
|
|
39
39
|
|
|
40
40
|
render(
|
|
41
41
|
<PortableTextEditor
|
|
@@ -104,7 +104,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
104
104
|
style: 'normal',
|
|
105
105
|
}
|
|
106
106
|
const initialValue: Array<PortableTextBlock> = [nonEmptyTextBlock]
|
|
107
|
-
const onChange: (change: EditorChange) => void =
|
|
107
|
+
const onChange: (change: EditorChange) => void = vi.fn()
|
|
108
108
|
|
|
109
109
|
render(
|
|
110
110
|
<PortableTextEditor
|
|
@@ -177,7 +177,7 @@ describe(PortableTextEditor.insertBlock.name, () => {
|
|
|
177
177
|
_type: 'image',
|
|
178
178
|
}
|
|
179
179
|
const initialValue: Array<PortableTextBlock> = [emptyTextBlock, imageBlock]
|
|
180
|
-
const onChange: (change: EditorChange) => void =
|
|
180
|
+
const onChange: (change: EditorChange) => void = vi.fn()
|
|
181
181
|
|
|
182
182
|
render(
|
|
183
183
|
<PortableTextEditor
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {describe, expect, it, jest} from '@jest/globals'
|
|
2
1
|
import type {PortableTextBlock} from '@sanity/types'
|
|
3
2
|
import {render, waitFor} from '@testing-library/react'
|
|
4
3
|
import {createRef, type RefObject} from 'react'
|
|
4
|
+
import {describe, expect, it, vi} from 'vitest'
|
|
5
5
|
import {PortableTextEditor} from '../PortableTextEditor'
|
|
6
6
|
import {PortableTextEditorTester, schemaType} from './PortableTextEditorTester'
|
|
7
7
|
|
|
@@ -24,7 +24,7 @@ describe('when PTE would display warnings, instead it self solves', () => {
|
|
|
24
24
|
},
|
|
25
25
|
]
|
|
26
26
|
|
|
27
|
-
const onChange =
|
|
27
|
+
const onChange = vi.fn()
|
|
28
28
|
render(
|
|
29
29
|
<PortableTextEditorTester
|
|
30
30
|
onChange={onChange}
|
|
@@ -80,7 +80,7 @@ describe('when PTE would display warnings, instead it self solves', () => {
|
|
|
80
80
|
},
|
|
81
81
|
]
|
|
82
82
|
|
|
83
|
-
const onChange =
|
|
83
|
+
const onChange = vi.fn()
|
|
84
84
|
render(
|
|
85
85
|
<PortableTextEditorTester
|
|
86
86
|
onChange={onChange}
|
|
@@ -137,7 +137,7 @@ describe('when PTE would display warnings, instead it self solves', () => {
|
|
|
137
137
|
},
|
|
138
138
|
]
|
|
139
139
|
|
|
140
|
-
const onChange =
|
|
140
|
+
const onChange = vi.fn()
|
|
141
141
|
render(
|
|
142
142
|
<PortableTextEditorTester
|
|
143
143
|
onChange={onChange}
|
|
@@ -209,7 +209,7 @@ describe('when PTE would display warnings, instead it self solves', () => {
|
|
|
209
209
|
},
|
|
210
210
|
]
|
|
211
211
|
|
|
212
|
-
const onChange =
|
|
212
|
+
const onChange = vi.fn()
|
|
213
213
|
render(
|
|
214
214
|
<PortableTextEditorTester
|
|
215
215
|
onChange={onChange}
|
|
@@ -273,7 +273,7 @@ describe('when PTE would display warnings, instead it self solves', () => {
|
|
|
273
273
|
},
|
|
274
274
|
]
|
|
275
275
|
|
|
276
|
-
const onChange =
|
|
276
|
+
const onChange = vi.fn()
|
|
277
277
|
render(
|
|
278
278
|
<PortableTextEditorTester
|
|
279
279
|
onChange={onChange}
|
|
@@ -316,7 +316,7 @@ describe('when PTE would display warnings, instead it self solves', () => {
|
|
|
316
316
|
const editorRef: RefObject<PortableTextEditor> = createRef()
|
|
317
317
|
const initialValue = [] as PortableTextBlock[]
|
|
318
318
|
|
|
319
|
-
const onChange =
|
|
319
|
+
const onChange = vi.fn()
|
|
320
320
|
render(
|
|
321
321
|
<PortableTextEditorTester
|
|
322
322
|
onChange={onChange}
|