@portabletext/editor 1.1.0 → 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.
Files changed (79) hide show
  1. package/README.md +3 -0
  2. package/lib/index.d.mts +1680 -12
  3. package/lib/index.d.ts +1680 -12
  4. package/lib/index.esm.js +310 -162
  5. package/lib/index.esm.js.map +1 -1
  6. package/lib/index.js +310 -163
  7. package/lib/index.js.map +1 -1
  8. package/lib/index.mjs +310 -162
  9. package/lib/index.mjs.map +1 -1
  10. package/package.json +25 -38
  11. package/src/editor/Editable.tsx +51 -50
  12. package/src/editor/PortableTextEditor.tsx +42 -26
  13. package/src/editor/__tests__/PortableTextEditor.test.tsx +11 -12
  14. package/src/editor/__tests__/PortableTextEditorTester.tsx +2 -5
  15. package/src/editor/__tests__/RangeDecorations.test.tsx +6 -7
  16. package/src/editor/__tests__/handleClick.test.tsx +27 -7
  17. package/src/editor/__tests__/insert-block.test.tsx +6 -6
  18. package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +8 -8
  19. package/src/editor/__tests__/self-solving.test.tsx +176 -0
  20. package/src/editor/components/Element.tsx +15 -17
  21. package/src/editor/components/Leaf.tsx +40 -35
  22. package/src/editor/components/SlateContainer.tsx +2 -2
  23. package/src/editor/components/Synchronizer.tsx +62 -34
  24. package/src/editor/editor-machine.ts +195 -0
  25. package/src/editor/hooks/usePortableTextEditor.ts +1 -1
  26. package/src/editor/hooks/usePortableTextEditorSelection.tsx +12 -14
  27. package/src/editor/hooks/useSyncValue.test.tsx +9 -9
  28. package/src/editor/hooks/useSyncValue.ts +16 -19
  29. package/src/editor/nodes/DefaultAnnotation.tsx +1 -2
  30. package/src/editor/nodes/DefaultObject.tsx +1 -1
  31. package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +2 -5
  32. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +28 -28
  33. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +17 -17
  34. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +8 -8
  35. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +6 -6
  36. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +2 -2
  37. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +47 -49
  38. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +22 -11
  39. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +9 -9
  40. package/src/editor/plugins/createWithEditableAPI.ts +8 -8
  41. package/src/editor/plugins/createWithHotKeys.ts +8 -12
  42. package/src/editor/plugins/createWithInsertBreak.ts +4 -4
  43. package/src/editor/plugins/createWithInsertData.ts +11 -16
  44. package/src/editor/plugins/createWithMaxBlocks.ts +1 -1
  45. package/src/editor/plugins/createWithObjectKeys.ts +10 -3
  46. package/src/editor/plugins/createWithPatches.ts +9 -12
  47. package/src/editor/plugins/createWithPlaceholderBlock.ts +2 -2
  48. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +13 -5
  49. package/src/editor/plugins/createWithPortableTextLists.ts +3 -4
  50. package/src/editor/plugins/createWithPortableTextMarkModel.ts +24 -10
  51. package/src/editor/plugins/createWithPortableTextSelections.ts +9 -10
  52. package/src/editor/plugins/createWithSchemaTypes.ts +13 -4
  53. package/src/editor/plugins/createWithUndoRedo.ts +3 -7
  54. package/src/editor/plugins/createWithUtils.ts +6 -6
  55. package/src/editor/plugins/index.ts +21 -11
  56. package/src/index.ts +9 -3
  57. package/src/types/editor.ts +33 -33
  58. package/src/types/options.ts +3 -3
  59. package/src/types/slate.ts +4 -4
  60. package/src/utils/__tests__/dmpToOperations.test.ts +4 -4
  61. package/src/utils/__tests__/operationToPatches.test.ts +62 -62
  62. package/src/utils/__tests__/patchToOperations.test.ts +40 -40
  63. package/src/utils/__tests__/ranges.test.ts +2 -2
  64. package/src/utils/__tests__/valueNormalization.test.tsx +14 -2
  65. package/src/utils/__tests__/values.test.ts +17 -17
  66. package/src/utils/applyPatch.ts +10 -12
  67. package/src/utils/getPortableTextMemberSchemaTypes.ts +8 -8
  68. package/src/utils/operationToPatches.ts +5 -9
  69. package/src/utils/paths.ts +5 -5
  70. package/src/utils/ranges.ts +4 -5
  71. package/src/utils/selection.ts +2 -2
  72. package/src/utils/ucs2Indices.ts +2 -2
  73. package/src/utils/validateValue.ts +3 -25
  74. package/src/utils/values.ts +7 -8
  75. package/src/utils/weakMaps.ts +2 -2
  76. package/src/utils/withChanges.ts +1 -1
  77. package/src/utils/withUndoRedo.ts +1 -1
  78. package/src/utils/withoutPatching.ts +1 -1
  79. package/src/editor/__tests__/utils.ts +0 -45
