@portabletext/editor 2.8.0 → 2.8.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 (46) hide show
  1. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs +10 -4
  2. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +1 -1
  3. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +0 -1
  4. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
  5. package/lib/_chunks-cjs/util.slice-blocks.cjs +3 -6
  6. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  7. package/lib/_chunks-dts/behavior.types.action.d.cts +27 -31
  8. package/lib/_chunks-dts/behavior.types.action.d.ts +18 -22
  9. package/lib/_chunks-es/selector.is-selection-expanded.js +10 -4
  10. package/lib/_chunks-es/selector.is-selection-expanded.js.map +1 -1
  11. package/lib/_chunks-es/util.merge-text-blocks.js +0 -1
  12. package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -1
  13. package/lib/_chunks-es/util.slice-blocks.js +3 -6
  14. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  15. package/lib/index.cjs +28 -51
  16. package/lib/index.cjs.map +1 -1
  17. package/lib/index.js +28 -51
  18. package/lib/index.js.map +1 -1
  19. package/lib/plugins/index.d.cts +3 -3
  20. package/lib/utils/index.d.ts +2 -2
  21. package/package.json +5 -5
  22. package/src/behaviors/behavior.abstract.split.ts +0 -1
  23. package/src/converters/converter.portable-text.ts +0 -1
  24. package/src/converters/converter.text-html.ts +0 -1
  25. package/src/converters/converter.text-plain.ts +0 -1
  26. package/src/editor/Editable.tsx +0 -1
  27. package/src/editor/PortableTextEditor.tsx +1 -1
  28. package/src/editor/plugins/createWithEditableAPI.ts +70 -28
  29. package/src/index.ts +1 -1
  30. package/src/internal-utils/parse-blocks.test.ts +23 -23
  31. package/src/internal-utils/parse-blocks.ts +11 -23
  32. package/src/internal-utils/test-editor.tsx +15 -21
  33. package/src/operations/behavior.operation.annotation.add.ts +2 -47
  34. package/src/operations/behavior.operation.block.set.ts +1 -1
  35. package/src/operations/behavior.operation.block.unset.ts +2 -2
  36. package/src/operations/behavior.operation.insert.block.ts +1 -1
  37. package/src/operations/behavior.operations.ts +1 -2
  38. package/src/plugins/plugin.internal.auto-close-brackets.test.tsx +25 -71
  39. package/src/plugins/plugin.markdown.test.tsx +12 -30
  40. package/src/selectors/selector.get-selected-value.test.ts +748 -0
  41. package/src/selectors/selector.get-selected-value.ts +28 -7
  42. package/src/selectors/selector.get-trimmed-selection.test.ts +0 -1
  43. package/src/types/editor.ts +19 -3
  44. package/src/utils/util.merge-text-blocks.ts +1 -1
  45. package/src/utils/util.slice-blocks.ts +3 -3
  46. package/src/utils/util.slice-blocks.test.ts +0 -499
@@ -1,5 +1,5 @@
1
1
  import { Behavior, Editor, EditorEmittedEvent, EditorSchema } from "../_chunks-dts/behavior.types.action.cjs";
2
- import * as react21 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
- }): react21.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(): react21.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 { BlockOffset, BlockPath, ChildPath, EditorContext, EditorSelection, EditorSelectionPoint } from "../_chunks-dts/behavior.types.action.js";
2
- import * as _sanity_types8 from "@sanity/types";
2
+ import * as _sanity_types9 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_types8.PortableTextObject | _sanity_types8.PortableTextSpan>;
146
+ }): PortableTextTextBlock<_sanity_types9.PortableTextObject | _sanity_types9.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.8.0",
3
+ "version": "2.8.2",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -80,9 +80,9 @@
80
80
  "slate-react": "0.117.4",
81
81
  "xstate": "^5.21.0",
82
82
  "@portabletext/block-tools": "^3.5.3",
83
- "@portabletext/patches": "^1.1.8",
83
+ "@portabletext/keyboard-shortcuts": "^1.1.1",
84
84
  "@portabletext/schema": "^1.2.0",
85
- "@portabletext/keyboard-shortcuts": "^1.1.1"
85
+ "@portabletext/patches": "^1.1.8"
86
86
  },
