@portabletext/editor 1.50.7 → 1.51.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 (98) hide show
  1. package/lib/_chunks-cjs/{util.slice-blocks.cjs → selection-point.cjs} +26 -18
  2. package/lib/_chunks-cjs/selection-point.cjs.map +1 -0
  3. package/lib/_chunks-cjs/selector.get-text-before.cjs +13 -10
  4. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  5. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +46 -46
  6. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
  7. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs +21 -17
  8. package/lib/_chunks-cjs/selector.is-selection-expanded.cjs.map +1 -1
  9. package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs +10 -10
  10. package/lib/_chunks-cjs/util.child-selection-point-to-block-offset.cjs.map +1 -1
  11. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs +5 -5
  12. package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +1 -1
  13. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +3 -3
  14. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
  15. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +7 -14
  16. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
  17. package/lib/_chunks-es/{util.slice-blocks.js → selection-point.js} +26 -18
  18. package/lib/_chunks-es/selection-point.js.map +1 -0
  19. package/lib/_chunks-es/selector.get-text-before.js +13 -10
  20. package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
  21. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +21 -21
  22. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
  23. package/lib/_chunks-es/selector.is-selection-expanded.js +14 -10
  24. package/lib/_chunks-es/selector.is-selection-expanded.js.map +1 -1
  25. package/lib/_chunks-es/util.child-selection-point-to-block-offset.js +2 -2
  26. package/lib/_chunks-es/util.child-selection-point-to-block-offset.js.map +1 -1
  27. package/lib/_chunks-es/util.is-equal-selection-points.js +1 -1
  28. package/lib/_chunks-es/util.merge-text-blocks.js +1 -1
  29. package/lib/_chunks-es/util.selection-point-to-block-offset.js +4 -11
  30. package/lib/_chunks-es/util.selection-point-to-block-offset.js.map +1 -1
  31. package/lib/behaviors/index.d.cts +1 -2007
  32. package/lib/behaviors/index.d.ts +1 -2007
  33. package/lib/index.cjs +130 -146
  34. package/lib/index.cjs.map +1 -1
  35. package/lib/index.d.cts +1 -3
  36. package/lib/index.d.ts +1 -3
  37. package/lib/index.js +63 -79
  38. package/lib/index.js.map +1 -1
  39. package/lib/plugins/index.cjs +11 -11
  40. package/lib/plugins/index.cjs.map +1 -1
  41. package/lib/plugins/index.d.cts +6 -1981
  42. package/lib/plugins/index.d.ts +6 -1981
  43. package/lib/plugins/index.js +1 -1
  44. package/lib/selectors/index.cjs +17 -27
  45. package/lib/selectors/index.cjs.map +1 -1
  46. package/lib/selectors/index.d.cts +5 -2645
  47. package/lib/selectors/index.d.ts +5 -2645
  48. package/lib/selectors/index.js +13 -23
  49. package/lib/selectors/index.js.map +1 -1
  50. package/lib/utils/index.cjs +25 -14
  51. package/lib/utils/index.cjs.map +1 -1
  52. package/lib/utils/index.d.cts +0 -2633
  53. package/lib/utils/index.d.ts +0 -2633
  54. package/lib/utils/index.js +14 -3
  55. package/lib/utils/index.js.map +1 -1
  56. package/package.json +18 -18
  57. package/src/behaviors/behavior.abstract.delete.ts +0 -1
  58. package/src/behaviors/behavior.abstract.insert.ts +8 -8
  59. package/src/behaviors/behavior.types.event.ts +1 -0
  60. package/src/converters/converter.portable-text.ts +1 -1
  61. package/src/converters/converter.text-plain.ts +2 -2
  62. package/src/editor/editor-machine.ts +0 -2
  63. package/src/editor/editor-selector.ts +0 -1
  64. package/src/editor/editor-snapshot.ts +0 -5
  65. package/src/editor/mutation-machine.ts +52 -63
  66. package/src/internal-utils/applyPatch.ts +2 -1
  67. package/src/internal-utils/create-test-snapshot.ts +0 -1
  68. package/src/internal-utils/event-position.ts +3 -5
  69. package/src/internal-utils/selection-block-keys.ts +7 -7
  70. package/src/internal-utils/selection-focus-text.ts +13 -9
  71. package/src/internal-utils/selection-text.ts +9 -78
  72. package/src/internal-utils/terse-pt.test.ts +108 -26
  73. package/src/internal-utils/terse-pt.ts +132 -14
  74. package/src/operations/behavior.operation.decorator.add.ts +0 -1
  75. package/src/operations/behavior.operation.delete.ts +18 -13
  76. package/src/operations/behavior.operation.insert.block.ts +5 -1
  77. package/src/selection/selection-point.ts +22 -0
  78. package/src/selectors/index.ts +1 -1
  79. package/src/selectors/selector.get-anchor-block.ts +6 -6
  80. package/src/selectors/selector.get-anchor-child.ts +6 -6
  81. package/src/selectors/selector.get-list-state.test.ts +14 -27
  82. package/src/selectors/selector.get-list-state.ts +9 -27
  83. package/src/selectors/selector.get-selected-spans.ts +16 -19
  84. package/src/selectors/selector.get-selected-text-blocks.ts +11 -19
  85. package/src/selectors/selector.get-selection-end-block.ts +30 -0
  86. package/src/selectors/selector.get-selection-start-block.ts +30 -0
  87. package/src/selectors/selector.get-text-before.ts +15 -16
  88. package/src/selectors/selector.get-trimmed-selection.ts +15 -21
  89. package/src/selectors/selector.is-point-after-selection.ts +11 -19
  90. package/src/selectors/selector.is-point-before-selection.ts +11 -19
  91. package/src/selectors/selectors.ts +23 -39
  92. package/src/utils/util.block-offset.ts +6 -7
  93. package/src/utils/util.child-selection-point-to-block-offset.ts +6 -7
  94. package/src/utils/util.selection-point-to-block-offset.ts +5 -6
  95. package/src/utils/util.slice-blocks.ts +11 -20
  96. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +0 -1
  97. package/lib/_chunks-es/util.slice-blocks.js.map +0 -1
  98. package/src/internal-utils/inline-object-selection.ts +0 -115
