@portabletext/editor 1.50.6 → 1.50.8

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 (42) hide show
  1. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +1 -1
  2. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
  3. package/lib/_chunks-es/util.selection-point-to-block-offset.js +1 -1
  4. package/lib/_chunks-es/util.selection-point-to-block-offset.js.map +1 -1
  5. package/lib/behaviors/index.d.cts +24 -16
  6. package/lib/behaviors/index.d.ts +24 -16
  7. package/lib/index.cjs +359 -304
  8. package/lib/index.cjs.map +1 -1
  9. package/lib/index.d.cts +24 -16
  10. package/lib/index.d.ts +24 -16
  11. package/lib/index.js +362 -307
  12. package/lib/index.js.map +1 -1
  13. package/lib/plugins/index.d.cts +24 -16
  14. package/lib/plugins/index.d.ts +24 -16
  15. package/lib/selectors/index.cjs +6 -20
  16. package/lib/selectors/index.cjs.map +1 -1
  17. package/lib/selectors/index.d.cts +27 -27
  18. package/lib/selectors/index.d.ts +27 -27
  19. package/lib/selectors/index.js +6 -20
  20. package/lib/selectors/index.js.map +1 -1
  21. package/lib/utils/index.d.cts +24 -16
  22. package/lib/utils/index.d.ts +24 -16
  23. package/package.json +14 -14
  24. package/src/behaviors/behavior.abstract.delete.ts +60 -0
  25. package/src/behaviors/behavior.abstract.split.ts +23 -13
  26. package/src/behaviors/behavior.types.event.ts +23 -16
  27. package/src/editor/mutation-machine.ts +52 -63
  28. package/src/editor/plugins/create-with-event-listeners.ts +41 -1
  29. package/src/editor/sync-machine.ts +26 -20
  30. package/src/internal-utils/applyPatch.ts +299 -207
  31. package/src/internal-utils/slate-utils.ts +23 -0
  32. package/src/internal-utils/test-editor.tsx +45 -0
  33. package/src/operations/behavior.operation.delete.ts +36 -22
  34. package/src/operations/behavior.operations.ts +0 -27
  35. package/src/selectors/index.ts +1 -1
  36. package/src/selectors/selector.get-list-state.test.ts +14 -27
  37. package/src/selectors/selector.get-list-state.ts +9 -27
  38. package/src/utils/util.is-selection-collapsed.ts +2 -1
  39. package/src/internal-utils/__tests__/dmpToOperations.test.ts +0 -207
  40. package/src/operations/behavior.operation.delete.backward.ts +0 -8
  41. package/src/operations/behavior.operation.delete.block.ts +0 -24
  42. package/src/operations/behavior.operation.delete.forward.ts +0 -8
@@ -15,7 +15,7 @@ import type {
15
15
  import {PortableTextObject, PortableTextSpan} from '@sanity/types'
16
16
  import {FocusEvent as FocusEvent_2} from 'react'
17
17
  import type {KeyboardEvent as KeyboardEvent_2} from 'react'
18
- import type {Descendant, Operation, TextUnit} from 'slate'
18
+ import type {Descendant, Operation} from 'slate'
19
19
  import type {DOMNode} from 'slate-dom'
20
20
  import type {ReactEditor} from 'slate-react'
21
21
  import {
@@ -59,6 +59,18 @@ declare type AbstractBehaviorEvent =
59
59
  focus: BlockOffset
60
60
  }
61
61
  }