87
87
  "devDependencies": {
88
88
  "@sanity/diff-match-patch": "^3.2.0",
@@ -110,9 +110,9 @@
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.8",
113
114
  "@portabletext/test": "^0.0.0",
114
- "racejar": "1.2.15",
115
- "@portabletext/sanity-bridge": "1.1.8"
115
+ "racejar": "1.2.15"
116
116
  },
117
117
  "peerDependencies": {
118
118
  "@portabletext/sanity-bridge": "^1.1.8",
@@ -186,7 +186,6 @@ export const abstractSplitBehaviors = [
186
186
  }),
187
187
  context: snapshot.context,
188
188
  options: {
189
- refreshKeys: false,
190
189
  validateFields: false,
191
190
  },
192
191
  })
@@ -50,7 +50,6 @@ export const converterPortableText = defineConverter({
50
50
  context: snapshot.context,
51
51
  block,
52
52
  options: {
53
- refreshKeys: false,
54
53
  validateFields: false,
55
54
  },
56
55
  })
@@ -61,7 +61,6 @@ export function createConverterTextHtml(
61
61
  context: snapshot.context,
62
62
  block,
63
63
  options: {
64
- refreshKeys: false,
65
64
  validateFields: false,
66
65
  },
67
66
  })
@@ -85,7 +85,6 @@ export function createConverterTextPlain(
85
85
  context: snapshot.context,
86
86
  block,
87
87
  options: {
88
- refreshKeys: false,
89
88
  validateFields: false,
90
89
  },
91
90
  })
@@ -461,7 +461,6 @@ export const PortableTextEditable = forwardRef<
461
461
  },
462
462
  blocks: result.insert,
463
463
  options: {
464
- refreshKeys: false,
465
464
  validateFields: false,
466
465
  },
467
466
  }),
@@ -16,8 +16,8 @@ import {Subject} from 'rxjs'
16
16
  import {Slate} from 'slate-react'
17
17
  import {debugWithName} from '../internal-utils/debug'
18
18
  import {stopActor} from '../internal-utils/stop-actor'
