@portabletext/editor 1.40.1 → 1.40.3

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 (65) hide show
  1. package/lib/_chunks-cjs/behavior.core.cjs +37 -16
  2. package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
  3. package/lib/_chunks-cjs/behavior.markdown.cjs +22 -10
  4. package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
  5. package/lib/_chunks-cjs/editor-provider.cjs +27 -67
  6. package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
  7. package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs +3 -2
  8. package/lib/_chunks-cjs/selector.is-overlapping-selection.cjs.map +1 -1
  9. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +26 -0
  10. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -0
  11. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +1 -0
  12. package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
  13. package/lib/_chunks-es/behavior.core.js +37 -16
  14. package/lib/_chunks-es/behavior.core.js.map +1 -1
  15. package/lib/_chunks-es/behavior.markdown.js +22 -10
  16. package/lib/_chunks-es/behavior.markdown.js.map +1 -1
  17. package/lib/_chunks-es/editor-provider.js +27 -67
  18. package/lib/_chunks-es/editor-provider.js.map +1 -1
  19. package/lib/_chunks-es/selector.is-overlapping-selection.js +3 -2
  20. package/lib/_chunks-es/selector.is-overlapping-selection.js.map +1 -1
  21. package/lib/_chunks-es/util.merge-text-blocks.js +27 -0
  22. package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -0
  23. package/lib/_chunks-es/util.selection-point-to-block-offset.js +1 -0
  24. package/lib/behaviors/index.d.cts +3881 -5053
  25. package/lib/behaviors/index.d.ts +3881 -5053
  26. package/lib/index.d.cts +3402 -4440
  27. package/lib/index.d.ts +3402 -4440
  28. package/lib/plugins/index.cjs +9 -127
  29. package/lib/plugins/index.cjs.map +1 -1
  30. package/lib/plugins/index.d.cts +3404 -4441
  31. package/lib/plugins/index.d.ts +3404 -4441
  32. package/lib/plugins/index.js +11 -129
  33. package/lib/plugins/index.js.map +1 -1
  34. package/lib/selectors/index.d.cts +3401 -4440
  35. package/lib/selectors/index.d.ts +3401 -4440
  36. package/lib/utils/index.cjs +45 -4
  37. package/lib/utils/index.cjs.map +1 -1
  38. package/lib/utils/index.d.cts +3402 -4441
  39. package/lib/utils/index.d.ts +3402 -4441
  40. package/lib/utils/index.js +45 -3
  41. package/lib/utils/index.js.map +1 -1
  42. package/package.json +8 -8
  43. package/src/behavior-actions/behavior.action.delete.block.ts +2 -2
  44. package/src/behavior-actions/behavior.actions.ts +0 -18
  45. package/src/behaviors/behavior.core.block-objects.ts +57 -7
  46. package/src/behaviors/behavior.core.insert-break.ts +0 -4
  47. package/src/behaviors/behavior.default.ts +1 -1
  48. package/src/behaviors/behavior.markdown.ts +22 -10
  49. package/src/behaviors/behavior.types.ts +171 -138
  50. package/src/editor/create-editor.ts +2 -0
  51. package/src/editor/editor-machine.ts +28 -28
  52. package/src/editor/plugins/create-with-event-listeners.ts +15 -0
  53. package/src/editor/plugins/createWithEditableAPI.ts +4 -4
  54. package/src/plugins/plugin.one-line.tsx +10 -128
  55. package/src/selectors/selector.get-selected-spans.test.ts +33 -0
  56. package/src/selectors/selector.get-selected-spans.ts +7 -1
  57. package/src/selectors/selector.is-active-decorator.test.ts +100 -27
  58. package/src/types/block-with-optional-key.ts +13 -0
  59. package/src/utils/util.is-text-block.ts +4 -3
  60. package/lib/_chunks-cjs/util.split-text-block.cjs +0 -68
  61. package/lib/_chunks-cjs/util.split-text-block.cjs.map +0 -1
  62. package/lib/_chunks-es/util.split-text-block.js +0 -70
  63. package/lib/_chunks-es/util.split-text-block.js.map +0 -1
  64. package/src/behavior-actions/behavior.action.insert.block-object.ts +0 -20
  65. package/src/behavior-actions/behavior.action.insert.text-block.ts +0 -33
