@portabletext/editor 1.0.19 → 1.1.1

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 (76) hide show
  1. package/lib/index.d.mts +142 -67
  2. package/lib/index.d.ts +142 -67
  3. package/lib/index.esm.js +1130 -371
  4. package/lib/index.esm.js.map +1 -1
  5. package/lib/index.js +1130 -371
  6. package/lib/index.js.map +1 -1
  7. package/lib/index.mjs +1130 -371
  8. package/lib/index.mjs.map +1 -1
  9. package/package.json +4 -18
  10. package/src/editor/Editable.tsx +128 -55
  11. package/src/editor/PortableTextEditor.tsx +66 -32
  12. package/src/editor/__tests__/PortableTextEditor.test.tsx +44 -18
  13. package/src/editor/__tests__/PortableTextEditorTester.tsx +50 -38
  14. package/src/editor/__tests__/RangeDecorations.test.tsx +4 -6
  15. package/src/editor/__tests__/handleClick.test.tsx +28 -9
  16. package/src/editor/__tests__/insert-block.test.tsx +24 -8
  17. package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +31 -63
  18. package/src/editor/__tests__/utils.ts +10 -4
  19. package/src/editor/components/DraggableBlock.tsx +36 -13
  20. package/src/editor/components/Element.tsx +73 -33
  21. package/src/editor/components/Leaf.tsx +114 -76
  22. package/src/editor/components/SlateContainer.tsx +14 -7
  23. package/src/editor/components/Synchronizer.tsx +8 -5
  24. package/src/editor/hooks/usePortableTextEditor.ts +3 -3
  25. package/src/editor/hooks/usePortableTextEditorSelection.tsx +10 -4
  26. package/src/editor/hooks/useSyncValue.test.tsx +9 -4
  27. package/src/editor/hooks/useSyncValue.ts +198 -133
  28. package/src/editor/nodes/DefaultAnnotation.tsx +6 -4
  29. package/src/editor/nodes/DefaultObject.tsx +1 -1
  30. package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +23 -8
  31. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +26 -9
  32. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +15 -5
  33. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +60 -19
  34. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +5 -3
  35. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +4 -2
  36. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +61 -19
  37. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +6 -3
  38. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +30 -13
  39. package/src/editor/plugins/createWithEditableAPI.ts +361 -131
  40. package/src/editor/plugins/createWithHotKeys.ts +46 -130
  41. package/src/editor/plugins/createWithInsertBreak.ts +167 -28
  42. package/src/editor/plugins/createWithInsertData.ts +66 -30
  43. package/src/editor/plugins/createWithMaxBlocks.ts +6 -3
  44. package/src/editor/plugins/createWithObjectKeys.ts +7 -3
  45. package/src/editor/plugins/createWithPatches.ts +66 -24
  46. package/src/editor/plugins/createWithPlaceholderBlock.ts +9 -5
  47. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +17 -7
  48. package/src/editor/plugins/createWithPortableTextLists.ts +21 -9
  49. package/src/editor/plugins/createWithPortableTextMarkModel.ts +217 -52
  50. package/src/editor/plugins/createWithPortableTextSelections.ts +11 -9
  51. package/src/editor/plugins/createWithSchemaTypes.ts +26 -10
  52. package/src/editor/plugins/createWithUndoRedo.ts +106 -27
  53. package/src/editor/plugins/createWithUtils.ts +33 -11
  54. package/src/editor/plugins/index.ts +34 -13
  55. package/src/types/editor.ts +73 -44
  56. package/src/types/options.ts +7 -5
  57. package/src/types/slate.ts +6 -6
  58. package/src/utils/__tests__/dmpToOperations.test.ts +41 -16
  59. package/src/utils/__tests__/operationToPatches.test.ts +4 -3
  60. package/src/utils/__tests__/patchToOperations.test.ts +16 -5
  61. package/src/utils/__tests__/ranges.test.ts +9 -4
  62. package/src/utils/__tests__/valueNormalization.test.tsx +12 -4
  63. package/src/utils/__tests__/values.test.ts +0 -1
  64. package/src/utils/applyPatch.ts +78 -29
  65. package/src/utils/getPortableTextMemberSchemaTypes.ts +38 -23
  66. package/src/utils/operationToPatches.ts +123 -44
  67. package/src/utils/paths.ts +26 -9
  68. package/src/utils/ranges.ts +16 -10
  69. package/src/utils/selection.ts +21 -9
  70. package/src/utils/ucs2Indices.ts +2 -2
  71. package/src/utils/validateValue.ts +118 -45
  72. package/src/utils/values.ts +38 -17
  73. package/src/utils/weakMaps.ts +20 -10
  74. package/src/utils/withChanges.ts +5 -3
  75. package/src/utils/withUndoRedo.ts +1 -1
  76. package/src/utils/withoutPatching.ts +1 -1