19
- import type {AddedAnnotationPaths} from '../operations/behavior.operation.annotation.add'
20
19
  import type {
20
+ AddedAnnotationPaths,
21
21
  EditableAPI,
22
22
  EditableAPIDeleteOptions,
23
23
  EditorChange,
@@ -1,3 +1,4 @@
1
+ import {isTextBlock} from '@portabletext/schema'
1
2
  import type {
2
3
  Path,
3
4
  PortableTextBlock,
@@ -29,8 +30,12 @@ import {
29
30
  KEY_TO_VALUE_ELEMENT,
30
31
  SLATE_TO_PORTABLE_TEXT_RANGE,
31
32
  } from '../../internal-utils/weakMaps'
32
- import {addAnnotationOperationImplementation} from '../../operations/behavior.operation.annotation.add'
33
- import {isActiveAnnotation} from '../../selectors'
33
+ import {
34
+ getFocusBlock,
35
+ getFocusSpan,
36
+ getSelectedValue,
37
+ isActiveAnnotation,
38
+ } from '../../selectors'
34
39
  import {getActiveAnnotationsMarks} from '../../selectors/selector.get-active-annotation-marks'
35
40
  import {getActiveDecorators} from '../../selectors/selector.get-active-decorators'
36
41
  import type {
@@ -424,40 +429,77 @@ export function createEditableAPI(
424
429
  return isActiveAnnotation(annotationType)(snapshot)
425
430
  },
426
431
  addAnnotation: (type, value) => {
427
- let paths: ReturnType<EditableAPI['addAnnotation']>
432
+ const snapshotBefore = getEditorSnapshot({
433
+ editorActorSnapshot: editorActor.getSnapshot(),
434
+ slateEditorInstance: editor,
435
+ })
436
+ const selectedValueBefore = getSelectedValue(snapshotBefore)
437
+ const focusSpanBefore = getFocusSpan(snapshotBefore)
438
+ const markDefsBefore = selectedValueBefore.flatMap((block) => {
439
+ if (isTextBlock(snapshotBefore.context, block)) {
440
+ return block.markDefs ?? []
441
+ }
428
442
 
429
- const snapshot = getEditorSnapshot({
443
+ return []
444
+ })
445
+
446
+ editorActor.send({
447
+ type: 'behavior event',
448
+ behaviorEvent: {
449
+ type: 'annotation.add',
450
+ annotation: {name: type.name, value: value ?? {}},
451
+ },
452
+ editor,
453
+ })
454
+
455
+ const snapshotAfter = getEditorSnapshot({
430
456
  editorActorSnapshot: editorActor.getSnapshot(),
431
457
  slateEditorInstance: editor,
432
458
  })
433
459
 
434
- if (isActiveAnnotation(type.name, {mode: 'partial'})(snapshot)) {
435
- editorActor.send({
436
- type: 'behavior event',
437
- behaviorEvent: {
438
- type: 'annotation.remove',
439
- annotation: {name: type.name},
440
- },
441
- editor,
442
- })
443
- }
460
+ const selectedValueAfter = getSelectedValue(snapshotAfter)
461
+ const focusBlockAfter = getFocusBlock(snapshotAfter)
462
+ const focusSpanAfter = getFocusSpan(snapshotAfter)
444
463
 
445
- Editor.withoutNormalizing(editor, () => {
446
- paths = addAnnotationOperationImplementation({
447
- context: {
448
- keyGenerator: editorActor.getSnapshot().context.keyGenerator,
449
- schema: types,
450
- },
451
- operation: {
452
- type: 'annotation.add',
453
- annotation: {name: type.name, value: value ?? {}},
454
- editor,
455
- },
456
- })
464
+ const newMarkDefKeysOnFocusSpan = focusSpanAfter?.node.marks?.filter(
465
+ (mark) =>
466
+ !focusSpanBefore?.node.marks?.includes(mark) &&
467
+ !snapshotAfter.context.schema.decorators
468
+ .map((decorator) => decorator.name)
469
+ .includes(mark),
470
+ )
471
+ const markDefsAfter = selectedValueAfter.flatMap((block) => {
472
+ if (isTextBlock(snapshotAfter.context, block)) {
473
+ return (
474
+ block.markDefs?.map((markDef) => ({
475
+ markDef,
476
+ path: [{_key: block._key}, 'markDefs', {_key: markDef._key}],
477
+ })) ?? []
478
+ )
479
+ }
480
+
481
+ return []
457
482
  })
458
- editor.onChange()
483
+ const markDefs = markDefsAfter.filter(
484
+ (markDef) =>
485
+ !markDefsBefore.some(
486
+ (markDefBefore) => markDefBefore._key === markDef.markDef._key,
487
+ ),
488
+ )
489
+ const spanPath = focusSpanAfter?.path
490
+ const markDef = markDefs.find((markDef) =>
491
+ newMarkDefKeysOnFocusSpan?.some(
492
+ (mark) => mark === markDef.markDef._key,
493
+ ),
494
+ )
459
495
 
460
- return paths
496
+ if (focusBlockAfter && spanPath && markDef) {
497
+ return {
498
+ markDefPath: markDef.path,
499
+ markDefPaths: markDefs.map((markDef) => markDef.path),
500
+ spanPath,
501
+ }
502
+ }
461
503
  },
462
504
  delete: (
463
505
  selection: EditorSelection,
package/src/index.ts CHANGED
@@ -45,7 +45,7 @@ export {PortableTextEditor} from './editor/PortableTextEditor'
45
45
  export type {PortableTextEditorProps} from './editor/PortableTextEditor'
46
46
  export type {EditorEmittedEvent, MutationEvent} from './editor/relay-machine'
47
47
  export {useEditor} from './editor/use-editor'
48
- export type {AddedAnnotationPaths} from './operations/behavior.operation.annotation.add'
48
+ export type {AddedAnnotationPaths} from './types/editor'
49
49
  export type {BlockOffset} from './types/block-offset'
50
50
  export type {
51
51
  BlockAnnotationRenderProps,
@@ -12,7 +12,7 @@ describe(parseBlock.name, () => {
12
12
  keyGenerator: createTestKeyGenerator(),
13
13
  schema: compileSchema(defineSchema({})),
14
14
  },
15
- options: {refreshKeys: false, validateFields: true},
15
+ options: {validateFields: true},
16
16
  }),
17
17
  ).toBe(undefined)
18
18
  })
@@ -25,7 +25,7 @@ describe(parseBlock.name, () => {
25
25
  keyGenerator: createTestKeyGenerator(),
26
26
  schema: compileSchema(defineSchema({})),
27
27
  },
28
- options: {refreshKeys: false, validateFields: true},
28
+ options: {validateFields: true},
29
29
  }),
30
30
  ).toBe(undefined)
31
31
  })
@@ -39,7 +39,7 @@ describe(parseBlock.name, () => {
39
39
  keyGenerator: createTestKeyGenerator(),
40
40
  schema: compileSchema(defineSchema({})),
41
41
  },
42
- options: {refreshKeys: false, validateFields: true},
42
+ options: {validateFields: true},
43
43
  }),