@@ -0,0 +1,195 @@
1
+ import type {Patch} from '@portabletext/patches'
2
+ import type {PortableTextBlock} from '@sanity/types'
3
+ import type {FocusEvent} from 'react'
4
+ import {
5
+ assertEvent,
6
+ assign,
7
+ emit,
8
+ enqueueActions,
9
+ fromCallback,
10
+ setup,
11
+ type ActorRefFrom,
12
+ } from 'xstate'
13
+ import type {EditorSelection, InvalidValueResolution} from '../types/editor'
14
+
15
+ /**
16
+ * @internal
17
+ */
18
+ export type EditorActor = ActorRefFrom<typeof editorMachine>
19
+
20
+ const networkLogic = fromCallback(({sendBack}) => {
21
+ const onlineHandler = () => {
22
+ sendBack({type: 'online'})
23
+ }
24
+ const offlineHandler = () => {
25
+ sendBack({type: 'offline'})
26
+ }
27
+
28
+ window.addEventListener('online', onlineHandler)
29
+ window.addEventListener('offline', offlineHandler)
30
+
31
+ return () => {
32
+ window.removeEventListener('online', onlineHandler)
33
+ window.removeEventListener('offline', offlineHandler)
34
+ }
35
+ })
36
+
37
+ /**
38
+ * @internal
39
+ */
40
+ export type PatchEvent = {type: 'patch'; patch: Patch}
41
+
42
+ /**
43
+ * @internal
44
+ */
45
+ export type MutationEvent = {
46
+ type: 'mutation'
47
+ patches: Array<Patch>
48
+ snapshot: Array<PortableTextBlock> | undefined
49
+ }
50
+
51
+ type EditorEvent =
52
+ | {type: 'normalizing'}
53
+ | {type: 'done normalizing'}
54
+ | EditorEmittedEvent
55
+
56
+ type EditorEmittedEvent =
57
+ | {type: 'ready'}
58
+ | PatchEvent
59
+ | MutationEvent
60
+ | {
61
+ type: 'unset'
62
+ previousValue: Array<PortableTextBlock>
63
+ }
64
+ | {
65
+ type: 'value changed'
66
+ value: Array<PortableTextBlock> | undefined
67
+ }
68
+ | {
69
+ type: 'invalid value'
70
+ resolution: InvalidValueResolution | null
71
+ value: Array<PortableTextBlock> | undefined
72
+ }
73
+ | {
74
+ type: 'error'
75
+ name: string
76
+ description: string
77
+ data: unknown
78
+ }
79
+ | {type: 'selection'; selection: EditorSelection}
80
+ | {type: 'blur'; event: FocusEvent<HTMLDivElement, Element>}
81
+ | {type: 'focus'; event: FocusEvent<HTMLDivElement, Element>}
82
+ | {type: 'online'}
83
+ | {type: 'offline'}
84
+ | {type: 'loading'}
85
+ | {type: 'done loading'}
86
+
87
+ /**
88
+ * @internal
89
+ */
90
+ export const editorMachine = setup({
91
+ types: {
92
+ context: {} as {
93
+ pendingEvents: Array<PatchEvent | MutationEvent>
94
+ },
95
+ events: {} as EditorEvent,
96
+ emitted: {} as EditorEmittedEvent,
97
+ },
98
+ actions: {
99
+ 'emit patch event': emit(({event}) => {
100
+ assertEvent(event, 'patch')
101
+ return event
102
+ }),
103
+ 'emit mutation event': emit(({event}) => {
104
+ assertEvent(event, 'mutation')
105
+ return event
106
+ }),
107
+ 'defer event': assign({
108
+ pendingEvents: ({context, event}) => {
109
+ assertEvent(event, ['patch', 'mutation'])
110
+ return [...context.pendingEvents, event]
111
+ },
112
+ }),
113
+ 'emit pending events': enqueueActions(({context, enqueue}) => {
114
+ for (const event of context.pendingEvents) {
115
+ enqueue(emit(event))
116
+ }
117
+ }),
118
+ 'clear pending events': assign({
119
+ pendingEvents: [],
120
+ }),
121
+ },
122
+ actors: {
123
+ networkLogic,
124
+ },
125
+ }).createMachine({
126
+ id: 'editor',
127
+ context: {
128
+ pendingEvents: [],
129
+ },
130
+ invoke: {
131
+ id: 'networkLogic',
132
+ src: 'networkLogic',
133
+ },
134
+ on: {
135
+ 'ready': {actions: emit(({event}) => event)},
136
+ 'unset': {actions: emit(({event}) => event)},
137
+ 'value changed': {actions: emit(({event}) => event)},
138
+ 'invalid value': {actions: emit(({event}) => event)},
139
+ 'error': {actions: emit(({event}) => event)},
140
+ 'selection': {actions: emit(({event}) => event)},
141
+ 'blur': {actions: emit(({event}) => event)},
142
+ 'focus': {actions: emit(({event}) => event)},
143
+ 'online': {actions: emit({type: 'online'})},
144
+ 'offline': {actions: emit({type: 'offline'})},
145
+ 'loading': {actions: emit({type: 'loading'})},
146
+ 'done loading': {actions: emit({type: 'done loading'})},
147
+ },
148
+ initial: 'pristine',
149
+ states: {
150
+ pristine: {
151
+ initial: 'idle',
152
+ states: {
153
+ idle: {
154
+ on: {
155
+ normalizing: {
156
+ target: 'normalizing',
157
+ },
158
+ patch: {
159
+ actions: 'defer event',
160
+ target: '#editor.dirty',
161
+ },
162
+ mutation: {
163
+ actions: 'defer event',
164
+ target: '#editor.dirty',
165
+ },
166
+ },
167
+ },
168
+ normalizing: {
169
+ on: {
170
+ 'done normalizing': {
171
+ target: 'idle',
172
+ },
173
+ 'patch': {
174
+ actions: 'defer event',
175
+ },
176
+ 'mutation': {
177
+ actions: 'defer event',
178
+ },
179
+ },
180
+ },
181
+ },
182
+ },
183
+ dirty: {
184
+ entry: ['emit pending events', 'clear pending events'],
185
+ on: {
186
+ patch: {
187
+ actions: 'emit patch event',
188
+ },
189
+ mutation: {
190
+ actions: 'emit mutation event',
191
+ },
192
+ },
193
+ },
194
+ },
195
+ })
@@ -1,5 +1,5 @@
1
1
  import {createContext, useContext} from 'react'