@@ -1,90 +1,21 @@
1
- import {isPortableTextBlock, isPortableTextSpan} from '@portabletext/toolkit'
2
1
  import type {PortableTextBlock} from '@sanity/types'
2
+ import {compileSchemaDefinition, defineSchema} from '../editor/editor-schema'
3
3
  import type {EditorSelection} from '../types/editor'
4
- import {isKeyedSegment} from '../utils'
5
- import {reverseSelection} from '../utils/util.reverse-selection'
4
+ import {sliceBlocks} from '../utils/util.slice-blocks'
5
+ import {getTersePt} from './terse-pt'
6
6
 
7
7
  export function getSelectionText(
8
8
  value: Array<PortableTextBlock> | undefined,
9
9
  selection: EditorSelection,
10
10
  ) {
11
11
  if (!value || !selection) {
12
- return undefined
12
+ return []
13
13
  }
14
14
 
15
- const forwardSelection = selection.backward
16
- ? reverseSelection(selection)
17
- : selection
15
+ const slice = sliceBlocks({
16
+ context: {schema: compileSchemaDefinition(defineSchema({})), selection},
17
+ blocks: value,
18
+ })
18
19
 
19
- if (!forwardSelection) {
20
- return undefined
21
- }
22
-
23
- const text: Array<string> = []
24
-
25
- for (const block of value) {
26
- if (
27
- text.length === 0 &&
28
- isKeyedSegment(forwardSelection.anchor.path[0]) &&
29
- block._key !== forwardSelection.anchor.path[0]._key
30
- ) {
31
- continue
32
- }
33
-
34
- if (text.length > 0) {
35
- text.push('|')
36
- }
37
-
38
- if (isPortableTextBlock(block)) {
39
- for (const child of block.children) {
40
- if (isPortableTextSpan(child)) {
41
- if (
42
- isKeyedSegment(forwardSelection.anchor.path[2]) &&
43
- child._key === forwardSelection.anchor.path[2]._key &&
44
- isKeyedSegment(forwardSelection.focus.path[2]) &&
45
- child._key === forwardSelection.focus.path[2]._key
46
- ) {
47
- text.push(
48
- child.text.slice(
49
- forwardSelection.anchor.offset,
50
- forwardSelection.focus.offset,
51
- ),
52
- )
53
- break
54
- }
55
-
56
- if (
57
- isKeyedSegment(forwardSelection.anchor.path[2]) &&
58
- child._key === forwardSelection.anchor.path[2]._key
59
- ) {
60
- text.push(child.text.slice(forwardSelection.anchor.offset))
61
- continue
62
- }
63
-
64
- if (
65
- isKeyedSegment(forwardSelection.focus.path[2]) &&
66
- child._key === forwardSelection.focus.path[2]._key
67
- ) {
68
- text.push(child.text.slice(0, forwardSelection.focus.offset))
69
- break
70
- }
71
-
72
- if (text.length > 0) {
73
- text.push(child.text)
74
- }
75
- }
76
- }
77
- } else {
78
- text.push(`[${block._type}]`)
79
- }
80
-
81
- if (
82
- isKeyedSegment(forwardSelection.focus.path[0]) &&
83
- block._key === forwardSelection.focus.path[0]._key
84
- ) {
85
- break
86
- }
87
- }
88
-
89
- return text
20
+ return getTersePt(slice)
90
21
  }
