@portabletext/editor 1.1.1 → 1.1.3
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 +1668 -1
- package/lib/index.d.ts +1668 -1
- package/lib/index.esm.js +320 -172
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +320 -173
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +320 -172
- package/lib/index.mjs.map +1 -1
- package/package.json +23 -23
- package/src/editor/Editable.tsx +32 -34
- package/src/editor/PortableTextEditor.tsx +23 -7
- 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 +12 -14
- 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/createWithEditableAPI.ts +5 -7
- package/src/editor/plugins/createWithInsertData.ts +4 -9
- 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 +40 -36
- 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 +13 -2
- package/src/utils/__tests__/values.test.ts +17 -17
- package/src/utils/applyPatch.ts +4 -10
- 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.3",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -47,29 +47,29 @@
|
|
|
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
|
-
"@sanity/test": "0.0.1-alpha.1",
|
|
65
64
|
"@sanity/types": "^3.55.0",
|
|
66
|
-
"@sanity/ui": "^2.8.
|
|
65
|
+
"@sanity/ui": "^2.8.9",
|
|
67
66
|
"@sanity/util": "^3.55.0",
|
|
68
67
|
"@testing-library/dom": "^10.4.0",
|
|
69
|
-
"@testing-library/
|
|
68
|
+
"@testing-library/jest-dom": "^6.5.0",
|
|
69
|
+
"@testing-library/react": "^16.0.1",
|
|
70
70
|
"@types/debug": "^4.1.5",
|
|
71
71
|
"@types/express": "^4.17.21",
|
|
72
|
-
"@types/express-ws": "^3.0.
|
|
72
|
+
"@types/express-ws": "^3.0.5",
|
|
73
73
|
"@types/lodash": "^4.17.7",
|
|
74
74
|
"@types/node": "^18.19.8",
|
|
75
75
|
"@types/node-ipc": "^9.2.3",
|
|
@@ -81,18 +81,19 @@
|
|
|
81
81
|
"express": "^4.19.2",
|
|
82
82
|
"express-ws": "^5.0.2",
|
|
83
83
|
"jest": "^29.7.0",
|
|
84
|
-
"jest-dev-server": "^10.1.
|
|
85
|
-
"jest-environment-jsdom": "^29.7.0",
|
|
84
|
+
"jest-dev-server": "^10.1.1",
|
|
86
85
|
"jest-environment-node": "^29.7.0",
|
|
86
|
+
"jsdom": "^25.0.1",
|
|
87
87
|
"node-ipc": "npm:@node-ipc/compat@9.2.5",
|
|
88
88
|
"react": "^18.3.1",
|
|
89
89
|
"react-dom": "^18.3.1",
|
|
90
90
|
"rxjs": "^7.8.1",
|
|
91
|
-
"styled-components": "^6.1.
|
|
91
|
+
"styled-components": "^6.1.13",
|
|
92
92
|
"ts-node": "^10.9.2",
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
93
|
+
"typescript": "5.6.2",
|
|
94
|
+
"vite": "^5.4.2",
|
|
95
|
+
"vitest": "^2.1.1",
|
|
96
|
+
"@sanity/gherkin-driver": "^0.0.1"
|
|
96
97
|
},
|
|
97
98
|
"peerDependencies": {
|
|
98
99
|
"@sanity/block-tools": "^3.47.1",
|
|
@@ -100,8 +101,8 @@
|
|
|
100
101
|
"@sanity/types": "^3.47.1",
|
|
101
102
|
"@sanity/util": "^3.47.1",
|
|
102
103
|
"react": "^16.9 || ^17 || ^18",
|
|
103
|
-
"rxjs": "^7",
|
|
104
|
-
"styled-components": "^6.1"
|
|
104
|
+
"rxjs": "^7.8.1",
|
|
105
|
+
"styled-components": "^6.1.13"
|
|
105
106
|
},
|
|
106
107
|
"engines": {
|
|
107
108
|
"node": ">=18"
|
|
@@ -115,11 +116,10 @@
|
|
|
115
116
|
"check:types": "tsc",
|
|
116
117
|
"clean": "del .turbo && del lib && del node_modules",
|
|
117
118
|
"dev": "pkg-utils watch",
|
|
118
|
-
"dev:e2e-server": "cd ./e2e-tests/ && tsx serve",
|
|
119
119
|
"lint:fix": "biome lint --write .",
|
|
120
|
-
"test": "
|
|
120
|
+
"test": "vitest --run",
|
|
121
|
+
"test:watch": "vitest",
|
|
121
122
|
"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"
|
|
123
|
+
"test:e2e:watch": "jest --config=e2e-tests/e2e.config.ts --watch"
|
|
124
124
|
}
|
|
125
125
|
}
|
package/src/editor/Editable.tsx
CHANGED
|
@@ -36,7 +36,6 @@ import {
|
|
|
36
36
|
type RenderLeafProps,
|
|
37
37
|
} from 'slate-react'
|
|
38
38
|
import type {
|
|
39
|
-
EditorChange,
|
|
40
39
|
EditorSelection,
|
|
41
40
|
OnCopyFn,
|
|
42
41
|
OnPasteFn,
|
|
@@ -161,15 +160,15 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
161
160
|
|
|
162
161
|
const rangeDecorationsRef = useRef(rangeDecorations)
|
|
163
162
|
|
|
164
|
-
const {
|
|
163
|
+
const {editorActor, schemaTypes} = portableTextEditor
|
|
165
164
|
const slateEditor = useSlate()
|
|
166
165
|
|
|
167
166
|
const blockTypeName = schemaTypes.block.name
|
|
168
167
|
|
|
169
168
|
// React/UI-specific plugins
|
|
170
169
|
const withInsertData = useMemo(
|
|
171
|
-
() => createWithInsertData(
|
|
172
|
-
[
|
|
170
|
+
() => createWithInsertData(editorActor, schemaTypes, keyGenerator),
|
|
171
|
+
[editorActor, keyGenerator, schemaTypes],
|
|
173
172
|
)
|
|
174
173
|
const withHotKeys = useMemo(
|
|
175
174
|
() => createWithHotkeys(schemaTypes, portableTextEditor, hotkeys),
|
|
@@ -278,13 +277,16 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
278
277
|
// Output selection here in those cases where the editor selection was the same, and there are no set_selection operations made.
|
|
279
278
|
// The selection is usually automatically emitted to change$ by the withPortableTextSelections plugin whenever there is a set_selection operation applied.
|
|
280
279
|
if (!slateEditor.operations.some((o) => o.type === 'set_selection')) {
|
|
281
|
-
|
|
280
|
+
editorActor.send({
|
|
281
|
+
type: 'selection',
|
|
282
|
+
selection: normalizedSelection,
|
|
283
|
+
})
|
|
282
284
|
}
|
|
283
285
|
slateEditor.onChange()
|
|
284
286
|
}
|
|
285
287
|
}
|
|
286
288
|
}
|
|
287
|
-
}, [propsSelection, slateEditor
|
|
289
|
+
}, [editorActor, propsSelection, slateEditor])
|
|
288
290
|
|
|
289
291
|
const syncRangeDecorations = useCallback(
|
|
290
292
|
(operation?: Operation) => {
|
|
@@ -348,28 +350,24 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
348
350
|
[portableTextEditor, rangeDecorations, schemaTypes, slateEditor],
|
|
349
351
|
)
|
|
350
352
|
|
|
351
|
-
//
|
|
353
|
+
// Restore selection from props when the editor has been initialized properly with it's value
|
|
352
354
|
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
|
-
}
|
|
355
|
+
const onReady = editorActor.on('ready', () => {
|
|
356
|
+
restoreSelectionFromProps()
|
|
367
357
|
})
|
|
358
|
+
const onInvalidValue = editorActor.on('invalid value', () => {
|
|
359
|
+
setHasInvalidValue(true)
|
|
360
|
+
})
|
|
361
|
+
const onValueChanged = editorActor.on('value changed', () => {
|
|
362
|
+
setHasInvalidValue(false)
|
|
363
|
+
})
|
|
364
|
+
|
|
368
365
|
return () => {
|
|
369
|
-
|
|
370
|
-
|
|
366
|
+
onReady.unsubscribe()
|
|
367
|
+
onInvalidValue.unsubscribe()
|
|
368
|
+
onValueChanged.unsubscribe()
|
|
371
369
|
}
|
|
372
|
-
}, [
|
|
370
|
+
}, [editorActor, restoreSelectionFromProps])
|
|
373
371
|
|
|
374
372
|
// Restore selection from props when it changes
|
|
375
373
|
useEffect(() => {
|
|
@@ -451,7 +449,7 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
451
449
|
slateEditor.insertData(event.clipboardData)
|
|
452
450
|
} else {
|
|
453
451
|
// Resolve it as promise (can be either async promise or sync return value)
|
|
454
|
-
|
|
452
|
+
editorActor.send({type: 'loading'})
|
|
455
453
|
Promise.resolve(onPasteResult)
|
|
456
454
|
.then((result) => {
|
|
457
455
|
debug('Custom paste function from client resolved', result)
|
|
@@ -476,11 +474,11 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
476
474
|
return error
|
|
477
475
|
})
|
|
478
476
|
.finally(() => {
|
|
479
|
-
|
|
477
|
+
editorActor.send({type: 'done loading'})
|
|
480
478
|
})
|
|
481
479
|
}
|
|
482
480
|
},
|
|
483
|
-
[
|
|
481
|
+
[onPaste, portableTextEditor, schemaTypes, slateEditor],
|
|
484
482
|
)
|
|
485
483
|
|
|
486
484
|
const handleOnFocus: FocusEventHandler<HTMLDivElement> = useCallback(
|
|
@@ -495,18 +493,18 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
495
493
|
Transforms.select(slateEditor, Editor.start(slateEditor, []))
|
|
496
494
|
slateEditor.onChange()
|
|
497
495
|
}
|
|
498
|
-
|
|
496
|
+
editorActor.send({type: 'focus', event})
|
|
499
497
|
const newSelection = PortableTextEditor.getSelection(portableTextEditor)
|
|
500
498
|
// If the selection is the same, emit it explicitly here as there is no actual onChange event triggered.
|
|
501
499
|
if (selection === newSelection) {
|
|
502
|
-
|
|
500
|
+
editorActor.send({
|
|
503
501
|
type: 'selection',
|
|
504
502
|
selection,
|
|
505
503
|
})
|
|
506
504
|
}
|
|
507
505
|
}
|
|
508
506
|
},
|
|
509
|
-
[onFocus, portableTextEditor,
|
|
507
|
+
[editorActor, onFocus, portableTextEditor, slateEditor],
|
|
510
508
|
)
|
|
511
509
|
|
|
512
510
|
const handleClick = useCallback(
|
|
@@ -542,10 +540,10 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
542
540
|
onBlur(event)
|
|
543
541
|
}
|
|
544
542
|
if (!event.isPropagationStopped()) {
|
|
545
|
-
|
|
543
|
+
editorActor.send({type: 'blur', event})
|
|
546
544
|
}
|
|
547
545
|
},
|
|
548
|
-
[
|
|
546
|
+
[editorActor, onBlur],
|
|
549
547
|
)
|
|
550
548
|
|
|
551
549
|
const handleOnBeforeInput = useCallback(
|
|
@@ -604,7 +602,7 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
604
602
|
// Set the correct range
|
|
605
603
|
domSelection.addRange(newDOMRange)
|
|
606
604
|
}
|
|
607
|
-
} catch
|
|
605
|
+
} catch {
|
|
608
606
|
debug(`Could not resolve selection, selecting top document`)
|
|
609
607
|
// Deselect the editor
|
|
610
608
|
Transforms.deselect(slateEditor)
|
|
@@ -657,7 +655,7 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
657
655
|
return noop
|
|
658
656
|
}
|
|
659
657
|
// Translate PortableTextEditor prop fn to Slate plugin fn
|
|
660
|
-
return (
|
|
658
|
+
return (_editor: ReactEditor, domRange: Range) => {
|
|
661
659
|
scrollSelectionIntoView(portableTextEditor, domRange)
|
|
662
660
|
}
|
|
663
661
|
}, [portableTextEditor, scrollSelectionIntoView])
|
|
@@ -11,6 +11,7 @@ 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} from 'xstate'
|
|
14
15
|
import type {
|
|
15
16
|
EditableAPI,
|
|
16
17
|
EditableAPIDeleteOptions,
|
|
@@ -25,6 +26,7 @@ import {getPortableTextMemberSchemaTypes} from '../utils/getPortableTextMemberSc
|
|
|
25
26
|
import {compileType} from '../utils/schema'
|
|
26
27
|
import {SlateContainer} from './components/SlateContainer'
|
|
27
28
|
import {Synchronizer} from './components/Synchronizer'
|
|
29
|
+
import {editorMachine, type EditorActor} from './editor-machine'
|
|
28
30
|
import {PortableTextEditorContext} from './hooks/usePortableTextEditor'
|
|
29
31
|
import {
|
|
30
32
|
defaultKeyGenerator,
|
|
@@ -92,6 +94,11 @@ export type PortableTextEditorProps = PropsWithChildren<{
|
|
|
92
94
|
* @public
|
|
93
95
|
*/
|
|
94
96
|
export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
97
|
+
/**
|
|
98
|
+
* @internal
|
|
99
|
+
* Don't use this API directly. It's subject to change.
|
|
100
|
+
*/
|
|
101
|
+
public editorActor: EditorActor
|
|
95
102
|
/**
|
|
96
103
|
* An observable of all the editor changes.
|
|
97
104
|
*/
|
|
@@ -118,7 +125,8 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
118
125
|
)
|
|
119
126
|
}
|
|
120
127
|
|
|
121
|
-
this.
|
|
128
|
+
this.editorActor = createActor(editorMachine)
|
|
129
|
+
this.editorActor.start()
|
|
122
130
|
|
|
123
131
|
this.schemaTypes = getPortableTextMemberSchemaTypes(
|
|
124
132
|
props.schemaType.hasOwnProperty('jsonType')
|
|
@@ -154,8 +162,7 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
154
162
|
}
|
|
155
163
|
|
|
156
164
|
render() {
|
|
157
|
-
const {
|
|
158
|
-
const {change$} = this
|
|
165
|
+
const {value, children, patches$, incomingPatches$} = this.props
|
|
159
166
|
const _patches$ = incomingPatches$ || patches$ // Backward compatibility
|
|
160
167
|
|
|
161
168
|
const maxBlocks =
|
|
@@ -176,11 +183,20 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
176
183
|
<PortableTextEditorKeyGeneratorContext.Provider value={keyGenerator}>
|
|
177
184
|
<PortableTextEditorContext.Provider value={this}>
|
|
178
185
|
<PortableTextEditorReadOnlyContext.Provider value={readOnly}>
|
|
179
|
-
<PortableTextEditorSelectionProvider
|
|
186
|
+
<PortableTextEditorSelectionProvider
|
|
187
|
+
editorActor={this.editorActor}
|
|
188
|
+
>
|
|
180
189
|
<Synchronizer
|
|
181
|
-
|
|
190
|
+
editorActor={this.editorActor}
|
|
182
191
|
getValue={this.getValue}
|
|
183
|
-
onChange={
|
|
192
|
+
onChange={(change) => {
|
|
193
|
+
this.props.onChange(change)
|
|
194
|
+
/**
|
|
195
|
+
* For backwards compatibility, we relay all changes to the
|
|
196
|
+
* `change$` Subject as well.
|
|
197
|
+
*/
|
|
198
|
+
this.change$.next(change)
|
|
199
|
+
}}
|
|
184
200
|
value={value}
|
|
185
201
|
/>
|
|
186
202
|
{children}
|
|
@@ -298,7 +314,7 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
298
314
|
) => {
|
|
299
315
|
return editor.editable?.isVoid(element)
|
|
300
316
|
}
|
|
301
|
-
static isObjectPath = (
|
|
317
|
+
static isObjectPath = (_editor: PortableTextEditor, path: Path): boolean => {
|
|
302
318
|
if (!path || !Array.isArray(path)) return false
|
|
303
319
|
const isChildObjectEditPath = path.length > 3 && path[1] === 'children'
|
|
304
320
|
const isBlockObjectEditPath = path.length > 1 && path[1] !== '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}
|