2
- import {type PortableTextEditor} from '../PortableTextEditor'
2
+ import type {PortableTextEditor} from '../PortableTextEditor'
3
3
 
4
4
  /**
5
5
  * A React context for sharing the editor object.
@@ -5,8 +5,9 @@ import {
5
5
  useEffect,
6
6
  useState,
7
7
  } from 'react'
8
- import {type EditorChanges, type EditorSelection} from '../../types/editor'
8
+ import type {EditorChanges, EditorSelection} from '../../types/editor'
9
9
  import {debugWithName} from '../../utils/debug'
10
+ import type {EditorActor} from '../editor-machine'
10
11
 
11
12
  /**
12
13
  * A React context for sharing the editor selection.
@@ -36,30 +37,27 @@ const debugVerbose = debug.enabled && false
36
37
  */
37
38
  export function PortableTextEditorSelectionProvider(
38
39
  props: React.PropsWithChildren<{
39
- change$: EditorChanges
40
+ editorActor: EditorActor
40
41
  }>,
41
42
  ) {
42
- const {change$} = props
43
43
  const [selection, setSelection] = useState<EditorSelection>(null)
44
44
 
45
45
  // Subscribe to, and handle changes from the editor
46
46
  useEffect(() => {
47
- debug('Subscribing to selection changes$')
48
- const subscription = change$.subscribe((next): void => {
49
- if (next.type === 'selection') {
50
- // Set the selection state in a transition, we don't need the state immediately.
51
- startTransition(() => {
52
- if (debugVerbose) debug('Setting selection')
53
- setSelection(next.selection)
54
- })
55
- }
47
+ debug('Subscribing to selection changes')
48
+ const subscription = props.editorActor.on('selection', (event) => {
49
+ // Set the selection state in a transition, we don't need the state immediately.
50
+ startTransition(() => {
51
+ if (debugVerbose) debug('Setting selection')
52
+ setSelection(event.selection)
53
+ })
56
54
  })
57
55
 
58
56
  return () => {
59
- debug('Unsubscribing to selection changes$')
57
+ debug('Unsubscribing to selection changes')
60
58
  subscription.unsubscribe()
61
59
  }
62
- }, [change$])
60
+ }, [props.editorActor])
63
61
 
64
62
  return (
65
63
  <PortableTextEditorSelectionContext.Provider value={selection}>
@@ -1,6 +1,6 @@
1
- import {describe, expect, it, jest} from '@jest/globals'
2
1
  import {render, waitFor} from '@testing-library/react'
3
2
  import {createRef, type RefObject} from 'react'
3
+ import {describe, expect, it, vi} from 'vitest'
4
4
  import {
5
5
  PortableTextEditorTester,
6
6
  schemaType,
@@ -27,7 +27,7 @@ const initialValue = [
27
27
  describe('useSyncValue', () => {
28
28
  it('updates span text', async () => {
29
29
  const editorRef: RefObject<PortableTextEditor> = createRef()
30
- const onChange = jest.fn()
30
+ const onChange = vi.fn()
31
31
  const syncedValue = [
32
32
  {
33
33
  _key: '77071c3af231',
@@ -70,7 +70,7 @@ describe('useSyncValue', () => {
70
70
  })
71
71
  it('replaces span nodes with different keys inside the same children array', async () => {
72
72
  const editorRef: RefObject<PortableTextEditor> = createRef()
73
- const onChange = jest.fn()
73
+ const onChange = vi.fn()
74
74
  const syncedValue = [
75
75
  {
76
76
  _key: '77071c3af231',
@@ -107,19 +107,19 @@ describe('useSyncValue', () => {
107
107
  if (editorRef.current) {
108
108
  expect(PortableTextEditor.getValue(editorRef.current))
109
109
  .toMatchInlineSnapshot(`
110
- Array [
111
- Object {
110
+ [
111
+ {
112
112
  "_key": "77071c3af231",
113
113
  "_type": "myTestBlockType",
114
- "children": Array [
115
- Object {
114
+ "children": [
115
+ {
116
116
  "_key": "c001f0e92c1f0__NEW_KEY_YA!",
117
117
  "_type": "span",
118
- "marks": Array [],
118
+ "marks": [],
119
119
  "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ",
120
120
  },
121
121
  ],
122
- "markDefs": Array [],
122
+ "markDefs": [],
123
123
  "style": "normal",
124
124
  },
125
125
  ]
@@ -1,13 +1,9 @@
1
- /* eslint-disable max-nested-callbacks */
2
- import {type PortableTextBlock} from '@sanity/types'
1
+ import type {PortableTextBlock} from '@sanity/types'
3
2
  import {debounce, isEqual} from 'lodash'
4
3
  import {useCallback, useMemo, useRef} from 'react'
5
4
  import {Editor, Text, Transforms, type Descendant, type Node} from 'slate'
6
5
  import {useSlate} from 'slate-react'
7
- import {
8
- type EditorChange,
9
- type PortableTextSlateEditor,
10
- } from '../../types/editor'
6
+ import type {PortableTextSlateEditor} from '../../types/editor'
11
7
  import {debugWithName} from '../../utils/debug'
12
8
  import {validateValue} from '../../utils/validateValue'
13
9
  import {toSlateValue, VOID_CHILD_KEY} from '../../utils/values'
@@ -17,8 +13,9 @@ import {
17
13
  withRemoteChanges,
18
14
  } from '../../utils/withChanges'
19
15
  import {withoutPatching} from '../../utils/withoutPatching'
16
+ import type {EditorActor} from '../editor-machine'
20
17
  import {withoutSaving} from '../plugins/createWithUndoRedo'
21
- import {type PortableTextEditor} from '../PortableTextEditor'
18
+ import type {PortableTextEditor} from '../PortableTextEditor'
22
19
 
23
20
  const debug = debugWithName('hook:useSyncValue')
24
21
 
@@ -26,8 +23,8 @@ const debug = debugWithName('hook:useSyncValue')
26
23
  * @internal
27
24
  */
28
25
  export interface UseSyncValueProps {
26
+ editorActor: EditorActor
29
27
  keyGenerator: () => string
30
- onChange: (change: EditorChange) => void
31
28
  portableTextEditor: PortableTextEditor
32
29
  readOnly: boolean
33
30
  }
@@ -55,8 +52,8 @@ export function useSyncValue(
55
52
  value: PortableTextBlock[] | undefined,
56
53
  userCallbackFn?: () => void,
57
54
  ) => void {
58
- const {portableTextEditor, readOnly, keyGenerator} = props
59
- const {change$, schemaTypes} = portableTextEditor
55
+ const {editorActor, portableTextEditor, readOnly, keyGenerator} = props
56
+ const {schemaTypes} = portableTextEditor
60
57
  const previousValue = useRef<PortableTextBlock[] | undefined>()
61
58
  const slateEditor = useSlate()
62
59
  const updateValueFunctionRef =
@@ -184,7 +181,7 @@ export function useSyncValue(
184
181
  `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`,
185
182
  )
186
183
  validation.resolution.patches.forEach((patch) => {
187
- change$.next({type: 'patch', patch})
184
+ editorActor.send({type: 'patch', patch})
188
185
  })
189
186
  }
190
187
  }
@@ -212,8 +209,8 @@ export function useSyncValue(
212
209
  }
213
210
  isChanged = true
214
211
  } else {
215
- change$.next({
216
- type: 'invalidValue',
212
+ editorActor.send({
213
+ type: 'invalid value',
217
214
  resolution: validation.resolution,
218
215
  value,
219
216
  })
@@ -241,8 +238,8 @@ export function useSyncValue(
241
238
  })
242
239
  } else {
243
240
  debug('Invalid', validation)
244
- change$.next({
245
- type: 'invalidValue',
241
+ editorActor.send({
242
+ type: 'invalid value',
246
243
  resolution: validation.resolution,
247
244
  value,
248
245
  })
@@ -267,8 +264,8 @@ export function useSyncValue(
267
264
  slateEditor.onChange()
268
265
  } catch (err) {
269
266
  console.error(err)
270
- change$.next({
271
- type: 'invalidValue',
267
+ editorActor.send({
268
+ type: 'invalid value',
272
269
  resolution: null,
273
270
  value,
274
271
  })
@@ -281,7 +278,7 @@ export function useSyncValue(
281
278
  })
282
279
  slateEditor.onChange()
283
280
  }
284
- change$.next({type: 'value', value})
281
+ editorActor.send({type: 'value changed', value})
285
282
  } else {
286
283
  debug('Server value and editor value is equal, no need to sync.')
287
284
  }
@@ -290,7 +287,7 @@ export function useSyncValue(
290
287
  updateValueFunctionRef.current = updateFunction
291
288
  return updateFunction
292
289
  }, [
293
- change$,
290
+ editorActor,
294
291
  keyGenerator,
295
292
  portableTextEditor,
296
293
  readOnly,
@@ -1,4 +1,4 @@
1
- import {type PortableTextObject} from '@sanity/types'
1
+ import type {PortableTextObject} from '@sanity/types'
2
2
  import {useCallback, type ReactNode} from 'react'
3
3
 
4
4
  type Props = {
@@ -7,7 +7,6 @@ type Props = {
7
7
  }
8
8
  export function DefaultAnnotation(props: Props) {
9
9
  const handleClick = useCallback(
10
- // eslint-disable-next-line no-alert
11
10
  () => alert(JSON.stringify(props.annotation)),
12
11
  [props.annotation],
13
12
  )
@@ -1,4 +1,4 @@
1
- import {type PortableTextBlock, type PortableTextChild} from '@sanity/types'
1
+ import type {PortableTextBlock, PortableTextChild} from '@sanity/types'
2
2
 
3
3
  type Props = {
4
4
  value: PortableTextBlock | PortableTextChild
@@ -1,6 +1,6 @@
1
- import {describe, expect, it} from '@jest/globals'
2
1
  import {isPortableTextSpan, isPortableTextTextBlock} from '@sanity/types'
3
- import {type Descendant} from 'slate'
2
+ import type {Descendant} from 'slate'
3
+ import {describe, expect, it} from 'vitest'
4
4
  import {exportedForTesting} from '../createWithInsertData'
5
5
 
6
6
  const initialValue = [
@@ -60,14 +60,12 @@ describe('plugin: createWithInsertData _regenerateKeys', () => {
60
60
  name: 'color',
61
61
  jsonType: 'object',
62
62
  fields: [],
63
- // eslint-disable-next-line camelcase
64
63
  __experimental_search: [],
65
64
  },
66
65
  {
67
66
  name: 'link',
68
67
  jsonType: 'object',
69
68
  fields: [],
70
- // eslint-disable-next-line camelcase
71
69
  __experimental_search: [],
72
70
  },
73
71
  ],
@@ -155,7 +153,6 @@ describe('plugin: createWithInsertData _regenerateKeys', () => {
155
153
  name: 'color',
156
154
  jsonType: 'object',
157
155
  fields: [],
158
- // eslint-disable-next-line camelcase
159
156
  __experimental_search: [],
160
157
  },
161
158
  ],
@@ -1,6 +1,6 @@
1
- import {describe, expect, it, jest} from '@jest/globals'
2
1
  import {render, waitFor} from '@testing-library/react'
3
2
  import {createRef, type RefObject} from 'react'
3
+ import {describe, expect, it, vi} from 'vitest'
4
4
  import {
5
5
  PortableTextEditorTester,
6
6
  schemaType,
@@ -46,7 +46,7 @@ const initialSelection = {
46
46
  describe('plugin:withEditableAPI: .delete()', () => {
47
47
  it('deletes block', async () => {
48
48
  const editorRef: RefObject<PortableTextEditor> = createRef()
49
- const onChange = jest.fn()
49
+ const onChange = vi.fn()
50
50
  render(
51
51
  <PortableTextEditorTester
52
52
  onChange={onChange}
@@ -77,19 +77,19 @@ describe('plugin:withEditableAPI: .delete()', () => {
77
77
  )
78
78
  expect(PortableTextEditor.getValue(editorRef.current))
79
79
  .toMatchInlineSnapshot(`
80
- Array [
81
- Object {
80
+ [
81
+ {
82
82
  "_key": "a",
83
83
  "_type": "myTestBlockType",
84
- "children": Array [
85
- Object {
84
+ "children": [
85
+ {
86
86
  "_key": "a1",
87
87
  "_type": "span",
88
- "marks": Array [],
88
+ "marks": [],
89
89
  "text": "Block A",
90
90
  },
91
91
  ],
92
- "markDefs": Array [],
92
+ "markDefs": [],
93
93
  "style": "normal",
94
94
  },
95
95
  ]
@@ -100,7 +100,7 @@ describe('plugin:withEditableAPI: .delete()', () => {
100
100
 
101
101
  it('deletes all the blocks, but leaves a placeholder block', async () => {
102
102
  const editorRef: RefObject<PortableTextEditor> = createRef()
103
- const onChange = jest.fn()
103
+ const onChange = vi.fn()
104
104
  render(
105
105
  <PortableTextEditorTester
106
106
  onChange={onChange}
@@ -135,19 +135,19 @@ describe('plugin:withEditableAPI: .delete()', () => {
135
135
  // New keys here confirms that a placeholder block has been created
136
136
  expect(PortableTextEditor.getValue(editorRef.current))
137
137
  .toMatchInlineSnapshot(`
138
- Array [
139
- Object {
138
+ [
139
+ {
140
140
  "_key": "1",
141
141
  "_type": "myTestBlockType",
142
- "children": Array [
143
- Object {
142
+ "children": [
143
+ {
144
144
  "_key": "2",
145
145
  "_type": "span",
146
- "marks": Array [],
146
+ "marks": [],
147
147
  "text": "",
148
148
  },
149
149
  ],
150
- "markDefs": Array [],
150
+ "markDefs": [],
151
151
  "style": "normal",
152
152
  },
153
153
  ]
@@ -158,7 +158,7 @@ describe('plugin:withEditableAPI: .delete()', () => {
158
158
 
159
159
  it('deletes children', async () => {
160
160
  const editorRef: RefObject<PortableTextEditor> = createRef()
161
- const onChange = jest.fn()
161
+ const onChange = vi.fn()
162
162
 
163
163
  render(
164
164
  <PortableTextEditorTester
@@ -202,33 +202,33 @@ describe('plugin:withEditableAPI: .delete()', () => {
202
202
  if (editorRef.current) {
203
203
  expect(PortableTextEditor.getValue(editorRef.current))
204
204
  .toMatchInlineSnapshot(`
205
- Array [
206
- Object {
205
+ [
206
+ {
207
207
  "_key": "a",
208
208
  "_type": "myTestBlockType",
209
- "children": Array [
210
- Object {
209
+ "children": [
210
+ {
211
211
  "_key": "a1",
212
212
  "_type": "span",
213
- "marks": Array [],
213
+ "marks": [],
214
214
  "text": "Block A",
215
215
  },
216
216
  ],
217
- "markDefs": Array [],
217
+ "markDefs": [],
218
218
  "style": "normal",
219
219
  },
220
- Object {
220
+ {
221
221
  "_key": "b",
222
222
  "_type": "myTestBlockType",
223
- "children": Array [
224
- Object {
223
+ "children": [
224
+ {
225
225
  "_key": "1",
226
226
  "_type": "span",
227
- "marks": Array [],
227
+ "marks": [],
228
228
  "text": "",
229
229
  },
230
230
  ],
231
- "markDefs": Array [],
231
+ "markDefs": [],
232
232
  "style": "normal",
233
233
  },
234
234
  ]
@@ -239,7 +239,7 @@ describe('plugin:withEditableAPI: .delete()', () => {
239
239
 
240
240
  it('deletes selected', async () => {
241
241
  const editorRef: RefObject<PortableTextEditor> = createRef()
242
- const onChange = jest.fn()
242
+ const onChange = vi.fn()
243
243
 
244
244
  render(
245
245
  <PortableTextEditorTester