@portabletext/editor 2.9.1 → 2.10.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 (53) hide show
  1. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +9 -1
  2. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
  3. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +1 -0
  4. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
  5. package/lib/_chunks-cjs/util.slice-blocks.cjs +6 -1
  6. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  7. package/lib/_chunks-dts/behavior.types.action.d.cts +141 -131
  8. package/lib/_chunks-dts/behavior.types.action.d.ts +71 -61
  9. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +9 -1
  10. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
  11. package/lib/_chunks-es/util.merge-text-blocks.js +1 -0
  12. package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -1
  13. package/lib/_chunks-es/util.slice-blocks.js +6 -1
  14. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  15. package/lib/index.cjs +419 -309
  16. package/lib/index.cjs.map +1 -1
  17. package/lib/index.js +422 -312
  18. package/lib/index.js.map +1 -1
  19. package/lib/plugins/index.d.cts +3 -3
  20. package/lib/plugins/index.d.ts +3 -3
  21. package/lib/utils/index.d.ts +2 -2
  22. package/package.json +8 -8
  23. package/src/behaviors/behavior.abstract.insert.ts +109 -24
  24. package/src/behaviors/behavior.abstract.split.ts +1 -0
  25. package/src/behaviors/behavior.perform-event.ts +84 -118
  26. package/src/behaviors/behavior.types.event.ts +9 -1
  27. package/src/converters/converter.portable-text.ts +1 -0
  28. package/src/converters/converter.text-html.ts +1 -0
  29. package/src/converters/converter.text-plain.ts +1 -0
  30. package/src/editor/Editable.tsx +1 -0
  31. package/src/editor/editor-selector.ts +10 -1
  32. package/src/editor/plugins/create-with-event-listeners.ts +13 -14
  33. package/src/editor/sync-machine.ts +9 -0
  34. package/src/editor/with-performing-behavior-operation.ts +21 -0
  35. package/src/editor/without-normalizing-conditional.ts +13 -0
  36. package/src/internal-utils/parse-blocks.test.ts +14 -14
  37. package/src/internal-utils/parse-blocks.ts +9 -2
  38. package/src/internal-utils/slate-utils.test.tsx +119 -0
  39. package/src/internal-utils/slate-utils.ts +14 -1
  40. package/src/internal-utils/text-marks.ts +1 -1
  41. package/src/internal-utils/values.ts +1 -55
  42. package/src/operations/behavior.operation.block.set.ts +18 -36
  43. package/src/operations/behavior.operation.block.unset.ts +8 -2
  44. package/src/operations/behavior.operation.insert.block.ts +4 -1
  45. package/src/operations/behavior.operation.insert.child.ts +95 -0
  46. package/src/operations/behavior.operations.ts +140 -128
  47. package/src/selectors/selector.get-mark-state.ts +19 -5
  48. package/src/selectors/selector.get-trimmed-selection.test.ts +1 -0
  49. package/src/types/block-with-optional-key.ts +13 -1
  50. package/src/utils/util.merge-text-blocks.ts +1 -1
  51. package/src/utils/util.slice-blocks.ts +3 -3
  52. package/src/utils/util.slice-text-block.test.ts +54 -28
  53. package/src/editor/with-applying-behavior-operations.ts +0 -18
@@ -1,5 +1,5 @@
1
1
  import { Behavior, Editor, EditorEmittedEvent, EditorSchema } from "../_chunks-dts/behavior.types.action.cjs";
2
- import * as react22 from "react";
2
+ import * as react12 from "react";
3
3
  import React from "react";
4
4
  /**
5
5
  * @beta
@@ -181,7 +181,7 @@ type MarkdownPluginConfig = MarkdownBehaviorsConfig & {
181
181
  */