44
44
  ).toBe(undefined)
45
45
  })
@@ -54,7 +54,7 @@ describe(parseBlock.name, () => {
54
54
  defineSchema({blockObjects: [{name: 'image'}]}),
55
55
  ),
56
56
  },
57
- options: {refreshKeys: false, validateFields: true},
57
+ options: {validateFields: true},
58
58
  }),
59
59
  ).toBe(undefined)
60
60
  })
@@ -69,7 +69,7 @@ describe(parseBlock.name, () => {
69
69
  defineSchema({blockObjects: [{name: 'image'}]}),
70
70
  ),
71
71
  },
72
- options: {refreshKeys: false, validateFields: true},
72
+ options: {validateFields: true},
73
73
  }),
74
74
  ).toEqual({
75
75
  _key: 'k0',
@@ -87,7 +87,7 @@ describe(parseBlock.name, () => {
87
87
  keyGenerator: createTestKeyGenerator(),
88
88
  schema: compileSchema(defineSchema({})),
89
89
  },
90
- options: {refreshKeys: false, validateFields: true},
90
+ options: {validateFields: true},
91
91
  }),
92
92
  ).toEqual({
93
93
  _key: 'k0',
@@ -114,7 +114,7 @@ describe(parseBlock.name, () => {
114
114
  keyGenerator: createTestKeyGenerator(),
115
115
  schema: {...schema, block: {...schema.block, name: 'text'}},
116
116
  },
117
- options: {refreshKeys: false, validateFields: true},
117
+ options: {validateFields: true},
118
118
  }),
119
119
  ).toEqual({
120
120
  _key: 'k0',
@@ -149,7 +149,7 @@ describe(parseBlock.name, () => {
149
149
  keyGenerator: createTestKeyGenerator(),
150
150
  schema: compileSchema(defineSchema({})),
151
151
  },
152
- options: {refreshKeys: false, validateFields: true},
152
+ options: {validateFields: true},
153
153
  }),
154
154
  ).toBe(undefined)
155
155
  })
@@ -188,7 +188,7 @@ describe(parseBlock.name, () => {
188
188
  }),
189
189
  ),
190
190
  },
191
- options: {refreshKeys: false, validateFields: true},
191
+ options: {validateFields: true},
192
192
  }),
193
193
  ).toEqual({
194
194
  _key: 'k0',
@@ -236,7 +236,7 @@ describe(parseBlock.name, () => {
236
236
  keyGenerator: createTestKeyGenerator(),
237
237
  schema: compileSchema(defineSchema({lists: [{name: 'bullet'}]})),
238
238
  },
239
- options: {refreshKeys: false, validateFields: true},
239
+ options: {validateFields: true},
240
240
  }),
241
241
  ).toEqual({
242
242
  _key: 'k0',
@@ -263,7 +263,7 @@ describe(parseBlock.name, () => {
263
263
  keyGenerator: createTestKeyGenerator(),
264
264
  schema: compileSchema(defineSchema({lists: [{name: 'bullet'}]})),
265
265
  },
266
- options: {refreshKeys: false, validateFields: true},
266
+ options: {validateFields: true},
267
267
  }),
268
268
  ).toEqual({
269
269
  _key: 'k0',
@@ -290,7 +290,7 @@ describe(parseBlock.name, () => {
290
290
  keyGenerator: createTestKeyGenerator(),
291
291
  schema: compileSchema(defineSchema({})),
292
292
  },
293
- options: {refreshKeys: false, validateFields: true},
293
+ options: {validateFields: true},
294
294
  }),
295
295
  ).toEqual({
296
296
  _type: 'block',
@@ -320,7 +320,7 @@ describe(parseBlock.name, () => {
320
320
  }),
321
321
  ),
322
322
  },
