@portabletext/editor 3.0.2 → 3.0.4

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": "3.0.2",
3
+ "version": "3.0.4",
4
4
  "description": "Portable Text Editor made in React",
5
5
  "keywords": [
6
6
  "sanity",
@@ -694,7 +694,7 @@ export class PortableTextEditor extends Component<
694
694
  * ```
695
695
  * import * as selectors from '@portabletext/editor/selectors'
696
696
  * const editor = useEditor()
697
- * const selectedSlice = useEditorSelector(editor, selectors.getSelectedSlice)
697
+ * const selectedValue = useEditorSelector(editor, selectors.getSelectedValue)
698
698
  * ```
699
699
  */
700
700
  static getFragment = (
@@ -3,7 +3,7 @@ import {withReact} from 'slate-react'
3
3
  import {buildIndexMaps} from '../internal-utils/build-index-maps'
4
4
  import {createPlaceholderBlock} from '../internal-utils/create-placeholder-block'
5
5
  import {debugWithName} from '../internal-utils/debug'
6
- import {toSlateValue} from '../internal-utils/values'
6
+ import {toSlateBlock} from '../internal-utils/values'
7
7
  import type {PortableTextSlateEditor} from '../types/editor'
8
8
  import type {EditorActor} from './editor-machine'
9
9
  import {withPlugins} from './plugins/with-plugins'
@@ -56,9 +56,11 @@ export function createSlateEditor(config: SlateEditorConfig): SlateEditor {
56
56
  },
57
57
  )
58
58
 
59
- const initialValue = toSlateValue(instance.value, {
60
- schemaTypes: config.editorActor.getSnapshot().context.schema,
61
- })
59
+ const initialValue = [
60
+ toSlateBlock(placeholderBlock, {
61
+ schemaTypes: config.editorActor.getSnapshot().context.schema,
62
+ }),
63
+ ]
62
64
 
63
65
  const slateEditor: SlateEditor = {
64
66
  instance,
@@ -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} from '../../internal-utils/values'
28
+ import {fromSlateBlock, 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'
@@ -157,11 +157,11 @@ export function createEditableAPI(
157
157
  editor.selection.focus.path.slice(0, 1),
158
158
  )
159
159
  if (block) {
160
- return fromSlateValue(
161
- [block],
160
+ return fromSlateBlock(
161
+ block,
162
162
  types.block.name,
163
163
  KEY_TO_VALUE_ELEMENT.get(editor),
164
- )[0]
164
+ )
165
165
  }
166
166
  }
167
167
  return undefined
@@ -173,11 +173,11 @@ export function createEditableAPI(
173
173
  editor.selection.focus.path.slice(0, 1),
174
174
  )
175
175
  if (block && editor.isTextBlock(block)) {
176
- const ptBlock = fromSlateValue(
177
- [block],
176
+ const ptBlock = fromSlateBlock(
177
+ block,
178
178
  types.block.name,
179
179
  KEY_TO_VALUE_ELEMENT.get(editor),
180
- )[0] as PortableTextTextBlock
180
+ ) as PortableTextTextBlock
181
181
  return ptBlock.children[editor.selection.focus.path[1]]
182
182
  }
183
183
  }
