@portabletext/editor 2.21.0 → 2.21.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/editor",
3
- "version": "2.21.0",
3
+ "version": "2.21.2",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -70,8 +70,8 @@
70
70
  "lodash.startcase": "^4.4.0",
71
71
  "react-compiler-runtime": "1.0.0",
72
72
  "slate": "0.118.1",
73
- "slate-dom": "^0.118.1",
74
- "slate-react": "0.118.2",
73
+ "slate-dom": "^0.119.0",
74
+ "slate-react": "0.119.0",
75
75
  "xstate": "^5.24.0",
76
76
  "@portabletext/block-tools": "^4.0.2",
77
77
  "@portabletext/keyboard-shortcuts": "^2.1.0",
@@ -25,7 +25,7 @@ import {
25
25
  slateRangeToSelection,
26
26
  } from '../../internal-utils/slate-utils'
27
27
  import {toSlateRange} from '../../internal-utils/to-slate-range'
28
- import {fromSlateValue, toSlateValue} from '../../internal-utils/values'
28
+ import {fromSlateValue} from '../../internal-utils/values'
29
29
  import {getActiveAnnotationsMarks} from '../../selectors/selector.get-active-annotation-marks'
30
30
  import {getActiveDecorators} from '../../selectors/selector.get-active-decorators'
31
31
  import {getFocusBlock} from '../../selectors/selector.get-focus-block'