323
- options: {refreshKeys: false, validateFields: true},
323
+ options: {validateFields: true},
324
324
  }),
325
325
  ).toEqual({
326
326
  _type: 'block',
@@ -351,7 +351,7 @@ describe(parseBlock.name, () => {
351
351
  }),
352
352
  ),
353
353
  },
354
- options: {refreshKeys: false, validateFields: true},
354
+ options: {validateFields: true},
355
355
  }),
356
356
  ).toEqual({
357
357
  _type: 'block',
@@ -382,7 +382,7 @@ describe(parseSpan.name, () => {
382
382
  schema: compileSchema(defineSchema({})),
383
383
  },
384
384
  markDefKeyMap: new Map(),
385
- options: {refreshKeys: false, validateFields: true},
385
+ options: {validateFields: true},
386
386
  }),
387
387
  ).toBe(undefined)
388
388
  })
@@ -396,7 +396,7 @@ describe(parseSpan.name, () => {
396
396
  schema: compileSchema(defineSchema({})),
397
397
  },
398
398
  markDefKeyMap: new Map(),
399
- options: {refreshKeys: false, validateFields: true},
399
+ options: {validateFields: true},
400
400
  }),
401
401
  ).toBe(undefined)
402
402
  })
@@ -410,7 +410,7 @@ describe(parseSpan.name, () => {
410
410
  schema: compileSchema(defineSchema({})),
411
411
  },
412
412
  markDefKeyMap: new Map(),
413
- options: {refreshKeys: false, validateFields: true},
413
+ options: {validateFields: true},
414
414
  }),
415
415
  ).toBe(undefined)
416
416
  })
@@ -424,7 +424,7 @@ describe(parseSpan.name, () => {
424
424
  schema: compileSchema(defineSchema({})),
425
425
  },
426
426
  markDefKeyMap: new Map(),
427
- options: {refreshKeys: false, validateFields: true},
427
+ options: {validateFields: true},
428
428
  }),
429
429
  ).toBe(undefined)
430
430
  })
@@ -438,7 +438,7 @@ describe(parseSpan.name, () => {
438
438
  schema: compileSchema(defineSchema({})),
439
439
  },
440
440
  markDefKeyMap: new Map(),
441
- options: {refreshKeys: false, validateFields: true},
441
+ options: {validateFields: true},
442
442
  }),