@@ -274,15 +274,15 @@ export function createEditableAPI(
274
274
  if (block && blockPath && typeof block._key === 'string') {
275
275
  if (path.length === 1 && slatePath.focus.path.length === 1) {
276
276
  return [
277
- fromSlateValue([block], types.block.name)[0],
277
+ fromSlateBlock(block, types.block.name),
278
278
  [{_key: block._key}],
279
279
  ]
280
280
  }
281
- const ptBlock = fromSlateValue(
282
- [block],
281
+ const ptBlock = fromSlateBlock(
282
+ block,
283
283
  types.block.name,
284
284
  KEY_TO_VALUE_ELEMENT.get(editor),
285
- )[0]
285
+ )
286
286
  if (editor.isTextBlock(ptBlock)) {
287
287
  const ptChild = ptBlock.children[slatePath.focus.path[1]]
288
288
  if (ptChild) {
@@ -559,7 +559,12 @@ export function createEditableAPI(
559
559
  editor.onChange()
560
560
  },
561
561
  getFragment: () => {
562
- return fromSlateValue(editor.getFragment(), types.block.name)
562
+ const snapshot = getEditorSnapshot({
563
+ editorActorSnapshot: editorActor.getSnapshot(),
564
+ slateEditorInstance: editor,
565
+ })
566
+
567
+ return getSelectedValue(snapshot)
563
568
  },
564
569
  isSelectionsOverlapping: (
565
570
  selectionA: EditorSelection,
@@ -1,139 +1,113 @@
1
1
  import {compileSchema, defineSchema} from '@portabletext/schema'
2
2
  import {describe, expect, it} from 'vitest'
3
- import {fromSlateValue, toSlateValue} from '../values'
3
+ import {fromSlateValue, toSlateBlock} from '../values'
4
4
 
5
5
  const schemaTypes = compileSchema(defineSchema({}))
6
6
 
7
- describe('toSlateValue', () => {
8
- it('checks undefined', () => {
9
- const result = toSlateValue(undefined, {schemaTypes})
10
- expect(result).toHaveLength(0)
11
- })
12
-
13
- it('runs given empty array', () => {
14
- const result = toSlateValue([], {schemaTypes})
15
- expect(result).toHaveLength(0)
16
- })
17
-
7
+ describe(toSlateBlock.name, () => {
18
8
  it('given type is custom with no custom properties, should include an empty text property in children and an empty value', () => {
19
- const result = toSlateValue(
20
- [
9
+ const result = toSlateBlock(
10
+ {
11
+ _type: 'image',
12
+ _key: '123',
13
+ },
14
+ {schemaTypes},
15
+ )
16
+
17
+ expect(result).toMatchObject({
18
+ _key: '123',
19
+ _type: 'image',
20
+ children: [
21
21
  {
22
- _type: 'image',
23
- _key: '123',
22
+ text: '',
24
23
  },
25
24
  ],
26
- {schemaTypes},
27
- )
25
+ value: {},
26
+ })
27
+ })
28
28
 
29
- expect(result).toMatchObject([
29
+ it('given type is block', () => {
30
+ const result = toSlateBlock(
30
31
  {
32
+ _type: schemaTypes.block.name,
31
33
  _key: '123',
32
- _type: 'image',
33
34
  children: [
34
35
  {
35
- text: '',
36
+ _type: 'span',
37
+ _key: '1231',
38
+ text: '123',
36
39
  },
37
40
  ],
38
- value: {},
39
41
  },
40
- ])
41
- })
42
-
43
- it('given type is block', () => {
44
- const result = toSlateValue(
45
- [
42
+ {schemaTypes},
43
+ )
44
+ expect(result).toEqual({
45
+ _key: '123',
46
+ _type: 'block',
47
+ children: [
46
48
  {
47
- _type: schemaTypes.block.name,
48
- _key: '123',
49
- children: [
50
- {
51
- _type: 'span',
52
- _key: '1231',
53
- text: '123',
54
- },
55
- ],
49
+ _key: '1231',
50
+ _type: 'span',
51
+ text: '123',
56
52
  },
57
53
  ],
58
- {schemaTypes},
59
- )
60
- expect(result).toMatchInlineSnapshot(`
61
- [
62
- {
63
- "_key": "123",
64
- "_type": "block",
65
- "children": [
66
- {
67
- "_key": "1231",
68
- "_type": "span",
69
- "text": "123",
70
- },
71
- ],
72
- "style": "normal",
73
- },
74
- ]
75
- `)
54
+ style: 'normal',
55
+ })
76
56
  })
77
57
 
78
58
  it('given type is block and has custom in children', () => {
79
- const result = toSlateValue(
80
- [
59
+ const result = toSlateBlock(
60
+ {
61
+ _type: schemaTypes.block.name,
62
+ _key: '123',
63
+ children: [
64
+ {
65
+ _type: 'span',
66
+ _key: '1231',
67
+ text: '123',
68
+ },
69
+ {
70
+ _type: 'image',
71
+ _key: '1232',
72
+ asset: {
73
+ _ref: 'ref-123',
74
+ },
75
+ },
76
+ ],
77
+ },
78
+ {schemaTypes},
79
+ )
80
+
81
+ expect(result).toEqual({
82
+ _key: '123',
83
+ _type: 'block',
84
+ children: [
85
+ {
86
+ _key: '1231',
87
+ _type: 'span',
88
+ text: '123',
89
+ },
81
90
  {
82
- _type: schemaTypes.block.name,
83
- _key: '123',
91
+ __inline: true,
92
+ _key: '1232',
93
+ _type: 'image',
84
94
  children: [
85
95
  {
96
+ _key: 'void-child',
86
97
  _type: 'span',
87
- _key: '1231',
88
- text: '123',
89
- },
90
- {
91
- _type: 'image',
92
- _key: '1232',
93
- asset: {
94
- _ref: 'ref-123',
95
- },
98
+ marks: [],
99
+ text: '',
96
100
  },
97
101
  ],
98
- },
99
- ],
100
- {schemaTypes},
101
- )
102
-
103
- expect(result).toMatchInlineSnapshot(`
104
- [
105
- {
106
- "_key": "123",
107
- "_type": "block",
108
- "children": [
109
- {
110
- "_key": "1231",
111
- "_type": "span",
112
- "text": "123",
113
- },
114
- {
115
- "__inline": true,
116
- "_key": "1232",
117
- "_type": "image",
118
- "children": [
119
- {
120
- "_key": "void-child",
121
- "_type": "span",
122
- "marks": [],
123
- "text": "",
124
- },
125
- ],
126
- "value": {
127
- "asset": {
128
- "_ref": "ref-123",
102
+ value: {
103
+ asset: {
104
+ _ref: 'ref-123',
105
+ },
129
106
  },
130
107
  },
131
- },
132
- ],
133
- "style": "normal",
134
- },
135
- ]
136
- `)
108
+ ],
109
+ style: 'normal',
110
+ })
137
111
  })
138
112
  })
139
113
 
@@ -240,8 +214,12 @@ describe('fromSlateValue', () => {
240
214
  style: 'normal',
241
215
  },
242
216
  ]
243
- const toSlate1 = toSlateValue(value, {schemaTypes}, keyMap)
244
- const toSlate2 = toSlateValue(value, {schemaTypes}, keyMap)
217
+ const toSlate1 = value.map((block) =>
218
+ toSlateBlock(block, {schemaTypes}, keyMap),
219
+ )
220
+ const toSlate2 = value.map((block) =>
221
+ toSlateBlock(block, {schemaTypes}, keyMap),
222
+ )
245
223
  expect(toSlate1[0]).toBe(toSlate2[0])
246
224
  expect(toSlate1[1]).toBe(toSlate2[1])
247
225
  const fromSlate1 = fromSlateValue(toSlate1, 'block', keyMap)
@@ -21,7 +21,7 @@ import type {EditorSchema} from '../editor/editor-schema'
21
21
  import {KEY_TO_SLATE_ELEMENT} from '../editor/weakMaps'
22
22
  import type {PortableTextSlateEditor} from '../types/editor'
23
23
  import {isKeyedSegment} from '../utils/util.is-keyed-segment'
24
- import {isEqualToEmptyEditor, toSlateValue} from './values'
24
+ import {isEqualToEmptyEditor, toSlateBlock} from './values'
25
25
 
26
26
  /**
27
27
  * Creates a function that can apply a patch onto a PortableTextSlateEditor.
@@ -134,11 +134,13 @@ function insertPatch(
134
134
  // Insert blocks
135
135
  if (patch.path.length === 1) {
136
136
  const {items, position} = patch
137
- const blocksToInsert = toSlateValue(
138
- items as PortableTextBlock[],
139
- {schemaTypes: schema},
140
- KEY_TO_SLATE_ELEMENT.get(editor),
141
- ) as Descendant[]
137
+ const blocksToInsert = items.map((item) =>
138
+ toSlateBlock(
139
+ item as PortableTextBlock,
140
+ {schemaTypes: schema},
141
+ KEY_TO_SLATE_ELEMENT.get(editor),
142
+ ),
143
+ )
142
144
  const targetBlockIndex = block.index
143
145
  const normalizedIdx =
144
146
  position === 'after' ? targetBlockIndex + 1 : targetBlockIndex
@@ -153,7 +155,11 @@ function insertPatch(
153
155
  patch.path[0] === 0
154
156
  ) {
155
157
  Transforms.removeNodes(editor, {
156
- at: [position === 'before' ? targetBlockIndex + 1 : targetBlockIndex],
158
+ at: [
159
+ position === 'before'
160
+ ? targetBlockIndex + blocksToInsert.length
161
+ : targetBlockIndex,
162
+ ],
157
163
  })
158
164
  }
159
165
 
@@ -169,8 +175,8 @@ function insertPatch(
169
175
  return false
170
176
  }
171
177
 
172
- const childrenToInsert = toSlateValue(
173
- [{...block.node, children: items as PortableTextChild[]}],
178
+ const childrenToInsert = toSlateBlock(
179
+ {...block.node, children: items as PortableTextChild[]},
174
180
  {schemaTypes: schema},
175
181
  KEY_TO_SLATE_ELEMENT.get(editor),
176
182
  )
@@ -178,8 +184,8 @@ function insertPatch(
178
184
  position === 'after' ? targetChild.index + 1 : targetChild.index
179
185
  const childInsertPath = [block.index, normalizedIdx]
180
186
 
181
- if (childrenToInsert && Element.isElement(childrenToInsert[0])) {
182
- Transforms.insertNodes(editor, childrenToInsert[0].children, {
187
+ if (childrenToInsert && Element.isElement(childrenToInsert)) {
188
+ Transforms.insertNodes(editor, childrenToInsert.children, {
183
189
  at: childInsertPath,
184
190
  })
185
191
  }
@@ -23,7 +23,7 @@ import {
23
23
  type SplitNodeOperation,
24
24
  } from 'slate'
25
25
  import type {EditorSchema} from '../editor/editor-schema'
26
- import {fromSlateValue} from './values'
26
+ import {fromSlateBlock} from './values'
27
27
 
28
28
  export function insertTextPatch(
29
29
  schema: EditorSchema,
@@ -281,12 +281,7 @@ export function insertNodePatch(
281
281
  if (targetKey) {
282
282
  return [
283
283
  insert(
284
- [
285
- fromSlateValue(
286
- [operation.node as Descendant],
287
- schema.block.name,
288
- )[0],
289
- ],
284
+ [fromSlateBlock(operation.node as Descendant, schema.block.name)],
290
285
  position,
291
286
  [{_key: targetKey}],
292
287
  ),
@@ -295,7 +290,7 @@ export function insertNodePatch(
295
290
  return [
296
291
  setIfMissing(beforeValue, []),
297
292
  insert(
298
- [fromSlateValue([operation.node as Descendant], schema.block.name)[0]],
293
+ [fromSlateBlock(operation.node as Descendant, schema.block.name)],
299
294
  'before',
300
295
  [operation.path[0]],
301
296
  ),
@@ -365,10 +360,10 @@ export function splitNodePatch(
365
360
  if (operation.path.length === 1) {
366
361
  const oldBlock = beforeValue[operation.path[0]]
367
362
  if (isTextBlock({schema}, oldBlock)) {
368
- const targetValue = fromSlateValue(
369
- [children[operation.path[0] + 1]],
363
+ const targetValue = fromSlateBlock(
364
+ children[operation.path[0] + 1],
370
365
  schema.block.name,
371
- )[0]
366
+ )
372
367
  if (targetValue) {
373
368
  patches.push(insert([targetValue], 'after', [{_key: splitBlock._key}]))
374
369
  const spansToUnset = oldBlock.children.slice(operation.position)
@@ -384,18 +379,16 @@ export function splitNodePatch(
384
379
  const splitSpan = splitBlock.children[operation.path[1]]
385
380
  if (isSpan({schema}, splitSpan)) {
386
381
  const targetSpans = (
387
- fromSlateValue(
388
- [
389
- {
390
- ...splitBlock,
391
- children: splitBlock.children.slice(
392
- operation.path[1] + 1,
393
- operation.path[1] + 2,
394
- ),
395
- } as Descendant,
396
- ],
382
+ fromSlateBlock(
383
+ {
384
+ ...splitBlock,
385
+ children: splitBlock.children.slice(
386
+ operation.path[1] + 1,
387
+ operation.path[1] + 2,
388
+ ),
389
+ } as Descendant,
397
390
  schema.block.name,
398
- )[0] as PortableTextTextBlock
391
+ ) as PortableTextTextBlock
399
392
  ).children
400
393
 
401
394
  patches.push(
@@ -470,10 +463,10 @@ export function mergeNodePatch(
470
463
 
471
464
  if (operation.path.length === 1) {
472
465
  if (block?._key) {
473
- const newBlock = fromSlateValue(
474
- [children[operation.path[0] - 1]],
466
+ const newBlock = fromSlateBlock(
467
+ children[operation.path[0] - 1],
475
468
  schema.block.name,
476
- )[0]
469
+ )
477
470
  patches.push(set(newBlock, [{_key: newBlock._key}]))
478
471
  patches.push(unset([{_key: block._key}]))
479
472
  } else {
@@ -555,7 +548,7 @@ export function moveNodePatch(
555
548
  operation.path[0] > operation.newPath[0] ? 'before' : 'after'
556
549
  patches.push(unset([{_key: block._key}]))
557
550
  patches.push(
558
- insert([fromSlateValue([block], schema.block.name)[0]], position, [
551
+ insert([fromSlateBlock(block, schema.block.name)], position, [
559
552
  {_key: targetBlock._key},
560
553
  ]),
561
554
  )
@@ -569,7 +562,7 @@ export function moveNodePatch(
569
562
  const position =
570
563
  operation.newPath[1] === targetBlock.children.length ? 'after' : 'before'
571
564
  const childToInsert = (
572
- fromSlateValue([block], schema.block.name)[0] as PortableTextTextBlock
565
+ fromSlateBlock(block, schema.block.name) as PortableTextTextBlock
573
566
  ).children[operation.path[1]]
574
567
  patches.push(unset([{_key: block._key}, 'children', {_key: child._key}]))
575
568
  patches.push(
@@ -2,7 +2,7 @@ import type {PortableTextSpan} from '@sanity/types'
2
2
  import {Editor, Element, Node, Range, type Path, type Point} from 'slate'
3
3
  import type {EditorSchema} from '../editor/editor-schema'
4
4
  import type {EditorSelection, PortableTextSlateEditor} from '../types/editor'
5
- import {fromSlateValue} from './values'
5
+ import {fromSlateBlock} from './values'
6
6
 
7
7
  export function getBlockPath({
8
8
  editor,
@@ -284,7 +284,7 @@ function elementToBlock({
284
284
  schema: EditorSchema
285
285
  element: Element
286
286
  }) {
287
- return fromSlateValue([element], schema.block.name)?.at(0)
287
+ return fromSlateBlock(element, schema.block.name)
288
288
  }
289
289
 
290
290
  function isBlockElement(