@@ -1,8 +1,10 @@
1
1
  import {describe, expect, it, jest} from '@jest/globals'
2
2
  import {render, waitFor} from '@testing-library/react'
3
3
  import {createRef, type RefObject} from 'react'
4
-
5
- import {PortableTextEditorTester, schemaType} from '../__tests__/PortableTextEditorTester'
4
+ import {
5
+ PortableTextEditorTester,
6
+ schemaType,
7
+ } from '../__tests__/PortableTextEditorTester'
6
8
  import {PortableTextEditor} from '../PortableTextEditor'
7
9
 
8
10
  const initialValue = [
@@ -60,7 +62,9 @@ describe('useSyncValue', () => {
60
62
  )
61
63
  await waitFor(() => {
62
64
  if (editorRef.current) {
63
- expect(PortableTextEditor.getValue(editorRef.current)).toEqual(syncedValue)
65
+ expect(PortableTextEditor.getValue(editorRef.current)).toEqual(
66
+ syncedValue,
67
+ )
64
68
  }
65
69
  })
66
70
  })
@@ -101,7 +105,8 @@ describe('useSyncValue', () => {
101
105
  )
102
106
  await waitFor(() => {
103
107
  if (editorRef.current) {
104
- expect(PortableTextEditor.getValue(editorRef.current)).toMatchInlineSnapshot(`
108
+ expect(PortableTextEditor.getValue(editorRef.current))
109
+ .toMatchInlineSnapshot(`
105
110
  Array [
106
111
  Object {
107
112
  "_key": "77071c3af231",
@@ -1,18 +1,20 @@
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
- import {type Descendant, Editor, type Node, Text, Transforms} from 'slate'
4
+ import {Editor, Text, Transforms, type Descendant, type Node} from 'slate'
6
5
  import {useSlate} from 'slate-react'
7
-
8
- import {type EditorChange, type PortableTextSlateEditor} from '../../types/editor'
6
+ import type {EditorChange, PortableTextSlateEditor} from '../../types/editor'
9
7
  import {debugWithName} from '../../utils/debug'
10
8
  import {validateValue} from '../../utils/validateValue'
11
9
  import {toSlateValue, VOID_CHILD_KEY} from '../../utils/values'
12
- import {isChangingLocally, isChangingRemotely, withRemoteChanges} from '../../utils/withChanges'
10
+ import {
11
+ isChangingLocally,
12
+ isChangingRemotely,
13
+ withRemoteChanges,
14
+ } from '../../utils/withChanges'
13
15
  import {withoutPatching} from '../../utils/withoutPatching'
14
16
  import {withoutSaving} from '../plugins/createWithUndoRedo'
15
- import {type PortableTextEditor} from '../PortableTextEditor'
17
+ import type {PortableTextEditor} from '../PortableTextEditor'
16
18
 
17
19
  const debug = debugWithName('hook:useSyncValue')
18
20
 
@@ -26,7 +28,10 @@ export interface UseSyncValueProps {
26
28
  readOnly: boolean
27
29
  }
28
30
 
29
- const CURRENT_VALUE = new WeakMap<PortableTextEditor, PortableTextBlock[] | undefined>()
31
+ const CURRENT_VALUE = new WeakMap<
32
+ PortableTextEditor,
33
+ PortableTextBlock[] | undefined
34
+ >()
30
35
 
31
36
  /**
32
37
  * Sync value with the editor state
@@ -42,12 +47,16 @@ const CURRENT_VALUE = new WeakMap<PortableTextEditor, PortableTextBlock[] | unde
42
47
  */
43
48
  export function useSyncValue(
44
49
  props: UseSyncValueProps,
45
- ): (value: PortableTextBlock[] | undefined, userCallbackFn?: () => void) => void {
50
+ ): (
51
+ value: PortableTextBlock[] | undefined,
52
+ userCallbackFn?: () => void,
53
+ ) => void {
46
54
  const {portableTextEditor, readOnly, keyGenerator} = props
47
55
  const {change$, schemaTypes} = portableTextEditor
48
56
  const previousValue = useRef<PortableTextBlock[] | undefined>()
49
57
  const slateEditor = useSlate()
50
- const updateValueFunctionRef = useRef<(value: PortableTextBlock[] | undefined) => void>()
58
+ const updateValueFunctionRef =
59
+ useRef<(value: PortableTextBlock[] | undefined) => void>()
51
60
 
52
61
  const updateFromCurrentValue = useCallback(() => {
53
62
  const currentValue = CURRENT_VALUE.get(portableTextEditor)
@@ -61,7 +70,8 @@ export function useSyncValue(
61
70
  }
62
71
  }, [portableTextEditor])
63
72
  const updateValueDebounced = useMemo(
64
- () => debounce(updateFromCurrentValue, 1000, {trailing: true, leading: false}),
73
+ () =>
74
+ debounce(updateFromCurrentValue, 1000, {trailing: true, leading: false}),
65
75
  [updateFromCurrentValue],
66
76
  )
67
77
 
@@ -103,7 +113,11 @@ export function useSyncValue(
103
113
  at: [childrenLength - 1 - index],
104
114
  })
105
115
  })
106
- Transforms.insertNodes(slateEditor, slateEditor.pteCreateEmptyBlock(), {at: [0]})
116
+ Transforms.insertNodes(
117
+ slateEditor,
118
+ slateEditor.pteCreateTextBlock({decorators: []}),
119
+ {at: [0]},
120
+ )
107
121
  // Add a new selection in the top of the document
108
122
  if (hadSelection) {
109
123
  Transforms.select(slateEditor, [0, 0])
@@ -125,7 +139,11 @@ export function useSyncValue(
125
139
  const childrenLength = slateEditor.children.length
126
140
  // Remove blocks that have become superfluous
127
141
  if (slateValueFromProps.length < childrenLength) {
128
- for (let i = childrenLength - 1; i > slateValueFromProps.length - 1; i--) {
142
+ for (
143
+ let i = childrenLength - 1;
144
+ i > slateValueFromProps.length - 1;
145
+ i--
146
+ ) {
129
147
  Transforms.removeNodes(slateEditor, {
130
148
  at: [i],
131
149
  })
@@ -133,70 +151,102 @@ export function useSyncValue(
133
151
  isChanged = true
134
152
  }
135
153
  // Go through all of the blocks and see if they need to be updated
136
- slateValueFromProps.forEach((currentBlock, currentBlockIndex) => {
137
- const oldBlock = slateEditor.children[currentBlockIndex]
138
- const hasChanges = oldBlock && !isEqual(currentBlock, oldBlock)
139
- if (hasChanges && isValid) {
140
- const validationValue = [value[currentBlockIndex]]
141
- const validation = validateValue(validationValue, schemaTypes, keyGenerator)
142
- // Resolve validations that can be resolved automatically, without involving the user (but only if the value was changed)
143
- if (
144
- !validation.valid &&
145
- validation.resolution?.autoResolve &&
146
- validation.resolution?.patches.length > 0
147
- ) {
148
- // Only apply auto resolution if the value has been populated before and is different from the last one.
149
- if (!readOnly && previousValue.current && previousValue.current !== value) {
150
- // Give a console warning about the fact that it did an auto resolution
151
- console.warn(
152
- `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`,
153
- )
154
- validation.resolution.patches.forEach((patch) => {
155
- change$.next({type: 'patch', patch})
156
- })
154
+ slateValueFromProps.forEach(
155
+ (currentBlock, currentBlockIndex) => {
156
+ const oldBlock = slateEditor.children[currentBlockIndex]
157
+ const hasChanges =
158
+ oldBlock && !isEqual(currentBlock, oldBlock)
159
+ if (hasChanges && isValid) {
160
+ const validationValue = [value[currentBlockIndex]]
161
+ const validation = validateValue(
162
+ validationValue,
163
+ schemaTypes,
164
+ keyGenerator,
165
+ )
166
+ // Resolve validations that can be resolved automatically, without involving the user (but only if the value was changed)
167
+ if (
168
+ !validation.valid &&
169
+ validation.resolution?.autoResolve &&
170
+ validation.resolution?.patches.length > 0
171
+ ) {
172
+ // Only apply auto resolution if the value has been populated before and is different from the last one.
173
+ if (
174
+ !readOnly &&
175
+ previousValue.current &&
176
+ previousValue.current !== value
177
+ ) {
178
+ // Give a console warning about the fact that it did an auto resolution
179
+ console.warn(
180
+ `${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`,
181
+ )
182
+ validation.resolution.patches.forEach((patch) => {
183
+ change$.next({type: 'patch', patch})
184
+ })
185
+ }
157
186
  }
158
- }
159
- if (validation.valid || validation.resolution?.autoResolve) {
160
- if (oldBlock._key === currentBlock._key) {
161
- if (debug.enabled) debug('Updating block', oldBlock, currentBlock)
162
- _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex)
187
+ if (
188
+ validation.valid ||
189
+ validation.resolution?.autoResolve
190
+ ) {
191
+ if (oldBlock._key === currentBlock._key) {
192
+ if (debug.enabled)
193
+ debug('Updating block', oldBlock, currentBlock)
194
+ _updateBlock(
195
+ slateEditor,
196
+ currentBlock,
197
+ oldBlock,
198
+ currentBlockIndex,
199
+ )
200
+ } else {
201
+ if (debug.enabled)
202
+ debug('Replacing block', oldBlock, currentBlock)
203
+ _replaceBlock(
204
+ slateEditor,
205
+ currentBlock,
206
+ currentBlockIndex,
207
+ )
208
+ }
209
+ isChanged = true
163
210
  } else {
164
- if (debug.enabled) debug('Replacing block', oldBlock, currentBlock)
165
- _replaceBlock(slateEditor, currentBlock, currentBlockIndex)
211
+ change$.next({
212
+ type: 'invalidValue',
213
+ resolution: validation.resolution,
214
+ value,
215
+ })
216
+ isValid = false
166
217
  }
167
- isChanged = true
168
- } else {
169
- change$.next({
170
- type: 'invalidValue',
171
- resolution: validation.resolution,
172
- value,
173
- })
174
- isValid = false
175
218
  }
176
- }
177
- if (!oldBlock && isValid) {
178
- const validationValue = [value[currentBlockIndex]]
179
- const validation = validateValue(validationValue, schemaTypes, keyGenerator)
180
- if (debug.enabled)
181
- debug(
182
- 'Validating and inserting new block in the end of the value',
183
- currentBlock,
219
+ if (!oldBlock && isValid) {
220
+ const validationValue = [value[currentBlockIndex]]
221
+ const validation = validateValue(
222
+ validationValue,
223
+ schemaTypes,
224
+ keyGenerator,
184
225
  )
185
- if (validation.valid || validation.resolution?.autoResolve) {
186
- Transforms.insertNodes(slateEditor, currentBlock, {
187
- at: [currentBlockIndex],
188
- })
189
- } else {
190
- debug('Invalid', validation)
191
- change$.next({
192
- type: 'invalidValue',
193
- resolution: validation.resolution,
194
- value,
195
- })
196
- isValid = false
226
+ if (debug.enabled)
227
+ debug(
228
+ 'Validating and inserting new block in the end of the value',
229
+ currentBlock,
230
+ )
231
+ if (
232
+ validation.valid ||
233
+ validation.resolution?.autoResolve
234
+ ) {
235
+ Transforms.insertNodes(slateEditor, currentBlock, {
236
+ at: [currentBlockIndex],
237
+ })
238
+ } else {
239
+ debug('Invalid', validation)
240
+ change$.next({
241
+ type: 'invalidValue',
242
+ resolution: validation.resolution,
243
+ value,
244
+ })
245
+ isValid = false
246
+ }
197
247
  }
198
- }
199
- })
248
+ },
249
+ )
200
250
  })
201
251
  })
202
252
  })
@@ -286,78 +336,93 @@ function _updateBlock(
286
336
  at: [currentBlockIndex],
287
337
  })
288
338
  // Text block's need to have their children updated as well (setNode does not target a node's children)
289
- if (slateEditor.isTextBlock(currentBlock) && slateEditor.isTextBlock(oldBlock)) {
339
+ if (
340
+ slateEditor.isTextBlock(currentBlock) &&
341
+ slateEditor.isTextBlock(oldBlock)
342
+ ) {
290
343
  const oldBlockChildrenLength = oldBlock.children.length
291
344
  if (currentBlock.children.length < oldBlockChildrenLength) {
292
345
  // Remove any children that have become superfluous
293
- Array.from(Array(oldBlockChildrenLength - currentBlock.children.length)).forEach(
294
- (_, index) => {
295
- const childIndex = oldBlockChildrenLength - 1 - index
296
- if (childIndex > 0) {
297
- debug('Removing child')
298
- Transforms.removeNodes(slateEditor, {
299
- at: [currentBlockIndex, childIndex],
300
- })
301
- }
302
- },
303
- )
304
- }
305
- currentBlock.children.forEach((currentBlockChild, currentBlockChildIndex) => {
306
- const oldBlockChild = oldBlock.children[currentBlockChildIndex]
307
- const isChildChanged = !isEqual(currentBlockChild, oldBlockChild)
308
- const isTextChanged = !isEqual(currentBlockChild.text, oldBlockChild?.text)
309
- const path = [currentBlockIndex, currentBlockChildIndex]
310
- if (isChildChanged) {
311
- // Update if this is the same child
312
- if (currentBlockChild._key === oldBlockChild?._key) {
313
- debug('Updating changed child', currentBlockChild, oldBlockChild)
314
- Transforms.setNodes(slateEditor, currentBlockChild as Partial<Node>, {
315
- at: path,
346
+ Array.from(
347
+ Array(oldBlockChildrenLength - currentBlock.children.length),
348
+ ).forEach((_, index) => {
349
+ const childIndex = oldBlockChildrenLength - 1 - index
350
+ if (childIndex > 0) {
351
+ debug('Removing child')
352
+ Transforms.removeNodes(slateEditor, {
353
+ at: [currentBlockIndex, childIndex],
316
354
  })
317
- const isSpanNode =
318
- Text.isText(currentBlockChild) &&
319
- currentBlockChild._type === 'span' &&
320
- Text.isText(oldBlockChild) &&
321
- oldBlockChild._type === 'span'
322
- if (isSpanNode && isTextChanged) {
323
- Transforms.delete(slateEditor, {
324
- at: {focus: {path, offset: 0}, anchor: {path, offset: oldBlockChild.text.length}},
325
- })
326
- Transforms.insertText(slateEditor, currentBlockChild.text, {
327
- at: path,
328
- })
329
- slateEditor.onChange()
330
- } else if (!isSpanNode) {
331
- // If it's a inline block, also update the void text node key
332
- debug('Updating changed inline object child', currentBlockChild)
355
+ }
356
+ })
357
+ }
358
+ currentBlock.children.forEach(
359
+ (currentBlockChild, currentBlockChildIndex) => {
360
+ const oldBlockChild = oldBlock.children[currentBlockChildIndex]
361
+ const isChildChanged = !isEqual(currentBlockChild, oldBlockChild)
362
+ const isTextChanged = !isEqual(
363
+ currentBlockChild.text,
364
+ oldBlockChild?.text,
365
+ )
366
+ const path = [currentBlockIndex, currentBlockChildIndex]
367
+ if (isChildChanged) {
368
+ // Update if this is the same child
369
+ if (currentBlockChild._key === oldBlockChild?._key) {
370
+ debug('Updating changed child', currentBlockChild, oldBlockChild)
333
371
  Transforms.setNodes(
334
372
  slateEditor,
335
- {_key: VOID_CHILD_KEY},
373
+ currentBlockChild as Partial<Node>,
336
374
  {
337
- at: [...path, 0],
338
- voids: true,
375
+ at: path,
339
376
  },
340
377
  )
378
+ const isSpanNode =
379
+ Text.isText(currentBlockChild) &&
380
+ currentBlockChild._type === 'span' &&
381
+ Text.isText(oldBlockChild) &&
382
+ oldBlockChild._type === 'span'
383
+ if (isSpanNode && isTextChanged) {
384
+ Transforms.delete(slateEditor, {
385
+ at: {
386
+ focus: {path, offset: 0},
387
+ anchor: {path, offset: oldBlockChild.text.length},
388
+ },
389
+ })
390
+ Transforms.insertText(slateEditor, currentBlockChild.text, {
391
+ at: path,
392
+ })
393
+ slateEditor.onChange()
394
+ } else if (!isSpanNode) {
395
+ // If it's a inline block, also update the void text node key
396
+ debug('Updating changed inline object child', currentBlockChild)
397
+ Transforms.setNodes(
398
+ slateEditor,
399
+ {_key: VOID_CHILD_KEY},
400
+ {
401
+ at: [...path, 0],
402
+ voids: true,
403
+ },
404
+ )
405
+ }
406
+ // Replace the child if _key's are different
407
+ } else if (oldBlockChild) {
408
+ debug('Replacing child', currentBlockChild)
409
+ Transforms.removeNodes(slateEditor, {
410
+ at: [currentBlockIndex, currentBlockChildIndex],
411
+ })
412
+ Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
413
+ at: [currentBlockIndex, currentBlockChildIndex],
414
+ })
415
+ slateEditor.onChange()
416
+ // Insert it if it didn't exist before
417
+ } else if (!oldBlockChild) {
418
+ debug('Inserting new child', currentBlockChild)
419
+ Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
420
+ at: [currentBlockIndex, currentBlockChildIndex],
421
+ })
422
+ slateEditor.onChange()
341
423
  }
342
- // Replace the child if _key's are different
343
- } else if (oldBlockChild) {
344
- debug('Replacing child', currentBlockChild)
345
- Transforms.removeNodes(slateEditor, {
346
- at: [currentBlockIndex, currentBlockChildIndex],
347
- })
348
- Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
349
- at: [currentBlockIndex, currentBlockChildIndex],
350
- })
351
- slateEditor.onChange()
352
- // Insert it if it didn't exist before
353
- } else if (!oldBlockChild) {
354
- debug('Inserting new child', currentBlockChild)
355
- Transforms.insertNodes(slateEditor, currentBlockChild as Node, {
356
- at: [currentBlockIndex, currentBlockChildIndex],
357
- })
358
- slateEditor.onChange()
359
424
  }
360
- }
361
- })
425
+ },
426
+ )
362
427
  }
363
428
  }
@@ -1,13 +1,15 @@
1
- import {type PortableTextObject} from '@sanity/types'
2
- import {type ReactNode, useCallback} from 'react'
1
+ import type {PortableTextObject} from '@sanity/types'
2
+ import {useCallback, type ReactNode} from 'react'
3
3
 
4
4
  type Props = {
5
5
  annotation: PortableTextObject
6
6
  children: ReactNode
7
7
  }
8
8
  export function DefaultAnnotation(props: Props) {
9
- // eslint-disable-next-line no-alert
10
- const handleClick = useCallback(() => alert(JSON.stringify(props.annotation)), [props.annotation])
9
+ const handleClick = useCallback(
10
+ () => alert(JSON.stringify(props.annotation)),
11
+ [props.annotation],
12
+ )
11
13
  return (
12
14
  <span style={{color: 'blue'}} onClick={handleClick}>
13
15
  {props.children}
@@ -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,7 +1,6 @@
1
1
  import {describe, expect, it} from '@jest/globals'
2
2
  import {isPortableTextSpan, isPortableTextTextBlock} from '@sanity/types'
3
- import {type Descendant} from 'slate'
4
-
3
+ import type {Descendant} from 'slate'
5
4
  import {exportedForTesting} from '../createWithInsertData'
6
5
 
7
6
  const initialValue = [
@@ -57,10 +56,18 @@ describe('plugin: createWithInsertData _regenerateKeys', () => {
57
56
  'span',
58
57
  {
59
58
  annotations: [
60
- // eslint-disable-next-line camelcase
61
- {name: 'color', jsonType: 'object', fields: [], __experimental_search: []},
62
- // eslint-disable-next-line camelcase
63
- {name: 'link', jsonType: 'object', fields: [], __experimental_search: []},
59
+ {
60
+ name: 'color',
61
+ jsonType: 'object',
62
+ fields: [],
63
+ __experimental_search: [],
64
+ },
65
+ {
66
+ name: 'link',
67
+ jsonType: 'object',
68
+ fields: [],
69
+ __experimental_search: [],
70
+ },
64
71
  ],
65
72
  },
66
73
  )
@@ -140,8 +147,16 @@ describe('plugin: createWithInsertData _regenerateKeys', () => {
140
147
  return `k${keyCursor}`
141
148
  },
142
149
  'span',
143
- // eslint-disable-next-line camelcase
144
- {annotations: [{name: 'color', jsonType: 'object', fields: [], __experimental_search: []}]},
150
+ {
151
+ annotations: [
152
+ {
153
+ name: 'color',
154
+ jsonType: 'object',
155
+ fields: [],
156
+ __experimental_search: [],
157
+ },
158
+ ],
159
+ },
145
160
  )
146
161
 
147
162
  // orphaned children marks are removed later in the normalize function
@@ -1,8 +1,10 @@
1
1
  import {describe, expect, it, jest} from '@jest/globals'
2
2
  import {render, waitFor} from '@testing-library/react'
3
3
  import {createRef, type RefObject} from 'react'
4
-
5
- import {PortableTextEditorTester, schemaType} from '../../__tests__/PortableTextEditorTester'
4
+ import {
5
+ PortableTextEditorTester,
6
+ schemaType,
7
+ } from '../../__tests__/PortableTextEditorTester'
6
8
  import {PortableTextEditor} from '../../PortableTextEditor'
7
9
 
8
10
  const initialValue = [
@@ -56,7 +58,10 @@ describe('plugin:withEditableAPI: .delete()', () => {
56
58
 
57
59
  await waitFor(() => {
58
60
  if (editorRef.current) {
59
- expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
61
+ expect(onChange).toHaveBeenCalledWith({
62
+ type: 'value',
63
+ value: initialValue,
64
+ })
60
65
  expect(onChange).toHaveBeenCalledWith({type: 'ready'})
61
66
  }
62
67
  })
@@ -70,7 +75,8 @@ describe('plugin:withEditableAPI: .delete()', () => {
70
75
  PortableTextEditor.getSelection(editorRef.current),
71
76
  {mode: 'blocks'},
72
77
  )
73
- expect(PortableTextEditor.getValue(editorRef.current)).toMatchInlineSnapshot(`
78
+ expect(PortableTextEditor.getValue(editorRef.current))
79
+ .toMatchInlineSnapshot(`
74
80
  Array [
75
81
  Object {
76
82
  "_key": "a",
@@ -105,7 +111,10 @@ describe('plugin:withEditableAPI: .delete()', () => {
105
111
  )
106
112
 
107
113
  await waitFor(() => {
108
- expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
114
+ expect(onChange).toHaveBeenCalledWith({
115
+ type: 'value',
116
+ value: initialValue,
117
+ })
109
118
  expect(onChange).toHaveBeenCalledWith({type: 'ready'})
110
119
  })
111
120
 
@@ -124,7 +133,8 @@ describe('plugin:withEditableAPI: .delete()', () => {
124
133
  await waitFor(() => {
125
134
  if (editorRef.current) {
126
135
  // New keys here confirms that a placeholder block has been created
127
- expect(PortableTextEditor.getValue(editorRef.current)).toMatchInlineSnapshot(`
136
+ expect(PortableTextEditor.getValue(editorRef.current))
137
+ .toMatchInlineSnapshot(`
128
138
  Array [
129
139
  Object {
130
140
  "_key": "1",
@@ -161,7 +171,10 @@ describe('plugin:withEditableAPI: .delete()', () => {
161
171
 
162
172
  await waitFor(() => {
163
173
  if (editorRef.current) {
164
- expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
174
+ expect(onChange).toHaveBeenCalledWith({
175
+ type: 'value',
176
+ value: initialValue,
177
+ })
165
178
  expect(onChange).toHaveBeenCalledWith({type: 'ready'})
166
179
  }
167
180
  })
@@ -187,7 +200,8 @@ describe('plugin:withEditableAPI: .delete()', () => {
187
200
 
188
201
  await waitFor(() => {
189
202
  if (editorRef.current) {
190
- expect(PortableTextEditor.getValue(editorRef.current)).toMatchInlineSnapshot(`
203
+ expect(PortableTextEditor.getValue(editorRef.current))
204
+ .toMatchInlineSnapshot(`
191
205
  Array [
192
206
  Object {
193
207
  "_key": "a",
@@ -238,7 +252,10 @@ describe('plugin:withEditableAPI: .delete()', () => {
238
252
 
239
253
  await waitFor(() => {
240
254
  if (editorRef.current) {
241
- expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
255
+ expect(onChange).toHaveBeenCalledWith({
256
+ type: 'value',
257
+ value: initialValue,
258
+ })
242
259
  expect(onChange).toHaveBeenCalledWith({type: 'ready'})
243
260
  }
244
261
  })
@@ -2,8 +2,10 @@ import {describe, expect, it, jest} from '@jest/globals'
2
2
  import {isPortableTextTextBlock} from '@sanity/types'
3
3
  import {render, waitFor} from '@testing-library/react'
4
4
  import {createRef, type RefObject} from 'react'
5
-
6
- import {PortableTextEditorTester, schemaType} from '../../__tests__/PortableTextEditorTester'
5
+ import {
6
+ PortableTextEditorTester,
7
+ schemaType,
8
+ } from '../../__tests__/PortableTextEditorTester'
7
9
  import {PortableTextEditor} from '../../PortableTextEditor'
8
10
 
9
11
  const initialValue = [
@@ -67,7 +69,10 @@ describe('plugin:withEditableAPI: .getFragment()', () => {
67
69
 
68
70
  await waitFor(() => {
69
71
  if (editorRef.current) {
70
- expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
72
+ expect(onChange).toHaveBeenCalledWith({
73
+ type: 'value',
74
+ value: initialValue,
75
+ })
71
76
  expect(onChange).toHaveBeenCalledWith({type: 'ready'})
72
77
  }
73
78
  })
@@ -78,7 +83,9 @@ describe('plugin:withEditableAPI: .getFragment()', () => {
78
83
  PortableTextEditor.select(editorRef.current, initialSelection)
79
84
  const fragment = PortableTextEditor.getFragment(editorRef.current)
80
85
  expect(
81
- fragment && isPortableTextTextBlock(fragment[0]) && fragment[0]?.children[0]?.text,
86
+ fragment &&
87
+ isPortableTextTextBlock(fragment[0]) &&
88
+ fragment[0]?.children[0]?.text,
82
89
  ).toBe('A')
83
90
  }
84
91
  })
@@ -103,7 +110,10 @@ describe('plugin:withEditableAPI: .getFragment()', () => {
103
110
 
104
111
  await waitFor(() => {
105
112
  if (editorRef.current) {
106
- expect(onChange).toHaveBeenCalledWith({type: 'value', value: initialValue})
113
+ expect(onChange).toHaveBeenCalledWith({
114
+ type: 'value',
115
+ value: initialValue,
116
+ })
107
117
  expect(onChange).toHaveBeenCalledWith({type: 'ready'})
108
118
  }
109
119
  })