@@ -1,5 +1,9 @@
1
1
  import {expect, test} from 'vitest'
2
- import {getTersePt, parseTersePt} from './terse-pt'
2
+ import {compileSchemaDefinition, defineSchema} from '../editor/editor-schema'
3
+ import {createTestKeyGenerator} from '../internal-utils/test-key-generator'
4
+ import {getTersePt, parseTersePt, parseTersePtString} from './terse-pt'
5
+
6
+ const keyGenerator = createTestKeyGenerator()
3
7
 
4
8
  test(getTersePt.name, () => {
5
9
  const fooBlock = {
@@ -23,38 +27,116 @@ test(getTersePt.name, () => {
23
27
  children: [{_key: 's4', _type: 'span', text: 'foo\nbar'}],
24
28
  }
25
29
 
26
- expect(getTersePt([fooBlock, barBlock])).toEqual(['foo', '|', 'bar'])
27
- expect(getTersePt([emptyBlock, barBlock])).toEqual(['', '|', 'bar'])
30
+ expect(getTersePt([fooBlock, barBlock])).toEqual(['foo', 'bar'])
31
+ expect(getTersePt([emptyBlock, barBlock])).toEqual(['', 'bar'])
28
32
  expect(getTersePt([fooBlock, emptyBlock, barBlock])).toEqual([
29
33
  'foo',
30
- '|',
31
34
  '',
32
- '|',
33
35
  'bar',
34
36
  ])
35
- expect(getTersePt([fooBlock, softReturnBlock])).toEqual([
36
- 'foo',
37
- '|',
38
- 'foo\nbar',
39
- ])
37
+ expect(getTersePt([fooBlock, softReturnBlock])).toEqual(['foo', 'foo\nbar'])
38
+
39
+ expect(
40
+ getTersePt([
41
+ {
42
+ _key: keyGenerator(),
43
+ _type: 'block',
44
+ children: [{_key: keyGenerator(), _type: 'span', text: 'foo'}],
45
+ },
46
+ ]),
47
+ ).toEqual(['foo'])
48
+ expect(
49
+ getTersePt([
50
+ {
51
+ _key: keyGenerator(),
52
+ _type: 'block',
53
+ children: [{_key: keyGenerator(), _type: 'span', text: 'foo'}],
54
+ listItem: 'number',
55
+ },
56
+ ]),
57
+ ).toEqual(['#:foo'])
58
+ expect(
59
+ getTersePt([
60
+ {
61
+ _key: keyGenerator(),
62
+ _type: 'block',
63
+ children: [{_key: keyGenerator(), _type: 'span', text: 'foo'}],
64
+ listItem: 'number',
65
+ style: 'h3',
66
+ },
67
+ ]),
68
+ ).toEqual(['#h3:foo'])
69
+ expect(
70
+ getTersePt([
71
+ {
72
+ _key: keyGenerator(),
73
+ _type: 'block',
74
+ children: [{_key: keyGenerator(), _type: 'span', text: 'foo'}],
75
+ level: 2,
76
+ listItem: 'number',
77
+ style: 'h3',
78
+ },
79
+ ]),
80
+ ).toEqual(['>>#h3:foo'])
81
+ })
82
+
83
+ test(parseTersePtString.name, () => {
84
+ expect(parseTersePtString('foo')).toEqual(['foo'])
85
+ expect(parseTersePtString('foo,bar')).toEqual(['foo,bar'])
86
+ expect(parseTersePtString('foo,bar|baz')).toEqual(['foo,bar', 'baz'])
87
+ expect(parseTersePtString('|foo')).toEqual(['', 'foo'])
88
+ expect(parseTersePtString('foo|')).toEqual(['foo', ''])
89
+ expect(parseTersePtString('foo|bar\nbaz')).toEqual(['foo', 'bar\nbaz'])
90
+ expect(parseTersePtString('f,oo||ba,r')).toEqual(['f,oo', '', 'ba,r'])
91
+ expect(parseTersePtString('|')).toEqual(['', ''])
92
+ expect(parseTersePtString('||')).toEqual(['', '', ''])
93
+ expect(parseTersePtString('>>#h3:foo')).toEqual(['>>#h3:foo'])
40
94
  })
41
95
 
42
96
  test(parseTersePt.name, () => {
43
- expect(parseTersePt('foo')).toEqual(['foo'])
44
- expect(parseTersePt('foo,bar')).toEqual(['foo', 'bar'])
45
- expect(parseTersePt('foo,bar|baz')).toEqual(['foo', 'bar', '|', 'baz'])
46
- expect(parseTersePt('|foo')).toEqual(['', '|', 'foo'])
47
- expect(parseTersePt('foo|')).toEqual(['foo', '|', ''])
48
- expect(parseTersePt('foo|bar\nbaz')).toEqual(['foo', '|', 'bar\nbaz'])
49
- expect(parseTersePt('f,oo||ba,r')).toEqual([
50
- 'f',
51
- 'oo',
52
- '|',
53
- '',
54
- '|',
55
- 'ba',
56
- 'r',
97
+ expect(
98
+ parseTersePt(
99
+ {
100
+ schema: compileSchemaDefinition(defineSchema({})),
101
+ keyGenerator: createTestKeyGenerator(),
102
+ },
103
+ parseTersePtString('[image]|foo|>>#h4:bar|-:baz,fizz|,[stock-ticker],'),
104
+ ),
105
+ ).toEqual([
106
+ {
107
+ _key: 'k0',
108
+ _type: 'image',
109
+ },
110
+ {
111
+ _key: 'k1',
112
+ _type: 'block',
113
+ children: [{_key: 'k2', _type: 'span', text: 'foo'}],
114
+ },
115
+ {
116
+ _key: 'k3',
117
+ _type: 'block',
118
+ children: [{_key: 'k4', _type: 'span', text: 'bar'}],
119
+ level: 2,
120
+ listItem: 'number',
121
+ style: 'h4',
122
+ },
123
+ {
124
+ _key: 'k5',
125
+ _type: 'block',
126
+ children: [
127
+ {_key: 'k6', _type: 'span', text: 'baz'},
128
+ {_key: 'k7', _type: 'span', text: 'fizz'},
129
+ ],
130
+ listItem: 'bullet',
131
+ },
132
+ {
133
+ _key: 'k8',
134
+ _type: 'block',
135
+ children: [
136
+ {_key: 'k9', _type: 'span', text: ''},
137
+ {_key: 'k10', _type: 'stock-ticker'},
138
+ {_key: 'k11', _type: 'span', text: ''},
139
+ ],
140
+ },
57
141
  ])
58
- expect(parseTersePt('|')).toEqual(['', '|', ''])
59
- expect(parseTersePt('||')).toEqual(['', '|', '', '|', ''])
60
142
  })
@@ -1,36 +1,154 @@
1
1
  import {isPortableTextBlock, isPortableTextSpan} from '@portabletext/toolkit'
2
- import type {PortableTextBlock} from '@sanity/types'
2
+ import type {PortableTextBlock, PortableTextTextBlock} from '@sanity/types'
3
+ import type {EditorContext} from '../editor/editor-snapshot'
3
4
 
4
- export function getTersePt(value: Array<PortableTextBlock> | undefined) {
5
+ type TersePtConfig = {
6
+ style: (name?: string) => string
7
+ listItem: (name?: string) => string
8
+ level: (level?: number) => string
9
+ }
10
+
11
+ const defaultConfig: TersePtConfig = {
12
+ style: (name) =>
13
+ name === undefined || name === 'normal'
14
+ ? ''
15
+ : name === 'blockquote'
16
+ ? 'q'
17
+ : `${name}`,
18
+ listItem: (name) => (name === undefined ? '' : name === 'number' ? '#' : '-'),
19
+ level: (level) => (level === undefined ? '' : '>'.repeat(level)),
20
+ }
21
+
22
+ export function getTersePt(
23
+ value: Array<PortableTextBlock> | undefined,
24
+ ): Array<string> {
5
25
  if (!value) {
6
- return undefined
26
+ return []
7
27
  }
8
28
 
9
29
  const blocks: Array<string> = []
10
30
 
11
31
  for (const block of value) {
12
- if (blocks.length > 0) {
13
- blocks.push('|')
14
- }
32
+ let terseBlock = ''
33
+
15
34
  if (isPortableTextBlock(block)) {
35
+ const blockPrefix = `${defaultConfig.level(block.level)}${defaultConfig.listItem(block.listItem)}${defaultConfig.style(block.style)}`
36
+
37
+ if (blockPrefix) {
38
+ terseBlock = `${blockPrefix}:`
39
+ }
40
+
41
+ let index = -1
16
42
  for (const child of block.children) {
43
+ index++
44
+
17
45
  if (isPortableTextSpan(child)) {
18
- blocks.push(child.text)
46
+ terseBlock = `${terseBlock}${index > 0 ? ',' : ''}${child.text}`
19
47
  } else {
20
- blocks.push(`[${child._type}]`)
48
+ terseBlock = `${terseBlock}${index > 0 ? ',' : ''}[${child._type}]`
21
49
  }
22
50
  }
23
51
  } else {
24
- blocks.push(`[${block._type}]`)
52
+ terseBlock = `[${block._type}]`
53
+ }
54
+
55
+ blocks.push(terseBlock)
56
+ }
57
+
58
+ return blocks
59
+ }
60
+
61
+ export function parseTersePt(
62
+ context: Pick<EditorContext, 'keyGenerator' | 'schema'>,
63
+ tersePt: Array<string>,
64
+ ): Array<PortableTextBlock> {
65
+ const blocks: Array<PortableTextBlock> = []
66
+
67
+ for (const terseBlock of tersePt) {
68
+ if (terseBlock.startsWith('[')) {
69
+ blocks.push({
70
+ _type: terseBlock.slice(1, -1),
71
+ _key: context.keyGenerator(),
72
+ })
73
+
74
+ continue
25
75
  }
76
+
77
+ const block: PortableTextTextBlock = {
78
+ _key: context.keyGenerator(),
79
+ _type: context.schema.block.name,
80
+ children: [],
81
+ }
82
+
83
+ if (terseBlock.includes(':')) {
84
+ const [prefix, content] = terseBlock.split(':')
85
+
86
+ const listItem = prefix.includes('#')
87
+ ? 'number'
88
+ : prefix.includes('-')
89
+ ? 'bullet'
90
+ : undefined
91
+
92
+ if (listItem !== undefined) {
93
+ block.listItem = listItem
94
+ }
95
+
96
+ const level = prefix.split('').filter((part) => part === '>').length
97
+
98
+ if (level > 0) {
99
+ block.level = level
100
+ }
101
+
102
+ const style = prefix
103
+ .split('')
104
+ .filter((part) => !['#', '-', '>'].includes(part))
105
+ .join('')
106
+
107
+ if (style) {
108
+ block.style = style
109
+ }
110
+
111
+ const textRuns = content.split(',')
112
+
113
+ for (const textRun of textRuns) {
114
+ if (textRun.startsWith('[')) {
115
+ block.children.push({
116
+ _key: context.keyGenerator(),
117
+ _type: textRun.slice(1, -1),
118
+ })
119
+ } else {
120
+ block.children.push({
121
+ _key: context.keyGenerator(),
122
+ _type: context.schema.span.name,
123
+ text: textRun,
124
+ })
125
+ }
126
+ }
127
+ } else {
128
+ const textRuns = terseBlock.split(',')
129
+
130
+ for (const textRun of textRuns) {
131
+ if (textRun.startsWith('[')) {
132
+ block.children.push({
133
+ _key: context.keyGenerator(),
134
+ _type: textRun.slice(1, -1),
135
+ })
136
+ } else {
137
+ block.children.push({
138
+ _key: context.keyGenerator(),
139
+ _type: context.schema.span.name,
140
+ text: textRun,
141
+ })
142
+ }
143
+ }
144
+ }
145
+
146
+ blocks.push(block)
26
147
  }
27
148
 
28
149
  return blocks
29
150
  }
30
151
 
31
- export function parseTersePt(text: string) {
32
- return text
33
- .replace(/\|/g, ',|,')
34
- .split(',')
35
- .map((span) => span.replace(/\\n/g, '\n'))
152
+ export function parseTersePtString(text: string) {
153
+ return text.split('|').map((span) => span.replace(/\\n/g, '\n'))
36
154
  }
@@ -111,7 +111,6 @@ export const decoratorAddOperationImplementation: BehaviorOperationImplementatio
111
111
  beta: {
112
112
  activeAnnotations: [],
113
113
  activeDecorators: [],
114
- hasTag: () => false,
115
114
  internalDrag: undefined,
116
115
  },
117
116
  context: {
@@ -1,24 +1,29 @@
1
1
  import {Transforms} from 'slate'
2
2
  import {toSlateRange} from '../internal-utils/ranges'
3
3
  import {getBlockPath} from '../internal-utils/slate-utils'
4
- import {isKeyedSegment} from '../utils'
4
+ import {getBlockKeyFromSelectionPoint} from '../selection/selection-point'
5
5
  import type {BehaviorOperationImplementation} from './behavior.operations'
6
6
 
7
7
  export const deleteOperationImplementation: BehaviorOperationImplementation<
8
8
  'delete'
9
9
  > = ({operation}) => {
10
- const anchorBlockPath = isKeyedSegment(operation.at.anchor.path[0])
11
- ? getBlockPath({
12
- editor: operation.editor,
13
- _key: operation.at.anchor.path[0]._key,
14
- })
15
- : undefined
16
- const focusBlockPath = isKeyedSegment(operation.at.focus.path[0])
17
- ? getBlockPath({
18
- editor: operation.editor,
19
- _key: operation.at.focus.path[0]._key,
20
- })
21
- : undefined
10
+ const anchorBlockKey = getBlockKeyFromSelectionPoint(operation.at.anchor)
11
+ const focusBlockKey = getBlockKeyFromSelectionPoint(operation.at.focus)
12
+
13
+ const anchorBlockPath =
14
+ anchorBlockKey !== undefined
15
+ ? getBlockPath({
16
+ editor: operation.editor,
17
+ _key: anchorBlockKey,
18
+ })
19
+ : undefined
20
+ const focusBlockPath =
21
+ focusBlockKey !== undefined
22
+ ? getBlockPath({
23
+ editor: operation.editor,
24
+ _key: focusBlockKey,
25
+ })
26
+ : undefined
22
27
 
23
28
  if (
24
29
  operation.at.anchor.path.length === 1 &&
@@ -82,7 +82,7 @@ export function insertBlock({
82
82
  }
83
83
  } else if (placement === 'after') {
84
84
  const nextPath = lastBlockPath ? [lastBlockPath[0] + 1] : [0]
85
- Transforms.insertNodes(editor, [block], {at: nextPath, select: false})
85
+ Transforms.insertNodes(editor, [block], {at: nextPath})
86
86
 
87
87
  if (select === 'start') {
88
88
  Transforms.select(editor, Editor.start(editor, nextPath))
@@ -358,6 +358,10 @@ export function insertBlock({
358
358
  const [focusChild] = getFocusChild({editor})
359
359
 
360
360
  if (focusChild && editor.isTextSpan(focusChild)) {
361
+ Transforms.splitNodes(editor, {
362
+ at: currentSelection,
363
+ })
364
+
361
365
  Transforms.insertFragment(editor, [block], {
362
366
  at: currentSelection,
363
367
  })
@@ -0,0 +1,22 @@
1
+ import type {EditorSelectionPoint} from '../types/editor'
2
+ import {isKeyedSegment} from '../utils'
3
+
4
+ export function getBlockKeyFromSelectionPoint(point: EditorSelectionPoint) {
5
+ const blockPathSegment = point.path.at(0)
6
+
7
+ if (isKeyedSegment(blockPathSegment)) {
8
+ return blockPathSegment._key
9
+ }
10
+
11
+ return undefined
12
+ }
13
+
14
+ export function getChildKeyFromSelectionPoint(point: EditorSelectionPoint) {
15
+ const childPathSegment = point.path.at(2)
16
+
17
+ if (isKeyedSegment(childPathSegment)) {
18
+ return childPathSegment._key
19
+ }
20
+
21
+ return undefined
22
+ }
@@ -8,7 +8,7 @@ export {getAnchorTextBlock} from './selector.get-anchor-text-block'
8
8
  export {getBlockOffsets} from './selector.get-block-offsets'
9
9
  export {getCaretWordSelection} from './selector.get-caret-word-selection'
10
10
  export {getFocusInlineObject} from './selector.get-focus-inline-object'
11
- export {getListState} from './selector.get-list-state'
11
+ export {getListIndex} from './selector.get-list-state'
12
12
  export {getNextInlineObject} from './selector.get-next-inline-object'
13
13
  export {getPreviousInlineObject} from './selector.get-previous-inline-object'
14
14
  export {getSelectedSlice} from './selector.get-selected-slice'
@@ -1,6 +1,6 @@
1
1
  import type {KeyedSegment, PortableTextBlock} from '@sanity/types'
2
2
  import type {EditorSelector} from '../editor/editor-selector'
3
- import {isKeyedSegment} from '../utils'
3
+ import {getBlockKeyFromSelectionPoint} from '../selection/selection-point'
4
4
 
5
5
  /**
6
6
  * @public
@@ -8,11 +8,11 @@ import {isKeyedSegment} from '../utils'
8
8
  export const getAnchorBlock: EditorSelector<
9
9
  {node: PortableTextBlock; path: [KeyedSegment]} | undefined
10
10
  > = (snapshot) => {
11
- const key = snapshot.context.selection
12
- ? isKeyedSegment(snapshot.context.selection.anchor.path[0])
13
- ? snapshot.context.selection.anchor.path[0]._key
14
- : undefined
15
- : undefined
11
+ if (!snapshot.context.selection) {
12
+ return undefined
13
+ }
14
+
15
+ const key = getBlockKeyFromSelectionPoint(snapshot.context.selection.anchor)
16
16
 
17
17
  const node = key
18
18
  ? snapshot.context.value.find((block) => block._key === key)
@@ -1,7 +1,7 @@
1
1
  import type {KeyedSegment} from '@portabletext/patches'
2
2
  import type {PortableTextObject, PortableTextSpan} from '@sanity/types'
3
3
  import type {EditorSelector} from '../editor/editor-selector'
4
- import {isKeyedSegment} from '../utils'
4
+ import {getChildKeyFromSelectionPoint} from '../selection/selection-point'
5
5
  import {getAnchorTextBlock} from './selector.get-anchor-text-block'
6
6
 
7
7
  /**
@@ -14,17 +14,17 @@ export const getAnchorChild: EditorSelector<
14
14
  }
15
15
  | undefined
16
16
  > = (snapshot) => {
17
+ if (!snapshot.context.selection) {
18
+ return undefined
19
+ }
20
+
17
21
  const anchorBlock = getAnchorTextBlock(snapshot)
18
22
 
19
23
  if (!anchorBlock) {
20
24
  return undefined
21
25
  }
22
26
 
23
- const key = snapshot.context.selection
24
- ? isKeyedSegment(snapshot.context.selection.anchor.path[2])
25
- ? snapshot.context.selection.anchor.path[2]._key
26
- : undefined
27
- : undefined
27
+ const key = getChildKeyFromSelectionPoint(snapshot.context.selection.anchor)
28
28
 
29
29
  const node = key
30
30
  ? anchorBlock.node.children.find((span) => span._key === key)