182
182
  declare function MarkdownPlugin(props: {
183
183
  config: MarkdownPluginConfig;
184
- }): react22.JSX.Element;
184
+ }): react12.JSX.Element;
185
185
  /**
186
186
  * @beta
187
187
  * Restrict the editor to one line. The plugin takes care of blocking
@@ -192,5 +192,5 @@ declare function MarkdownPlugin(props: {
192
192
  *
193
193
  * @deprecated Install the plugin from `@portabletext/plugin-one-line`
194
194
  */
195
- declare function OneLinePlugin(): react22.JSX.Element;
195
+ declare function OneLinePlugin(): react12.JSX.Element;
196
196
  export { BehaviorPlugin, DecoratorShortcutPlugin, EditorRefPlugin, EventListenerPlugin, MarkdownPlugin, type MarkdownPluginConfig, OneLinePlugin };
@@ -1,5 +1,5 @@
1
1
  import { Behavior, Editor, EditorEmittedEvent, EditorSchema } from "../_chunks-dts/behavior.types.action.js";
2
- import * as react21 from "react";
2
+ import * as react22 from "react";
3
3
  import React from "react";
4
4
  /**
5
5
  * @beta
@@ -181,7 +181,7 @@ type MarkdownPluginConfig = MarkdownBehaviorsConfig & {
181
181
  */
182
182
  declare function MarkdownPlugin(props: {
183
183
  config: MarkdownPluginConfig;
184
- }): react21.JSX.Element;
184
+ }): react22.JSX.Element;
185
185
  /**
186
186
  * @beta
187
187
  * Restrict the editor to one line. The plugin takes care of blocking
@@ -192,5 +192,5 @@ declare function MarkdownPlugin(props: {
192
192
  *
193
193
  * @deprecated Install the plugin from `@portabletext/plugin-one-line`
194
194
  */
195
- declare function OneLinePlugin(): react21.JSX.Element;
195
+ declare function OneLinePlugin(): react22.JSX.Element;
196
196
  export { BehaviorPlugin, DecoratorShortcutPlugin, EditorRefPlugin, EventListenerPlugin, MarkdownPlugin, type MarkdownPluginConfig, OneLinePlugin };
@@ -1,5 +1,5 @@
1
1
  import { BlockOffset, BlockPath, ChildPath, EditorContext, EditorSelection, EditorSelectionPoint } from "../_chunks-dts/behavior.types.action.js";
2
- import * as _sanity_types9 from "@sanity/types";
2
+ import * as _sanity_types8 from "@sanity/types";
3
3
  import { KeyedSegment, PortableTextBlock, PortableTextTextBlock } from "@sanity/types";
4
4
  import { isSpan, isTextBlock } from "@portabletext/schema";