@@ -187,83 +187,17 @@ export function createEditableAPI(
187
187
  type: TSchemaType,
188
188
  value?: {[prop: string]: any},
189
189
  ): Path => {
190
- if (type.name !== types.span.name) {
191
- editorActor.send({
192
- type: 'behavior event',
193
- behaviorEvent: {
194
- type: 'insert.inline object',
195
- inlineObject: {
196
- name: type.name,
197
- value,
198
- },
199
- },
200
- editor,
201
- })
202
-
203
- return editor.selection
204
- ? (slateRangeToSelection({
205
- schema: editorActor.getSnapshot().context.schema,
206
- editor,
207
- range: editor.selection,
208
- })?.focus.path ?? [])
209
- : []
210
- }
211
-
212
- if (!editor.selection) {
213
- throw new Error('The editor has no selection')
214
- }
215
- const [focusBlock] = Array.from(
216
- Editor.nodes(editor, {
217
- at: editor.selection.focus.path.slice(0, 1),
218
- match: (n) => n._type === types.block.name,
219
- }),
220
- )[0] || [undefined]
221
- if (!focusBlock) {
222
- throw new Error('No focused text block')
223
- }
224
- if (
225
- type.name !== types.span.name &&
226
- !types.inlineObjects.some((t) => t.name === type.name)
227
- ) {
228
- throw new Error(
229
- 'This type cannot be inserted as a child to a text block',
230
- )
231
- }
232
- const block = toSlateValue(
233
- [
234
- {
235
- _key: editorActor.getSnapshot().context.keyGenerator(),
236
- _type: types.block.name,
237
- children: [
238
- {
239
- _key: editorActor.getSnapshot().context.keyGenerator(),
240
- _type: type.name,
241
- ...(value ? value : {}),
242
- },
243
- ],
190
+ editorActor.send({
191
+ type: 'behavior event',
192
+ behaviorEvent: {
193
+ type: 'insert.child',
194
+ child: {
195
+ _type: type.name,
196
+ ...(value ? value : {}),
244
197
  },
245
- ],
246
- {schemaTypes: editorActor.getSnapshot().context.schema},
247
- )[0] as unknown as SlateElement
248
- const child = block.children[0]
249
- const focusChildPath = editor.selection.focus.path.slice(0, 2)
250
- const isSpanNode = child._type === types.span.name
251
- const focusNode = Node.get(editor, focusChildPath)
252
-
253
- // If we are inserting a span, and currently have focus on an inline object,
254
- // move the selection to the next span (guaranteed by normalizing rules) before inserting it.
255
- if (isSpanNode && focusNode._type !== types.span.name) {
256
- debug(
257
- 'Inserting span child next to inline object child, moving selection + 1',
258
- )
259
- editor.move({distance: 1, unit: 'character'})
260
- }
261
-
262
- Transforms.insertNodes(editor, child, {
263
- select: true,
264
- at: editor.selection,
198
+ },
199
+ editor,
265
200
  })
266
- editor.onChange()
267
201
 
268
202
  return editor.selection
269
203
  ? (slateRangeToSelection({
@@ -1,4 +1,4 @@
1
- import {toSlateValue} from '../../internal-utils/values'
1
+ import {toSlateBlock} from '../../internal-utils/values'
2
2
  import type {PortableTextSlateEditor} from '../../types/editor'
3
3
  import type {EditorActor} from '../editor-machine'
4
4
 
@@ -19,36 +19,33 @@ export function createWithUtils({editorActor}: Options) {
19
19
  listItem?: string
20
20
  level?: number
21
21
  }) => {
22
- const block = toSlateValue(
23
- [
24
- {
25
- _type: editorActor.getSnapshot().context.schema.block.name,
26
- _key: editorActor.getSnapshot().context.keyGenerator(),
27
- style:
28
- editorActor.getSnapshot().context.schema.styles[0].name ||
29
- 'normal',
30
- ...(options.listItem ? {listItem: options.listItem} : {}),
31
- ...(options.level ? {level: options.level} : {}),
32
- markDefs: [],
33
- children: [
34
- {
35
- _type: 'span',
36
- _key: editorActor.getSnapshot().context.keyGenerator(),
37
- text: '',
38
- marks: options.decorators.filter((decorator) =>
39
- editorActor
40
- .getSnapshot()
41
- .context.schema.decorators.find(
42
- ({name}) => name === decorator,
43
- ),
44
- ),
45
- },
46
- ],
47
- },
48
- ],
22
+ return toSlateBlock(
23
+ {
24
+ _type: editorActor.getSnapshot().context.schema.block.name,
25
+ _key: editorActor.getSnapshot().context.keyGenerator(),
26
+ style:
27
+ editorActor.getSnapshot().context.schema.styles[0].name || 'normal',
28
+ ...(options.listItem ? {listItem: options.listItem} : {}),
29
+ ...(options.level ? {level: options.level} : {}),
30
+ markDefs: [],
31
+ children: [
32
+ {
33
+ _type: 'span',
34
+ _key: editorActor.getSnapshot().context.keyGenerator(),
35
+ text: '',
36
+ marks: options.decorators.filter((decorator) =>
37
+ editorActor
38
+ .getSnapshot()
39
+ .context.schema.decorators.find(
40
+ ({name}) => name === decorator,
41
+ ),
42
+ ),
43
+ },
44
+ ],
45
+ },
46
+
49
47
  {schemaTypes: editorActor.getSnapshot().context.schema},
50
- )[0]
51
- return block
48
+ )
52
49
  }
53
50
  return editor
54
51
  }
@@ -2,7 +2,7 @@ import {compileSchemaDefinitionToPortableTextMemberSchemaTypes} from '@portablet
2
2
  import {compileSchema, defineSchema} from '@portabletext/schema'
3
3
  import type {PortableTextTextBlock} from '@sanity/types'
4
4
  import {createEditor, type Descendant} from 'slate'
5
- import {beforeEach, describe, expect, it} from 'vitest'
5
+ import {beforeEach, describe, expect, it, test} from 'vitest'
6
6
  import {createActor} from 'xstate'
7
7
  import {editorMachine} from '../editor/editor-machine'
8
8
  import {withPlugins} from '../editor/plugins/with-plugins'
@@ -59,6 +59,66 @@ const createDefaultValue = () =>
59
59
  },
60
60
  ] as Descendant[]
61
61
 
62
+ describe(insertNodePatch.name, () => {
63
+ test('Scenario: Inserting block object on empty editor', () => {
64
+ expect(
65
+ insertNodePatch(
66
+ compileSchema(defineSchema({blockObjects: [{name: 'image'}]})),
67
+ [
68
+ {
69
+ _key: 'k2',
70
+ _type: 'image',
71
+ children: [
72
+ {
73
+ _key: 'void-child',
74
+ _type: 'span',
75
+ marks: [],
76
+ text: '',
77
+ },
78
+ ],
79
+ value: {},
80
+ },
81
+ ],
82
+ {
83
+ type: 'insert_node',
84
+ path: [0],
85
+ node: {
86
+ _key: 'k2',
87
+ _type: 'image',
88
+ children: [
89
+ {
90
+ _key: 'void-child',
91
+ _type: 'span',
92
+ marks: [],
93
+ text: '',
94
+ },
95
+ ],
96
+ value: {},
97
+ },
98
+ },
99
+ [],
100
+ ),
101
+ ).toEqual([
102
+ {
103
+ path: [],
104
+ type: 'setIfMissing',
105
+ value: [],
106
+ },
107
+ {
108
+ path: [0],
109
+ type: 'insert',
110
+ items: [
111
+ {
112
+ _key: 'k2',
113
+ _type: 'image',
114
+ },
115
+ ],
116
+ position: 'before',
117
+ },
118
+ ])
119
+ })
120
+ })
121
+
62
122
  describe('operationToPatches', () => {
63
123
  beforeEach(() => {
64
124
  editor.children = createDefaultValue()
@@ -121,15 +121,15 @@ export function insertBlock(options: {
121
121
  // placement === 'auto'
122
122
 
123
123
  if (endBlock && isEqualToEmptyEditor([endBlock], context.schema)) {
124
- // And if the last block was an empty text block, let's remove
125
- // that too
126
- Transforms.removeNodes(editor, {at: endBlockPath})
127
-
128
124
  Transforms.insertNodes(editor, [block], {
129
125
  at: endBlockPath,
130
126
  select: false,
131
127
  })
132
128
 
129
+ // And if the last block was an empty text block, let's remove
130
+ // that too
131
+ Transforms.removeNodes(editor, {at: Path.next(endBlockPath)})
132
+
133
133
  Transforms.deselect(editor)
134
134
 
135
135
  if (select === 'start') {
@@ -71,7 +71,7 @@ export const stepDefinitions = [
71
71
  context.keyMap = new Map()
72
72
  }),
73
73
 
74
- Given('the editor is focused', async (context: Context) => {
74
+ When('the editor is focused', async (context: Context) => {
75
75
  await userEvent.click(context.locator)
76
76
  }),
77
77