62
+ | {
63
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.backward'>
64
+ unit: 'character' | 'word' | 'line' | 'block'
65
+ }
66
+ | {
67
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.block'>
68
+ at: [KeyedSegment]
69
+ }
70
+ | {
71
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.forward'>
72
+ unit: 'character' | 'word' | 'line' | 'block'
73
+ }
62
74
  | {
63
75
  type: StrictExtract<SyntheticBehaviorEventType, 'delete.text'>
64
76
  at: {
@@ -189,6 +201,9 @@ declare type AbstractBehaviorEvent =
189
201
  declare const abstractBehaviorEventTypes: readonly [
190
202
  'annotation.toggle',
191
203
  'decorator.toggle',
204
+ 'delete.backward',
205
+ 'delete.block',
206
+ 'delete.forward',
192
207
  'delete.text',
193
208
  'deserialize',
194
209
  'deserialization.success',
@@ -2982,18 +2997,14 @@ declare type SyntheticBehaviorEvent =
2982
2997
  | {
2983
2998
  type: StrictExtract<SyntheticBehaviorEventType, 'delete'>
2984
2999
  at: NonNullable<EditorSelection>
2985
- }
2986
- | {
2987
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.backward'>
2988
- unit: TextUnit
2989
- }
2990
- | {
2991
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.block'>
2992
- at: [KeyedSegment]
2993
- }
2994
- | {
2995
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.forward'>
2996
- unit: TextUnit
3000
+ /**
3001
+ * Defaults to forward deletion.
3002
+ */
3003
+ direction?: 'backward' | 'forward'
3004
+ /**
3005
+ * Defaults to character deletion.
3006
+ */
3007
+ unit?: 'character' | 'word' | 'line' | 'block'
2997
3008
  }
2998
3009
  | {
2999
3010
  type: StrictExtract<SyntheticBehaviorEventType, 'history.redo'>
@@ -3068,9 +3079,6 @@ declare const syntheticBehaviorEventTypes: readonly [
3068
3079
  'decorator.add',
3069
3080
  'decorator.remove',
3070
3081
  'delete',
3071
- 'delete.backward',
3072
- 'delete.block',
3073
- 'delete.forward',
3074
3082
  'history.redo',
3075
3083
  'history.undo',
3076
3084
  'insert.inline object',
@@ -15,7 +15,7 @@ import type {
15
15
  import {PortableTextObject, PortableTextSpan} from '@sanity/types'
16
16
  import {FocusEvent as FocusEvent_2} from 'react'
17
17
  import type {KeyboardEvent as KeyboardEvent_2} from 'react'
18
- import type {Descendant, Operation, TextUnit} from 'slate'
18
+ import type {Descendant, Operation} from 'slate'
19
19
  import type {DOMNode} from 'slate-dom'
20
20
  import type {ReactEditor} from 'slate-react'
21
21
  import {
@@ -59,6 +59,18 @@ declare type AbstractBehaviorEvent =
59
59
  focus: BlockOffset
60
60
  }
61
61
  }
62
+ | {
63
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.backward'>
64
+ unit: 'character' | 'word' | 'line' | 'block'
65
+ }
66
+ | {
67
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.block'>
68
+ at: [KeyedSegment]
69
+ }
70
+ | {
71
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.forward'>
72
+ unit: 'character' | 'word' | 'line' | 'block'
73
+ }
62
74
  | {
63
75
  type: StrictExtract<SyntheticBehaviorEventType, 'delete.text'>
64
76
  at: {
@@ -189,6 +201,9 @@ declare type AbstractBehaviorEvent =
189
201
  declare const abstractBehaviorEventTypes: readonly [
190
202
  'annotation.toggle',
191
203
  'decorator.toggle',
204
+ 'delete.backward',
205
+ 'delete.block',
206
+ 'delete.forward',
192
207
  'delete.text',
193
208
  'deserialize',
194
209
  'deserialization.success',
@@ -2982,18 +2997,14 @@ declare type SyntheticBehaviorEvent =
2982
2997
  | {
2983
2998
  type: StrictExtract<SyntheticBehaviorEventType, 'delete'>
2984
2999
  at: NonNullable<EditorSelection>
2985
- }
2986
- | {
2987
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.backward'>
2988
- unit: TextUnit
2989
- }
2990
- | {
2991
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.block'>
2992
- at: [KeyedSegment]
2993
- }
2994
- | {
2995
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.forward'>
2996
- unit: TextUnit
3000
+ /**
3001
+ * Defaults to forward deletion.
3002
+ */
3003
+ direction?: 'backward' | 'forward'
3004
+ /**
3005
+ * Defaults to character deletion.
3006
+ */
3007
+ unit?: 'character' | 'word' | 'line' | 'block'
2997
3008
  }
2998
3009
  | {
2999
3010
  type: StrictExtract<SyntheticBehaviorEventType, 'history.redo'>
@@ -3068,9 +3079,6 @@ declare const syntheticBehaviorEventTypes: readonly [
3068
3079
  'decorator.add',
3069
3080
  'decorator.remove',
3070
3081
  'delete',
3071
- 'delete.backward',
3072
- 'delete.block',
3073
- 'delete.forward',
3074
3082
  'history.redo',
3075
3083
  'history.undo',
3076
3084
  'insert.inline object',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "1.50.6",
3
+ "version": "1.50.8",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -80,15 +80,15 @@
80
80
  "slate-react": "0.114.2",
81
81
  "use-effect-event": "^1.0.2",
82
82
  "xstate": "^5.19.3",
83
- "@portabletext/block-tools": "1.1.27",
84
- "@portabletext/patches": "1.1.3"
83
+ "@portabletext/patches": "1.1.4",
84
+ "@portabletext/block-tools": "1.1.28"
85
85
  },
86
86
  "devDependencies": {
87
87
  "@portabletext/toolkit": "^2.0.17",
88
88
  "@sanity/diff-match-patch": "^3.2.0",
89
- "@sanity/pkg-utils": "^7.2.2",
90
- "@sanity/schema": "^3.89.0",
91
- "@sanity/types": "^3.89.0",
89
+ "@sanity/pkg-utils": "^7.2.3",
90
+ "@sanity/schema": "^3.90.0",
91
+ "@sanity/types": "^3.90.0",
92
92
  "@testing-library/jest-dom": "^6.6.3",
93
93
  "@testing-library/react": "^16.3.0",
94
94
  "@types/debug": "^4.1.12",
@@ -96,27 +96,27 @@
96
96
  "@types/lodash.startcase": "^4.4.9",
97
97
  "@types/react": "^19.1.4",
98
98
  "@types/react-dom": "^19.1.5",
99
- "@typescript-eslint/eslint-plugin": "^8.32.1",
100
- "@typescript-eslint/parser": "^8.32.1",
99
+ "@typescript-eslint/eslint-plugin": "^8.33.0",
100
+ "@typescript-eslint/parser": "^8.33.0",
101
101
  "@vitejs/plugin-react": "^4.4.1",
102
- "@vitest/browser": "^3.1.3",
103
- "@vitest/coverage-istanbul": "^3.1.3",
102
+ "@vitest/browser": "^3.1.4",
103
+ "@vitest/coverage-istanbul": "^3.1.4",
104
104
  "babel-plugin-react-compiler": "19.1.0-rc.1",
105
105
  "eslint": "8.57.1",
106
- "eslint-plugin-react-hooks": "0.0.0-experimental-7a2c7045-20250506",
106
+ "eslint-plugin-react-hooks": "0.0.0-experimental-f9ae0a4c-20250527",
107
107
  "jsdom": "^26.0.0",
108
108
  "react": "^19.1.0",
109
109
  "react-dom": "^19.1.0",
110
110
  "rxjs": "^7.8.2",
111
111
  "typescript": "5.8.3",
112
112
  "vite": "^6.2.5",
113
- "vitest": "^3.1.3",
113
+ "vitest": "^3.1.4",
114
114
  "vitest-browser-react": "^0.2.0",
115
115
  "racejar": "1.2.5"
116
116
  },
117
117
  "peerDependencies": {
118
- "@sanity/schema": "^3.89.0",
119
- "@sanity/types": "^3.89.0",
118
+ "@sanity/schema": "^3.90.0",
119
+ "@sanity/types": "^3.90.0",
120
120
  "react": "^16.9 || ^17 || ^18 || ^19",
121
121
  "rxjs": "^7.8.2"
122
122
  },
@@ -4,6 +4,66 @@ import {raise} from './behavior.types.action'
4
4
  import {defineBehavior} from './behavior.types.behavior'
5
5
 
6
6
  export const abstractDeleteBehaviors = [
7
+ defineBehavior({
8
+ on: 'delete.backward',
9
+ guard: ({snapshot}) => {
10
+ if (!snapshot.context.selection) {
11
+ return false
12
+ }
13
+
14
+ return {selection: snapshot.context.selection}
15
+ },
16
+ actions: [
17
+ ({event}, {selection}) => [
18
+ raise({
19
+ type: 'delete',
20
+ direction: 'backward',
21
+ unit: event.unit,
22
+ at: selection,
23
+ }),
24
+ ],
25
+ ],
26
+ }),
27
+ defineBehavior({
28
+ on: 'delete.forward',
29
+ guard: ({snapshot}) => {
30
+ if (!snapshot.context.selection) {
31
+ return false
32
+ }
33
+
34
+ return {selection: snapshot.context.selection}
35
+ },
36
+ actions: [
37
+ ({event}, {selection}) => [
38
+ raise({
39
+ type: 'delete',
40
+ direction: 'forward',
41
+ unit: event.unit,
42
+ at: selection,
43
+ }),
44
+ ],
45
+ ],
46
+ }),
47
+ defineBehavior({
48
+ on: 'delete.block',
49
+ actions: [
50
+ ({event}) => [
51
+ raise({
52
+ type: 'delete',
53
+ at: {
54
+ anchor: {
55
+ path: event.at,
56
+ offset: 0,
57
+ },
58
+ focus: {
59
+ path: event.at,
60
+ offset: 0,
61
+ },
62
+ },
63
+ }),
64
+ ],
65
+ ],
66
+ }),
7
67
  defineBehavior({
8
68
  on: 'delete.text',
9
69
  guard: ({snapshot, event}) => {
@@ -1,6 +1,6 @@
1
1
  import {isTextBlock, parseBlock} from '../internal-utils/parse-blocks'
2
2
  import * as selectors from '../selectors'
3
- import {getSelectionStartPoint} from '../utils'
3
+ import {getSelectionStartPoint, isSelectionCollapsed} from '../utils'
4
4
  import {getBlockEndPoint} from '../utils/util.get-block-end-point'
5
5
  import {getSelectionEndPoint} from '../utils/util.get-selection-end-point'
6
6
  import {sliceBlocks} from '../utils/util.slice-blocks'
@@ -104,18 +104,28 @@ export const abstractSplitBehaviors = [
104
104
  return false
105
105
  },
106
106
  actions: [
107
- (_, {newTextBlock, selection}) => [
108
- raise({
109
- type: 'delete',
110
- at: selection,
111
- }),
112
- raise({
113
- type: 'insert.block',
114
- block: newTextBlock,
115
- placement: 'after',
116
- select: 'start',
117
- }),
118
- ],
107
+ (_, {newTextBlock, selection}) =>
108
+ isSelectionCollapsed(selection)
109
+ ? [
110
+ raise({
111
+ type: 'insert.block',
112
+ block: newTextBlock,
113
+ placement: 'after',
114
+ select: 'start',
115
+ }),
116
+ ]
117
+ : [
118
+ raise({
119
+ type: 'delete',
120
+ at: selection,
121
+ }),
122
+ raise({
123
+ type: 'insert.block',
124
+ block: newTextBlock,
125
+ placement: 'after',
126
+ select: 'start',
127
+ }),
128
+ ],
119
129
  ],
120
130
  }),
121
131
  ]
@@ -1,5 +1,4 @@
1
1
  import type {KeyedSegment, PortableTextBlock} from '@sanity/types'
2
- import type {TextUnit} from 'slate'
3
2
  import type {EventPosition} from '../internal-utils/event-position'
4
3
  import type {MIMEType} from '../internal-utils/mime-type'
5
4
  import type {OmitFromUnion, PickFromUnion, StrictExtract} from '../type-utils'
@@ -67,9 +66,6 @@ const syntheticBehaviorEventTypes = [
67
66
  'decorator.add',
68
67
  'decorator.remove',
69
68
  'delete',
70
- 'delete.backward',
71
- 'delete.block',
72
- 'delete.forward',
73
69
  'history.redo',
74
70
  'history.undo',
75
71
  'insert.inline object',
@@ -131,18 +127,14 @@ export type SyntheticBehaviorEvent =
131
127
  | {
132
128
  type: StrictExtract<SyntheticBehaviorEventType, 'delete'>
133
129
  at: NonNullable<EditorSelection>
134
- }
135
- | {
136
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.backward'>
137
- unit: TextUnit
138
- }
139
- | {
140
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.block'>
141
- at: [KeyedSegment]
142
- }
143
- | {
144
- type: StrictExtract<SyntheticBehaviorEventType, 'delete.forward'>
145
- unit: TextUnit
130
+ /**
131
+ * Defaults to forward deletion.
132
+ */
133
+ direction?: 'backward' | 'forward'
134
+ /**
135
+ * Defaults to character deletion.
136
+ */
137
+ unit?: 'character' | 'word' | 'line' | 'block'
146
138
  }
147
139
  | {
148
140
  type: StrictExtract<SyntheticBehaviorEventType, 'history.redo'>
@@ -218,6 +210,9 @@ export function isSyntheticBehaviorEvent(
218
210
  const abstractBehaviorEventTypes = [
219
211
  'annotation.toggle',
220
212
  'decorator.toggle',
213
+ 'delete.backward',
214
+ 'delete.block',
215
+ 'delete.forward',
221
216
  'delete.text',
222
217
  'deserialize',
223
218
  'deserialization.success',
@@ -257,6 +252,18 @@ type AbstractBehaviorEvent =
257
252
  decorator: string
258
253
  at?: {anchor: BlockOffset; focus: BlockOffset}
259
254
  }
255
+ | {
256
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.backward'>
257
+ unit: 'character' | 'word' | 'line' | 'block'
258
+ }
259
+ | {
260
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.block'>
261
+ at: [KeyedSegment]
262
+ }
263
+ | {
264
+ type: StrictExtract<SyntheticBehaviorEventType, 'delete.forward'>
265
+ unit: 'character' | 'word' | 'line' | 'block'
266
+ }
260
267
  | {
261
268
  type: StrictExtract<SyntheticBehaviorEventType, 'delete.text'>
262
269
  at: {
@@ -40,6 +40,9 @@ export const mutationMachine = setup({
40
40
  slateEditor: PortableTextSlateEditor
41
41
  },
42
42
  events: {} as
43
+ | {
44
+ type: 'mutation delay passed'
45
+ }
43
46
  | {
44
47
  type: 'patch'
45
48
  patch: Patch
@@ -162,17 +165,26 @@ export const mutationMachine = setup({
162
165
  input.slateEditor.apply = originalApply
163
166
  }
164
167
  }),
168
+ 'mutation debouncer': fromCallback(({sendBack}) => {
169
+ const interval = setInterval(
170
+ () => {
171
+ sendBack({type: 'mutation delay passed'})
172
+ },
173
+ process.env.NODE_ENV === 'test' ? 250 : 0,
174
+ )
175
+
176
+ return () => {
177
+ clearInterval(interval)
178
+ }
179
+ }),
165
180
  },
166
181
  guards: {
167
182
  'is read-only': ({context}) => context.readOnly,
168
183
  'is typing': stateIn({typing: 'typing'}),
169
- 'no pending mutations': ({context}) =>
170
- context.pendingMutations.length === 0,
171
184
  'slate is normalizing': ({context}) =>
172
185
  Editor.isNormalizing(context.slateEditor),
173
186
  },
174
187
  delays: {
175
- 'mutation debounce': process.env.NODE_ENV === 'test' ? 250 : 0,
176
188
  'type debounce': process.env.NODE_ENV === 'test' ? 0 : 250,
177
189
  },
178
190
  }).createMachine({
@@ -207,6 +219,7 @@ export const mutationMachine = setup({
207
219
  exit: [
208
220
  () => {
209
221
  debug('exit: typing->idle')
222
+ debug('entry: typing->typing')
210
223
  },
211
224
  ],
212
225
  on: {
@@ -216,19 +229,14 @@ export const mutationMachine = setup({
216
229
  },
217
230
  },
218
231
  typing: {
219
- entry: [
220
- () => {
221
- debug('entry: typing->typing')
222
- },
223
- ],
224
- exit: [
225
- () => {
226
- debug('exit: typing->typing')
227
- },
228
- ],
229
232
  after: {
230
233
  'type debounce': {
231
234
  target: 'idle',
235
+ actions: [
236
+ () => {
237
+ debug('exit: typing->typing')
238
+ },
239
+ ],
232
240
  },
233
241
  },
234
242
  on: {
@@ -258,77 +266,58 @@ export const mutationMachine = setup({
258
266
  },
259
267
  ],
260
268
  on: {
261
- patch: {
262
- actions: [
263
- 'emit patch',
264
- 'defer mutation',
265
- 'emit has pending mutations',
266
- ],
267
- target: 'emitting mutations',
268
- },
269
- },
270
- },
271
- 'emitting mutations': {
272
- entry: [
273
- () => {
274
- debug('entry: mutations->emitting mutations')
275
- },
276
- ],
277
- exit: [
278
- () => {
279
- debug('exit: mutations->emitting mutations')
280
- },
281
- ],
282
- after: {
283
- 'mutation debounce': [
269
+ patch: [
284
270
  {
285
271
  guard: 'is read-only',
286
- target: 'read-only',
272
+ actions: ['defer patch', 'defer mutation'],
273
+ target: 'has pending mutations',
287
274
  },
288
275
  {
289
- guard: and([not('is typing'), 'slate is normalizing']),
290
- target: 'idle',
291
- actions: ['emit mutations', 'clear pending mutations'],
292
- },
293
- {
294
- target: 'emitting mutations',
295
- reenter: true,
276
+ actions: ['emit patch', 'defer mutation'],
277
+ target: 'has pending mutations',
296
278
  },
297
279
  ],
298
280
  },
299
- on: {
300
- patch: {
301
- target: 'emitting mutations',
302
- actions: ['emit patch', 'defer mutation'],
303
- reenter: true,
304
- },
305
- },
306
281
  },
307
- 'read-only': {
282
+ 'has pending mutations': {
308
283
  entry: [
309
284
  () => {
310
- debug('entry: mutations->read-only')
285
+ debug('entry: mutations->has pending mutations')
311
286
  },
287
+ 'emit has pending mutations',
312
288
  ],
313
289
  exit: [
314
290
  () => {
315
- debug('exit: mutations->read-only')
291
+ debug('exit: mutations->has pending mutations')
316
292
  },
317
293
  ],
318
- always: [
319
- {
320
- guard: not('is read-only'),
321
- target: 'emitting mutations',
294
+ invoke: {
295
+ src: 'mutation debouncer',
296
+ },
297
+ on: {
298
+ 'mutation delay passed': {
299
+ guard: and([
300
+ not('is read-only'),
301
+ not('is typing'),
302
+ 'slate is normalizing',
303
+ ]),
304
+ target: 'idle',
322
305
  actions: [
323
306
  'emit pending patch events',
324
307
  'clear pending patch events',
308
+ 'emit mutations',
309
+ 'clear pending mutations',
325
310
  ],
326
311
  },
327
- ],
328
- on: {
329
- patch: {
330
- actions: ['defer patch', 'defer mutation'],
331
- },
312
+ 'patch': [
313
+ {
314
+ guard: 'is read-only',
315
+ actions: ['defer patch', 'defer mutation'],
316
+ },
317
+ {
318
+ actions: ['emit patch', 'defer mutation'],
319
+ },
320
+ ],
332
321
  },
333
322
  },
334
323
  },
@@ -11,7 +11,47 @@ export function createWithEventListeners(editorActor: EditorActor) {
11
11
  return editor
12
12
  }
13
13
 
14
- const {select} = editor
14
+ const {delete: editorDelete, select} = editor
15
+
16
+ editor.delete = (options) => {
17
+ if (isApplyingBehaviorOperations(editor)) {
18
+ editorDelete(options)
19
+ return
20
+ }
21
+
22
+ const at = options?.at ?? editor.selection
23
+
24
+ if (!at) {
25
+ console.error('Unexpected call to .delete(...) without `at` option')
26
+ return
27
+ }
28
+
29
+ const range = Editor.range(editor, at)
30
+
31
+ const selection = slateRangeToSelection({
32
+ schema: editorActor.getSnapshot().context.schema,
33
+ editor,
34
+ range,
35
+ })
36
+
37
+ if (!selection) {
38
+ console.error(
39
+ 'Unexpected call to .delete(...) with invalid `at` option',
40
+ )
41
+ return
42
+ }
43
+
44
+ editorActor.send({
45
+ type: 'behavior event',
46
+ behaviorEvent: {
47
+ type: 'delete',
48
+ at: selection,
49
+ direction: options?.reverse ? 'backward' : 'forward',
50
+ unit: options?.unit,
51
+ },
52
+ editor,
53
+ })
54
+ }
15
55
 
16
56
  editor.deleteBackward = (unit) => {
17
57
  if (isApplyingBehaviorOperations(editor)) {
@@ -428,29 +428,35 @@ async function updateValue({
428
428
  debug('Value is empty')
429
429
  Editor.withoutNormalizing(slateEditor, () => {
430
430
  withoutSaving(slateEditor, () => {
431
- withoutPatching(slateEditor, () => {
432
- if (doneSyncing) {
433
- return
434
- }
431
+ withRemoteChanges(slateEditor, () => {
432
+ withoutPatching(slateEditor, () => {
433
+ if (doneSyncing) {
434
+ return
435
+ }
435
436
 
436
- if (hadSelection) {
437
- Transforms.deselect(slateEditor)
438
- }
439
- const childrenLength = slateEditor.children.length
440
- slateEditor.children.forEach((_, index) => {
441
- Transforms.removeNodes(slateEditor, {
442
- at: [childrenLength - 1 - index],
437
+ if (hadSelection) {
438
+ Transforms.deselect(slateEditor)
439
+ }
440
+
441
+ const childrenLength = slateEditor.children.length
442
+
443
+ slateEditor.children.forEach((_, index) => {
444
+ Transforms.removeNodes(slateEditor, {
445
+ at: [childrenLength - 1 - index],
446
+ })
443
447
  })
448
+
449
+ Transforms.insertNodes(
450
+ slateEditor,
451
+ slateEditor.pteCreateTextBlock({decorators: []}),
452
+ {at: [0]},
453
+ )
454
+
455
+ // Add a new selection in the top of the document
456
+ if (hadSelection) {
457
+ Transforms.select(slateEditor, [0, 0])
458
+ }
444
459
  })
445
- Transforms.insertNodes(
446
- slateEditor,
447
- slateEditor.pteCreateTextBlock({decorators: []}),
448
- {at: [0]},
449
- )
450
- // Add a new selection in the top of the document
451
- if (hadSelection) {
452
- Transforms.select(slateEditor, [0, 0])
453
- }
454
460
  })
455
461
  })
456
462
  })