@portabletext/editor 1.48.7 → 1.48.8

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 (128) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +20 -8
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +5 -5
  4. package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
  5. package/lib/_chunks-cjs/editor-provider.cjs +121 -90
  6. package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
  7. package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs +2 -2
  8. package/lib/_chunks-cjs/selector.get-focus-inline-object.cjs.map +1 -1
  9. package/lib/_chunks-cjs/selector.get-text-before.cjs +7 -4
  10. package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
  11. package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs +63 -47
  12. package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs.map +1 -1
  13. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs +29 -23
  14. package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
  15. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +3 -3
  16. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
  17. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +15 -15
  18. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
  19. package/lib/_chunks-cjs/util.slice-blocks.cjs +258 -38
  20. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  21. package/lib/_chunks-es/behavior.core.js +21 -10
  22. package/lib/_chunks-es/behavior.core.js.map +1 -1
  23. package/lib/_chunks-es/behavior.markdown.js +5 -6
  24. package/lib/_chunks-es/behavior.markdown.js.map +1 -1
  25. package/lib/_chunks-es/editor-provider.js +75 -46
  26. package/lib/_chunks-es/editor-provider.js.map +1 -1
  27. package/lib/_chunks-es/selector.get-focus-inline-object.js +1 -2
  28. package/lib/_chunks-es/selector.get-focus-inline-object.js.map +1 -1
  29. package/lib/_chunks-es/selector.get-text-before.js +7 -4
  30. package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
  31. package/lib/_chunks-es/selector.is-overlapping-selection.js +61 -46
  32. package/lib/_chunks-es/selector.is-overlapping-selection.js.map +1 -1
  33. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +30 -26
  34. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
  35. package/lib/_chunks-es/util.merge-text-blocks.js +1 -1
  36. package/lib/_chunks-es/util.selection-point-to-block-offset.js +15 -16
  37. package/lib/_chunks-es/util.selection-point-to-block-offset.js.map +1 -1
  38. package/lib/_chunks-es/util.slice-blocks.js +258 -38
  39. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  40. package/lib/behaviors/index.d.cts +2552 -251
  41. package/lib/behaviors/index.d.ts +2552 -251
  42. package/lib/index.cjs +45 -21
  43. package/lib/index.cjs.map +1 -1
  44. package/lib/index.d.cts +2350 -51
  45. package/lib/index.d.ts +2350 -51
  46. package/lib/index.js +44 -21
  47. package/lib/index.js.map +1 -1
  48. package/lib/plugins/index.cjs +16 -7
  49. package/lib/plugins/index.cjs.map +1 -1
  50. package/lib/plugins/index.d.cts +2324 -24
  51. package/lib/plugins/index.d.ts +2324 -24
  52. package/lib/plugins/index.js +16 -7
  53. package/lib/plugins/index.js.map +1 -1
  54. package/lib/selectors/index.cjs +5 -5
  55. package/lib/selectors/index.cjs.map +1 -1
  56. package/lib/selectors/index.d.cts +2321 -28
  57. package/lib/selectors/index.d.ts +2321 -28
  58. package/lib/selectors/index.js +5 -6
  59. package/lib/selectors/index.js.map +1 -1
  60. package/lib/utils/index.cjs +30 -24
  61. package/lib/utils/index.cjs.map +1 -1
  62. package/lib/utils/index.d.cts +2350 -44
  63. package/lib/utils/index.d.ts +2350 -44
  64. package/lib/utils/index.js +30 -24
  65. package/lib/utils/index.js.map +1 -1
  66. package/package.json +1 -2
  67. package/src/behavior-actions/behavior.action.block.unset.ts +1 -1
  68. package/src/behavior-actions/behavior.action.decorator.add.ts +20 -5
  69. package/src/behaviors/behavior.abstract.decorator.ts +1 -1
  70. package/src/behaviors/behavior.abstract.delete.ts +1 -1
  71. package/src/behaviors/behavior.abstract.insert.ts +2 -2
  72. package/src/behaviors/behavior.abstract.select.ts +16 -4
  73. package/src/behaviors/behavior.abstract.split.ts +9 -6
  74. package/src/behaviors/behavior.core.block-objects.ts +5 -5
  75. package/src/behaviors/behavior.core.insert-break.ts +16 -4
  76. package/src/behaviors/behavior.core.lists.ts +4 -6
  77. package/src/behaviors/behavior.decorator-pair.ts +13 -4
  78. package/src/behaviors/behavior.default.ts +1 -1
  79. package/src/behaviors/behavior.markdown.ts +5 -5
  80. package/src/converters/converter.portable-text.ts +1 -1
  81. package/src/converters/converter.text-html.ts +1 -1
  82. package/src/converters/converter.text-plain.ts +4 -4
  83. package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +10 -2
  84. package/src/editor/plugins/createWithSchemaTypes.ts +12 -19
  85. package/src/internal-utils/__tests__/dmpToOperations.test.ts +13 -12
  86. package/src/internal-utils/drag-selection.ts +16 -4
  87. package/src/internal-utils/event-position.ts +20 -8
  88. package/src/internal-utils/parse-blocks.ts +17 -5
  89. package/src/internal-utils/validateValue.ts +6 -6
  90. package/src/plugins/plugin.decorator-shortcut.ts +2 -2
  91. package/src/selectors/selector.get-active-annotations.ts +5 -2
  92. package/src/selectors/selector.get-active-list-item.ts +4 -3
  93. package/src/selectors/selector.get-active-style.ts +4 -3
  94. package/src/selectors/selector.get-anchor-text-block.ts +3 -6
  95. package/src/selectors/selector.get-block-offsets.ts +2 -2
  96. package/src/selectors/selector.get-caret-word-selection.ts +11 -5
  97. package/src/selectors/selector.get-selected-slice.ts +1 -1
  98. package/src/selectors/selector.get-selected-spans.ts +11 -15
  99. package/src/selectors/selector.get-selected-text-blocks.ts +3 -3
  100. package/src/selectors/selector.get-selection-text.ts +3 -3
  101. package/src/selectors/selector.get-text-before.ts +5 -2
  102. package/src/selectors/selector.get-trimmed-selection.ts +20 -14
  103. package/src/selectors/selector.is-active-annotation.ts +4 -2
  104. package/src/selectors/selector.is-active-decorator.test.ts +3 -3
  105. package/src/selectors/selector.is-at-the-end-of-block.ts +4 -1
  106. package/src/selectors/selector.is-at-the-start-of-block.ts +4 -1
  107. package/src/selectors/selector.is-point-after-selection.ts +7 -6
  108. package/src/selectors/selector.is-point-before-selection.ts +7 -6
  109. package/src/selectors/selector.is-selecting-entire-blocks.ts +8 -2
  110. package/src/selectors/selectors.ts +25 -28
  111. package/src/utils/util.block-offset-to-block-selection-point.ts +4 -4
  112. package/src/utils/util.block-offset-to-selection-point.ts +5 -5
  113. package/src/utils/util.block-offset.test.ts +219 -156
  114. package/src/utils/util.block-offset.ts +14 -17
  115. package/src/utils/util.block-offsets-to-selection.ts +5 -5
  116. package/src/utils/util.child-selection-point-to-block-offset.ts +7 -10
  117. package/src/utils/util.get-block-end-point.ts +15 -15
  118. package/src/utils/util.get-block-start-point.ts +13 -12
  119. package/src/utils/util.is-empty-text-block.ts +9 -8
  120. package/src/utils/util.selection-point-to-block-offset.ts +4 -4
  121. package/src/utils/util.slice-blocks.test.ts +178 -121
  122. package/src/utils/util.slice-blocks.ts +25 -24
  123. package/src/utils/util.split-text-block.ts +18 -12
  124. package/lib/_chunks-cjs/parse-blocks.cjs +0 -205
  125. package/lib/_chunks-cjs/parse-blocks.cjs.map +0 -1
  126. package/lib/_chunks-es/parse-blocks.js +0 -206
  127. package/lib/_chunks-es/parse-blocks.js.map +0 -1
  128. package/src/behavior-actions/behavior.guards.ts +0 -24
