@portabletext/editor 1.0.18 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/lib/index.d.mts +140 -66
  2. package/lib/index.d.ts +140 -66
  3. package/lib/index.esm.js +1164 -410
  4. package/lib/index.esm.js.map +1 -1
  5. package/lib/index.js +1164 -410
  6. package/lib/index.js.map +1 -1
  7. package/lib/index.mjs +1164 -410
  8. package/lib/index.mjs.map +1 -1
  9. package/package.json +8 -4
  10. package/src/editor/Editable.tsx +107 -36
  11. package/src/editor/PortableTextEditor.tsx +47 -12
  12. package/src/editor/__tests__/PortableTextEditor.test.tsx +42 -15
  13. package/src/editor/__tests__/PortableTextEditorTester.tsx +50 -38
  14. package/src/editor/__tests__/RangeDecorations.test.tsx +0 -1
  15. package/src/editor/__tests__/handleClick.test.tsx +28 -9
  16. package/src/editor/__tests__/insert-block.test.tsx +22 -6
  17. package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +30 -62
  18. package/src/editor/__tests__/utils.ts +10 -3
  19. package/src/editor/components/DraggableBlock.tsx +36 -13
  20. package/src/editor/components/Element.tsx +59 -17
  21. package/src/editor/components/Leaf.tsx +106 -68
  22. package/src/editor/components/SlateContainer.tsx +12 -5
  23. package/src/editor/components/Synchronizer.tsx +5 -2
  24. package/src/editor/hooks/usePortableTextEditor.ts +2 -2
  25. package/src/editor/hooks/usePortableTextEditorSelection.tsx +9 -3
  26. package/src/editor/hooks/useSyncValue.test.tsx +9 -4
  27. package/src/editor/hooks/useSyncValue.ts +199 -130
  28. package/src/editor/nodes/DefaultAnnotation.tsx +6 -3
  29. package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +25 -7
  30. package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +26 -9
  31. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +15 -5
  32. package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +60 -19
  33. package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +4 -2
  34. package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +4 -2
  35. package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +61 -550
  36. package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +6 -3
  37. package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +30 -13
  38. package/src/editor/plugins/createWithEditableAPI.ts +354 -115
  39. package/src/editor/plugins/createWithHotKeys.ts +41 -121
  40. package/src/editor/plugins/createWithInsertBreak.ts +166 -27
  41. package/src/editor/plugins/createWithInsertData.ts +60 -23
  42. package/src/editor/plugins/createWithMaxBlocks.ts +5 -2
  43. package/src/editor/plugins/createWithObjectKeys.ts +7 -3
  44. package/src/editor/plugins/createWithPatches.ts +60 -16
  45. package/src/editor/plugins/createWithPlaceholderBlock.ts +7 -3
  46. package/src/editor/plugins/createWithPortableTextBlockStyle.ts +17 -7
  47. package/src/editor/plugins/createWithPortableTextLists.ts +21 -8
  48. package/src/editor/plugins/createWithPortableTextMarkModel.ts +301 -155
  49. package/src/editor/plugins/createWithPortableTextSelections.ts +4 -2
  50. package/src/editor/plugins/createWithSchemaTypes.ts +25 -9
  51. package/src/editor/plugins/createWithUndoRedo.ts +107 -24
  52. package/src/editor/plugins/createWithUtils.ts +32 -10
  53. package/src/editor/plugins/index.ts +31 -10
  54. package/src/types/editor.ts +44 -15
  55. package/src/types/options.ts +4 -2
  56. package/src/types/slate.ts +2 -2
  57. package/src/utils/__tests__/dmpToOperations.test.ts +38 -13
  58. package/src/utils/__tests__/operationToPatches.test.ts +3 -2
  59. package/src/utils/__tests__/patchToOperations.test.ts +15 -4
  60. package/src/utils/__tests__/ranges.test.ts +8 -3
  61. package/src/utils/__tests__/valueNormalization.test.tsx +12 -4
  62. package/src/utils/__tests__/values.test.ts +0 -1
  63. package/src/utils/applyPatch.ts +71 -20
  64. package/src/utils/getPortableTextMemberSchemaTypes.ts +30 -15
  65. package/src/utils/operationToPatches.ts +126 -43
  66. package/src/utils/paths.ts +24 -7
  67. package/src/utils/ranges.ts +12 -5
  68. package/src/utils/selection.ts +19 -7
  69. package/src/utils/validateValue.ts +118 -45
  70. package/src/utils/values.ts +31 -10
  71. package/src/utils/weakMaps.ts +18 -8
  72. package/src/utils/withChanges.ts +4 -2
  73. package/src/editor/plugins/__tests__/withHotkeys.test.tsx +0 -212
  74. package/src/editor/plugins/__tests__/withInsertBreak.test.tsx +0 -220
  75. package/src/editor/plugins/__tests__/withPlaceholderBlock.test.tsx +0 -133