443
443
  ).toEqual({
444
444
  _key: 'k0',
@@ -457,7 +457,7 @@ describe(parseSpan.name, () => {
457
457
  schema: compileSchema(defineSchema({})),
458
458
  },
459
459
  markDefKeyMap: new Map(),
460
- options: {refreshKeys: false, validateFields: true},
460
+ options: {validateFields: true},
461
461
  }),
462
462
  ).toEqual({
463
463
  _key: 'k0',
@@ -479,7 +479,7 @@ describe(parseSpan.name, () => {
479
479
  schema: compileSchema(defineSchema({})),
480
480
  },
481
481
  markDefKeyMap: new Map(),
482
- options: {refreshKeys: false, validateFields: true},
482
+ options: {validateFields: true},
483
483
  }),
484
484
  ).toEqual({
485
485
  _key: 'k0',
@@ -501,7 +501,7 @@ describe(parseSpan.name, () => {
501
501
  schema: compileSchema(defineSchema({decorators: [{name: 'strong'}]})),
502
502
  },
503
503
  markDefKeyMap: new Map(),
504
- options: {refreshKeys: false, validateFields: true},
504
+ options: {validateFields: true},
505
505
  }),
506
506
  ).toEqual({
507
507
  _key: 'k0',
@@ -523,7 +523,7 @@ describe(parseSpan.name, () => {
523
523
  schema: compileSchema(defineSchema({decorators: [{name: 'strong'}]})),
524
524
  },
525
525
  markDefKeyMap: new Map(),
526
- options: {refreshKeys: false, validateFields: true},
526
+ options: {validateFields: true},
527
527
  }),
528
528
  ).toEqual({
529
529
  _key: 'k0',
@@ -19,7 +19,6 @@ export function parseBlocks({
19
19
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
20
20
  blocks: unknown
21
21
  options: {
22
- refreshKeys: boolean
23
22
  validateFields: boolean
24
23
  }
25
24
  }): Array<PortableTextBlock> {
@@ -42,7 +41,6 @@ export function parseBlock({
42
41
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
43
42
  block: unknown
44
43
  options: {
45
- refreshKeys: boolean
46
44
  validateFields: boolean
47
45
  }
48
46
  }): PortableTextBlock | undefined {
@@ -59,7 +57,7 @@ export function parseBlockObject({
59
57
  }: {
60
58
  blockObject: unknown
61
59
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
62
- options: {refreshKeys: boolean; validateFields: boolean}
60
+ options: {validateFields: boolean}
63
61
  }): PortableTextObject | undefined {
64
62
  if (!isTypedObject(blockObject)) {
65
63
  return undefined
@@ -101,7 +99,7 @@ export function parseTextBlock({
101
99
  }: {
102
100
  block: unknown
103
101
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
104
- options: {refreshKeys: boolean; validateFields: boolean}
102
+ options: {validateFields: boolean}
105
103
  }): PortableTextTextBlock | undefined {
106
104
  if (!isTypedObject(block)) {
107
105
  return undefined
@@ -135,11 +133,8 @@ export function parseTextBlock({
135
133
  return undefined
136
134
  }
137
135
 
138
- const _key = options.refreshKeys
139
- ? context.keyGenerator()
140
- : typeof block._key === 'string'
141
- ? block._key
142
- : context.keyGenerator()
136
+ const _key =
137
+ typeof block._key === 'string' ? block._key : context.keyGenerator()
143
138
 
144
139
  const unparsedMarkDefs: Array<unknown> = Array.isArray(block.markDefs)
145
140
  ? block.markDefs
@@ -251,7 +246,7 @@ export function parseSpan({
251
246
  span: unknown
252
247
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
253
248
  markDefKeyMap: Map<string, string>
254
- options: {refreshKeys: boolean; validateFields: boolean}
249
+ options: {validateFields: boolean}
255
250
  }): PortableTextSpan | undefined {
256
251
  if (!isTypedObject(span)) {
257
252
  return undefined
@@ -300,11 +295,7 @@ export function parseSpan({
300
295
 
301
296
  return {
302
297
  _type: 'span',
303
- _key: options.refreshKeys
304
- ? context.keyGenerator()
305
- : typeof span._key === 'string'
306
- ? span._key
307
- : context.keyGenerator(),
298
+ _key: typeof span._key === 'string' ? span._key : context.keyGenerator(),
308
299
  text: typeof span.text === 'string' ? span.text : '',
309
300
  marks,
310
301
  ...(options.validateFields ? {} : customFields),
@@ -318,7 +309,7 @@ export function parseInlineObject({
318
309
  }: {
319
310
  inlineObject: unknown
320
311
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
321
- options: {refreshKeys: boolean; validateFields: boolean}
312
+ options: {validateFields: boolean}
322
313
  }): PortableTextObject | undefined {
323
314
  if (!isTypedObject(inlineObject)) {
324
315
  return undefined
@@ -349,7 +340,7 @@ export function parseAnnotation({
349
340
  }: {
350
341
  annotation: TypedObject
351
342
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
352
- options: {refreshKeys: boolean; validateFields: boolean}
343
+ options: {validateFields: boolean}
353
344
  }): PortableTextObject | undefined {
354
345
  if (!isTypedObject(annotation)) {
355
346
  return undefined
@@ -382,7 +373,7 @@ function parseObject({
382
373
  context: Pick<EditorContext, 'keyGenerator'> & {
383
374
  schemaType: EditorSchema['blockObjects'][0]
384
375
  }
385
- options: {refreshKeys: boolean; validateFields: boolean}
376
+ options: {validateFields: boolean}
386
377
  }): PortableTextObject {
387
378
  const {_type, _key, ...customFields} = object
388
379
 
@@ -405,11 +396,8 @@ function parseObject({
405
396
 
406
397
  return {
407
398
  _type: context.schemaType.name,
408
- _key: options.refreshKeys
409
- ? context.keyGenerator()
410
- : typeof object._key === 'string'
411
- ? object._key
412
- : context.keyGenerator(),
399
+ _key:
400
+ typeof object._key === 'string' ? object._key : context.keyGenerator(),
413
401
  ...values,
414
402
  }
415
403
  }
@@ -5,13 +5,16 @@ import {page} from '@vitest/browser/context'
5
5
  import React from 'react'
6
6
  import {expect, vi} from 'vitest'
7
7
  import {render} from 'vitest-browser-react'
8
+ import type {Context} from '../../gherkin-tests-v2/step-context'
9
+ import type {NativeBehaviorEvent} from '../behaviors'
8
10
  import type {Editor} from '../editor'
9
- import {PortableTextEditable} from '../editor/Editable'
11
+ import {
12
+ PortableTextEditable,
13
+ type PortableTextEditableProps,
14
+ } from '../editor/Editable'
10
15
  import type {EditorActor} from '../editor/editor-machine'
11
16
  import {EditorProvider} from '../editor/editor-provider'
12
- import type {EditorEmittedEvent} from '../editor/relay-machine'
13
17
  import {EditorRefPlugin} from '../plugins/plugin.editor-ref'
14
- import {EventListenerPlugin} from '../plugins/plugin.event-listener'
15
18
  import {InternalEditorAfterRefPlugin} from '../plugins/plugin.internal.editor-actor-ref'
16
19
  import {InternalSlateEditorRefPlugin} from '../plugins/plugin.internal.slate-editor-ref'
17
20
  import type {PortableTextSlateEditor} from '../types/editor'
@@ -22,12 +25,12 @@ export async function createTestEditor(
22
25
  keyGenerator?: () => string
23
26
  schemaDefinition?: SchemaDefinition
24
27
  children?: React.ReactNode
28
+ editableProps?: PortableTextEditableProps
25
29
  } = {},
26
- ) {
30
+ ): Promise<Pick<Context, 'editor' | 'locator'>> {
27
31
  const editorRef = React.createRef<Editor>()
28
32
  const editorActorRef = React.createRef<EditorActor>()
29
33
  const slateRef = React.createRef<PortableTextSlateEditor>()
30
- const onEvent = vi.fn<() => EditorEmittedEvent>()
31
34
  const keyGenerator = options.keyGenerator ?? createTestKeyGenerator()
32
35
 
33
36
  render(
@@ -41,8 +44,7 @@ export async function createTestEditor(
41
44
  <EditorRefPlugin ref={editorRef} />
42
45
  <InternalEditorAfterRefPlugin ref={editorActorRef} />
43
46
  <InternalSlateEditorRefPlugin ref={slateRef} />
44
- <EventListenerPlugin on={onEvent} />
45
- <PortableTextEditable />
47
+ <PortableTextEditable {...options.editableProps} />
46
48
  {options.children}
47
49
  </EditorProvider>,
48
50
  )
@@ -51,27 +53,19 @@ export async function createTestEditor(
51
53
 
52
54
  await vi.waitFor(() => expect.element(locator).toBeInTheDocument())
53
55
 
54
- function paste(dataTransfer: DataTransfer) {
56
+ function sendNativeEvent(event: NativeBehaviorEvent) {
55
57
  editorActorRef.current?.send({
56
58
  type: 'behavior event',
57
- behaviorEvent: {
58
- type: 'clipboard.paste',
59
- originEvent: {dataTransfer},
60
- position: {
61
- selection: editorRef.current?.getSnapshot().context.selection!,
62
- },
63
- },
59
+ behaviorEvent: event,
64
60
  editor: slateRef.current!,
65
61
  })
66
62
  }
67
63
 
68
64
  return {
69
- editorActorRef,
70
- editorRef,
71
- keyGenerator,
65
+ editor: {
66
+ ...editorRef.current!,
67
+ sendNativeEvent,
68
+ },
72
69
  locator,
73
- onEvent,
74
- slateRef,
75
- paste,
76
70
  }
77
71
  }