@@ -1,17 +1,16 @@
1
1
  import type {DiffMatchPatch} from '@portabletext/patches'
2
2
  import {makeDiff, makePatches, stringifyPatches} from '@sanity/diff-match-patch'
3
- import {
4
- isPortableTextSpan,
5
- isPortableTextTextBlock,
6
- type Path,
7
- type PortableTextBlock,
8
- type PortableTextSpan,
9
- type PortableTextTextBlock,
3
+ import type {
4
+ Path,
5
+ PortableTextBlock,
6
+ PortableTextSpan,
7
+ PortableTextTextBlock,
10
8
  } from '@sanity/types'
11
9
  import type {Descendant, Operation} from 'slate'
12
10
  import {describe, expect, test} from 'vitest'
13
11
  import type {PortableTextSlateEditor} from '../../types/editor'
14
12
  import {diffMatchPatch} from '../applyPatch'
13
+ import {isTypedObject} from '../asserters'
15
14
 
16
15
  describe('operationToPatches: diffMatchPatch', () => {
17
16
  test.todo('skips patches for blocks that cannot be found locally')
@@ -152,13 +151,11 @@ function getMockEditor(options: MockEditorOptions): Pick<
152
151
 
153
152
  function getText(blockKey?: string) {
154
153
  return children
155
- .filter((child): child is PortableTextTextBlock =>
156
- isPortableTextTextBlock(child),
157
- )
154
+ .filter(isTextBlock)
158
155
  .filter((child) => (blockKey ? child._key === blockKey : true))
159
156
  .flatMap((block) =>
160
157
  block.children
161
- .filter((span) => isPortableTextSpan(span))
158
+ .filter((span) => isSpan(span))
162
159
  .map((span) => span.text)
163
160
  .join(''),
164
161
  )
@@ -166,7 +163,11 @@ function getMockEditor(options: MockEditorOptions): Pick<
166
163
  }
167
164
 
168
165
  function isTextBlock(value: unknown): value is PortableTextTextBlock {
169
- return isPortableTextTextBlock(value)
166
+ return isTypedObject(value) && value._type === 'block'
167
+ }
168
+
169
+ function isSpan(value: unknown): value is PortableTextSpan {
170
+ return isTypedObject(value) && value._type === 'span'
170
171
  }
171
172
 
172
173
  function apply(operation: Operation): void {
@@ -55,8 +55,14 @@ export function getDragSelection({
55
55
  // Looks like we are dragging an empty span
56
56
  // Let's drag the entire block instead
57
57
  dragSelection = {
58
- anchor: utils.getBlockStartPoint(draggedTextBlock),
59
- focus: utils.getBlockEndPoint(draggedTextBlock),
58
+ anchor: utils.getBlockStartPoint({
59
+ context: snapshot.context,
60
+ block: draggedTextBlock,
61
+ }),
62
+ focus: utils.getBlockEndPoint({
63
+ context: snapshot.context,
64
+ block: draggedTextBlock,
65
+ }),
60
66
  }
61
67
  }
62
68
 
@@ -74,8 +80,14 @@ export function getDragSelection({
74
80
  return dragSelection
75
81
  }
76
82
 
77
- const selectionStartPoint = utils.getBlockStartPoint(selectionStartBlock)
78
- const selectionEndPoint = utils.getBlockEndPoint(selectionEndBlock)
83
+ const selectionStartPoint = utils.getBlockStartPoint({
84
+ context: snapshot.context,
85
+ block: selectionStartBlock,
86
+ })
87
+ const selectionEndPoint = utils.getBlockEndPoint({
88
+ context: snapshot.context,
89
+ block: selectionEndBlock,
90
+ })
79
91
 
80
92
  const eventSelectionInsideBlocks = selectors.isOverlappingSelection(
81
93
  eventSelection,
@@ -59,12 +59,18 @@ export function getEventPosition({
59
59
  isEditor: false,
60
60
  selection: {
61
61
  anchor: utils.getBlockStartPoint({
62
- node: block,
63
- path: [{_key: block._key}],
62
+ context: editorActor.getSnapshot().context,
63
+ block: {
64
+ node: block,
65
+ path: [{_key: block._key}],
66
+ },
64
67
  }),
65
68
  focus: utils.getBlockEndPoint({
66
- node: block,
67
- path: [{_key: block._key}],
69
+ context: editorActor.getSnapshot().context,
70
+ block: {
71
+ node: block,
72
+ path: [{_key: block._key}],
73
+ },
68
74
  }),
69
75
  },
70
76
  }
@@ -93,12 +99,18 @@ export function getEventPosition({
93
99
  isEditor: false,
94
100
  selection: {
95
101
  anchor: utils.getBlockStartPoint({
96
- node: block,
97
- path: [{_key: block._key}],
102
+ context: editorActor.getSnapshot().context,
103
+ block: {
104
+ node: block,
105
+ path: [{_key: block._key}],
106
+ },
98
107
  }),
99
108
  focus: utils.getBlockEndPoint({
100
- node: block,
101
- path: [{_key: block._key}],
109
+ context: editorActor.getSnapshot().context,
110
+ block: {
111
+ node: block,
112
+ path: [{_key: block._key}],
113
+ },
102
114
  }),
103
115
  },
104
116
  }
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  PortableTextBlock,
3
+ PortableTextListBlock,
3
4
  PortableTextObject,
4
5
  PortableTextSpan,
5
6
  PortableTextTextBlock,
@@ -79,14 +80,25 @@ function parseBlockObject({
79
80
  })
80
81
  }
81
82
 
83
+ export function isListBlock(
84
+ context: Pick<EditorContext, 'schema'>,
85
+ block: unknown,
86
+ ): block is PortableTextListBlock {
87
+ return (
88
+ isTextBlock(context, block) &&
89
+ block.level !== undefined &&
90
+ block.listItem !== undefined
91
+ )
92
+ }
93
+
82
94
  export function isTextBlock(
83
- schema: EditorSchema,
95
+ context: Pick<EditorContext, 'schema'>,
84
96
  block: unknown,
85
97
  ): block is PortableTextTextBlock {
86
98
  return (
87
99
  parseTextBlock({
88
100
  block,
89
- context: {schema, keyGenerator: () => ''},
101
+ context: {schema: context.schema, keyGenerator: () => ''},
90
102
  options: {refreshKeys: false},
91
103
  }) !== undefined
92
104
  )
@@ -215,14 +227,14 @@ function parseTextBlock({
215
227
  }
216
228
 
217
229
  export function isSpan(
218
- schema: EditorSchema,
219
- child: PortableTextSpan | PortableTextObject,
230
+ context: Pick<EditorContext, 'schema'>,
231
+ child: unknown,
220
232
  ): child is PortableTextSpan {
221
233
  return (
222
234
  parseSpan({
223
235
  span: child,
224
236
  markDefKeyMap: new Map(),
225
- context: {schema, keyGenerator: () => ''},
237
+ context: {schema: context.schema, keyGenerator: () => ''},
226
238
  options: {refreshKeys: false},
227
239
  }) !== undefined
228
240
  )
@@ -1,13 +1,13 @@
1
1
  import {insert, set, setIfMissing, unset} from '@portabletext/patches'
2
- import {
3
- isPortableTextTextBlock,
4
- type PortableTextBlock,
5
- type PortableTextSpan,
6
- type PortableTextTextBlock,
2
+ import type {
3
+ PortableTextBlock,
4
+ PortableTextSpan,
5
+ PortableTextTextBlock,
7
6
  } from '@sanity/types'
8
7
  import {flatten, isPlainObject, uniq} from 'lodash'
9
8
  import type {EditorSchema} from '../editor/editor-schema'
10
9
  import type {InvalidValueResolution} from '../types/editor'
10
+ import {isTextBlock} from './parse-blocks'
11
11
 
12
12
  export interface Validation {
13
13
  valid: boolean
@@ -118,7 +118,7 @@ export function validateValue(
118
118
  // If the block has no `_type`, but aside from that is a valid Portable Text block
119
119
  if (
120
120
  !blk._type &&
121
- isPortableTextTextBlock({...blk, _type: types.block.name})
121
+ isTextBlock({schema: types}, {...blk, _type: types.block.name})
122
122
  ) {
123
123
  resolution = {
124
124
  patches: [
@@ -89,11 +89,11 @@ const selectionListenerCallback: CallbackLogicFunction<
89
89
  }
90
90
 
91
91
  const anchor = utils.spanSelectionPointToBlockOffset({
92
- value: snapshot.context.value,
92
+ context: snapshot.context,
93
93
  selectionPoint: event.at.anchor,
94
94
  })
95
95
  const focus = utils.spanSelectionPointToBlockOffset({
96
- value: snapshot.context.value,
96
+ context: snapshot.context,
97
97
  selectionPoint: event.at.focus,
98
98
  })
99
99
 
@@ -1,5 +1,6 @@
1
- import {isPortableTextTextBlock, type PortableTextObject} from '@sanity/types'
1
+ import type {PortableTextObject} from '@sanity/types'
2
2
  import type {EditorSelector} from '../editor/editor-selector'
3
+ import {isTextBlock} from '../internal-utils/parse-blocks'
3
4
  import {getSelectedSpans} from './selector.get-selected-spans'
4
5
  import {isSelectionCollapsed} from './selector.is-selection-collapsed'
5
6
  import {getFocusSpan, getSelectedBlocks} from './selectors'
@@ -34,7 +35,9 @@ export const getActiveAnnotations: EditorSelector<Array<PortableTextObject>> = (
34
35
  }
35
36
 
36
37
  const selectionMarkDefs = selectedBlocks.flatMap((block) =>
37
- isPortableTextTextBlock(block.node) ? (block.node.markDefs ?? []) : [],
38
+ isTextBlock(snapshot.context, block.node)
39
+ ? (block.node.markDefs ?? [])
40
+ : [],
38
41
  )
39
42
 
40
43
  return selectionMarkDefs.filter((markDef) =>
@@ -1,6 +1,6 @@
1
1
  import type {PortableTextListBlock} from '@sanity/types'
2
- import {createGuards} from '../behavior-actions/behavior.guards'
3
2
  import type {EditorSelector} from '../editor/editor-selector'
3
+ import {isTextBlock} from '../internal-utils/parse-blocks'
4
4
  import {getSelectedBlocks} from './selectors'
5
5
 
6
6
  /**
@@ -13,9 +13,10 @@ export const getActiveListItem: EditorSelector<
13
13
  return undefined
14
14
  }
15
15
 
16
- const guards = createGuards(snapshot.context)
17
16
  const selectedBlocks = getSelectedBlocks(snapshot).map((block) => block.node)
18
- const selectedTextBlocks = selectedBlocks.filter(guards.isTextBlock)
17
+ const selectedTextBlocks = selectedBlocks.filter((block) =>
18
+ isTextBlock(snapshot.context, block),
19
+ )
19
20
 
20
21
  const firstTextBlock = selectedTextBlocks.at(0)
21
22
 
@@ -1,6 +1,6 @@
1
1
  import type {PortableTextTextBlock} from '@sanity/types'
2
- import {createGuards} from '../behavior-actions/behavior.guards'
3
2
  import type {EditorSelector} from '../editor/editor-selector'
3
+ import {isTextBlock} from '../internal-utils/parse-blocks'
4
4
  import {getSelectedBlocks} from './selectors'
5
5
 
6
6
  /**
@@ -13,9 +13,10 @@ export const getActiveStyle: EditorSelector<PortableTextTextBlock['style']> = (
13
13
  return undefined
14
14
  }
15
15
 
16
- const guards = createGuards(snapshot.context)
17
16
  const selectedBlocks = getSelectedBlocks(snapshot).map((block) => block.node)
18
- const selectedTextBlocks = selectedBlocks.filter(guards.isTextBlock)
17
+ const selectedTextBlocks = selectedBlocks.filter((block) =>
18
+ isTextBlock(snapshot.context, block),
19
+ )
19
20
 
20
21
  const firstTextBlock = selectedTextBlocks.at(0)
21
22
 
@@ -1,9 +1,6 @@
1
- import {
2
- isPortableTextTextBlock,
3
- type KeyedSegment,
4
- type PortableTextTextBlock,
5
- } from '@sanity/types'
1
+ import type {KeyedSegment, PortableTextTextBlock} from '@sanity/types'
6
2
  import type {EditorSelector} from '../editor/editor-selector'
3
+ import {isTextBlock} from '../internal-utils/parse-blocks'
7
4
  import {getAnchorBlock} from './selector.get-anchor-block'
8
5
 
9
6
  /**
@@ -14,7 +11,7 @@ export const getAnchorTextBlock: EditorSelector<
14
11
  > = (snapshot) => {
15
12
  const anchorBlock = getAnchorBlock(snapshot)
16
13
 
17
- return anchorBlock && isPortableTextTextBlock(anchorBlock.node)
14
+ return anchorBlock && isTextBlock(snapshot.context, anchorBlock.node)
18
15
  ? {node: anchorBlock.node, path: anchorBlock.path}
19
16
  : undefined
20
17
  }
@@ -22,11 +22,11 @@ export const getBlockOffsets: EditorSelector<
22
22
  }
23
23
 
24
24
  const start = utils.spanSelectionPointToBlockOffset({
25
- value: snapshot.context.value,
25
+ context: snapshot.context,
26
26
  selectionPoint: selectionStartPoint,
27
27
  })
28
28
  const end = utils.spanSelectionPointToBlockOffset({
29
- value: snapshot.context.value,
29
+ context: snapshot.context,
30
30
  selectionPoint: selectionEndPoint,
31
31
  })
32
32
 
@@ -35,7 +35,7 @@ export const getCaretWordSelection: EditorSelector<EditorSelection> = (
35
35
  const selectionStartPoint = getSelectionStartPoint(snapshot)
36
36
  const selectionStartOffset = selectionStartPoint
37
37
  ? spanSelectionPointToBlockOffset({
38
- value: snapshot.context.value,
38
+ context: snapshot.context,
39
39
  selectionPoint: selectionStartPoint,
40
40
  })
41
41
  : undefined
@@ -45,7 +45,10 @@ export const getCaretWordSelection: EditorSelector<EditorSelection> = (
45
45
  }
46
46
 
47
47
  const previousInlineObject = getPreviousInlineObject(snapshot)
48
- const blockStartPoint = getBlockStartPoint(focusTextBlock)
48
+ const blockStartPoint = getBlockStartPoint({
49
+ context: snapshot.context,
50
+ block: focusTextBlock,
51
+ })
49
52
  const textBefore = getSelectionText({
50
53
  ...snapshot,
51
54
  context: {
@@ -61,7 +64,10 @@ export const getCaretWordSelection: EditorSelector<EditorSelection> = (
61
64
  const textDirectlyBefore = textBefore.split(/\s+/).at(-1)
62
65
 
63
66
  const nextInlineObject = getNextInlineObject(snapshot)
64
- const blockEndPoint = getBlockEndPoint(focusTextBlock)
67
+ const blockEndPoint = getBlockEndPoint({
68
+ context: snapshot.context,
69
+ block: focusTextBlock,
70
+ })
65
71
  const textAfter = getSelectionText({
66
72
  ...snapshot,
67
73
  context: {
@@ -97,12 +103,12 @@ export const getCaretWordSelection: EditorSelector<EditorSelection> = (
97
103
  : selectionStartOffset
98
104
 
99
105
  const caretWordStartSelectionPoint = blockOffsetToSpanSelectionPoint({
100
- value: snapshot.context.value,
106
+ context: snapshot.context,
101
107
  blockOffset: caretWordStartOffset,
102
108
  direction: 'backward',
103
109
  })
104
110
  const caretWordEndSelectionPoint = blockOffsetToSpanSelectionPoint({
105
- value: snapshot.context.value,
111
+ context: snapshot.context,
106
112
  blockOffset: caretWordEndOffset,
107
113
  direction: 'forward',
108
114
  })
@@ -9,7 +9,7 @@ export const getSelectedSlice: EditorSelector<Array<PortableTextBlock>> = (
9
9
  snapshot,
10
10
  ) => {
11
11
  return sliceBlocks({
12
+ context: snapshot.context,
12
13
  blocks: snapshot.context.value,
13
- selection: snapshot.context.selection,
14
14
  })
15
15
  }
@@ -1,11 +1,7 @@
1
- import {
2
- isKeySegment,
3
- isPortableTextSpan,
4
- isPortableTextTextBlock,
5
- type KeyedSegment,
6
- type PortableTextSpan,
7
- } from '@sanity/types'
1
+ import type {KeyedSegment, PortableTextSpan} from '@sanity/types'
8
2
  import type {EditorSelector} from '../editor/editor-selector'
3
+ import {isSpan, isTextBlock} from '../internal-utils/parse-blocks'
4
+ import {isKeyedSegment} from '../utils'
9
5
 
10
6
  /**
11
7
  * @public
@@ -32,10 +28,10 @@ export const getSelectedSpans: EditorSelector<
32
28
  ? snapshot.context.selection.anchor
33
29
  : snapshot.context.selection.focus
34
30
 
35
- const startBlockKey = isKeySegment(startPoint.path[0])
31
+ const startBlockKey = isKeyedSegment(startPoint.path[0])
36
32
  ? startPoint.path[0]._key
37
33
  : undefined
38
- const endBlockKey = isKeySegment(endPoint.path[0])
34
+ const endBlockKey = isKeyedSegment(endPoint.path[0])
39
35
  ? endPoint.path[0]._key
40
36
  : undefined
41
37
 
@@ -43,10 +39,10 @@ export const getSelectedSpans: EditorSelector<
43
39
  return selectedSpans
44
40
  }
45
41
 
46
- const startSpanKey = isKeySegment(startPoint.path[2])
42
+ const startSpanKey = isKeyedSegment(startPoint.path[2])
47
43
  ? startPoint.path[2]._key
48
44
  : undefined
49
- const endSpanKey = isKeySegment(endPoint.path[2])
45
+ const endSpanKey = isKeyedSegment(endPoint.path[2])
50
46
  ? endPoint.path[2]._key
51
47
  : undefined
52
48
 
@@ -57,13 +53,13 @@ export const getSelectedSpans: EditorSelector<
57
53
  startBlockFound = true
58
54
  }
59
55
 
60
- if (!isPortableTextTextBlock(block)) {
56
+ if (!isTextBlock(snapshot.context, block)) {
61
57
  continue
62
58
  }
63
59
 
64
60
  if (block._key === startBlockKey) {
65
61
  for (const child of block.children) {
66
- if (!isPortableTextSpan(child)) {
62
+ if (!isSpan(snapshot.context, child)) {
67
63
  continue
68
64
  }
69
65
 
@@ -109,7 +105,7 @@ export const getSelectedSpans: EditorSelector<
109
105
 
110
106
  if (block._key === endBlockKey) {
111
107
  for (const child of block.children) {
112
- if (!isPortableTextSpan(child)) {
108
+ if (!isSpan(snapshot.context, child)) {
113
109
  continue
114
110
  }
115
111
 
@@ -134,7 +130,7 @@ export const getSelectedSpans: EditorSelector<
134
130
 
135
131
  if (startBlockFound) {
136
132
  for (const child of block.children) {
137
- if (!isPortableTextSpan(child)) {
133
+ if (!isSpan(snapshot.context, child)) {
138
134
  continue
139
135
  }
140
136
 
@@ -38,7 +38,7 @@ export const getSelectedTextBlocks: EditorSelector<
38
38
 
39
39
  for (const block of snapshot.context.value) {
40
40
  if (block._key === startKey) {
41
- if (isTextBlock(snapshot.context.schema, block)) {
41
+ if (isTextBlock(snapshot.context, block)) {
42
42
  selectedTextBlocks.push({node: block, path: [{_key: block._key}]})
43
43
  }
44
44
 
@@ -49,7 +49,7 @@ export const getSelectedTextBlocks: EditorSelector<
49
49
  }
50
50
 
51
51
  if (block._key === endKey) {
52
- if (isTextBlock(snapshot.context.schema, block)) {
52
+ if (isTextBlock(snapshot.context, block)) {
53
53
  selectedTextBlocks.push({node: block, path: [{_key: block._key}]})
54
54
  }
55
55
 
@@ -57,7 +57,7 @@ export const getSelectedTextBlocks: EditorSelector<
57
57
  }
58
58
 
59
59
  if (selectedTextBlocks.length > 0) {
60
- if (isTextBlock(snapshot.context.schema, block)) {
60
+ if (isTextBlock(snapshot.context, block)) {
61
61
  selectedTextBlocks.push({node: block, path: [{_key: block._key}]})
62
62
  }
63
63
  }
@@ -1,5 +1,5 @@
1
- import {isPortableTextSpan, isPortableTextTextBlock} from '@sanity/types'
2
1
  import type {EditorSelector} from '../editor/editor-selector'
2
+ import {isSpan, isTextBlock} from '../internal-utils/parse-blocks'
3
3
  import {getSelectedSlice} from './selector.get-selected-slice'
4
4
 
5
5
  /**
@@ -9,14 +9,14 @@ export const getSelectionText: EditorSelector<string> = (snapshot) => {
9
9
  const selectedSlice = getSelectedSlice(snapshot)
10
10
 
11
11
  return selectedSlice.reduce((text, block) => {
12
- if (!isPortableTextTextBlock(block)) {
12
+ if (!isTextBlock(snapshot.context, block)) {
13
13
  return text
14
14
  }
15
15
 
16
16
  return (
17
17
  text +
18
18
  block.children.reduce((text, child) => {
19
- if (isPortableTextSpan(child)) {
19
+ if (isSpan(snapshot.context, child)) {
20
20
  return text + child.text
21
21
  }
22
22
 
@@ -27,8 +27,11 @@ export const getBlockTextBefore: EditorSelector<string> = (snapshot) => {
27
27
  }
28
28
 
29
29
  const startOfBlock = getBlockStartPoint({
30
- node: block,
31
- path: [{_key: block._key}],
30
+ context: snapshot.context,
31
+ block: {
32
+ node: block,
33
+ path: [{_key: block._key}],
34
+ },
32
35
  })
33
36
 
34
37
  return getSelectionText({
@@ -1,9 +1,6 @@
1
- import {
2
- isPortableTextSpan,
3
- isPortableTextTextBlock,
4
- type PortableTextSpan,
5
- } from '@sanity/types'
1
+ import type {PortableTextSpan} from '@sanity/types'
6
2
  import type {EditorSelector} from '../editor/editor-selector'
3
+ import {isSpan, isTextBlock} from '../internal-utils/parse-blocks'
7
4
  import type {EditorSelection, EditorSelectionPoint} from '../types/editor'
8
5
  import {isEmptyTextBlock, isKeyedSegment} from '../utils'
9
6
  import {getSelectionEndPoint} from './selector.get-selection-end-point'
@@ -58,7 +55,10 @@ export const getTrimmedSelection: EditorSelector<EditorSelection> = (
58
55
  if (block._key === startBlockKey) {
59
56
  startBlockFound = true
60
57
 
61
- if (isPortableTextTextBlock(block) && isEmptyTextBlock(block)) {
58
+ if (
59
+ isTextBlock(snapshot.context, block) &&
60
+ isEmptyTextBlock(snapshot.context, block)
61
+ ) {
62
62
  continue
63
63
  }
64
64
  }
@@ -67,17 +67,20 @@ export const getTrimmedSelection: EditorSelector<EditorSelection> = (
67
67
  continue
68
68
  }
69
69
 
70
- if (!isPortableTextTextBlock(block)) {
70
+ if (!isTextBlock(snapshot.context, block)) {
71
71
  continue
72
72
  }
73
73
 
74
- if (block._key === endBlockKey && isEmptyTextBlock(block)) {
74
+ if (
75
+ block._key === endBlockKey &&
76
+ isEmptyTextBlock(snapshot.context, block)
77
+ ) {
75
78
  break
76
79
  }
77
80
 
78
81
  for (const child of block.children) {
79
82
  if (child._key === endChildKey) {
80
- if (!isPortableTextSpan(child) || endPoint.offset === 0) {
83
+ if (!isSpan(snapshot.context, child) || endPoint.offset === 0) {
81
84
  adjustedEndPoint = previousPotentialEndpoint
82
85
  ? {
83
86
  path: [
@@ -96,10 +99,10 @@ export const getTrimmedSelection: EditorSelector<EditorSelection> = (
96
99
 
97
100
  if (trimStartPoint) {
98
101
  const lonelySpan =
99
- isPortableTextSpan(child) && block.children.length === 1
102
+ isSpan(snapshot.context, child) && block.children.length === 1
100
103
 
101
104
  if (
102
- (isPortableTextSpan(child) && child.text.length > 0) ||
105
+ (isSpan(snapshot.context, child) && child.text.length > 0) ||
103
106
  lonelySpan
104
107
  ) {
105
108
  adjustedStartPoint = {
@@ -114,7 +117,7 @@ export const getTrimmedSelection: EditorSelector<EditorSelection> = (
114
117
  }
115
118
 
116
119
  if (child._key === startChildKey) {
117
- if (!isPortableTextSpan(child)) {
120
+ if (!isSpan(snapshot.context, child)) {
118
121
  trimStartPoint = true
119
122
  continue
120
123
  }
@@ -130,7 +133,7 @@ export const getTrimmedSelection: EditorSelector<EditorSelection> = (
130
133
  }
131
134
 
132
135
  previousPotentialEndpoint =
133
- isPortableTextSpan(child) && child.text.length > 0
136
+ isSpan(snapshot.context, child) && child.text.length > 0
134
137
  ? {blockKey: block._key, span: child}
135
138
  : previousPotentialEndpoint
136
139
  }
@@ -168,7 +171,10 @@ export const getTrimmedSelection: EditorSelector<EditorSelection> = (
168
171
  },
169
172
  })
170
173
 
171
- if (focusTextBlock && !isEmptyTextBlock(focusTextBlock.node)) {
174
+ if (
175
+ focusTextBlock &&
176
+ !isEmptyTextBlock(snapshot.context, focusTextBlock.node)
177
+ ) {
172
178
  return null
173
179
  }
174
180
  }
@@ -1,5 +1,5 @@
1
- import {isPortableTextTextBlock} from '@sanity/types'
2
1
  import type {EditorSelector} from '../editor/editor-selector'
2
+ import {isTextBlock} from '../internal-utils/parse-blocks'
3
3
  import {getSelectedSpans} from './selector.get-selected-spans'
4
4
  import {isSelectionExpanded} from './selector.is-selection-expanded'
5
5
  import {getFocusSpan, getSelectedBlocks} from './selectors'
@@ -37,7 +37,9 @@ export function isActiveAnnotation(
37
37
  }
38
38
 
39
39
  const selectionMarkDefs = selectedBlocks.flatMap((block) =>
40
- isPortableTextTextBlock(block.node) ? (block.node.markDefs ?? []) : [],
40
+ isTextBlock(snapshot.context, block.node)
41
+ ? (block.node.markDefs ?? [])
42
+ : [],
41
43
  )
42
44
 
43
45
  return selectedSpans.every((span) => {
@@ -21,7 +21,7 @@ test(isActiveDecorator.name, () => {
21
21
  snapshot(
22
22
  [
23
23
  {
24
- _type: '_block',
24
+ _type: 'block',
25
25
  _key: 'b1',
26
26
  children: [
27
27
  {
@@ -57,7 +57,7 @@ test(isActiveDecorator.name, () => {
57
57
  snapshot(
58
58
  [
59
59
  {
60
- _type: '_block',
60
+ _type: 'block',
61
61
  _key: 'b1',
62
62
  children: [
63
63
  {
@@ -94,7 +94,7 @@ test(isActiveDecorator.name, () => {
94
94
  [
95
95
  {_key: 'b0', _type: 'image'},
96
96
  {
97
- _type: '_block',
97
+ _type: 'block',
98
98
  _key: 'b1',
99
99
  children: [
100
100
  {