@@ -22,6 +22,7 @@ import {
22
22
  type Behavior,
23
23
  type CustomBehaviorEvent,
24
24
  type DataBehaviorEvent,
25
+ type ExternalBehaviorEvent,
25
26
  type InternalBehaviorAction,
26
27
  type NativeBehaviorEvent,
27
28
  type SyntheticBehaviorEvent,
@@ -203,6 +204,7 @@ export type InternalEditorEvent =
203
204
  nativeEvent?: {preventDefault: () => void}
204
205
  }
205
206
  | CustomBehaviorEvent
207
+ | ExternalBehaviorEvent
206
208
  | ExternalEditorEvent
207
209
  | MutationEvent
208
210
  | InternalPatchEvent
@@ -222,6 +224,7 @@ export type InternalEditorEvent =
222
224
  */
223
225
  export type InternalEditorEmittedEvent =
224
226
  | EditorEmittedEvent
227
+ | ExternalBehaviorEvent
225
228
  | InternalPatchEvent
226
229
  | PatchesEvent
227
230
  | UnsetEvent
@@ -352,40 +355,37 @@ export const editorMachine = setup({
352
355
  ...context.behaviors.values(),
353
356
  ...defaultBehaviors,
354
357
  ].filter((behavior) => {
358
+ // Catches all events
355
359
  if (behavior.on === '*') {
356
360
  return true
357
361
  }
358
362
 
359
- if (isClipboardBehaviorEvent(event.behaviorEvent)) {
360
- return (
361
- behavior.on === 'clipboard.*' ||
362
- behavior.on === event.behaviorEvent.type
363
- )
364
- }
365
-
366
- if (isDragBehaviorEvent(event.behaviorEvent)) {
367
- return (
368
- behavior.on === 'drag.*' ||
369
- behavior.on === event.behaviorEvent.type
370
- )
371
- }
372
-
373
- if (isInputBehaviorEvent(event.behaviorEvent)) {
374
- return behavior.on === 'input.*'
375
- }
376
-
377
- if (isKeyboardBehaviorEvent(event.behaviorEvent)) {
378
- return (
379
- behavior.on === 'keyboard.*' ||
380
- behavior.on === event.behaviorEvent.type
381
- )
363
+ const [listenedNamespace] =
364
+ behavior.on.includes('*') && behavior.on.includes('.')
365
+ ? behavior.on.split('.')
366
+ : [undefined]
367
+ const [eventNamespace] = event.behaviorEvent.type.includes('.')
368
+ ? event.behaviorEvent.type.split('.')
369
+ : [undefined]
370
+
371
+ // Handles scenarios like a Behavior listening for `select.*` and the event
372
+ // `select.block` is fired.
373
+ if (
374
+ listenedNamespace !== undefined &&
375
+ eventNamespace !== undefined &&
376
+ listenedNamespace === eventNamespace
377
+ ) {
378
+ return true
382
379
  }
383
380
 
384
- if (isMouseBehaviorEvent(event.behaviorEvent)) {
385
- return (
386
- behavior.on === 'mouse.*' ||
387
- behavior.on === event.behaviorEvent.type
388
- )
381
+ // Handles scenarios like a Behavior listening for `select.*` and the event
382
+ // `select` is fired.
383
+ if (
384
+ listenedNamespace !== undefined &&
385
+ eventNamespace === undefined &&
386
+ listenedNamespace === event.behaviorEvent.type
387
+ ) {
388
+ return true
389
389
  }
390
390
 
391
391
  return behavior.on === event.behaviorEvent.type
@@ -46,6 +46,21 @@ export function createWithEventListeners(
46
46
  })
47
47
  break
48
48
 
49
+ case 'insert.block object':
50
+ editorActor.send({
51
+ type: 'behavior event',
52
+ behaviorEvent: {
53
+ type: 'insert.block',
54
+ block: {
55
+ _type: event.blockObject.name,
56
+ ...(event.blockObject.value ?? {}),
57
+ },
58
+ placement: event.placement,
59
+ },
60
+ editor,
61
+ })
62
+ break
63
+
49
64
  default:
50
65
  editorActor.send({
51
66
  type: 'behavior event',
@@ -276,10 +276,10 @@ export function createEditableAPI(
276
276
  editorActor.send({
277
277
  type: 'behavior event',
278
278
  behaviorEvent: {
279
- type: 'insert.block object',
280
- blockObject: {
281
- name: type.name,
282
- value,
279
+ type: 'insert.block',
280
+ block: {
281
+ _type: type.name,
282
+ ...(value ? value : {}),
283
283
  },
284
284
  placement: 'auto',
285
285
  },
@@ -32,58 +32,6 @@ const oneLineBehaviors = [
32
32
  event.placement === 'before' || event.placement === 'after',
33
33
  actions: [() => [{type: 'noop'}]],
34
34
  }),
35
- /**
36
- * Other cases of `insert.block` are allowed.
37
- *
38
- * If a text block is inserted and the focus block is fully selected, then
39
- * the focus block can be replaced with the inserted block.
40
- */
41
- defineBehavior({
42
- on: 'insert.block',
43
- guard: ({snapshot, event}) => {
44
- const focusTextBlock = selectors.getFocusTextBlock(snapshot)
45
- const selectionStartPoint = selectors.getSelectionStartPoint(snapshot)
46
- const selectionEndPoint = selectors.getSelectionEndPoint(snapshot)
47
-
48
- if (
49
- !focusTextBlock ||
50
- !utils.isTextBlock(snapshot.context, event.block) ||
51
- !selectionStartPoint ||
52
- !selectionEndPoint
53
- ) {
54
- return false
55
- }
56
-
57
- const blockStartPoint = utils.getBlockStartPoint(focusTextBlock)
58
- const blockEndPoint = utils.getBlockEndPoint(focusTextBlock)
59
- const newFocus = utils.getBlockEndPoint({
60
- node: event.block,
61
- path: [{_key: event.block._key}],
62
- })
63
-
64
- if (
65
- utils.isEqualSelectionPoints(blockStartPoint, selectionStartPoint) &&
66
- utils.isEqualSelectionPoints(blockEndPoint, selectionEndPoint)
67
- ) {
68
- return {focusTextBlock, newFocus}
69
- }
70
-
71
- return false
72
- },
73
- actions: [
74
- ({event}, {focusTextBlock, newFocus}) => [
75
- {type: 'delete.block', blockPath: focusTextBlock.path},
76
- {type: 'insert.block', block: event.block, placement: 'auto'},
77
- {
78
- type: 'select',
79
- selection: {
80
- anchor: newFocus,
81
- focus: newFocus,
82
- },
83
- },
84
- ],
85
- ],
86
- }),
87
35
  /**
88
36
  * An ordinary `insert.block` is acceptable if it's a text block. In that
89
37
  * case it will get merged into the existing text block.
@@ -92,62 +40,23 @@ const oneLineBehaviors = [
92
40
  on: 'insert.block',
93
41
  guard: ({snapshot, event}) => {
94
42
  const focusTextBlock = selectors.getFocusTextBlock(snapshot)
95
- const selectionStartPoint = selectors.getSelectionStartPoint(snapshot)
96
- const selectionEndPoint = selectors.getSelectionEndPoint(snapshot)
97
43
 
98
44
  if (
99
45
  !focusTextBlock ||
100
- !utils.isTextBlock(snapshot.context, event.block) ||
101
- !selectionStartPoint ||
102
- !selectionEndPoint
46
+ !utils.isTextBlock(snapshot.context, event.block)
103
47
  ) {
104
48
  return false
105
49
  }
106
50
 
107
- const blockBeforeStartPoint = utils.splitTextBlock({
108
- context: snapshot.context,
109
- block: focusTextBlock.node,
110
- point: selectionStartPoint,
111
- })?.before
112
- const blockAfterEndPoint = utils.splitTextBlock({
113
- context: snapshot.context,
114
- block: focusTextBlock.node,
115
- point: selectionEndPoint,
116
- })?.after
117
-
118
- if (!blockBeforeStartPoint || !blockAfterEndPoint) {
119
- return false
120
- }
121
-
122
- const targetBlock = utils.mergeTextBlocks({
123
- context: snapshot.context,
124
- targetBlock: blockBeforeStartPoint,
125
- incomingBlock: event.block,
126
- })
127
-
128
- const newFocus = utils.getBlockEndPoint({
129
- node: targetBlock,
130
- path: [{_key: targetBlock._key}],
131
- })
132
-
133
- const mergedBlock = utils.mergeTextBlocks({
134
- context: snapshot.context,
135
- targetBlock,
136
- incomingBlock: blockAfterEndPoint,
137
- })
138
-
139
- return {focusTextBlock, mergedBlock, newFocus}
51
+ return true
140
52
  },
141
53
  actions: [
142
- (_, {focusTextBlock, mergedBlock, newFocus}) => [
143
- {type: 'delete.block', blockPath: focusTextBlock.path},
144
- {type: 'insert.block', block: mergedBlock, placement: 'auto'},
54
+ ({event}) => [
145
55
  {
146
- type: 'select',
147
- selection: {
148
- anchor: newFocus,
149
- focus: newFocus,
150
- },
56
+ type: 'insert.block',
57
+ block: event.block,
58
+ placement: 'auto',
59
+ select: 'end',
151
60
  },
152
61
  ],
153
62
  ],
@@ -166,12 +75,12 @@ const oneLineBehaviors = [
166
75
  */
167
76
  defineBehavior({
168
77
  on: 'insert.blocks',
169
- guard: ({context, event}) => {
78
+ guard: ({snapshot, event}) => {
170
79
  return event.blocks
171
- .filter((block) => utils.isTextBlock(context, block))
80
+ .filter((block) => utils.isTextBlock(snapshot.context, block))
172
81
  .reduce((targetBlock, incomingBlock) => {
173
82
  return utils.mergeTextBlocks({
174
- context,
83
+ context: snapshot.context,
175
84
  targetBlock,
176
85
  incomingBlock,
177
86
  })
@@ -183,33 +92,6 @@ const oneLineBehaviors = [
183
92
  (_, block) => [raise({type: 'insert.block', block, placement: 'auto'})],
184
93
  ],
185
94
  }),
186
- /**
187
- * Block objects do not fit in a one-line editor
188
- */
189
- defineBehavior({
190
- on: 'insert.block object',
191
- actions: [() => [{type: 'noop'}]],
192
- }),
193
- /**
194
- * `insert.text block` is raised as an `insert.block` so it can be handled
195
- * by the Behaviors above.
196
- */
197
- defineBehavior({
198
- on: 'insert.text block',
199
- actions: [
200
- ({context, event}) => [
201
- raise({
202
- type: 'insert.block',
203
- block: {
204
- _key: context.keyGenerator(),
205
- _type: context.schema.block.name,
206
- children: event.textBlock?.children ?? [],
207
- },
208
- placement: event.placement,
209
- }),
210
- ],
211
- ],
212
- }),
213
95
  ]
214
96
 
215
97
  /**
@@ -215,4 +215,37 @@ describe(getSelectedSpans.name, () => {
215
215
  },
216
216
  ])
217
217
  })
218
+
219
+ test('selecting from block object to empty span', () => {
220
+ expect(
221
+ getSelectedSpans(
222
+ snapshot(
223
+ [
224
+ image,
225
+ baz,
226
+ {
227
+ _key: 'b4',
228
+ _type: 'block',
229
+ children: [{_key: 's4', _type: 'span', text: ''}],
230
+ },
231
+ ],
232
+ {
233
+ anchor: {
234
+ path: [{_key: 'b2'}],
235
+ offset: 0,
236
+ },
237
+ focus: {
238
+ path: [{_key: 'b4'}, 'children', {_key: 's4'}],
239
+ offset: 0,
240
+ },
241
+ },
242
+ ),
243
+ ),
244
+ ).toEqual([
245
+ {
246
+ node: {_key: 's3', _type: 'span', text: 'baz'},
247
+ path: [{_key: 'b3'}, 'children', {_key: 's3'}],
248
+ },
249
+ ])
250
+ })
218
251
  })
@@ -50,7 +50,13 @@ export const getSelectedSpans: EditorSelector<
50
50
  ? endPoint.path[2]._key
51
51
  : undefined
52
52
 
53
+ let startBlockFound = false
54
+
53
55
  for (const block of snapshot.context.value) {
56
+ if (block._key === startBlockKey) {
57
+ startBlockFound = true
58
+ }
59
+
54
60
  if (!isPortableTextTextBlock(block)) {
55
61
  continue
56
62
  }
@@ -126,7 +132,7 @@ export const getSelectedSpans: EditorSelector<
126
132
  break
127
133
  }
128
134
 
129
- if (selectedSpans.length > 0) {
135
+ if (startBlockFound) {
130
136
  for (const child of block.children) {
131
137
  if (!isPortableTextSpan(child)) {
132
138
  continue
@@ -1,13 +1,25 @@
1
1
  import {expect, test} from 'vitest'
2
- import type {EditorSelection} from '..'
2
+ import type {EditorSelection, PortableTextBlock} from '..'
3
3
  import {createTestSnapshot} from '../internal-utils/create-test-snapshot'
4
4
  import {isActiveDecorator} from './selector.is-active-decorator'
5
5
 
6
6
  test(isActiveDecorator.name, () => {
7
- function snapshot(selection: EditorSelection) {
7
+ function snapshot(
8
+ value: Array<PortableTextBlock>,
9
+ selection: EditorSelection,
10
+ ) {
8
11
  return createTestSnapshot({
9
12
  context: {
10
- value: [
13
+ value,
14
+ selection,
15
+ },
16
+ })
17
+ }
18
+
19
+ expect(
20
+ isActiveDecorator('strong')(
21
+ snapshot(
22
+ [
11
23
  {
12
24
  _type: '_block',
13
25
  _key: 'b1',
@@ -26,37 +38,98 @@ test(isActiveDecorator.name, () => {
26
38
  ],
27
39
  },
28
40
  ],
29
- selection,
30
- },
31
- })
32
- }
41
+ {
42
+ anchor: {
43
+ path: [{_key: 'b1'}, 'children', {_key: 's1'}],
44
+ offset: 0,
45
+ },
46
+ focus: {
47
+ path: [{_key: 'b1'}, 'children', {_key: 's1'}],
48
+ offset: 3,
49
+ },
50
+ },
51
+ ),
52
+ ),
53
+ ).toBe(true)
33
54
 
34
55
  expect(
35
56
  isActiveDecorator('strong')(
36
- snapshot({
37
- anchor: {
38
- path: [{_key: 'b1'}, 'children', {_key: 's1'}],
39
- offset: 0,
40
- },
41
- focus: {
42
- path: [{_key: 'b1'}, 'children', {_key: 's1'}],
43
- offset: 3,
57
+ snapshot(
58
+ [
59
+ {
60
+ _type: '_block',
61
+ _key: 'b1',
62
+ children: [
63
+ {
64
+ _type: 'span',
65
+ _key: 's1',
66
+ text: 'foo',
67
+ marks: ['strong'],
68
+ },
69
+ {
70
+ _type: 'span',
71
+ _key: 's2',
72
+ text: 'bar',
73
+ },
74
+ ],
75
+ },
76
+ ],
77
+ {
78
+ anchor: {
79
+ path: [{_key: 'b1'}, 'children', {_key: 's1'}],
80
+ offset: 2,
81
+ },
82
+ focus: {
83
+ path: [{_key: 'b1'}, 'children', {_key: 's2'}],
84
+ offset: 3,
85
+ },
44
86
  },
45
- }),
87
+ ),
46
88
  ),
47
- ).toBe(true)
89
+ ).toBe(false)
90
+
48
91
  expect(
49
92
  isActiveDecorator('strong')(
50
- snapshot({
51
- anchor: {
52
- path: [{_key: 'b1'}, 'children', {_key: 's1'}],
53
- offset: 2,
54
- },
55
- focus: {
56
- path: [{_key: 'b1'}, 'children', {_key: 's2'}],
57
- offset: 3,
93
+ snapshot(
94
+ [
95
+ {_key: 'b0', _type: 'image'},
96
+ {
97
+ _type: '_block',
98
+ _key: 'b1',
99
+ children: [
100
+ {
101
+ _type: 'span',
102
+ _key: 's1',
103
+ text: 'foo',
104
+ marks: ['strong'],
105
+ },
106
+ {
107
+ _type: 'span',
108
+ _key: 's2',
109
+ text: 'bar',
110
+ marks: ['strong'],
111
+ },
112
+ ],
113
+ },
114
+ {
115
+ _key: 'b2',
116
+ _type: 'block',
117
+ children: [
118
+ {_key: 's3', _type: 'span', text: '', marks: ['strong']},
119
+ ],
120
+ },
121
+ ],
122
+ {
123
+ anchor: {
124
+ path: [{_key: 'b0'}],
125
+ offset: 0,
126
+ },
127
+ focus: {
128
+ path: [{_key: 'b2'}, 'children', {_key: 's3'}],
129
+ offset: 0,
130
+ },
58
131
  },
59
- }),
132
+ ),
60
133
  ),
61
- ).toBe(false)
134
+ ).toBe(true)
62
135
  })
@@ -0,0 +1,13 @@
1
+ import type {PortableTextObject, PortableTextTextBlock} from '@sanity/types'
2
+
3
+ export type TextBlockWithOptionalKey = Omit<PortableTextTextBlock, '_key'> & {
4
+ _key?: PortableTextTextBlock['_key']
5
+ }
6
+
7
+ export type ObjectBlockWithOptionalKey = Omit<PortableTextObject, '_key'> & {
8
+ _key?: PortableTextObject['_key']
9
+ }
10
+
11
+ export type BlockWithOptionalKey =
12
+ | TextBlockWithOptionalKey
13
+ | ObjectBlockWithOptionalKey
@@ -1,12 +1,13 @@
1
- import type {PortableTextBlock, PortableTextTextBlock} from '@sanity/types'
1
+ import type {PortableTextTextBlock} from '@sanity/types'
2
2
  import type {EditorContext} from '..'
3
+ import {isTypedObject} from '../internal-utils/asserters'
3
4
 
4
5
  /**
5
6
  * @public
6
7
  */
7
8
  export function isTextBlock(
8
9
  context: Pick<EditorContext, 'schema'>,
9
- block: PortableTextBlock,
10
+ block: unknown,
10
11
  ): block is PortableTextTextBlock {
11
- return block._type === context.schema.block.name
12
+ return isTypedObject(block) && block._type === context.schema.block.name
12
13
  }
@@ -1,68 +0,0 @@
1
- "use strict";
2
- var util_selectionPointToBlockOffset = require("./util.selection-point-to-block-offset.cjs"), util_sliceBlocks = require("./util.slice-blocks.cjs");
3
- function isTextBlock(context, block) {
4
- return block._type === context.schema.block.name;
5
- }
6
- function mergeTextBlocks({
7
- context,
8
- targetBlock,
9
- incomingBlock
10
- }) {
11
- const parsedIncomingBlock = util_selectionPointToBlockOffset.parseBlock({
12
- context,
13
- block: incomingBlock,
14
- options: {
15
- refreshKeys: !0
16
- }
17
- });
18
- return !parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock) ? targetBlock : {
19
- ...targetBlock,
20
- children: [...targetBlock.children, ...parsedIncomingBlock.children],
21
- markDefs: [...targetBlock.markDefs ?? [], ...parsedIncomingBlock.markDefs ?? []]
22
- };
23
- }
24
- function splitTextBlock({
25
- context,
26
- block,
27
- point
28
- }) {
29
- const firstChild = block.children.at(0), lastChild = block.children.at(block.children.length - 1);
30
- if (!firstChild || !lastChild)
31
- return;
32
- const before = util_sliceBlocks.sliceBlocks({
33
- blocks: [block],
34
- selection: {
35
- anchor: {
36
- path: [{
37
- _key: block._key
38
- }, "children", {
39
- _key: firstChild._key
40
- }],
41
- offset: 0
42
- },
43
- focus: point
44
- }
45
- }).at(0), after = util_sliceBlocks.sliceBlocks({
46
- blocks: [block],
47
- selection: {
48
- anchor: point,
49
- focus: {
50
- path: [{
51
- _key: block._key
52
- }, "children", {
53
- _key: lastChild._key
54
- }],
55
- offset: util_sliceBlocks.isSpan(context, lastChild) ? lastChild.text.length : 0
56
- }
57
- }
58
- }).at(0);
59
- if (!(!before || !after) && !(!isTextBlock(context, before) || !isTextBlock(context, after)))
60
- return {
61
- before,
62
- after
63
- };
64
- }
65
- exports.isTextBlock = isTextBlock;
66
- exports.mergeTextBlocks = mergeTextBlocks;
67
- exports.splitTextBlock = splitTextBlock;
68
- //# sourceMappingURL=util.split-text-block.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"util.split-text-block.cjs","sources":["../../src/utils/util.is-text-block.ts","../../src/utils/util.merge-text-blocks.ts","../../src/utils/util.split-text-block.ts"],"sourcesContent":["import type {PortableTextBlock, PortableTextTextBlock} from '@sanity/types'\nimport type {EditorContext} from '..'\n\n/**\n * @public\n */\nexport function isTextBlock(\n context: Pick<EditorContext, 'schema'>,\n block: PortableTextBlock,\n): block is PortableTextTextBlock {\n return block._type === context.schema.block.name\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport type {EditorContext} from '..'\nimport {parseBlock} from '../internal-utils/parse-blocks'\nimport {isTextBlock} from './util.is-text-block'\n\n/**\n * @beta\n */\nexport function mergeTextBlocks({\n context,\n targetBlock,\n incomingBlock,\n}: {\n context: Pick<EditorContext, 'keyGenerator' | 'schema'>\n targetBlock: PortableTextTextBlock\n incomingBlock: PortableTextTextBlock\n}) {\n const parsedIncomingBlock = parseBlock({\n context,\n block: incomingBlock,\n options: {refreshKeys: true},\n })\n\n if (!parsedIncomingBlock || !isTextBlock(context, parsedIncomingBlock)) {\n return targetBlock\n }\n\n return {\n ...targetBlock,\n children: [...targetBlock.children, ...parsedIncomingBlock.children],\n markDefs: [\n ...(targetBlock.markDefs ?? []),\n ...(parsedIncomingBlock.markDefs ?? []),\n ],\n }\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelectionPoint} from '..'\nimport type {EditorContext} from '../editor/editor-snapshot'\nimport {isSpan} from './util.is-span'\nimport {isTextBlock} from './util.is-text-block'\nimport {sliceBlocks} from './util.slice-blocks'\n\n/**\n * @beta\n */\nexport function splitTextBlock({\n context,\n block,\n point,\n}: {\n context: Pick<EditorContext, 'schema'>\n block: PortableTextTextBlock\n point: EditorSelectionPoint\n}): {before: PortableTextTextBlock; after: PortableTextTextBlock} | undefined {\n const firstChild = block.children.at(0)\n const lastChild = block.children.at(block.children.length - 1)\n\n if (!firstChild || !lastChild) {\n return undefined\n }\n\n const before = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: {\n path: [{_key: block._key}, 'children', {_key: firstChild._key}],\n offset: 0,\n },\n focus: point,\n },\n }).at(0)\n const after = sliceBlocks({\n blocks: [block],\n selection: {\n anchor: point,\n focus: {\n path: [{_key: block._key}, 'children', {_key: lastChild._key}],\n offset: isSpan(context, lastChild) ? lastChild.text.length : 0,\n },\n },\n }).at(0)\n\n if (!before || !after) {\n return undefined\n }\n\n if (!isTextBlock(context, before) || !isTextBlock(context, after)) {\n return undefined\n }\n\n return {before, after}\n}\n"],"names":["isTextBlock","context","block","_type","schema","name","mergeTextBlocks","targetBlock","incomingBlock","parsedIncomingBlock","parseBlock","options","refreshKeys","children","markDefs","splitTextBlock","point","firstChild","at","lastChild","length","before","sliceBlocks","blocks","selection","anchor","path","_key","offset","focus","after","isSpan","text"],"mappings":";;AAMgBA,SAAAA,YACdC,SACAC,OACgC;AAChC,SAAOA,MAAMC,UAAUF,QAAQG,OAAOF,MAAMG;AAC9C;ACHO,SAASC,gBAAgB;AAAA,EAC9BL;AAAAA,EACAM;AAAAA,EACAC;AAKF,GAAG;AACD,QAAMC,sBAAsBC,iCAAAA,WAAW;AAAA,IACrCT;AAAAA,IACAC,OAAOM;AAAAA,IACPG,SAAS;AAAA,MAACC,aAAa;AAAA,IAAA;AAAA,EAAI,CAC5B;AAED,SAAI,CAACH,uBAAuB,CAACT,YAAYC,SAASQ,mBAAmB,IAC5DF,cAGF;AAAA,IACL,GAAGA;AAAAA,IACHM,UAAU,CAAC,GAAGN,YAAYM,UAAU,GAAGJ,oBAAoBI,QAAQ;AAAA,IACnEC,UAAU,CACR,GAAIP,YAAYO,YAAY,CAAA,GAC5B,GAAIL,oBAAoBK,YAAY,CAAG,CAAA;AAAA,EAE3C;AACF;ACzBO,SAASC,eAAe;AAAA,EAC7Bd;AAAAA,EACAC;AAAAA,EACAc;AAKF,GAA8E;AAC5E,QAAMC,aAAaf,MAAMW,SAASK,GAAG,CAAC,GAChCC,YAAYjB,MAAMW,SAASK,GAAGhB,MAAMW,SAASO,SAAS,CAAC;AAEzD,MAAA,CAACH,cAAc,CAACE;AAClB;AAGF,QAAME,SAASC,iBAAAA,YAAY;AAAA,IACzBC,QAAQ,CAACrB,KAAK;AAAA,IACdsB,WAAW;AAAA,MACTC,QAAQ;AAAA,QACNC,MAAM,CAAC;AAAA,UAACC,MAAMzB,MAAMyB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMV,WAAWU;AAAAA,QAAAA,CAAK;AAAA,QAC9DC,QAAQ;AAAA,MACV;AAAA,MACAC,OAAOb;AAAAA,IAAAA;AAAAA,EAEV,CAAA,EAAEE,GAAG,CAAC,GACDY,QAAQR,iBAAAA,YAAY;AAAA,IACxBC,QAAQ,CAACrB,KAAK;AAAA,IACdsB,WAAW;AAAA,MACTC,QAAQT;AAAAA,MACRa,OAAO;AAAA,QACLH,MAAM,CAAC;AAAA,UAACC,MAAMzB,MAAMyB;AAAAA,WAAO,YAAY;AAAA,UAACA,MAAMR,UAAUQ;AAAAA,QAAAA,CAAK;AAAA,QAC7DC,QAAQG,iBAAO9B,OAAAA,SAASkB,SAAS,IAAIA,UAAUa,KAAKZ,SAAS;AAAA,MAAA;AAAA,IAC/D;AAAA,EACF,CACD,EAAEF,GAAG,CAAC;AAEP,MAAI,EAACG,CAAAA,UAAU,CAACS,UAIZ,EAAC9B,CAAAA,YAAYC,SAASoB,MAAM,KAAK,CAACrB,YAAYC,SAAS6B,KAAK;AAIzD,WAAA;AAAA,MAACT;AAAAA,MAAQS;AAAAA,IAAK;AACvB;;;;"}