@portabletext/editor 1.40.2 → 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.
- package/lib/_chunks-cjs/behavior.core.cjs +37 -16
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/behavior.markdown.cjs +22 -10
- package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
- package/lib/_chunks-cjs/editor-provider.cjs +27 -67
- package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
- package/lib/_chunks-cjs/util.merge-text-blocks.cjs +26 -0
- package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -0
- package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs +1 -0
- package/lib/_chunks-cjs/util.selection-point-to-block-offset.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js +37 -16
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/behavior.markdown.js +22 -10
- package/lib/_chunks-es/behavior.markdown.js.map +1 -1
- package/lib/_chunks-es/editor-provider.js +27 -67
- package/lib/_chunks-es/editor-provider.js.map +1 -1
- package/lib/_chunks-es/util.merge-text-blocks.js +27 -0
- package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -0
- package/lib/_chunks-es/util.selection-point-to-block-offset.js +1 -0
- package/lib/behaviors/index.d.cts +3881 -5053
- package/lib/behaviors/index.d.ts +3881 -5053
- package/lib/index.d.cts +3402 -4440
- package/lib/index.d.ts +3402 -4440
- package/lib/plugins/index.cjs +9 -127
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.d.cts +3404 -4441
- package/lib/plugins/index.d.ts +3404 -4441
- package/lib/plugins/index.js +11 -129
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.d.cts +3401 -4440
- package/lib/selectors/index.d.ts +3401 -4440
- package/lib/utils/index.cjs +45 -4
- package/lib/utils/index.cjs.map +1 -1
- package/lib/utils/index.d.cts +3402 -4441
- package/lib/utils/index.d.ts +3402 -4441
- package/lib/utils/index.js +45 -3
- package/lib/utils/index.js.map +1 -1
- package/package.json +7 -7
- package/src/behavior-actions/behavior.action.delete.block.ts +2 -2
- package/src/behavior-actions/behavior.actions.ts +0 -18
- package/src/behaviors/behavior.core.block-objects.ts +57 -7
- package/src/behaviors/behavior.core.insert-break.ts +0 -4
- package/src/behaviors/behavior.default.ts +1 -1
- package/src/behaviors/behavior.markdown.ts +22 -10
- package/src/behaviors/behavior.types.ts +171 -138
- package/src/editor/create-editor.ts +2 -0
- package/src/editor/editor-machine.ts +28 -28
- package/src/editor/plugins/create-with-event-listeners.ts +15 -0
- package/src/editor/plugins/createWithEditableAPI.ts +4 -4
- package/src/plugins/plugin.one-line.tsx +10 -128
- package/src/types/block-with-optional-key.ts +13 -0
- package/src/utils/util.is-text-block.ts +4 -3
- package/lib/_chunks-cjs/util.split-text-block.cjs +0 -68
- package/lib/_chunks-cjs/util.split-text-block.cjs.map +0 -1
- package/lib/_chunks-es/util.split-text-block.js +0 -70
- package/lib/_chunks-es/util.split-text-block.js.map +0 -1
- package/src/behavior-actions/behavior.action.insert.block-object.ts +0 -20
- 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
|
-
|
|
360
|
-
|
|
361
|
-
behavior.on
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return
|
|
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
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
143
|
-
{type: 'delete.block', blockPath: focusTextBlock.path},
|
|
144
|
-
{type: 'insert.block', block: mergedBlock, placement: 'auto'},
|
|
54
|
+
({event}) => [
|
|
145
55
|
{
|
|
146
|
-
type: '
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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: ({
|
|
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
|
/**
|
|
@@ -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 {
|
|
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:
|
|
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;;;;"}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { parseBlock } from "./util.selection-point-to-block-offset.js";
|
|
2
|
-
import { sliceBlocks, isSpan } from "./util.slice-blocks.js";
|
|
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 = 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 = 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 = 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: 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
|
-
export {
|
|
66
|
-
isTextBlock,
|
|
67
|
-
mergeTextBlocks,
|
|
68
|
-
splitTextBlock
|
|
69
|
-
};
|
|
70
|
-
//# sourceMappingURL=util.split-text-block.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"util.split-text-block.js","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,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,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,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,OAAO9B,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;"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import {insertBlockActionImplementation} from './behavior.action.insert.block'
|
|
2
|
-
import type {BehaviorActionImplementation} from './behavior.actions'
|
|
3
|
-
|
|
4
|
-
export const insertBlockObjectActionImplementation: BehaviorActionImplementation<
|
|
5
|
-
'insert.block object'
|
|
6
|
-
> = ({context, action}) => {
|
|
7
|
-
insertBlockActionImplementation({
|
|
8
|
-
context,
|
|
9
|
-
action: {
|
|
10
|
-
type: 'insert.block',
|
|
11
|
-
block: {
|
|
12
|
-
_key: context.keyGenerator(),
|
|
13
|
-
_type: action.blockObject.name,
|
|
14
|
-
...(action.blockObject.value ? action.blockObject.value : {}),
|
|
15
|
-
},
|
|
16
|
-
editor: action.editor,
|
|
17
|
-
placement: action.placement,
|
|
18
|
-
},
|
|
19
|
-
})
|
|
20
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import {insertBlockActionImplementation} from './behavior.action.insert.block'
|
|
2
|
-
import type {BehaviorActionImplementation} from './behavior.actions'
|
|
3
|
-
|
|
4
|
-
export const insertTextBlockActionImplementation: BehaviorActionImplementation<
|
|
5
|
-
'insert.text block'
|
|
6
|
-
> = ({context, action}) => {
|
|
7
|
-
insertBlockActionImplementation({
|
|
8
|
-
context,
|
|
9
|
-
action: {
|
|
10
|
-
type: 'insert.block',
|
|
11
|
-
block: {
|
|
12
|
-
_key: context.keyGenerator(),
|
|
13
|
-
_type: context.schema.block.name,
|
|
14
|
-
children: action.textBlock?.children?.map((child) => ({
|
|
15
|
-
...child,
|
|
16
|
-
_key: context.keyGenerator(),
|
|
17
|
-
})) ?? [
|
|
18
|
-
{
|
|
19
|
-
_type: context.schema.span.name,
|
|
20
|
-
_key: context.keyGenerator(),
|
|
21
|
-
text: '',
|
|
22
|
-
marks: [],
|
|
23
|
-
},
|
|
24
|
-
],
|
|
25
|
-
markDefs: [],
|
|
26
|
-
style: context.schema.styles[0].value ?? 'normal',
|
|
27
|
-
},
|
|
28
|
-
editor: action.editor,
|
|
29
|
-
placement: action.placement,
|
|
30
|
-
select: 'start',
|
|
31
|
-
},
|
|
32
|
-
})
|
|
33
|
-
}
|