@portabletext/editor 2.9.2 → 2.11.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 (42) hide show
  1. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +1 -0
  2. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
  3. package/lib/_chunks-cjs/util.slice-blocks.cjs +6 -1
  4. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  5. package/lib/_chunks-dts/behavior.types.action.d.cts +79 -69
  6. package/lib/_chunks-dts/behavior.types.action.d.ts +79 -69
  7. package/lib/_chunks-es/util.merge-text-blocks.js +1 -0
  8. package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -1
  9. package/lib/_chunks-es/util.slice-blocks.js +6 -1
  10. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  11. package/lib/index.cjs +232 -68
  12. package/lib/index.cjs.map +1 -1
  13. package/lib/index.js +234 -70
  14. package/lib/index.js.map +1 -1
  15. package/lib/plugins/index.d.cts +3 -3
  16. package/lib/plugins/index.d.ts +3 -3
  17. package/lib/utils/index.d.cts +2 -2
  18. package/package.json +10 -10
  19. package/src/behaviors/behavior.abstract.insert.ts +109 -24
  20. package/src/behaviors/behavior.abstract.split.ts +1 -0
  21. package/src/behaviors/behavior.perform-event.ts +89 -67
  22. package/src/behaviors/behavior.types.event.ts +10 -3
  23. package/src/converters/converter.portable-text.ts +1 -0
  24. package/src/converters/converter.text-html.ts +1 -0
  25. package/src/converters/converter.text-plain.ts +1 -0
  26. package/src/editor/Editable.tsx +1 -0
  27. package/src/editor/editor-selector.ts +10 -1
  28. package/src/editor/without-normalizing-conditional.ts +13 -0
  29. package/src/internal-utils/parse-blocks.test.ts +14 -14
  30. package/src/internal-utils/parse-blocks.ts +9 -2
  31. package/src/internal-utils/test-editor.tsx +1 -25
  32. package/src/operations/behavior.operation.block.set.ts +4 -3
  33. package/src/operations/behavior.operation.block.unset.ts +8 -2
  34. package/src/operations/behavior.operation.insert.block.ts +4 -1
  35. package/src/operations/behavior.operation.insert.child.ts +95 -0
  36. package/src/operations/behavior.operations.ts +9 -0
  37. package/src/selectors/selector.get-trimmed-selection.test.ts +1 -0
  38. package/src/types/block-with-optional-key.ts +13 -1
  39. package/src/utils/util.merge-text-blocks.ts +1 -1
  40. package/src/utils/util.slice-blocks.ts +3 -3
  41. package/src/utils/util.slice-text-block.test.ts +54 -28
  42. package/src/plugins/plugin.internal.editor-actor-ref.tsx +0 -15
@@ -12,7 +12,7 @@ describe(parseBlock.name, () => {
12
12
  keyGenerator: createTestKeyGenerator(),
13
13
  schema: compileSchema(defineSchema({})),
14
14
  },
15
- options: {validateFields: true},
15
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
28
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
42
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
57
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
72
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
90
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
117
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
152
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
191
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
239
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
266
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
293
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
323
+ options: {removeUnusedMarkDefs: true, 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: {validateFields: true},
354
+ options: {removeUnusedMarkDefs: true, validateFields: true},
355
355
  }),
