@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
@@ -1,10 +1,10 @@
1
1
  import {isEqual} from 'lodash'
2
2
  import {Editor, Node, Path, Range, Transforms} from 'slate'
3
- import {
4
- type PortableTextMemberSchemaTypes,
5
- type PortableTextSlateEditor,
3
+ import type {
4
+ PortableTextMemberSchemaTypes,
5
+ PortableTextSlateEditor,
6
6
  } from '../../types/editor'
7
- import {type SlateTextBlock, type VoidElement} from '../../types/slate'
7
+ import type {SlateTextBlock, VoidElement} from '../../types/slate'
8
8
 
9
9
  export function createWithInsertBreak(
10
10
  types: PortableTextMemberSchemaTypes,
@@ -1,12 +1,12 @@
1
1
  import {htmlToBlocks, normalizeBlock} from '@sanity/block-tools'
2
- import {type PortableTextBlock, type PortableTextChild} from '@sanity/types'
2
+ import type {PortableTextBlock, PortableTextChild} from '@sanity/types'
3
3
  import {isEqual, uniq} from 'lodash'
4
4
  import {Editor, Range, Transforms, type Descendant, type Node} from 'slate'
5
5
  import {ReactEditor} from 'slate-react'
6
- import {
7
- type EditorChanges,
8
- type PortableTextMemberSchemaTypes,
9
- type PortableTextSlateEditor,
6
+ import type {
7
+ EditorChanges,
8
+ PortableTextMemberSchemaTypes,
9
+ PortableTextSlateEditor,
10
10
  } from '../../types/editor'
11
11
  import {debugWithName} from '../../utils/debug'
12
12
  import {validateValue} from '../../utils/validateValue'
@@ -15,6 +15,7 @@ import {
15
15
  isEqualToEmptyEditor,
16
16
  toSlateValue,
17
17
  } from '../../utils/values'
18
+ import type {EditorActor} from '../editor-machine'
18
19
 
19
20
  const debug = debugWithName('plugin:withInsertData')
20
21
 
@@ -23,7 +24,7 @@ const debug = debugWithName('plugin:withInsertData')
23
24
  *
24
25
  */
25
26
  export function createWithInsertData(
26
- change$: EditorChanges,
27
+ editorActor: EditorActor,
27
28
  schemaTypes: PortableTextMemberSchemaTypes,
28
29
  keyGenerator: () => string,
29
30
  ) {
@@ -158,9 +159,8 @@ export function createWithInsertData(
158
159
  // Bail out if it's not valid
159
160
  if (!validation.valid && !validation.resolution?.autoResolve) {
160
161
  const errorDescription = `${validation.resolution?.description}`
161
- change$.next({
162
+ editorActor.send({
162
163
  type: 'error',
163
- level: 'warning',
164
164
  name: 'pasteError',
165
165
  description: errorDescription,
166
166
  data: validation,
@@ -180,7 +180,6 @@ export function createWithInsertData(
180
180
  debug('No selection, not inserting')
181
181
  return false
182
182
  }
183
- change$.next({type: 'loading', isLoading: true}) // This could potentially take some time
184
183
  const html = data.getData('text/html')
185
184
  const text = data.getData('text/plain')
186
185
 
@@ -188,7 +187,7 @@ export function createWithInsertData(
188
187
  debug('Inserting data', data)
189
188
  let portableText: PortableTextBlock[]
190
189
  let fragment: Node[]
191
- let insertedType
190
+ let insertedType: string | undefined
192
191
 
193
192
  if (html) {
194
193
  portableText = htmlToBlocks(html, schemaTypes.portableText, {
@@ -232,9 +231,8 @@ export function createWithInsertData(
232
231
  // Bail out if it's not valid
233
232
  if (!validation.valid) {
234
233
  const errorDescription = `Could not validate the resulting portable text to insert.\n${validation.resolution?.description}\nTry to insert as plain text (shift-paste) instead.`
235
- change$.next({
234
+ editorActor.send({
236
235
  type: 'error',
237
- level: 'warning',
238
236
  name: 'pasteError',
239
237
  description: errorDescription,
240
238
  data: validation,
@@ -246,10 +244,8 @@ export function createWithInsertData(
246
244
  `Inserting ${insertedType} fragment at ${JSON.stringify(editor.selection)}`,
247
245
  )
248
246
  _insertFragment(editor, fragment, schemaTypes)
249
- change$.next({type: 'loading', isLoading: false})
250
247
  return true
251
248
  }
252
- change$.next({type: 'loading', isLoading: false})
253
249
  return false
254
250
  }
255
251
 
@@ -335,8 +331,7 @@ function _regenerateKeys(
335
331
  ...child,
336
332
  marks:
337
333
  child.marks && child.marks.includes(oldKey)
338
- ? // eslint-disable-next-line max-nested-callbacks
339
- [...child.marks]
334
+ ? [...child.marks]
340
335
  .filter((mark) => mark !== oldKey)
341
336
  .concat(newKey)
342
337
  : child.marks,
@@ -1,4 +1,4 @@
1
- import {type PortableTextSlateEditor} from '../../types/editor'
1
+ import type {PortableTextSlateEditor} from '../../types/editor'
2
2
  import {isChangingRemotely} from '../../utils/withChanges'
3
3
  import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
4
4
 
@@ -1,16 +1,18 @@
1
1
  import {Editor, Element, Node, Transforms} from 'slate'
2
- import {
3
- type PortableTextMemberSchemaTypes,
4
- type PortableTextSlateEditor,
2
+ import type {
3
+ PortableTextMemberSchemaTypes,
4
+ PortableTextSlateEditor,
5
5
  } from '../../types/editor'
6
6
  import {isChangingRemotely} from '../../utils/withChanges'
7
7
  import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
8
+ import type {EditorActor} from '../editor-machine'
8
9
 
9
10
  /**
10
11
  * This plugin makes sure that every new node in the editor get a new _key prop when created
11
12
  *
12
13
  */
13
14
  export function createWithObjectKeys(
15
+ editorActor: EditorActor,
14
16
  schemaTypes: PortableTextMemberSchemaTypes,
15
17
  keyGenerator: () => string,
16
18
  ) {
@@ -75,12 +77,17 @@ export function createWithObjectKeys(
75
77
  if (Element.isElement(node) && node._type === schemaTypes.block.name) {
76
78
  // Set key on block itself
77
79
  if (!node._key) {
80
+ editorActor.send({type: 'normalizing'})
78
81
  Transforms.setNodes(editor, {_key: keyGenerator()}, {at: path})
82
+ editorActor.send({type: 'done normalizing'})
83
+ return
79
84
  }
80
85
  // Set keys on it's children
81
86
  for (const [child, childPath] of Node.children(editor, path)) {
82
87
  if (!child._key) {
88
+ editorActor.send({type: 'normalizing'})
83
89
  Transforms.setNodes(editor, {_key: keyGenerator()}, {at: childPath})
90
+ editorActor.send({type: 'done normalizing'})
84
91
  return
85
92
  }
86
93
  }
@@ -1,6 +1,4 @@
1
- /* eslint-disable max-nested-callbacks */
2
1
  import {insert, setIfMissing, unset, type Patch} from '@portabletext/patches'
3
- import {type Subject} from 'rxjs'
4
2
  import {
5
3
  Editor,
6
4
  type Descendant,
@@ -14,11 +12,10 @@ import {
14
12
  type SetNodeOperation,
15
13
  type SplitNodeOperation,
16
14
  } from 'slate'
17
- import {
18
- type EditorChange,
19
- type PatchObservable,
20
- type PortableTextMemberSchemaTypes,
21
- type PortableTextSlateEditor,
15
+ import type {
16
+ PatchObservable,
17
+ PortableTextMemberSchemaTypes,
18
+ PortableTextSlateEditor,
22
19
  } from '../../types/editor'
23
20
  import {createApplyPatch} from '../../utils/applyPatch'
24
21
  import {debugWithName} from '../../utils/debug'
@@ -33,6 +30,7 @@ import {
33
30
  PATCHING,
34
31
  withoutPatching,
35
32
  } from '../../utils/withoutPatching'
33
+ import type {EditorActor} from '../editor-machine'
36
34
  import {withoutSaving} from './createWithUndoRedo'
37
35
 
38
36
  const debug = debugWithName('plugin:withPatches')
@@ -82,7 +80,7 @@ export interface PatchFunctions {
82
80
  }
83
81
 
84
82
  interface Options {
85
- change$: Subject<EditorChange>
83
+ editorActor: EditorActor
86
84
  keyGenerator: () => string
87
85
  patches$?: PatchObservable
88
86
  patchFunctions: PatchFunctions
@@ -91,7 +89,7 @@ interface Options {
91
89
  }
92
90
 
93
91
  export function createWithPatches({
94
- change$,
92
+ editorActor,
95
93
  patches$,
96
94
  patchFunctions,
97
95
  readOnly,
@@ -269,7 +267,6 @@ export function createWithPatches({
269
267
  ),
270
268
  ]
271
269
  break
272
- case 'set_selection':
273
270
  default:
274
271
  // Do nothing
275
272
  }
@@ -283,7 +280,7 @@ export function createWithPatches({
283
280
  )
284
281
  ) {
285
282
  patches = [...patches, unset([])]
286
- change$.next({
283
+ editorActor.send({
287
284
  type: 'unset',
288
285
  previousValue: fromSlateValue(
289
286
  previousChildren,
@@ -301,7 +298,7 @@ export function createWithPatches({
301
298
  // Emit all patches
302
299
  if (patches.length > 0) {
303
300
  patches.forEach((patch) => {
304
- change$.next({
301
+ editorActor.send({
305
302
  type: 'patch',
306
303
  patch: {...patch, origin: 'local'},
307
304
  })
@@ -1,6 +1,6 @@
1
1
  import {Editor, Path} from 'slate'
2
- import {type PortableTextSlateEditor} from '../../types/editor'
3
- import {type SlateTextBlock, type VoidElement} from '../../types/slate'
2
+ import type {PortableTextSlateEditor} from '../../types/editor'
3
+ import type {SlateTextBlock, VoidElement} from '../../types/slate'
4
4
  import {debugWithName} from '../../utils/debug'
5
5
  import {isChangingRemotely} from '../../utils/withChanges'
6
6
  import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
@@ -1,13 +1,15 @@
1
1
  import {Editor, Path, Text as SlateText, Transforms, type Node} from 'slate'
2
- import {
3
- type PortableTextMemberSchemaTypes,
4
- type PortableTextSlateEditor,
2
+ import type {
3
+ PortableTextMemberSchemaTypes,
4
+ PortableTextSlateEditor,
5
5
  } from '../../types/editor'
6
6
  import {debugWithName} from '../../utils/debug'
7
+ import type {EditorActor} from '../editor-machine'
7
8
 
8
9
  const debug = debugWithName('plugin:withPortableTextBlockStyle')
9
10
 
10
11
  export function createWithPortableTextBlockStyle(
12
+ editorActor: EditorActor,
11
13
  types: PortableTextMemberSchemaTypes,
12
14
  ): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
13
15
  const defaultStyle = types.styles[0].value
@@ -17,9 +19,10 @@ export function createWithPortableTextBlockStyle(
17
19
  // Extend Slate's default normalization to reset split node to normal style
18
20
  // if there is no text at the right end of the split.
19
21
  const {normalizeNode} = editor
22
+
20
23
  editor.normalizeNode = (nodeEntry) => {
21
- normalizeNode(nodeEntry)
22
24
  const [, path] = nodeEntry
25
+
23
26
  for (const op of editor.operations) {
24
27
  if (
25
28
  op.type === 'split_node' &&
@@ -32,16 +35,21 @@ export function createWithPortableTextBlockStyle(
32
35
  const [child] = Editor.node(editor, [op.path[0] + 1, 0])
33
36
  if (SlateText.isText(child) && child.text === '') {
34
37
  debug(`Normalizing split node to ${defaultStyle} style`, op)
38
+ editorActor.send({type: 'normalizing'})
35
39
  Transforms.setNodes(
36
40
  editor,
37
41
  {style: defaultStyle},
38
42
  {at: [op.path[0] + 1], voids: false},
39
43
  )
40
- break
44
+ editorActor.send({type: 'done normalizing'})
45
+ return
41
46
  }
42
47
  }
43
48
  }
49
+
50
+ normalizeNode(nodeEntry)
44
51
  }
52
+
45
53
  editor.pteHasBlockStyle = (style: string): boolean => {
46
54
  if (!editor.selection) {
47
55
  return false
@@ -1,7 +1,7 @@
1
1
  import {Editor, Element, Text, Transforms, type Node} from 'slate'
2
- import {
3
- type PortableTextMemberSchemaTypes,
4
- type PortableTextSlateEditor,
2
+ import type {
3
+ PortableTextMemberSchemaTypes,
4
+ PortableTextSlateEditor,
5
5
  } from '../../types/editor'
6
6
  import {debugWithName} from '../../utils/debug'
7
7
 
@@ -38,7 +38,6 @@ export function createWithPortableTextLists(
38
38
  ]
39
39
  selectedBlocks.forEach(([node, path]) => {
40
40
  if (editor.isListBlock(node)) {
41
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
42
41
  const {listItem, level, ...rest} = node
43
42
  const newNode = {
44
43
  ...rest,
@@ -1,5 +1,3 @@
1
- /* eslint-disable max-statements */
2
- /* eslint-disable complexity */
3
1
  /**
4
2
  *
5
3
  * This plugin will change Slate's default marks model (every prop is a mark) with the Portable Text model (marks is an array of strings on prop .marks).
@@ -7,9 +5,8 @@
7
5
  */
8
6
 
9
7
  import {isPortableTextBlock, isPortableTextSpan} from '@portabletext/toolkit'
10
- import {type PortableTextObject} from '@sanity/types'
8
+ import type {PortableTextObject} from '@sanity/types'
11
9
  import {isEqual, uniq} from 'lodash'
12
- import {type Subject} from 'rxjs'
13
10
  import {
14
11
  Editor,
15
12
  Element,
@@ -20,21 +17,21 @@ import {
20
17
  Transforms,
21
18
  type Descendant,
22
19
  } from 'slate'
23
- import {
24
- type EditorChange,
25
- type PortableTextMemberSchemaTypes,
26
- type PortableTextSlateEditor,
20
+ import type {
21
+ PortableTextMemberSchemaTypes,
22
+ PortableTextSlateEditor,
27
23
  } from '../../types/editor'
28
24
  import {debugWithName} from '../../utils/debug'
29
25
  import {toPortableTextRange} from '../../utils/ranges'
30
26
  import {isChangingRemotely} from '../../utils/withChanges'
31
27
  import {isRedoing, isUndoing} from '../../utils/withUndoRedo'
28
+ import type {EditorActor} from '../editor-machine'
32
29
 
33
30
  const debug = debugWithName('plugin:withPortableTextMarkModel')
34
31
 
35
32
  export function createWithPortableTextMarkModel(
33
+ editorActor: EditorActor,
36
34
  types: PortableTextMemberSchemaTypes,
37
- change$: Subject<EditorChange>,
38
35
  keyGenerator: () => string,
39
36
  ): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
40
37
  return function withPortableTextMarkModel(editor: PortableTextSlateEditor) {
@@ -61,7 +58,7 @@ export function createWithPortableTextMarkModel(
61
58
  editor.selection,
62
59
  types,
63
60
  )
64
- change$.next({type: 'selection', selection: ptRange})
61
+ editorActor.send({type: 'selection', selection: ptRange})
65
62
  }
66
63
 
67
64
  // Extend Slate's default normalization. Merge spans with same set of .marks when doing merge_node operations, and clean up markDefs / marks
@@ -84,10 +81,12 @@ export function createWithPortableTextMarkModel(
84
81
  JSON.stringify(child, null, 2),
85
82
  JSON.stringify(nextNode, null, 2),
86
83
  )
84
+ editorActor.send({type: 'normalizing'})
87
85
  Transforms.mergeNodes(editor, {
88
86
  at: [childPath[0], childPath[1] + 1],
89
87
  voids: true,
90
88
  })
89
+ editorActor.send({type: 'done normalizing'})
91
90
  return
92
91
  }
93
92
  }
@@ -98,7 +97,9 @@ export function createWithPortableTextMarkModel(
98
97
  */
99
98
  if (editor.isTextBlock(node) && !Array.isArray(node.markDefs)) {
100
99
  debug('Adding .markDefs to block node')
100
+ editorActor.send({type: 'normalizing'})
101
101
  Transforms.setNodes(editor, {markDefs: []}, {at: path})
102
+ editorActor.send({type: 'done normalizing'})
102
103
  return
103
104
  }
104
105
 
@@ -107,7 +108,9 @@ export function createWithPortableTextMarkModel(
107
108
  */
108
109
  if (editor.isTextSpan(node) && !Array.isArray(node.marks)) {
109
110
  debug('Adding .marks to span node')
111
+ editorActor.send({type: 'normalizing'})
110
112
  Transforms.setNodes(editor, {marks: []}, {at: path})
113
+ editorActor.send({type: 'done normalizing'})
111
114
  return
112
115
  }
113
116
 
@@ -125,11 +128,13 @@ export function createWithPortableTextMarkModel(
125
128
  if (editor.isTextBlock(block)) {
126
129
  if (node.text === '' && annotations && annotations.length > 0) {
127
130
  debug('Removing annotations from empty span node')
131
+ editorActor.send({type: 'normalizing'})
128
132
  Transforms.setNodes(
129
133
  editor,
130
134
  {marks: node.marks?.filter((mark) => decorators.includes(mark))},
131
135
  {at: path},
132
136
  )
137
+ editorActor.send({type: 'done normalizing'})
133
138
  return
134
139
  }
135
140
  }
@@ -153,6 +158,7 @@ export function createWithPortableTextMarkModel(
153
158
 
154
159
  if (orphanedAnnotations.length > 0) {
155
160
  debug('Removing orphaned annotations from span node')
161
+ editorActor.send({type: 'normalizing'})
156
162
  Transforms.setNodes(
157
163
  editor,
158
164
  {
@@ -162,6 +168,7 @@ export function createWithPortableTextMarkModel(
162
168
  },
163
169
  {at: childPath},
164
170
  )
171
+ editorActor.send({type: 'done normalizing'})
165
172
  return
166
173
  }
167
174
  }
@@ -189,6 +196,7 @@ export function createWithPortableTextMarkModel(
189
196
 
190
197
  if (orphanedAnnotations.length > 0) {
191
198
  debug('Removing orphaned annotations from span node')
199
+ editorActor.send({type: 'normalizing'})
192
200
  Transforms.setNodes(
193
201
  editor,
194
202
  {
@@ -198,6 +206,7 @@ export function createWithPortableTextMarkModel(
198
206
  },
199
207
  {at: path},
200
208
  )
209
+ editorActor.send({type: 'done normalizing'})
201
210
  return
202
211
  }
203
212
  }
@@ -218,7 +227,10 @@ export function createWithPortableTextMarkModel(
218
227
 
219
228
  if (markDefs.length !== newMarkDefs.length) {
220
229
  debug('Removing duplicate markDefs')
230
+ editorActor.send({type: 'normalizing'})
221
231
  Transforms.setNodes(editor, {markDefs: newMarkDefs}, {at: path})
232
+ editorActor.send({type: 'done normalizing'})
233
+ return
222
234
  }
223
235
  }
224
236
 
@@ -243,6 +255,7 @@ export function createWithPortableTextMarkModel(
243
255
  })
244
256
  if (node.markDefs && !isEqual(newMarkDefs, node.markDefs)) {
245
257
  debug('Removing markDef not in use')
258
+ editorActor.send({type: 'normalizing'})
246
259
  Transforms.setNodes(
247
260
  editor,
248
261
  {
@@ -250,6 +263,7 @@ export function createWithPortableTextMarkModel(
250
263
  },
251
264
  {at: path},
252
265
  )
266
+ editorActor.send({type: 'done normalizing'})
253
267
  return
254
268
  }
255
269
  }
@@ -1,10 +1,8 @@
1
- import {type Subject} from 'rxjs'
2
- import {type BaseRange} from 'slate'
3
- import {
4
- type EditorChange,
5
- type EditorSelection,
6
- type PortableTextMemberSchemaTypes,
7
- type PortableTextSlateEditor,
1
+ import type {BaseRange} from 'slate'
2
+ import type {
3
+ EditorSelection,
4
+ PortableTextMemberSchemaTypes,
5
+ PortableTextSlateEditor,
8
6
  } from '../../types/editor'
9
7
  import {debugWithName} from '../../utils/debug'
10
8
  import {
@@ -12,13 +10,14 @@ import {
12
10
  type ObjectWithKeyAndType,
13
11
  } from '../../utils/ranges'
14
12
  import {SLATE_TO_PORTABLE_TEXT_RANGE} from '../../utils/weakMaps'
13
+ import type {EditorActor} from '../editor-machine'
15
14
 
16
15
  const debug = debugWithName('plugin:withPortableTextSelections')
17
16
  const debugVerbose = debug.enabled && false
18
17
 
19
18
  // This plugin will make sure that we emit a PT selection whenever the editor has changed.
20
19
  export function createWithPortableTextSelections(
21
- change$: Subject<EditorChange>,
20
+ editorActor: EditorActor,
22
21
  types: PortableTextMemberSchemaTypes,
23
22
  ): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
24
23
  let prevSelection: BaseRange | null = null
@@ -46,9 +45,9 @@ export function createWithPortableTextSelections(
46
45
  )
47
46
  }
48
47
  if (ptRange) {
49
- change$.next({type: 'selection', selection: ptRange})
48
+ editorActor.send({type: 'selection', selection: ptRange})
50
49
  } else {
51
- change$.next({type: 'selection', selection: null})
50
+ editorActor.send({type: 'selection', selection: null})
52
51
  }
53
52
  }
54
53
  prevSelection = editor.selection
@@ -7,11 +7,12 @@ import {
7
7
  type PortableTextTextBlock,
8
8
  } from '@sanity/types'
9
9
  import {Transforms, type Element} from 'slate'
10
- import {
11
- type PortableTextMemberSchemaTypes,
12
- type PortableTextSlateEditor,
10
+ import type {
11
+ PortableTextMemberSchemaTypes,
12
+ PortableTextSlateEditor,
13
13
  } from '../../types/editor'
14
14
  import {debugWithName} from '../../utils/debug'
15
+ import type {EditorActor} from '../editor-machine'
15
16
 
16
17
  const debug = debugWithName('plugin:withSchemaTypes')
17
18
  /**
@@ -19,9 +20,11 @@ const debug = debugWithName('plugin:withSchemaTypes')
19
20
  *
20
21
  */
21
22
  export function createWithSchemaTypes({
23
+ editorActor,
22
24
  schemaTypes,
23
25
  keyGenerator,
24
26
  }: {
27
+ editorActor: EditorActor
25
28
  schemaTypes: PortableTextMemberSchemaTypes
26
29
  keyGenerator: () => string
27
30
  }) {
@@ -34,7 +37,7 @@ export function createWithSchemaTypes({
34
37
  )
35
38
  }
36
39
  editor.isTextSpan = (value: unknown): value is PortableTextSpan => {
37
- return isPortableTextSpan(value) && value._type == schemaTypes.span.name
40
+ return isPortableTextSpan(value) && value._type === schemaTypes.span.name
38
41
  }
39
42
  editor.isListBlock = (value: unknown): value is PortableTextListBlock => {
40
43
  return (
@@ -71,18 +74,24 @@ export function createWithSchemaTypes({
71
74
  debug('Setting span type on text node without a type')
72
75
  const span = node as PortableTextSpan
73
76
  const key = span._key || keyGenerator()
77
+ editorActor.send({type: 'normalizing'})
74
78
  Transforms.setNodes(
75
79
  editor,
76
80
  {...span, _type: schemaTypes.span.name, _key: key},
77
81
  {at: path},
78
82
  )
83
+ editorActor.send({type: 'done normalizing'})
84
+ return
79
85
  }
80
86
 
81
87
  // catches cases when the children are missing keys but excludes it when the normalize is running the node as the editor object
82
88
  if (node._key === undefined && (path.length === 1 || path.length === 2)) {
83
89
  debug('Setting missing key on child node without a key')
84
90
  const key = keyGenerator()
91
+ editorActor.send({type: 'normalizing'})
85
92
  Transforms.setNodes(editor, {_key: key}, {at: path})
93
+ editorActor.send({type: 'done normalizing'})
94
+ return
86
95
  }
87
96
 
88
97
  normalizeNode(entry)
@@ -3,14 +3,14 @@
3
3
  * The undo/redo steps are rebased against incoming patches since the step occurred.
4
4
  */
5
5
 
6
- import {type Patch} from '@portabletext/patches'
6
+ import type {Patch} from '@portabletext/patches'
7
7
  import {
8
8
  DIFF_DELETE,
9
9
  DIFF_EQUAL,
10
10
  DIFF_INSERT,
11
11
  parsePatch,
12
12
  } from '@sanity/diff-match-patch'
13
- import {type ObjectSchemaType, type PortableTextBlock} from '@sanity/types'
13
+ import type {ObjectSchemaType, PortableTextBlock} from '@sanity/types'
14
14
  import {flatten, isEqual} from 'lodash'
15
15
  import {
16
16
  Editor,
@@ -20,10 +20,7 @@ import {
20
20
  type Descendant,
21
21
  type SelectionOperation,
22
22
  } from 'slate'
23
- import {
24
- type PatchObservable,
25
- type PortableTextSlateEditor,
26
- } from '../../types/editor'
23
+ import type {PatchObservable, PortableTextSlateEditor} from '../../types/editor'
27
24
  import {debugWithName} from '../../utils/debug'
28
25
  import {fromSlateValue} from '../../utils/values'
29
26
  import {
@@ -248,7 +245,6 @@ export function createWithUndoRedo(
248
245
  Editor.withoutNormalizing(editor, () => {
249
246
  withRedoing(editor, () => {
250
247
  withoutSaving(editor, () => {
251
- // eslint-disable-next-line max-nested-callbacks
252
248
  transformedOperations.forEach((op) => {
253
249
  editor.apply(op)
254
250
  })
@@ -1,11 +1,11 @@
1
1
  import {Editor, Range, Text, Transforms} from 'slate'
2
- import {
3
- type PortableTextMemberSchemaTypes,
4
- type PortableTextSlateEditor,
2
+ import type {
3
+ PortableTextMemberSchemaTypes,
4
+ PortableTextSlateEditor,
5
5
  } from '../../types/editor'
6
6
  import {debugWithName} from '../../utils/debug'
7
7
  import {toSlateValue} from '../../utils/values'
8
- import {type PortableTextEditor} from '../PortableTextEditor'
8
+ import type {PortableTextEditor} from '../PortableTextEditor'
9
9
 
10
10
  const debug = debugWithName('plugin:withUtils')
11
11
 
@@ -59,8 +59,8 @@ export function createWithUtils({
59
59
  if (
60
60
  !(
61
61
  newStartOffset === newEndOffset ||
62
- isNaN(newStartOffset) ||
63
- isNaN(newEndOffset)
62
+ Number.isNaN(newStartOffset) ||
63
+ Number.isNaN(newEndOffset)
64
64
  )
65
65
  ) {
66
66
  debug('pteExpandToWord: Expanding to focused word')