5
5
  /**
@@ -143,7 +143,7 @@ declare function mergeTextBlocks({
143
143
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>;
144
144
  targetBlock: PortableTextTextBlock;
145
145
  incomingBlock: PortableTextTextBlock;
146
- }): PortableTextTextBlock<_sanity_types9.PortableTextObject | _sanity_types9.PortableTextSpan>;
146
+ }): PortableTextTextBlock<_sanity_types8.PortableTextObject | _sanity_types8.PortableTextSpan>;
147
147
  /**
148
148
  * @public
149
149
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "2.9.1",
3
+ "version": "2.10.0",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -79,7 +79,7 @@
79
79
  "slate-dom": "^0.118.1",
80
80
  "slate-react": "0.117.4",
81
81
  "xstate": "^5.21.0",
82
- "@portabletext/block-tools": "^3.5.5",
82
+ "@portabletext/block-tools": "^3.5.6",
83
83
  "@portabletext/keyboard-shortcuts": "^1.1.1",
84
84
  "@portabletext/patches": "^1.1.8",
85
85
  "@portabletext/schema": "^1.2.0"
@@ -87,8 +87,8 @@
87
87
  "devDependencies": {
88
88
  "@sanity/diff-match-patch": "^3.2.0",
89
89
  "@sanity/pkg-utils": "^8.1.4",
90
- "@sanity/schema": "^4.8.1",
91
- "@sanity/types": "^4.8.1",
90
+ "@sanity/schema": "^4.9.0",
91
+ "@sanity/types": "^4.9.0",
92
92
  "@types/debug": "^4.1.12",
93
93
  "@types/lodash": "^4.17.20",
94
94
  "@types/lodash.startcase": "^4.4.9",
@@ -110,14 +110,14 @@
110
110
  "vite": "^7.1.3",
111
111
  "vitest": "^3.2.4",
112
112
  "vitest-browser-react": "^1.0.1",
113
- "@portabletext/sanity-bridge": "1.1.9",
113
+ "@portabletext/sanity-bridge": "1.1.10",
114
114
  "@portabletext/test": "^0.0.0",
115
115
  "racejar": "1.2.15"
116
116
  },
117
117
  "peerDependencies": {
118
- "@portabletext/sanity-bridge": "^1.1.9",
119
- "@sanity/schema": "^4.8.1",
120
- "@sanity/types": "^4.8.1",
118
+ "@portabletext/sanity-bridge": "^1.1.10",
119
+ "@sanity/schema": "^4.9.0",
120
+ "@sanity/types": "^4.9.0",
121
121
  "react": "^18.3 || ^19",
122
122
  "rxjs": "^7.8.2"
123
123
  },
@@ -1,4 +1,4 @@
1
- import {getFocusTextBlock} from '../selectors'
1
+ import {getFocusTextBlock, getLastBlock} from '../selectors'
2
2
  import {
3
3
  getBlockEndPoint,
4
4
  getBlockStartPoint,
@@ -6,7 +6,7 @@ import {
6
6
  isEqualSelectionPoints,
7
7
  } from '../utils'
8
8
  import {sliceTextBlock} from '../utils/util.slice-text-block'
9
- import {execute, raise} from './behavior.types.action'
9
+ import {raise} from './behavior.types.action'
10
10
  import {defineBehavior} from './behavior.types.behavior'
11
11
 
12
12
  export const abstractInsertBehaviors = [
@@ -328,23 +328,77 @@ export const abstractInsertBehaviors = [
328
328
  actions: [() => [raise({type: 'split'})]],
329
329
  }),
330
330
  defineBehavior({
331
- on: 'insert.inline object',
331
+ on: 'insert.child',
332
+ guard: ({snapshot}) => {
333
+ const lastBlock = getLastBlock(snapshot)
334
+
335
+ if (!lastBlock) {
336
+ return false
337
+ }
338
+
339
+ if (snapshot.context.selection) {
340
+ return false
341
+ }
342
+
343
+ const lastBlockEndPoint = getBlockEndPoint({
344
+ context: snapshot.context,
345
+ block: lastBlock,
346
+ })
347
+
348
+ return {lastBlockEndPoint}
349
+ },
350
+ actions: [
351
+ ({event}, {lastBlockEndPoint}) => [
352
+ raise({
353
+ type: 'select',
354
+ at: {
355
+ anchor: lastBlockEndPoint,
356
+ focus: lastBlockEndPoint,
357
+ },
358
+ }),
359
+ raise(event),
360
+ ],
361
+ ],
362
+ }),
363
+ defineBehavior({
364
+ on: 'insert.child',
365
+ guard: ({snapshot}) => {
366
+ const focusTextBlock = getFocusTextBlock(snapshot)
367
+
368
+ return snapshot.context.selection && !focusTextBlock
369
+ },
332
370
  actions: [
333
371
  ({snapshot, event}) => [
334
- execute({
372
+ raise({
335
373
  type: 'insert.block',
336
374
  block: {
337
375
  _type: snapshot.context.schema.block.name,
338
376
  children: [
339
377
  {
340
- _type: event.inlineObject.name,
341
- ...event.inlineObject.value,
378
+ _type: snapshot.context.schema.span.name,
379
+ text: '',
380
+ marks: [],
342
381
  },
343
382
  ],
344
383
  },
345
384
  placement: 'auto',
346
385
  select: 'end',
347
386
  }),
387
+ raise(event),
388
+ ],
389
+ ],
390
+ }),
391
+ defineBehavior({
392
+ on: 'insert.inline object',
393
+ actions: [
394
+ ({event}) => [
395
+ raise({
396
+ type: 'insert.child',
397
+ child: {
398
+ _type: event.inlineObject.name,
399
+ ...event.inlineObject.value,
400
+ },
401
+ }),
348
402
  ],
349
403
  ],
350
404
  }),
@@ -354,37 +408,68 @@ export const abstractInsertBehaviors = [
354
408
  }),
355
409
  defineBehavior({
356
410
  on: 'insert.span',
357
- guard: ({snapshot, event}) => {
358
- const markDefs =
359
- event.annotations?.map((annotation) => ({
360
- _type: annotation.name,
361
- _key: snapshot.context.keyGenerator(),
362
- ...annotation.value,
363
- })) ?? []
364
-
365
- return {markDefs}
366
- },
411
+ guard: ({snapshot}) => !getFocusTextBlock(snapshot),
367
412
  actions: [
368
- ({snapshot, event}, {markDefs}) => [
369
- execute({
413
+ ({snapshot, event}) => [
414
+ raise({
370
415
  type: 'insert.block',
371
416
  block: {
372
417
  _type: snapshot.context.schema.block.name,
373
418
  children: [
374
419
  {
375
420
  _type: snapshot.context.schema.span.name,
376
- text: event.text,
377
- marks: [
378
- ...(event.decorators ?? []),
379
- ...markDefs.map((markDef) => markDef._key),
380
- ],
421
+ text: '',
422
+ marks: [],
381
423
  },
382
424
  ],
383
- markDefs,
384
425
  },
385
426
  placement: 'auto',
386
427
  select: 'end',
387
428
  }),
429
+ raise(event),
430
+ ],
431
+ ],
432
+ }),
433
+ defineBehavior({
434
+ on: 'insert.span',
435
+ guard: ({snapshot, event}) => {
436
+ const focusTextBlock = getFocusTextBlock(snapshot)
437
+ const markDefs =
438
+ event.annotations?.map((annotation) => ({
439
+ _type: annotation.name,
440
+ _key: snapshot.context.keyGenerator(),
441
+ ...annotation.value,
442
+ })) ?? []
443
+
444
+ return {markDefs, focusTextBlock}
445
+ },
446
+ actions: [
447
+ ({snapshot, event}, {markDefs, focusTextBlock}) => [
448
+ ...(focusTextBlock
449
+ ? [
450
+ raise({
451
+ type: 'block.set',
452
+ at: focusTextBlock.path,
453
+ props: {
454
+ markDefs: [
455
+ ...(focusTextBlock.node.markDefs ?? []),
456
+ ...markDefs,
457
+ ],
458
+ },
459
+ }),
460
+ ]
461
+ : []),
462
+ raise({
463
+ type: 'insert.child',
464
+ child: {
465
+ _type: snapshot.context.schema.span.name,
466
+ text: event.text,
467
+ marks: [
468
+ ...(event.decorators ?? []),
469
+ ...markDefs.map((markDef) => markDef._key),
470
+ ],
471
+ },
472
+ }),
388
473
  ],
389
474
  ],
390
475
  }),
@@ -186,6 +186,7 @@ export const abstractSplitBehaviors = [
186
186
  }),
187
187
  context: snapshot.context,
188
188
  options: {
189
+ removeUnusedMarkDefs: true,
189
190
  validateFields: false,
190
191
  },
191
192
  })
@@ -1,8 +1,9 @@
1
1
  import {createEditorDom} from '../editor/editor-dom'
2
2
  import type {EditorSchema} from '../editor/editor-schema'
3
3
  import type {EditorSnapshot} from '../editor/editor-snapshot'
4
- import {withApplyingBehaviorOperations} from '../editor/with-applying-behavior-operations'
4
+ import {withPerformingBehaviorOperation} from '../editor/with-performing-behavior-operation'
5
5
  import {clearUndoStep, createUndoStep} from '../editor/with-undo-step'
6
+ import {withoutNormalizingConditional} from '../editor/without-normalizing-conditional'
6
7
  import {debugWithName} from '../internal-utils/debug'
7
8
  import {performOperation} from '../operations/behavior.operations'
8
9
  import type {PortableTextSlateEditor} from '../types/editor'
@@ -112,7 +113,7 @@ export function performEvent({
112
113
  clearUndoStep(editor)
113
114
  }
114
115
 
115
- withApplyingBehaviorOperations(editor, () => {
116
+ withPerformingBehaviorOperation(editor, () => {
116
117
  debug(`(execute:${eventCategory(event)})`, JSON.stringify(event, null, 2))
117
118
 
118
119
  performOperation({
@@ -198,6 +199,8 @@ export function performEvent({
198
199
  (action) => action.type === 'raise' || action.type === 'execute',
199
200
  ) || !actions.some((action) => action.type === 'forward')
200
201
 
202
+ let undoStepCreated = false
203
+
201
204
  if (actions.some((action) => action.type === 'execute')) {
202
205
  // Since at least one action is about to `execute` changes in the editor,
203
206
  // we set up a new undo step.
@@ -205,139 +208,102 @@ export function performEvent({
205
208
  // undo step
206
209
  createUndoStep(editor)
207
210
 
208
- for (const action of actions) {
209
- if (action.type === 'effect') {
210
- try {
211
- action.effect({
212
- send: sendBack,
213
- })
214
- } catch (error) {
215
- console.error(
216
- new Error(
217
- `Executing effect as a result of "${event.type}" failed due to: ${error.message}`,
218
- ),
219
- )
211
+ undoStepCreated = true
212
+ }
213
+
214
+ const actionTypes = actions.map((action) => action.type)
215
+ const uniqueActionTypes = new Set(actionTypes)
216
+
217
+ // The set of actions are all `raise` actions
218
+ const raiseGroup =
219
+ actionTypes.length > 1 &&
220
+ uniqueActionTypes.size === 1 &&
221
+ uniqueActionTypes.has('raise')
222
+
223
+ // The set of actions are all `execute` actions
224
+ const executeGroup =
225
+ actionTypes.length > 1 &&
226
+ uniqueActionTypes.size === 1 &&
227
+ uniqueActionTypes.has('execute')
228
+
229
+ withoutNormalizingConditional(
230
+ editor,
231
+ () => raiseGroup || executeGroup,
232
+ () => {
233
+ for (const action of actions) {
234
+ if (action.type === 'effect') {
235
+ try {
236
+ action.effect({
237
+ send: sendBack,
238
+ })
239
+ } catch (error) {
240
+ console.error(
241
+ new Error(
242
+ `Executing effect as a result of "${event.type}" failed due to: ${error.message}`,
243
+ ),
244
+ )
245
+ }
246
+
247
+ continue
220
248
  }
221
249
 
222
- continue
223
- }
250
+ if (action.type === 'forward') {
251
+ const remainingEventBehaviors = eventBehaviors.slice(
252
+ eventBehaviorIndex + 1,
253
+ )
224
254
 
225
- if (action.type === 'forward') {
226
- const remainingEventBehaviors = eventBehaviors.slice(
227
- eventBehaviorIndex + 1,
228
- )
255
+ performEvent({
256
+ mode: mode === 'execute' ? 'execute' : 'forward',
257
+ behaviors,
258
+ remainingEventBehaviors: remainingEventBehaviors,
259
+ event: action.event,
260
+ editor,
261
+ keyGenerator,
262
+ schema,
263
+ getSnapshot,
264
+ nativeEvent,
265
+ sendBack,
266
+ })
229
267
 
230
- performEvent({
231
- mode: 'forward',
232
- behaviors,
233
- remainingEventBehaviors: remainingEventBehaviors,
234
- event: action.event,
235
- editor,
236
- keyGenerator,
237
- schema,
238
- getSnapshot,
239
- nativeEvent,
240
- sendBack,
241
- })
268
+ continue
269
+ }
242
270
 
243
- continue
244
- }
271
+ if (action.type === 'raise') {
272
+ performEvent({
273
+ mode: mode === 'execute' ? 'execute' : 'raise',
274
+ behaviors,
275
+ remainingEventBehaviors:
276
+ mode === 'execute' ? remainingEventBehaviors : behaviors,
277
+ event: action.event,
278
+ editor,
279
+ keyGenerator,
280
+ schema,
281
+ getSnapshot,
282
+ nativeEvent,
283
+ sendBack,
284
+ })
285
+
286
+ continue
287
+ }
245
288
 
246
- if (action.type === 'raise') {
247
289
  performEvent({
248
- mode: 'raise',
290
+ mode: 'execute',
249
291
  behaviors,
250
- remainingEventBehaviors: behaviors,
292
+ remainingEventBehaviors: [],
251
293
  event: action.event,
252
294
  editor,
253
295
  keyGenerator,
254
296
  schema,
255
297
  getSnapshot,
256
- nativeEvent,
298
+ nativeEvent: undefined,
257
299
  sendBack,
258
300
  })
259
-
260
- continue
261
301
  }
302
+ },
303
+ )
262
304
 
263
- performEvent({
264
- mode: 'execute',
265
- behaviors,
266
- remainingEventBehaviors: [],
267
- event: action.event,
268
- editor,
269
- keyGenerator,
270
- schema,
271
- getSnapshot,
272
- nativeEvent: undefined,
273
- sendBack,
274
- })
275
- }
276
-
305
+ if (undoStepCreated) {
277
306
  clearUndoStep(editor)
278
-
279
- continue
280
- }
281
-
282
- for (const action of actions) {
283
- if (action.type === 'effect') {
284
- try {
285
- action.effect({
286
- send: sendBack,
287
- })
288
- } catch (error) {
289
- console.error(
290
- new Error(
291
- `Executing effect as a result of "${event.type}" failed due to: ${error.message}`,
292
- ),
293
- )
294
- }
295
-
296
- continue
297
- }
298
-
299
- if (action.type === 'forward') {
300
- const remainingEventBehaviors = eventBehaviors.slice(
301
- eventBehaviorIndex + 1,
302
- )
303
-
304
- performEvent({
305
- mode: 'forward',
306
- behaviors,
307
- remainingEventBehaviors: remainingEventBehaviors,
308
- event: action.event,
309
- editor,
310
- keyGenerator,
311
- schema,
312
- getSnapshot,
313
- nativeEvent,
314
- sendBack,
315
- })
316
-
317
- continue
318
- }
319
-
320
- if (action.type === 'raise') {
321
- performEvent({
322
- mode: 'raise',
323
- behaviors,
324
- remainingEventBehaviors:
325
- mode === 'execute' ? remainingEventBehaviors : behaviors,
326
- event: action.event,
327
- editor,
328
- keyGenerator,
329
- schema,
330
- getSnapshot,
331
- nativeEvent,
332
- sendBack,
333
- })
334
-
335
- continue
336
- }
337
-
338
- if (action.type === 'execute') {
339
- console.error('Unexpected action type: `execute`')
340
- }
341
307
  }
342
308
  }
343
309
 
@@ -351,7 +317,7 @@ export function performEvent({
351
317
  clearUndoStep(editor)
352
318
  }
353
319
 
354
- withApplyingBehaviorOperations(editor, () => {
320
+ withPerformingBehaviorOperation(editor, () => {
355
321
  debug(`(execute:${eventCategory(event)})`, JSON.stringify(event, null, 2))
356
322
 
357
323
  performOperation({
@@ -3,7 +3,10 @@ import type {EventPosition} from '../internal-utils/event-position'
3
3
  import type {MIMEType} from '../internal-utils/mime-type'
4
4
  import type {OmitFromUnion, PickFromUnion, StrictExtract} from '../type-utils'
5
5
  import type {BlockOffset} from '../types/block-offset'
6
- import type {BlockWithOptionalKey} from '../types/block-with-optional-key'
6
+ import type {
7
+ BlockWithOptionalKey,
8
+ ChildWithOptionalKey,
9
+ } from '../types/block-with-optional-key'
7
10
  import type {EditorSelection} from '../types/editor'
8
11
  import type {AnnotationPath, BlockPath, ChildPath} from '../types/paths'
9
12
 
@@ -72,6 +75,7 @@ const syntheticBehaviorEventTypes = [
72
75
  'history.redo',
73
76
  'history.undo',
74
77
  'insert.block',
78
+ 'insert.child',
75
79
  'insert.text',
76
80
  'move.backward',
77
81
  'move.block',
@@ -159,6 +163,10 @@ export type SyntheticBehaviorEvent =
159
163
  placement: InsertPlacement
160
164
  select?: 'start' | 'end' | 'none'
161
165
  }
166
+ | {
167
+ type: StrictExtract<SyntheticBehaviorEventType, 'insert.child'>
168
+ child: ChildWithOptionalKey
169
+ }
162
170
  | {
163
171
  type: StrictExtract<SyntheticBehaviorEventType, 'insert.text'>
164
172
  text: string
@@ -50,6 +50,7 @@ export const converterPortableText = defineConverter({
50
50
  context: snapshot.context,
51
51
  block,
52
52
  options: {
53
+ removeUnusedMarkDefs: true,
53
54
  validateFields: false,
54
55
  },
55
56
  })
@@ -61,6 +61,7 @@ export function createConverterTextHtml(
61
61
  context: snapshot.context,
62
62
  block,
63
63
  options: {
64
+ removeUnusedMarkDefs: true,
64
65
  validateFields: false,
65
66
  },
66
67
  })
@@ -85,6 +85,7 @@ export function createConverterTextPlain(
85
85
  context: snapshot.context,
86
86
  block,
87
87
  options: {
88
+ removeUnusedMarkDefs: true,
88
89
  validateFields: false,
89
90
  },
90
91
  })
@@ -461,6 +461,7 @@ export const PortableTextEditable = forwardRef<
461
461
  },
462
462
  blocks: result.insert,
463
463
  options: {
464
+ removeUnusedMarkDefs: true,
464
465
  validateFields: false,
465
466
  },
466
467
  }),
@@ -1,5 +1,6 @@
1
1
  import {useSelector} from '@xstate/react'
2
2
  import type {Editor} from '../editor'
3
+ import {slateRangeToSelection} from '../internal-utils/slate-utils'
3
4
  import type {PortableTextSlateEditor} from '../types/editor'
4
5
  import type {InternalEditor} from './create-editor'
5
6
  import type {EditorActor} from './editor-machine'
@@ -65,6 +66,14 @@ export function getEditorSnapshot({
65
66
  editorActorSnapshot: ReturnType<EditorActor['getSnapshot']>
66
67
  slateEditorInstance: PortableTextSlateEditor
67
68
  }): EditorSnapshot {
69
+ const selection = slateEditorInstance.selection
70
+ ? slateRangeToSelection({
71
+ schema: editorActorSnapshot.context.schema,
72
+ editor: slateEditorInstance,
73
+ range: slateEditorInstance.selection,
74
+ })
75
+ : null
76
+
68
77
  return {
69
78
  blockIndexMap: slateEditorInstance.blockIndexMap,
70
79
  context: {
@@ -72,7 +81,7 @@ export function getEditorSnapshot({
72
81
  keyGenerator: editorActorSnapshot.context.keyGenerator,
73
82
  readOnly: editorActorSnapshot.matches({'edit mode': 'read only'}),
74
83
  schema: editorActorSnapshot.context.schema,
75
- selection: editorActorSnapshot.context.selection,
84
+ selection,
76
85
  value: slateEditorInstance.value,
77
86
  },
78
87
  decoratorState: slateEditorInstance.decoratorState,