356
356
  ).toEqual({
357
357
  _type: 'block',
@@ -19,6 +19,7 @@ export function parseBlocks({
19
19
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
20
20
  blocks: unknown
21
21
  options: {
22
+ removeUnusedMarkDefs: boolean
22
23
  validateFields: boolean
23
24
  }
24
25
  }): Array<PortableTextBlock> {
@@ -41,6 +42,7 @@ export function parseBlock({
41
42
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
42
43
  block: unknown
43
44
  options: {
45
+ removeUnusedMarkDefs: boolean
44
46
  validateFields: boolean
45
47
  }
46
48
  }): PortableTextBlock | undefined {
@@ -99,7 +101,10 @@ export function parseTextBlock({
99
101
  }: {
100
102
  block: unknown
101
103
  context: Pick<EditorContext, 'keyGenerator' | 'schema'>
102
- options: {validateFields: boolean}
104
+ options: {
105
+ removeUnusedMarkDefs: boolean
106
+ validateFields: boolean
107
+ }
103
108
  }): PortableTextTextBlock | undefined {
104
109
  if (!isTypedObject(block)) {
105
110
  return undefined
@@ -204,7 +209,9 @@ export function parseTextBlock({
204
209
  marks: [],
205
210
  },
206
211
  ],
207
- markDefs: markDefs.filter((markDef) => marks.includes(markDef._key)),
212
+ markDefs: options.removeUnusedMarkDefs
213
+ ? markDefs.filter((markDef) => marks.includes(markDef._key))
214
+ : markDefs,
208
215
  ...customFields,
209
216
  }
210
217
 
@@ -6,18 +6,13 @@ import React from 'react'
6
6
  import {expect, vi} from 'vitest'
7
7
  import {render} from 'vitest-browser-react'
8
8
  import type {Context} from '../../gherkin-tests-v2/step-context'
9
- import type {NativeBehaviorEvent} from '../behaviors'
10
9
  import type {Editor} from '../editor'
11
10
  import {
12
11
  PortableTextEditable,
13
12
  type PortableTextEditableProps,
14
13
  } from '../editor/Editable'
15
- import type {EditorActor} from '../editor/editor-machine'
16
14
  import {EditorProvider} from '../editor/editor-provider'
17
15
  import {EditorRefPlugin} from '../plugins/plugin.editor-ref'
18
- import {InternalEditorAfterRefPlugin} from '../plugins/plugin.internal.editor-actor-ref'
19
- import {InternalSlateEditorRefPlugin} from '../plugins/plugin.internal.slate-editor-ref'
20
- import type {PortableTextSlateEditor} from '../types/editor'
21
16
 
22
17
  type CreateTestEditorOptions = {
23
18
  initialValue?: Array<PortableTextBlock>
@@ -35,8 +30,6 @@ export async function createTestEditor(
35
30
  }
36
31
  > {
37
32
  const editorRef = React.createRef<Editor>()
38
- const editorActorRef = React.createRef<EditorActor>()
39
- const slateRef = React.createRef<PortableTextSlateEditor>()
40
33
  const keyGenerator = options.keyGenerator ?? createTestKeyGenerator()
41
34
 
42
35
  const renderResult = render(
@@ -48,8 +41,6 @@ export async function createTestEditor(
48
41
  }}
49
42
  >
50
43
  <EditorRefPlugin ref={editorRef} />
51
- <InternalEditorAfterRefPlugin ref={editorActorRef} />
52
- <InternalSlateEditorRefPlugin ref={slateRef} />
53
44
  <PortableTextEditable {...options.editableProps} />
54
45
  {options.children}
55
46
  </EditorProvider>,
@@ -66,8 +57,6 @@ export async function createTestEditor(
66
57
  }}
67
58
  >
68
59
  <EditorRefPlugin ref={editorRef} />
69
- <InternalEditorAfterRefPlugin ref={editorActorRef} />
70
- <InternalSlateEditorRefPlugin ref={slateRef} />
71
60
  <PortableTextEditable {...newOptions.editableProps} />
72
61
  {newOptions.children}
73
62
  </EditorProvider>,
@@ -81,8 +70,6 @@ export async function createTestEditor(
81
70
  }}
82
71
  >
83
72
  <EditorRefPlugin ref={editorRef} />
84
- <InternalEditorAfterRefPlugin ref={editorActorRef} />
85
- <InternalSlateEditorRefPlugin ref={slateRef} />
86
73
  <PortableTextEditable {...options.editableProps} />
87
74
  {options.children}
88
75
  </EditorProvider>,
@@ -93,19 +80,8 @@ export async function createTestEditor(
93
80
 
94
81
  await vi.waitFor(() => expect.element(locator).toBeInTheDocument())
95
82
 
96
- function sendNativeEvent(event: NativeBehaviorEvent) {
97
- editorActorRef.current?.send({
98
- type: 'behavior event',
99
- behaviorEvent: event,
100
- editor: slateRef.current!,
101
- })
102
- }
103
-
104
83
  return {
105
- editor: {
106
- ...editorRef.current!,
107
- sendNativeEvent,
108
- },
84
+ editor: editorRef.current!,
109
85
  locator,
110
86
  rerender,
111
87
  }
@@ -30,15 +30,16 @@ export const blockSetOperationImplementation: BehaviorOperationImplementation<
30
30
  const parsedBlock = parseBlock({
31
31
  context,
32
32
  block: updatedBlock,
33
- options: {validateFields: true},
33
+ options: {
34
+ removeUnusedMarkDefs: false,
35
+ validateFields: true,
36
+ },
34
37
  })
35
38
 
36
39
  if (!parsedBlock) {
37
40
  throw new Error(`Unable to update block at ${JSON.stringify(operation.at)}`)
38
41
  }
39
42
 
40
- parsedBlock.markDefs = updatedBlock.markDefs
41
-
42
43
  const slateBlock = toSlateValue([parsedBlock], {
43
44
  schemaTypes: context.schema,
44
45
  })?.at(0) as SlateElement | undefined
@@ -51,7 +51,10 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
51
51
  const updatedTextBlock = parseBlock({
52
52
  context,
53
53
  block: omit(parsedBlock, propsToRemove),
54
- options: {validateFields: true},
54
+ options: {
55
+ removeUnusedMarkDefs: true,
56
+ validateFields: true,
57
+ },
55
58
  })
56
59
 
57
60
  if (!updatedTextBlock) {
@@ -81,7 +84,10 @@ export const blockUnsetOperationImplementation: BehaviorOperationImplementation<
81
84
  parsedBlock,
82
85
  operation.props.filter((prop) => prop !== '_type'),
83
86
  ),
84
- options: {validateFields: true},
87
+ options: {
88
+ removeUnusedMarkDefs: true,
89
+ validateFields: true,
90
+ },
85
91
  })
86
92
 
87
93
  if (!updatedBlockObject) {
@@ -24,7 +24,10 @@ export const insertBlockOperationImplementation: BehaviorOperationImplementation
24
24
  const parsedBlock = parseBlock({
25
25
  block: operation.block,
26
26
  context,
27
- options: {validateFields: true},
27
+ options: {
28
+ removeUnusedMarkDefs: true,
29
+ validateFields: true,
30
+ },
28
31
  })
29
32
 
30
33
  if (!parsedBlock) {
@@ -0,0 +1,95 @@
1
+ import {isTextBlock} from '@portabletext/schema'
2
+ import {Transforms} from 'slate'
3
+ import {parseInlineObject, parseSpan} from '../internal-utils/parse-blocks'
4
+ import {getFocusBlock, getFocusSpan} from '../internal-utils/slate-utils'
5
+ import {VOID_CHILD_KEY} from '../internal-utils/values'
6
+ import type {BehaviorOperationImplementation} from './behavior.operations'
7
+
8
+ export const insertChildOperationImplementation: BehaviorOperationImplementation<
9
+ 'insert.child'
10
+ > = ({context, operation}) => {
11
+ const focus = operation.editor.selection?.focus
12
+ const focusBlockIndex = focus?.path.at(0)
13
+ const focusChildIndex = focus?.path.at(1)
14
+
15
+ if (focusBlockIndex === undefined || focusChildIndex === undefined) {
16
+ throw new Error('Unable to insert child without a focus')
17
+ }
18
+
19
+ const [focusBlock, focusBlockPath] = getFocusBlock({editor: operation.editor})
20
+
21
+ if (!focus || !focusBlock || !focusBlockPath) {
22
+ throw new Error('Unable to insert child without a focus block')
23
+ }
24
+
25
+ if (!isTextBlock(context, focusBlock)) {
26
+ throw new Error('Unable to insert child into a non-text block')
27
+ }
28
+
29
+ const markDefs = focusBlock.markDefs ?? []
30
+ const markDefKeyMap = new Map<string, string>()
31
+ for (const markDef of markDefs) {
32
+ markDefKeyMap.set(markDef._key, markDef._key)
33
+ }
34
+
35
+ const span = parseSpan({
36
+ span: operation.child,
37
+ context,
38
+ markDefKeyMap,
39
+ options: {validateFields: true},
40
+ })
41
+
42
+ if (span) {
43
+ const [focusSpan] = getFocusSpan({editor: operation.editor})
44
+
45
+ if (focusSpan) {
46
+ Transforms.insertNodes(operation.editor, span, {
47
+ at: focus,
48
+ select: true,
49
+ })
50
+ } else {
51
+ Transforms.insertNodes(operation.editor, span, {
52
+ at: [focusBlockIndex, focusChildIndex + 1],
53
+ select: true,
54
+ })
55
+ }
56
+
57
+ return
58
+ }
59
+
60
+ const inlineObject = parseInlineObject({
61
+ inlineObject: operation.child,
62
+ context,
63
+ options: {validateFields: true},
64
+ })
65
+
66
+ if (inlineObject) {
67
+ const {_key, _type, ...rest} = inlineObject
68
+
69
+ Transforms.insertNodes(
70
+ operation.editor,
71
+ {
72
+ _key,
73
+ _type,
74
+ children: [
75
+ {
76
+ _key: VOID_CHILD_KEY,
77
+ _type: 'span',
78
+ text: '',
79
+ marks: [],
80
+ },
81
+ ],
82
+ value: rest,
83
+ __inline: true,
84
+ },
85
+ {
86
+ at: [focusBlockIndex, focusChildIndex + 1],
87
+ select: true,
88
+ },
89
+ )
90
+
91
+ return
92
+ }
93
+
94
+ throw new Error('Unable to parse child')
95
+ }
@@ -20,6 +20,7 @@ import {childUnsetOperationImplementation} from './behavior.operation.child.unse
20
20
  import {decoratorAddOperationImplementation} from './behavior.operation.decorator.add'
21
21
  import {deleteOperationImplementation} from './behavior.operation.delete'
22
22
  import {insertBlockOperationImplementation} from './behavior.operation.insert.block'
23
+ import {insertChildOperationImplementation} from './behavior.operation.insert.child'
23
24
  import {insertTextOperationImplementation} from './behavior.operation.insert.text'
24
25
  import {moveBackwardOperationImplementation} from './behavior.operation.move.backward'
25
26
  import {moveBlockOperationImplementation} from './behavior.operation.move.block'
@@ -66,6 +67,7 @@ const behaviorOperationImplementations: BehaviorOperationImplementations = {
66
67
  'history.redo': historyRedoOperationImplementation,
67
68
  'history.undo': historyUndoOperationImplementation,
68
69
  'insert.block': insertBlockOperationImplementation,
70
+ 'insert.child': insertChildOperationImplementation,
69
71
  'insert.text': insertTextOperationImplementation,
70
72
  'move.backward': moveBackwardOperationImplementation,
71
73
  'move.block': moveBlockOperationImplementation,
@@ -167,6 +169,13 @@ export function performOperation({
167
169
  })
168
170
  break
169
171
  }
172
+ case 'insert.child': {
173
+ behaviorOperationImplementations['insert.child']({
174
+ context,
175
+ operation: operation,
176
+ })
177
+ break
178
+ }
170
179
  case 'insert.text': {
171
180
  behaviorOperationImplementations['insert.text']({
172
181
  context,
@@ -33,6 +33,7 @@ function snapshot(
33
33
  },
34
34
  block,
35
35
  options: {
36
+ removeUnusedMarkDefs: true,
36
37
  validateFields: false,
37
38
  },
38
39
  })
@@ -1,4 +1,8 @@
1
- import type {PortableTextObject, PortableTextTextBlock} from '@sanity/types'
1
+ import type {
2
+ PortableTextObject,
3
+ PortableTextSpan,
4
+ PortableTextTextBlock,
5
+ } from '@portabletext/schema'
2
6
 
3
7
  export type TextBlockWithOptionalKey = Omit<PortableTextTextBlock, '_key'> & {
4
8
  _key?: PortableTextTextBlock['_key']
@@ -11,3 +15,11 @@ export type ObjectBlockWithOptionalKey = Omit<PortableTextObject, '_key'> & {
11
15
  export type BlockWithOptionalKey =
12
16
  | TextBlockWithOptionalKey
13
17
  | ObjectBlockWithOptionalKey
18
+
19
+ export type SpanWithOptionalKey = Omit<PortableTextSpan, '_key'> & {
20
+ _key?: PortableTextSpan['_key']
21
+ }
22
+
23
+ export type ChildWithOptionalKey =
24
+ | SpanWithOptionalKey
25
+ | ObjectBlockWithOptionalKey
@@ -18,7 +18,7 @@ export function mergeTextBlocks({
18
18
  const parsedIncomingBlock = parseBlock({
19
19
  context,
20
20
  block: incomingBlock,
21
- options: {validateFields: false},
21
+ options: {removeUnusedMarkDefs: true, validateFields: false},
22
22
  })
23
23
 
24
24
  if (!parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock)) {
@@ -171,7 +171,7 @@ export function sliceBlocks({
171
171
  keyGenerator: defaultKeyGenerator,
172
172
  },
173
173
  block,
174
- options: {validateFields: false},
174
+ options: {removeUnusedMarkDefs: true, validateFields: false},
175
175
  }) ?? block,
176
176
  )
177
177
  }
@@ -184,7 +184,7 @@ export function sliceBlocks({
184
184
  keyGenerator: defaultKeyGenerator,
185
185
  },
186
186
  block: startBlock,
187
- options: {validateFields: false},
187
+ options: {removeUnusedMarkDefs: true, validateFields: false},
188
188
  })
189
189
  : undefined
190
190
 
@@ -195,7 +195,7 @@ export function sliceBlocks({
195
195
  keyGenerator: defaultKeyGenerator,
196
196
  },
197
197
  block: endBlock,
198
- options: {validateFields: false},
198
+ options: {removeUnusedMarkDefs: true, validateFields: false},
199
199
  })
200
200
  : undefined
201
201
 
@@ -107,7 +107,7 @@ describe(sliceTextBlock.name, () => {
107
107
  })
108
108
  })
109
109
 
110
- test('multiple children', () => {
110
+ describe('multiple children', () => {
111
111
  const fooSpan = createSpan({
112
112
  text: 'foo',
113
113
  marks: ['strong'],
@@ -127,36 +127,62 @@ describe(sliceTextBlock.name, () => {
127
127
  children: [fooSpan, barSpan, stockTicker, bazSpan],
128
128
  })
129
129
 
130
- expect(
131
- sliceTextBlock({
132
- context: {
133
- schema,
134
- selection: {
135
- anchor: {
136
- path: [{_key: block._key}, 'children', {_key: barSpan._key}],
137
- offset: 1,
130
+ test('mid-span', () => {
131
+ expect(
132
+ sliceTextBlock({
133
+ context: {
134
+ schema,
135
+ selection: {
136
+ anchor: {
137
+ path: [{_key: block._key}, 'children', {_key: barSpan._key}],
138
+ offset: 1,
139
+ },
140
+ focus: {
141
+ path: [{_key: block._key}, 'children', {_key: bazSpan._key}],
142
+ offset: 1,
143
+ },
138
144
  },
139
- focus: {
140
- path: [{_key: block._key}, 'children', {_key: bazSpan._key}],
141
- offset: 1,
145
+ },
146
+ block,
147
+ }),
148
+ ).toEqual({
149
+ ...block,
150
+ children: [
151
+ {
152
+ ...barSpan,
153
+ text: 'ar',
154
+ },
155
+ stockTicker,
156
+ {
157
+ ...bazSpan,
158
+ text: 'b',
159
+ },
160
+ ],
161
+ })
162
+ })
163
+
164
+ test('from end of span to end of block', () => {
165
+ expect(
166
+ sliceTextBlock({
167
+ context: {
168
+ schema,
169
+ selection: {
170
+ anchor: {
171
+ path: [{_key: block._key}, 'children', {_key: fooSpan._key}],
172
+ offset: 3,
173
+ },
174
+ focus: {
175
+ path: [{_key: block._key}, 'children', {_key: bazSpan._key}],
176
+ offset: 3,
177
+ },
142
178
  },
143
179
  },
144
- },
145
- block,
146
- }),
147
- ).toEqual({
148
- ...block,
149
- children: [
150
- {
151
- ...barSpan,
152
- text: 'ar',
153
- },
154
- stockTicker,
155
- {
156
- ...bazSpan,
157
- text: 'b',
158
- },
159
- ],
180
+ block,
181
+ }),
182
+ ).toEqual({
183
+ ...block,
184
+ children: [{...fooSpan, text: ''}, barSpan, stockTicker, bazSpan],
185
+ })
160
186
  })
161
187
  })
162
188
  })
@@ -1,15 +0,0 @@
1
- import React, {useContext} from 'react'
2
- import {EditorActorContext} from '../editor/editor-actor-context'
3
- import type {EditorActor} from '../editor/editor-machine'
4
-
5
- export const InternalEditorAfterRefPlugin =
6
- React.forwardRef<EditorActor | null>((_, ref) => {
7
- const editorActor = useContext(EditorActorContext)
8
-
9
- const editorActorRef = React.useRef(editorActor)
10
-
11
- React.useImperativeHandle(ref, () => editorActorRef.current, [])
12
-
13
- return null
14
- })
15
- InternalEditorAfterRefPlugin.displayName = 'InternalEditorAfterRefPlugin'