@@ -6,9 +6,11 @@ import {
6
6
  type PortableTextSpan,
7
7
  type PortableTextTextBlock,
8
8
  } from '@sanity/types'
9
- import {type Element, Transforms} from 'slate'
10
-
11
- import {type PortableTextMemberSchemaTypes, type PortableTextSlateEditor} from '../../types/editor'
9
+ import {Transforms, type Element} from 'slate'
10
+ import {
11
+ type PortableTextMemberSchemaTypes,
12
+ type PortableTextSlateEditor,
13
+ } from '../../types/editor'
12
14
  import {debugWithName} from '../../utils/debug'
13
15
 
14
16
  const debug = debugWithName('plugin:withSchemaTypes')
@@ -23,21 +25,31 @@ export function createWithSchemaTypes({
23
25
  schemaTypes: PortableTextMemberSchemaTypes
24
26
  keyGenerator: () => string
25
27
  }) {
26
- return function withSchemaTypes(editor: PortableTextSlateEditor): PortableTextSlateEditor {
28
+ return function withSchemaTypes(
29
+ editor: PortableTextSlateEditor,
30
+ ): PortableTextSlateEditor {
27
31
  editor.isTextBlock = (value: unknown): value is PortableTextTextBlock => {
28
- return isPortableTextTextBlock(value) && value._type === schemaTypes.block.name
32
+ return (
33
+ isPortableTextTextBlock(value) && value._type === schemaTypes.block.name
34
+ )
29
35
  }
30
36
  editor.isTextSpan = (value: unknown): value is PortableTextSpan => {
31
37
  return isPortableTextSpan(value) && value._type == schemaTypes.span.name
32
38
  }
33
39
  editor.isListBlock = (value: unknown): value is PortableTextListBlock => {
34
- return isPortableTextListBlock(value) && value._type === schemaTypes.block.name
40
+ return (
41
+ isPortableTextListBlock(value) && value._type === schemaTypes.block.name
42
+ )
35
43
  }
36
44
  editor.isVoid = (element: Element): boolean => {
37
45
  return (
38
46
  schemaTypes.block.name !== element._type &&
39
- (schemaTypes.blockObjects.map((obj) => obj.name).includes(element._type) ||
40
- schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type))
47
+ (schemaTypes.blockObjects
48
+ .map((obj) => obj.name)
49
+ .includes(element._type) ||
50
+ schemaTypes.inlineObjects
51
+ .map((obj) => obj.name)
52
+ .includes(element._type))
41
53
  )
42
54
  }
43
55
  editor.isInline = (element: Element): boolean => {
@@ -59,7 +71,11 @@ export function createWithSchemaTypes({
59
71
  debug('Setting span type on text node without a type')
60
72
  const span = node as PortableTextSpan
61
73
  const key = span._key || keyGenerator()
62
- Transforms.setNodes(editor, {...span, _type: schemaTypes.span.name, _key: key}, {at: path})
74
+ Transforms.setNodes(
75
+ editor,
76
+ {...span, _type: schemaTypes.span.name, _key: key},
77
+ {at: path},
78
+ )
63
79
  }
64
80
 
65
81
  // catches cases when the children are missing keys but excludes it when the normalize is running the node as the editor object
@@ -4,15 +4,34 @@
4
4
  */
5
5
 
6
6
  import {type Patch} from '@portabletext/patches'
7
- import {DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, parsePatch} from '@sanity/diff-match-patch'
7
+ import {
8
+ DIFF_DELETE,
9
+ DIFF_EQUAL,
10
+ DIFF_INSERT,
11
+ parsePatch,
12
+ } from '@sanity/diff-match-patch'
8
13
  import {type ObjectSchemaType, type PortableTextBlock} from '@sanity/types'
9
14
  import {flatten, isEqual} from 'lodash'
10
- import {type Descendant, Editor, Operation, Path, type SelectionOperation, Transforms} from 'slate'
11
-
12
- import {type PatchObservable, type PortableTextSlateEditor} from '../../types/editor'
15
+ import {
16
+ Editor,
17
+ Operation,
18
+ Path,
19
+ Transforms,
20
+ type Descendant,
21
+ type SelectionOperation,
22
+ } from 'slate'
23
+ import {
24
+ type PatchObservable,
25
+ type PortableTextSlateEditor,
26
+ } from '../../types/editor'
13
27
  import {debugWithName} from '../../utils/debug'
14
28
  import {fromSlateValue} from '../../utils/values'
15
- import {setIsRedoing, setIsUndoing, withRedoing, withUndoing} from '../../utils/withUndoRedo'
29
+ import {
30
+ setIsRedoing,
31
+ setIsUndoing,
32
+ withRedoing,
33
+ withUndoing,
34
+ } from '../../utils/withUndoRedo'
16
35
 
17
36
  const debug = debugWithName('plugin:withUndoRedo')
18
37
  const debugVerbose = debug.enabled && false
@@ -66,14 +85,21 @@ export function createWithUndoRedo(
66
85
  patches.forEach((patch) => {
67
86
  if (!reset && patch.origin !== 'local' && remotePatches) {
68
87
  if (patch.type === 'unset' && patch.path.length === 0) {
69
- debug('Someone else cleared the content, resetting undo/redo history')
88
+ debug(
89
+ 'Someone else cleared the content, resetting undo/redo history',
90
+ )
70
91
  editor.history = {undos: [], redos: []}
71
92
  remotePatches.splice(0, remotePatches.length)
72
93
  SAVING.set(editor, true)
73
94
  reset = true
74
95
  return
75
96
  }
76
- remotePatches.push({patch, time: new Date(), snapshot, previousSnapshot})
97
+ remotePatches.push({
98
+ patch,
99
+ time: new Date(),
100
+ snapshot,
101
+ previousSnapshot,
102
+ })
77
103
  }
78
104
  })
79
105
  previousSnapshot = snapshot
@@ -94,7 +120,8 @@ export function createWithUndoRedo(
94
120
  const {operations, history} = editor
95
121
  const {undos} = history
96
122
  const step = undos[undos.length - 1]
97
- const lastOp = step && step.operations && step.operations[step.operations.length - 1]
123
+ const lastOp =
124
+ step && step.operations && step.operations[step.operations.length - 1]
98
125
  const overwrite = shouldOverwrite(op, lastOp)
99
126
  const save = isSaving(editor)
100
127
 
@@ -110,7 +137,12 @@ export function createWithUndoRedo(
110
137
  step.operations.push(op)
111
138
  } else {
112
139
  const newStep = {
113
- operations: [...(editor.selection === null ? [] : [createSelectOperation(editor)]), op],
140
+ operations: [
141
+ ...(editor.selection === null
142
+ ? []
143
+ : [createSelectOperation(editor)]),
144
+ op,
145
+ ],
114
146
  timestamp: new Date(),
115
147
  }
116
148
  undos.push(newStep)
@@ -137,16 +169,26 @@ export function createWithUndoRedo(
137
169
  const step = undos[undos.length - 1]
138
170
  debug('Undoing', step)
139
171
  if (step.operations.length > 0) {
140
- const otherPatches = remotePatches.filter((item) => item.time >= step.timestamp)
172
+ const otherPatches = remotePatches.filter(
173
+ (item) => item.time >= step.timestamp,
174
+ )
141
175
  let transformedOperations = step.operations
142
176
  otherPatches.forEach((item) => {
143
177
  transformedOperations = flatten(
144
178
  transformedOperations.map((op) =>
145
- transformOperation(editor, item.patch, op, item.snapshot, item.previousSnapshot),
179
+ transformOperation(
180
+ editor,
181
+ item.patch,
182
+ op,
183
+ item.snapshot,
184
+ item.previousSnapshot,
185
+ ),
146
186
  ),
147
187
  )
148
188
  })
149
- const reversedOperations = transformedOperations.map(Operation.inverse).reverse()
189
+ const reversedOperations = transformedOperations
190
+ .map(Operation.inverse)
191
+ .reverse()
150
192
 
151
193
  try {
152
194
  Editor.withoutNormalizing(editor, () => {
@@ -185,12 +227,20 @@ export function createWithUndoRedo(
185
227
  const step = redos[redos.length - 1]
186
228
  debug('Redoing', step)
187
229
  if (step.operations.length > 0) {
188
- const otherPatches = remotePatches.filter((item) => item.time >= step.timestamp)
230
+ const otherPatches = remotePatches.filter(
231
+ (item) => item.time >= step.timestamp,
232
+ )
189
233
  let transformedOperations = step.operations
190
234
  otherPatches.forEach((item) => {
191
235
  transformedOperations = flatten(
192
236
  transformedOperations.map((op) =>
193
- transformOperation(editor, item.patch, op, item.snapshot, item.previousSnapshot),
237
+ transformOperation(
238
+ editor,
239
+ item.patch,
240
+ op,
241
+ item.snapshot,
242
+ item.previousSnapshot,
243
+ ),
194
244
  ),
195
245
  )
196
246
  })
@@ -240,7 +290,9 @@ function transformOperation(
240
290
  previousSnapshot: PortableTextBlock[] | undefined,
241
291
  ): Operation[] {
242
292
  if (debugVerbose) {
243
- debug(`Adjusting '${operation.type}' operation paths for '${patch.type}' patch`)
293
+ debug(
294
+ `Adjusting '${operation.type}' operation paths for '${patch.type}' patch`,
295
+ )
244
296
  debug(`Operation ${JSON.stringify(operation)}`)
245
297
  debug(`Patch ${JSON.stringify(patch)}`)
246
298
  }
@@ -254,7 +306,13 @@ function transformOperation(
254
306
  debug(
255
307
  `Adjusting block path (+${patch.items.length}) for '${transformedOperation.type}' operation and patch '${patch.type}'`,
256
308
  )
257
- return [adjustBlockPath(transformedOperation, patch.items.length, insertBlockIndex)]
309
+ return [
310
+ adjustBlockPath(
311
+ transformedOperation,
312
+ patch.items.length,
313
+ insertBlockIndex,
314
+ ),
315
+ ]
258
316
  }
259
317
 
260
318
  if (patch.type === 'unset' && patch.path.length === 1) {
@@ -281,13 +339,21 @@ function transformOperation(
281
339
 
282
340
  // Someone reset the whole value
283
341
  if (patch.type === 'unset' && patch.path.length === 0) {
284
- debug(`Adjusting selection for unset everything patch and ${operation.type} operation`)
342
+ debug(
343
+ `Adjusting selection for unset everything patch and ${operation.type} operation`,
344
+ )
285
345
  return []
286
346
  }
287
347
 
288
348
  if (patch.type === 'diffMatchPatch') {
289
- const operationTargetBlock = findOperationTargetBlock(editor, transformedOperation)
290
- if (!operationTargetBlock || !isEqual({_key: operationTargetBlock._key}, patch.path[0])) {
349
+ const operationTargetBlock = findOperationTargetBlock(
350
+ editor,
351
+ transformedOperation,
352
+ )
353
+ if (
354
+ !operationTargetBlock ||
355
+ !isEqual({_key: operationTargetBlock._key}, patch.path[0])
356
+ ) {
291
357
  return [transformedOperation]
292
358
  }
293
359
  const diffPatches = parsePatch(patch.value)
@@ -318,7 +384,10 @@ function transformOperation(
318
384
  }
319
385
  // Adjust accordingly if someone removed text in the same node before us
320
386
  if (transformedOperation.type === 'remove_text') {
321
- if (changedOffset <= transformedOperation.offset - transformedOperation.text.length) {
387
+ if (
388
+ changedOffset <=
389
+ transformedOperation.offset - transformedOperation.text.length
390
+ ) {
322
391
  transformedOperation.offset += adjustOffsetBy
323
392
  }
324
393
  }
@@ -365,7 +434,11 @@ function transformOperation(
365
434
  /**
366
435
  * Adjust the block path for a operation
367
436
  */
368
- function adjustBlockPath(operation: Operation, level: number, blockIndex: number): Operation {
437
+ function adjustBlockPath(
438
+ operation: Operation,
439
+ level: number,
440
+ blockIndex: number,
441
+ ): Operation {
369
442
  const transformedOperation = {...operation}
370
443
  if (
371
444
  blockIndex >= 0 &&
@@ -374,7 +447,10 @@ function adjustBlockPath(operation: Operation, level: number, blockIndex: number
374
447
  transformedOperation.path[0] >= blockIndex + level &&
375
448
  transformedOperation.path[0] + level > -1
376
449
  ) {
377
- const newPath = [transformedOperation.path[0] + level, ...transformedOperation.path.slice(1)]
450
+ const newPath = [
451
+ transformedOperation.path[0] + level,
452
+ ...transformedOperation.path.slice(1),
453
+ ]
378
454
  transformedOperation.path = newPath
379
455
  }
380
456
  if (transformedOperation.type === 'set_selection') {
@@ -393,7 +469,11 @@ function adjustBlockPath(operation: Operation, level: number, blockIndex: number
393
469
  if ((currentFocus && currentAnchor) || (newFocus && newAnchor)) {
394
470
  const points = [currentFocus, currentAnchor, newFocus, newAnchor]
395
471
  points.forEach((point) => {
396
- if (point && point.path[0] >= blockIndex + level && point.path[0] + level > -1) {
472
+ if (
473
+ point &&
474
+ point.path[0] >= blockIndex + level &&
475
+ point.path[0] + level > -1
476
+ ) {
397
477
  point.path = [point.path[0] + level, ...point.path.slice(1)]
398
478
  }
399
479
  })
@@ -449,7 +529,10 @@ const shouldMerge = (op: Operation, prev: Operation | undefined): boolean => {
449
529
  return false
450
530
  }
451
531
 
452
- const shouldOverwrite = (op: Operation, prev: Operation | undefined): boolean => {
532
+ const shouldOverwrite = (
533
+ op: Operation,
534
+ prev: Operation | undefined,
535
+ ): boolean => {
453
536
  if (prev && op.type === 'set_selection' && prev.type === 'set_selection') {
454
537
  return true
455
538
  }
@@ -1,6 +1,8 @@
1
1
  import {Editor, Range, Text, Transforms} from 'slate'
2
-
3
- import {type PortableTextMemberSchemaTypes, type PortableTextSlateEditor} from '../../types/editor'
2
+ import {
3
+ type PortableTextMemberSchemaTypes,
4
+ type PortableTextSlateEditor,
5
+ } from '../../types/editor'
4
6
  import {debugWithName} from '../../utils/debug'
5
7
  import {toSlateValue} from '../../utils/values'
6
8
  import {type PortableTextEditor} from '../PortableTextEditor'
@@ -16,8 +18,14 @@ interface Options {
16
18
  * This plugin makes various util commands available in the editor
17
19
  *
18
20
  */
19
- export function createWithUtils({schemaTypes, keyGenerator, portableTextEditor}: Options) {
20
- return function withUtils(editor: PortableTextSlateEditor): PortableTextSlateEditor {
21
+ export function createWithUtils({
22
+ schemaTypes,
23
+ keyGenerator,
24
+ portableTextEditor,
25
+ }: Options) {
26
+ return function withUtils(
27
+ editor: PortableTextSlateEditor,
28
+ ): PortableTextSlateEditor {
21
29
  // Expands the the selection to wrap around the word the focus is at
22
30
  editor.pteExpandToWord = () => {
23
31
  const {selection} = editor
@@ -37,12 +45,24 @@ export function createWithUtils({schemaTypes, keyGenerator, portableTextEditor}:
37
45
  .reverse()
38
46
  .findIndex((str) => isEmpty(str))
39
47
  const newStartOffset =
40
- whiteSpaceBeforeIndex > -1 ? charsBefore.length - whiteSpaceBeforeIndex : 0
41
- const whiteSpaceAfterIndex = charsAfter.split('').findIndex((obj) => isEmpty(obj))
48
+ whiteSpaceBeforeIndex > -1
49
+ ? charsBefore.length - whiteSpaceBeforeIndex
50
+ : 0
51
+ const whiteSpaceAfterIndex = charsAfter
52
+ .split('')
53
+ .findIndex((obj) => isEmpty(obj))
42
54
  const newEndOffset =
43
55
  charsBefore.length +
44
- (whiteSpaceAfterIndex > -1 ? whiteSpaceAfterIndex : charsAfter.length + 1)
45
- if (!(newStartOffset === newEndOffset || isNaN(newStartOffset) || isNaN(newEndOffset))) {
56
+ (whiteSpaceAfterIndex > -1
57
+ ? whiteSpaceAfterIndex
58
+ : charsAfter.length + 1)
59
+ if (
60
+ !(
61
+ newStartOffset === newEndOffset ||
62
+ isNaN(newStartOffset) ||
63
+ isNaN(newEndOffset)
64
+ )
65
+ ) {
46
66
  debug('pteExpandToWord: Expanding to focused word')
47
67
  Transforms.setSelection(editor, {
48
68
  anchor: {...selection.anchor, offset: newStartOffset},
@@ -54,7 +74,7 @@ export function createWithUtils({schemaTypes, keyGenerator, portableTextEditor}:
54
74
  }
55
75
  }
56
76
 
57
- editor.pteCreateEmptyBlock = () => {
77
+ editor.pteCreateTextBlock = (options: {decorators: Array<string>}) => {
58
78
  const block = toSlateValue(
59
79
  [
60
80
  {
@@ -67,7 +87,9 @@ export function createWithUtils({schemaTypes, keyGenerator, portableTextEditor}:
67
87
  _type: 'span',
68
88
  _key: keyGenerator(),
69
89
  text: '',
70
- marks: [],
90
+ marks: options.decorators.filter((decorator) =>
91
+ schemaTypes.decorators.find(({value}) => value === decorator),
92
+ ),
71
93
  },
72
94
  ],
73
95
  },
@@ -1,6 +1,5 @@
1
1
  import {noop} from 'lodash'
2
2
  import {type BaseOperation, type Editor, type Node, type NodeEntry} from 'slate'
3
-
4
3
  import {type PortableTextSlateEditor} from '../../types/editor'
5
4
  import {type createEditorOptions} from '../../types/options'
6
5
  import {createOperationToPatches} from '../../utils/operationToPatches'
@@ -38,14 +37,18 @@ export interface OriginalEditorFunctions {
38
37
  normalizeNode: (entry: NodeEntry<Node>) => void
39
38
  }
40
39
 
41
- const originalFnMap = new WeakMap<PortableTextSlateEditor, OriginalEditorFunctions>()
40
+ const originalFnMap = new WeakMap<
41
+ PortableTextSlateEditor,
42
+ OriginalEditorFunctions
43
+ >()
42
44
 
43
45
  export const withPlugins = <T extends Editor>(
44
46
  editor: T,
45
47
  options: createEditorOptions,
46
48
  ): {editor: PortableTextSlateEditor; subscribe: () => () => void} => {
47
49
  const e = editor as T & PortableTextSlateEditor
48
- const {keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks} = options
50
+ const {keyGenerator, portableTextEditor, patches$, readOnly, maxBlocks} =
51
+ options
49
52
  const {schemaTypes, change$} = portableTextEditor
50
53
  e.subscriptions = []
51
54
  if (e.destroy) {
@@ -62,7 +65,11 @@ export const withPlugins = <T extends Editor>(
62
65
  const operationToPatches = createOperationToPatches(schemaTypes)
63
66
  const withObjectKeys = createWithObjectKeys(schemaTypes, keyGenerator)
64
67
  const withSchemaTypes = createWithSchemaTypes({schemaTypes, keyGenerator})
65
- const withEditableAPI = createWithEditableAPI(portableTextEditor, schemaTypes, keyGenerator)
68
+ const withEditableAPI = createWithEditableAPI(
69
+ portableTextEditor,
70
+ schemaTypes,
71
+ keyGenerator,
72
+ )
66
73
  const withPatches = createWithPatches({
67
74
  change$,
68
75
  keyGenerator,
@@ -83,14 +90,22 @@ export const withPlugins = <T extends Editor>(
83
90
  change$,
84
91
  keyGenerator,
85
92
  )
86
- const withPortableTextBlockStyle = createWithPortableTextBlockStyle(schemaTypes)
93
+ const withPortableTextBlockStyle =
94
+ createWithPortableTextBlockStyle(schemaTypes)
87
95
 
88
96
  const withPlaceholderBlock = createWithPlaceholderBlock()
89
97
 
90
- const withInsertBreak = createWithInsertBreak(schemaTypes)
98
+ const withInsertBreak = createWithInsertBreak(schemaTypes, keyGenerator)
91
99
 
92
- const withUtils = createWithUtils({keyGenerator, schemaTypes, portableTextEditor})
93
- const withPortableTextSelections = createWithPortableTextSelections(change$, schemaTypes)
100
+ const withUtils = createWithUtils({
101
+ keyGenerator,
102
+ schemaTypes,
103
+ portableTextEditor,
104
+ })
105
+ const withPortableTextSelections = createWithPortableTextSelections(
106
+ change$,
107
+ schemaTypes,
108
+ )
94
109
 
95
110
  e.destroy = () => {
96
111
  const originalFunctions = originalFnMap.get(e)
@@ -111,7 +126,9 @@ export const withPlugins = <T extends Editor>(
111
126
  withUtils(
112
127
  withPlaceholderBlock(
113
128
  withPortableTextLists(
114
- withPortableTextSelections(withEditableAPI(withInsertBreak(e))),
129
+ withPortableTextSelections(
130
+ withEditableAPI(withInsertBreak(e)),
131
+ ),
115
132
  ),
116
133
  ),
117
134
  ),
@@ -134,7 +151,11 @@ export const withPlugins = <T extends Editor>(
134
151
  withUtils(
135
152
  withMaxBlocks(
136
153
  withUndoRedo(
137
- withPatches(withPortableTextSelections(withEditableAPI(withInsertBreak(e)))),
154
+ withPatches(
155
+ withPortableTextSelections(
156
+ withEditableAPI(withInsertBreak(e)),
157
+ ),
158
+ ),
138
159
  ),
139
160
  ),
140
161
  ),
@@ -25,10 +25,13 @@ import {
25
25
  type RefObject,
26
26
  } from 'react'
27
27
  import {type Observable, type Subject} from 'rxjs'
28
- import {type Descendant, type Node as SlateNode, type Operation as SlateOperation} from 'slate'
28
+ import {
29
+ type Descendant,
30
+ type Node as SlateNode,
31
+ type Operation as SlateOperation,
32
+ } from 'slate'
29
33
  import {type ReactEditor} from 'slate-react'
30
34
  import {type DOMNode} from 'slate-react/dist/utils/dom'
31
-
32
35
  import {type PortableTextEditableProps} from '../editor/Editable'
33
36
  import {type PortableTextEditor} from '../editor/PortableTextEditor'
34
37
 
@@ -44,11 +47,20 @@ export interface EditableAPI {
44
47
  addAnnotation: (
45
48
  type: ObjectSchemaType,
46
49
  value?: {[prop: string]: unknown},
47
- ) => {spanPath: Path; markDefPath: Path} | undefined
50
+ ) =>
51
+ | {markDefPath: Path; markDefPaths: Array<Path>; spanPath: Path}
52
+ | undefined
48
53
  blur: () => void
49
- delete: (selection: EditorSelection, options?: EditableAPIDeleteOptions) => void
50
- findByPath: (path: Path) => [PortableTextBlock | PortableTextChild | undefined, Path | undefined]
51
- findDOMNode: (element: PortableTextBlock | PortableTextChild) => DOMNode | undefined
54
+ delete: (
55
+ selection: EditorSelection,
56
+ options?: EditableAPIDeleteOptions,
57
+ ) => void
58
+ findByPath: (
59
+ path: Path,
60
+ ) => [PortableTextBlock | PortableTextChild | undefined, Path | undefined]
61
+ findDOMNode: (
62
+ element: PortableTextBlock | PortableTextChild,
63
+ ) => DOMNode | undefined
52
64
  focus: () => void
53
65
  focusBlock: () => PortableTextBlock | undefined
54
66
  focusChild: () => PortableTextChild | undefined
@@ -57,13 +69,22 @@ export interface EditableAPI {
57
69
  getValue: () => PortableTextBlock[] | undefined
58
70
  hasBlockStyle: (style: string) => boolean
59
71
  hasListStyle: (listStyle: string) => boolean
60
- insertBlock: (type: BlockSchemaType | ObjectSchemaType, value?: {[prop: string]: unknown}) => Path
61
- insertChild: (type: SpanSchemaType | ObjectSchemaType, value?: {[prop: string]: unknown}) => Path
72
+ insertBlock: (
73
+ type: BlockSchemaType | ObjectSchemaType,
74
+ value?: {[prop: string]: unknown},
75
+ ) => Path
76
+ insertChild: (
77
+ type: SpanSchemaType | ObjectSchemaType,
78
+ value?: {[prop: string]: unknown},
79
+ ) => Path
62
80
  insertBreak: () => void
63
81
  isCollapsedSelection: () => boolean
64
82
  isExpandedSelection: () => boolean
65
83
  isMarkActive: (mark: string) => boolean
66
- isSelectionsOverlapping: (selectionA: EditorSelection, selectionB: EditorSelection) => boolean
84
+ isSelectionsOverlapping: (
85
+ selectionA: EditorSelection,
86
+ selectionB: EditorSelection,
87
+ ) => boolean
67
88
  isVoid: (element: PortableTextBlock | PortableTextChild) => boolean
68
89
  marks: () => string[]
69
90
  redo: () => void
@@ -199,9 +220,9 @@ export interface PortableTextSlateEditor extends ReactEditor {
199
220
  pteWithHotKeys: (event: KeyboardEvent<HTMLDivElement>) => void
200
221
 
201
222
  /**
202
- * Helper function that creates an empty text block
223
+ * Helper function that creates a text block
203
224
  */
204
- pteCreateEmptyBlock: () => Descendant
225
+ pteCreateTextBlock: (options: {decorators: Array<string>}) => Descendant
205
226
 
206
227
  /**
207
228
  * Undo
@@ -498,10 +519,14 @@ export type RenderBlockFunction = (props: BlockRenderProps) => JSX.Element
498
519
  export type RenderChildFunction = (props: BlockChildRenderProps) => JSX.Element
499
520
 
500
521
  /** @beta */
501
- export type RenderEditableFunction = (props: PortableTextEditableProps) => JSX.Element
522
+ export type RenderEditableFunction = (
523
+ props: PortableTextEditableProps,
524
+ ) => JSX.Element
502
525
 
503
526
  /** @beta */
504
- export type RenderAnnotationFunction = (props: BlockAnnotationRenderProps) => JSX.Element
527
+ export type RenderAnnotationFunction = (
528
+ props: BlockAnnotationRenderProps,
529
+ ) => JSX.Element
505
530
 
506
531
  /** @beta */
507
532
  export type RenderPlaceholderFunction = () => React.ReactNode
@@ -522,10 +547,14 @@ export interface BlockStyleRenderProps {
522
547
  }
523
548
 
524
549
  /** @beta */
525
- export type RenderListItemFunction = (props: BlockListItemRenderProps) => JSX.Element
550
+ export type RenderListItemFunction = (
551
+ props: BlockListItemRenderProps,
552
+ ) => JSX.Element
526
553
 
527
554
  /** @beta */
528
- export type RenderDecoratorFunction = (props: BlockDecoratorRenderProps) => JSX.Element
555
+ export type RenderDecoratorFunction = (
556
+ props: BlockDecoratorRenderProps,
557
+ ) => JSX.Element
529
558
 
530
559
  /** @beta */
531
560
  export type ScrollSelectionIntoViewFunction = (
@@ -1,5 +1,4 @@
1
1
  import {type BaseSyntheticEvent} from 'react'
2
-
3
2
  import {type PortableTextEditor} from '../editor/PortableTextEditor'
4
3
  import {type PatchObservable} from './editor'
5
4
 
@@ -19,5 +18,8 @@ export type createEditorOptions = {
19
18
  */
20
19
  export type HotkeyOptions = {
21
20
  marks?: Record<string, string>
22
- custom?: Record<string, (event: BaseSyntheticEvent, editor: PortableTextEditor) => void>
21
+ custom?: Record<
22
+ string,
23
+ (event: BaseSyntheticEvent, editor: PortableTextEditor) => void
24
+ >
23
25
  }
@@ -1,7 +1,6 @@
1
1
  import {type PortableTextSpan, type PortableTextTextBlock} from '@sanity/types'
2
2
  import {type BaseEditor, type Descendant} from 'slate'
3
3
  import {type ReactEditor} from 'slate-react'
4
-
5
4
  import {type PortableTextSlateEditor} from '..'
6
5
 
7
6
  export interface VoidElement {
@@ -12,7 +11,8 @@ export interface VoidElement {
12
11
  value: Record<string, unknown>
13
12
  }
14
13
 
15
- export interface SlateTextBlock extends Omit<PortableTextTextBlock, 'children'> {
14
+ export interface SlateTextBlock
15
+ extends Omit<PortableTextTextBlock, 'children'> {
16
16
  children: Descendant[]
17
17
  }
18
18