@portabletext/editor 3.1.0 → 3.1.1
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/index.js +98 -139
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/editor/create-slate-editor.tsx +1 -8
- package/src/editor/plugins/createWithPatches.ts +2 -0
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +14 -0
- package/src/editor/plugins/with-plugins.ts +8 -13
- package/src/editor/range-decorations-machine.ts +13 -3
- package/src/editor/sync-machine.ts +0 -23
- package/src/internal-utils/applyPatch.ts +25 -40
- package/src/internal-utils/values.ts +22 -0
- package/src/operations/behavior.operation.delete.ts +0 -5
- package/src/operations/behavior.operation.insert.block.ts +5 -0
- package/src/editor/plugins/createWithPlaceholderBlock.ts +0 -71
package/package.json
CHANGED
|
@@ -3,7 +3,6 @@ import {withReact} from 'slate-react'
|
|
|
3
3
|
import {buildIndexMaps} from '../internal-utils/build-index-maps'
|
|
4
4
|
import {createPlaceholderBlock} from '../internal-utils/create-placeholder-block'
|
|
5
5
|
import {debugWithName} from '../internal-utils/debug'
|
|
6
|
-
import {toSlateBlock} from '../internal-utils/values'
|
|
7
6
|
import type {PortableTextSlateEditor} from '../types/editor'
|
|
8
7
|
import type {EditorActor} from './editor-machine'
|
|
9
8
|
import {withPlugins} from './plugins/with-plugins'
|
|
@@ -56,15 +55,9 @@ export function createSlateEditor(config: SlateEditorConfig): SlateEditor {
|
|
|
56
55
|
},
|
|
57
56
|
)
|
|
58
57
|
|
|
59
|
-
const initialValue = [
|
|
60
|
-
toSlateBlock(placeholderBlock, {
|
|
61
|
-
schemaTypes: config.editorActor.getSnapshot().context.schema,
|
|
62
|
-
}),
|
|
63
|
-
]
|
|
64
|
-
|
|
65
58
|
const slateEditor: SlateEditor = {
|
|
66
59
|
instance,
|
|
67
|
-
initialValue,
|
|
60
|
+
initialValue: [placeholderBlock],
|
|
68
61
|
}
|
|
69
62
|
|
|
70
63
|
return slateEditor
|
|
@@ -110,6 +110,7 @@ export function createWithPatches({
|
|
|
110
110
|
previousValue = editor.value
|
|
111
111
|
|
|
112
112
|
const editorWasEmpty = isEqualToEmptyEditor(
|
|
113
|
+
editorActor.getSnapshot().context.initialValue,
|
|
113
114
|
previousValue,
|
|
114
115
|
editorActor.getSnapshot().context.schema,
|
|
115
116
|
)
|
|
@@ -118,6 +119,7 @@ export function createWithPatches({
|
|
|
118
119
|
apply(operation)
|
|
119
120
|
|
|
120
121
|
const editorIsEmpty = isEqualToEmptyEditor(
|
|
122
|
+
editorActor.getSnapshot().context.initialValue,
|
|
121
123
|
editor.value,
|
|
122
124
|
editorActor.getSnapshot().context.schema,
|
|
123
125
|
)
|
|
@@ -10,6 +10,7 @@ import {isEqual, uniq} from 'lodash'
|
|
|
10
10
|
import {Editor, Element, Node, Path, Range, Text, Transforms} from 'slate'
|
|
11
11
|
import {isRedoing} from '../../history/slate-plugin.redoing'
|
|
12
12
|
import {isUndoing} from '../../history/slate-plugin.undoing'
|
|
13
|
+
import {createPlaceholderBlock} from '../../internal-utils/create-placeholder-block'
|
|
13
14
|
import {debugWithName} from '../../internal-utils/debug'
|
|
14
15
|
import {getNextSpan, getPreviousSpan} from '../../internal-utils/sibling-utils'
|
|
15
16
|
import type {BehaviorOperationImplementation} from '../../operations/behavior.operations'
|
|
@@ -19,6 +20,7 @@ import type {EditorActor} from '../editor-machine'
|
|
|
19
20
|
import {getEditorSnapshot} from '../editor-selector'
|
|
20
21
|
import {withNormalizeNode} from '../with-normalizing-node'
|
|
21
22
|
import {isChangingRemotely} from '../withChanges'
|
|
23
|
+
import {withoutPatching} from '../withoutPatching'
|
|
22
24
|
|
|
23
25
|
const debug = debugWithName('plugin:withPortableTextMarkModel')
|
|
24
26
|
|
|
@@ -38,6 +40,18 @@ export function createWithPortableTextMarkModel(
|
|
|
38
40
|
editor.normalizeNode = (nodeEntry) => {
|
|
39
41
|
const [node, path] = nodeEntry
|
|
40
42
|
|
|
43
|
+
if (Editor.isEditor(node) && node.children.length === 0) {
|
|
44
|
+
withoutPatching(editor, () => {
|
|
45
|
+
withNormalizeNode(editor, () => {
|
|
46
|
+
Transforms.insertNodes(
|
|
47
|
+
editor,
|
|
48
|
+
createPlaceholderBlock(editorActor.getSnapshot().context),
|
|
49
|
+
{at: [0], select: true},
|
|
50
|
+
)
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
41
55
|
if (editor.isTextBlock(node)) {
|
|
42
56
|
const children = Node.children(editor, path)
|
|
43
57
|
|
|
@@ -6,7 +6,6 @@ import type {RelayActor} from '../relay-machine'
|
|
|
6
6
|
import {createWithEventListeners} from './create-with-event-listeners'
|
|
7
7
|
import {createWithObjectKeys} from './createWithObjectKeys'
|
|
8
8
|
import {createWithPatches} from './createWithPatches'
|
|
9
|
-
import {createWithPlaceholderBlock} from './createWithPlaceholderBlock'
|
|
10
9
|
import {createWithPortableTextMarkModel} from './createWithPortableTextMarkModel'
|
|
11
10
|
import {createWithSchemaTypes} from './createWithSchemaTypes'
|
|
12
11
|
import {pluginUpdateSelection} from './slate-plugin.update-selection'
|
|
@@ -45,8 +44,6 @@ export const withPlugins = <T extends Editor>(
|
|
|
45
44
|
})
|
|
46
45
|
const withPortableTextMarkModel = createWithPortableTextMarkModel(editorActor)
|
|
47
46
|
|
|
48
|
-
const withPlaceholderBlock = createWithPlaceholderBlock(editorActor)
|
|
49
|
-
|
|
50
47
|
const withEventListeners = createWithEventListeners(editorActor)
|
|
51
48
|
|
|
52
49
|
// Ordering is important here, selection dealing last, data manipulation in the middle and core model stuff first.
|
|
@@ -54,16 +51,14 @@ export const withPlugins = <T extends Editor>(
|
|
|
54
51
|
withSchemaTypes(
|
|
55
52
|
withObjectKeys(
|
|
56
53
|
withPortableTextMarkModel(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}),
|
|
66
|
-
),
|
|
54
|
+
withUndoRedo(
|
|
55
|
+
withPatches(
|
|
56
|
+
pluginUpdateValue(
|
|
57
|
+
editorActor.getSnapshot().context,
|
|
58
|
+
pluginUpdateSelection({
|
|
59
|
+
editorActor,
|
|
60
|
+
editor: e,
|
|
61
|
+
}),
|
|
67
62
|
),
|
|
68
63
|
),
|
|
69
64
|
),
|
|
@@ -18,8 +18,8 @@ import {
|
|
|
18
18
|
import {moveRangeByOperation} from '../internal-utils/move-range-by-operation'
|
|
19
19
|
import {slateRangeToSelection} from '../internal-utils/slate-utils'
|
|
20
20
|
import {toSlateRange} from '../internal-utils/to-slate-range'
|
|
21
|
-
import {isEqualToEmptyEditor} from '../internal-utils/values'
|
|
22
21
|
import type {PortableTextSlateEditor, RangeDecoration} from '../types/editor'
|
|
22
|
+
import {isEmptyTextBlock} from '../utils'
|
|
23
23
|
import type {EditorSchema} from './editor-schema'
|
|
24
24
|
|
|
25
25
|
const slateOperationCallback: CallbackLogicFunction<
|
|
@@ -282,7 +282,9 @@ export const rangeDecorationsMachine = setup({
|
|
|
282
282
|
skipSetup: input.skipSetup,
|
|
283
283
|
schema: input.schema,
|
|
284
284
|
slateEditor: input.slateEditor,
|
|
285
|
-
decorate: {
|
|
285
|
+
decorate: {
|
|
286
|
+
fn: createDecorate(input.schema, input.slateEditor),
|
|
287
|
+
},
|
|
286
288
|
}),
|
|
287
289
|
invoke: {
|
|
288
290
|
src: 'slate operation listener',
|
|
@@ -357,7 +359,15 @@ function createDecorate(
|
|
|
357
359
|
slateEditor: PortableTextSlateEditor,
|
|
358
360
|
) {
|
|
359
361
|
return function decorate([node, path]: NodeEntry): Array<BaseRange> {
|
|
360
|
-
|
|
362
|
+
const defaultStyle = schema.styles.at(0)?.name
|
|
363
|
+
const editorOnlyContainsEmptyParagraph =
|
|
364
|
+
slateEditor.value.length === 1 &&
|
|
365
|
+
isEmptyTextBlock({schema}, slateEditor.value[0]) &&
|
|
366
|
+
(!slateEditor.value[0].style ||
|
|
367
|
+
slateEditor.value[0].style === defaultStyle) &&
|
|
368
|
+
!slateEditor.value[0].listItem
|
|
369
|
+
|
|
370
|
+
if (editorOnlyContainsEmptyParagraph) {
|
|
361
371
|
return [
|
|
362
372
|
{
|
|
363
373
|
anchor: {
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
type CallbackLogicFunction,
|
|
18
18
|
} from 'xstate'
|
|
19
19
|
import {pluginWithoutHistory} from '../history/slate-plugin.without-history'
|
|
20
|
-
import {createPlaceholderBlock} from '../internal-utils/create-placeholder-block'
|
|
21
20
|
import {debugWithName} from '../internal-utils/debug'
|
|
22
21
|
import {validateValue} from '../internal-utils/validateValue'
|
|
23
22
|
import {toSlateBlock, VOID_CHILD_KEY} from '../internal-utils/values'
|
|
@@ -425,10 +424,8 @@ async function updateValue({
|
|
|
425
424
|
debug('Value is empty')
|
|
426
425
|
|
|
427
426
|
clearEditor({
|
|
428
|
-
context,
|
|
429
427
|
slateEditor,
|
|
430
428
|
doneSyncing,
|
|
431
|
-
hadSelection,
|
|
432
429
|
})
|
|
433
430
|
|
|
434
431
|
isChanged = true
|
|
@@ -575,18 +572,11 @@ async function* getStreamedBlocks({value}: {value: Array<PortableTextBlock>}) {
|
|
|
575
572
|
* Remove all blocks and insert a placeholder block
|
|
576
573
|
*/
|
|
577
574
|
function clearEditor({
|
|
578
|
-
context,
|
|
579
575
|
slateEditor,
|
|
580
576
|
doneSyncing,
|
|
581
|
-
hadSelection,
|
|
582
577
|
}: {
|
|
583
|
-
context: {
|
|
584
|
-
keyGenerator: () => string
|
|
585
|
-
schema: EditorSchema
|
|
586
|
-
}
|
|
587
578
|
slateEditor: PortableTextSlateEditor
|
|
588
579
|
doneSyncing: boolean
|
|
589
|
-
hadSelection: boolean
|
|
590
580
|
}) {
|
|
591
581
|
Editor.withoutNormalizing(slateEditor, () => {
|
|
592
582
|
pluginWithoutHistory(slateEditor, () => {
|
|
@@ -596,10 +586,6 @@ function clearEditor({
|
|
|
596
586
|
return
|
|
597
587
|
}
|
|
598
588
|
|
|
599
|
-
if (hadSelection) {
|
|
600
|
-
Transforms.deselect(slateEditor)
|
|
601
|
-
}
|
|
602
|
-
|
|
603
589
|
const childrenLength = slateEditor.children.length
|
|
604
590
|
|
|
605
591
|
slateEditor.children.forEach((_, index) => {
|
|
@@ -607,15 +593,6 @@ function clearEditor({
|
|
|
607
593
|
at: [childrenLength - 1 - index],
|
|
608
594
|
})
|
|
609
595
|
})
|
|
610
|
-
|
|
611
|
-
Transforms.insertNodes(slateEditor, createPlaceholderBlock(context), {
|
|
612
|
-
at: [0],
|
|
613
|
-
})
|
|
614
|
-
|
|
615
|
-
// Add a new selection in the top of the document
|
|
616
|
-
if (hadSelection) {
|
|
617
|
-
Transforms.select(slateEditor, [0, 0])
|
|
618
|
-
}
|
|
619
596
|
})
|
|
620
597
|
})
|
|
621
598
|
})
|
|
@@ -21,14 +21,15 @@ import type {EditorContext} from '../editor/editor-snapshot'
|
|
|
21
21
|
import {KEY_TO_SLATE_ELEMENT} from '../editor/weakMaps'
|
|
22
22
|
import type {PortableTextSlateEditor} from '../types/editor'
|
|
23
23
|
import {isKeyedSegment} from '../utils/util.is-keyed-segment'
|
|
24
|
-
import {createPlaceholderBlock} from './create-placeholder-block'
|
|
25
24
|
import {isEqualToEmptyEditor, toSlateBlock} from './values'
|
|
26
25
|
|
|
27
26
|
/**
|
|
28
27
|
* Creates a function that can apply a patch onto a PortableTextSlateEditor.
|
|
29
28
|
*/
|
|
30
29
|
export function createApplyPatch(
|
|
31
|
-
context: Pick<EditorContext, 'schema' | 'keyGenerator'
|
|
30
|
+
context: Pick<EditorContext, 'schema' | 'keyGenerator'> & {
|
|
31
|
+
initialValue: Array<PortableTextBlock> | undefined
|
|
32
|
+
},
|
|
32
33
|
): (editor: PortableTextSlateEditor, patch: Patch) => boolean {
|
|
33
34
|
return (editor: PortableTextSlateEditor, patch: Patch): boolean => {
|
|
34
35
|
let changed = false
|
|
@@ -39,7 +40,7 @@ export function createApplyPatch(
|
|
|
39
40
|
changed = insertPatch(context, editor, patch)
|
|
40
41
|
break
|
|
41
42
|
case 'unset':
|
|
42
|
-
changed = unsetPatch(
|
|
43
|
+
changed = unsetPatch(editor, patch)
|
|
43
44
|
break
|
|
44
45
|
case 'set':
|
|
45
46
|
changed = setPatch(editor, patch)
|
|
@@ -118,13 +119,31 @@ function diffMatchPatch(
|
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
function insertPatch(
|
|
121
|
-
context: Pick<EditorContext, 'schema' | 'keyGenerator'
|
|
122
|
+
context: Pick<EditorContext, 'schema' | 'keyGenerator'> & {
|
|
123
|
+
initialValue: Array<PortableTextBlock> | undefined
|
|
124
|
+
},
|
|
122
125
|
editor: PortableTextSlateEditor,
|
|
123
126
|
patch: InsertPatch,
|
|
124
127
|
) {
|
|
125
128
|
const block = findBlock(editor.children, patch.path)
|
|
126
129
|
|
|
127
130
|
if (!block) {
|
|
131
|
+
if (patch.path.length === 1 && patch.path[0] === 0) {
|
|
132
|
+
const blocksToInsert = patch.items.map((item) =>
|
|
133
|
+
toSlateBlock(
|
|
134
|
+
item as PortableTextBlock,
|
|
135
|
+
{schemaTypes: context.schema},
|
|
136
|
+
KEY_TO_SLATE_ELEMENT.get(editor),
|
|
137
|
+
),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
Transforms.insertNodes(editor, blocksToInsert, {
|
|
141
|
+
at: [0],
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
|
|
128
147
|
return false
|
|
129
148
|
}
|
|
130
149
|
|
|
@@ -147,6 +166,7 @@ function insertPatch(
|
|
|
147
166
|
position === 'after' ? targetBlockIndex + 1 : targetBlockIndex
|
|
148
167
|
|
|
149
168
|
const editorWasEmptyBefore = isEqualToEmptyEditor(
|
|
169
|
+
context.initialValue,
|
|
150
170
|
editor.value,
|
|
151
171
|
context.schema,
|
|
152
172
|
)
|
|
@@ -418,14 +438,9 @@ function setPatch(editor: PortableTextSlateEditor, patch: SetPatch) {
|
|
|
418
438
|
return true
|
|
419
439
|
}
|
|
420
440
|
|
|
421
|
-
function unsetPatch(
|
|
422
|
-
context: Pick<EditorContext, 'keyGenerator' | 'schema'>,
|
|
423
|
-
editor: PortableTextSlateEditor,
|
|
424
|
-
patch: UnsetPatch,
|
|
425
|
-
) {
|
|
441
|
+
function unsetPatch(editor: PortableTextSlateEditor, patch: UnsetPatch) {
|
|
426
442
|
// Value
|
|
427
443
|
if (patch.path.length === 0) {
|
|
428
|
-
const previousSelection = editor.selection
|
|
429
444
|
Transforms.deselect(editor)
|
|
430
445
|
|
|
431
446
|
const children = Node.children(editor, [], {
|
|
@@ -436,15 +451,6 @@ function unsetPatch(
|
|
|
436
451
|
Transforms.removeNodes(editor, {at: path})
|
|
437
452
|
}
|
|
438
453
|
|
|
439
|
-
Transforms.insertNodes(editor, createPlaceholderBlock(context))
|
|
440
|
-
if (previousSelection) {
|
|
441
|
-
Transforms.select(editor, {
|
|
442
|
-
anchor: {path: [0, 0], offset: 0},
|
|
443
|
-
focus: {path: [0, 0], offset: 0},
|
|
444
|
-
})
|
|
445
|
-
}
|
|
446
|
-
// call OnChange here to emit the new selection
|
|
447
|
-
editor.onChange()
|
|
448
454
|
return true
|
|
449
455
|
}
|
|
450
456
|
|
|
@@ -456,27 +462,6 @@ function unsetPatch(
|
|
|
456
462
|
|
|
457
463
|
// Single blocks
|
|
458
464
|
if (patch.path.length === 1) {
|
|
459
|
-
if (editor.children.length === 1) {
|
|
460
|
-
// `unset`ing the last block should be treated similar to `unset`ing the
|
|
461
|
-
// entire editor value
|
|
462
|
-
const previousSelection = editor.selection
|
|
463
|
-
|
|
464
|
-
Transforms.deselect(editor)
|
|
465
|
-
Transforms.removeNodes(editor, {at: [block.index]})
|
|
466
|
-
Transforms.insertNodes(editor, createPlaceholderBlock(context))
|
|
467
|
-
|
|
468
|
-
if (previousSelection) {
|
|
469
|
-
Transforms.select(editor, {
|
|
470
|
-
anchor: {path: [0, 0], offset: 0},
|
|
471
|
-
focus: {path: [0, 0], offset: 0},
|
|
472
|
-
})
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
editor.onChange()
|
|
476
|
-
|
|
477
|
-
return true
|
|
478
|
-
}
|
|
479
|
-
|
|
480
465
|
Transforms.removeNodes(editor, {at: [block.index]})
|
|
481
466
|
|
|
482
467
|
return true
|
|
@@ -169,9 +169,14 @@ export function fromSlateBlock(
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
export function isEqualToEmptyEditor(
|
|
172
|
+
initialValue: Array<PortableTextBlock> | undefined,
|
|
172
173
|
blocks: Array<Descendant> | Array<PortableTextBlock>,
|
|
173
174
|
schemaTypes: EditorSchema,
|
|
174
175
|
): boolean {
|
|
176
|
+
if (!blocks) {
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
|
|
175
180
|
// Must have exactly one block
|
|
176
181
|
if (blocks.length !== 1) {
|
|
177
182
|
return false
|
|
@@ -240,5 +245,22 @@ export function isEqualToEmptyEditor(
|
|
|
240
245
|
return false
|
|
241
246
|
}
|
|
242
247
|
|
|
248
|
+
if (
|
|
249
|
+
Object.keys(firstBlock).some(
|
|
250
|
+
(key) =>
|
|
251
|
+
key !== '_type' &&
|
|
252
|
+
key !== '_key' &&
|
|
253
|
+
key !== 'children' &&
|
|
254
|
+
key !== 'markDefs' &&
|
|
255
|
+
key !== 'style',
|
|
256
|
+
)
|
|
257
|
+
) {
|
|
258
|
+
return false
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (isEqual(initialValue, [firstBlock])) {
|
|
262
|
+
return false
|
|
263
|
+
}
|
|
264
|
+
|
|
243
265
|
return true
|
|
244
266
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {isSpan, isTextBlock} from '@portabletext/schema'
|
|
2
2
|
import {deleteText, Editor, Element, Range, Transforms} from 'slate'
|
|
3
3
|
import {DOMEditor} from 'slate-dom'
|
|
4
|
-
import {createPlaceholderBlock} from '../internal-utils/create-placeholder-block'
|
|
5
4
|
import {slateRangeToSelection} from '../internal-utils/slate-utils'
|
|
6
5
|
import {toSlateRange} from '../internal-utils/to-slate-range'
|
|
7
6
|
import {VOID_CHILD_KEY} from '../internal-utils/values'
|
|
@@ -68,10 +67,6 @@ export const deleteOperationImplementation: BehaviorOperationImplementation<
|
|
|
68
67
|
mode: 'highest',
|
|
69
68
|
})
|
|
70
69
|
|
|
71
|
-
if (operation.editor.children.length === 0) {
|
|
72
|
-
Transforms.insertNodes(operation.editor, createPlaceholderBlock(context))
|
|
73
|
-
}
|
|
74
|
-
|
|
75
70
|
return
|
|
76
71
|
}
|
|
77
72
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type Descendant,
|
|
11
11
|
} from 'slate'
|
|
12
12
|
import {DOMEditor} from 'slate-dom'
|
|
13
|
+
import {createPlaceholderBlock} from '../internal-utils/create-placeholder-block'
|
|
13
14
|
import {getFocusBlock, getFocusChild} from '../internal-utils/slate-utils'
|
|
14
15
|
import {toSlateRange} from '../internal-utils/to-slate-range'
|
|
15
16
|
import {toSlateBlock} from '../internal-utils/values'
|
|
@@ -70,6 +71,10 @@ export function insertBlock(options: {
|
|
|
70
71
|
})
|
|
71
72
|
: editor.selection
|
|
72
73
|
|
|
74
|
+
if (editor.children.length === 0) {
|
|
75
|
+
Transforms.insertNodes(editor, createPlaceholderBlock(context), {at: [0]})
|
|
76
|
+
}
|
|
77
|
+
|
|
73
78
|
// Fall back to the start and end of the editor if neither an editor
|
|
74
79
|
// selection nor an `at` range is provided
|
|
75
80
|
const start = at ? Range.start(at) : Editor.start(editor, [])
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import {Editor} from 'slate'
|
|
2
|
-
import {isRedoing} from '../../history/slate-plugin.redoing'
|
|
3
|
-
import {isUndoing} from '../../history/slate-plugin.undoing'
|
|
4
|
-
import {createPlaceholderBlock} from '../../internal-utils/create-placeholder-block'
|
|
5
|
-
import {debugWithName} from '../../internal-utils/debug'
|
|
6
|
-
import type {PortableTextSlateEditor} from '../../types/editor'
|
|
7
|
-
import type {EditorActor} from '../editor-machine'
|
|
8
|
-
import {isChangingRemotely} from '../withChanges'
|
|
9
|
-
|
|
10
|
-
const debug = debugWithName('plugin:withPlaceholderBlock')
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Keep a "placeholder" block present when the editor is empty
|
|
14
|
-
*
|
|
15
|
-
*/
|
|
16
|
-
export function createWithPlaceholderBlock(
|
|
17
|
-
editorActor: EditorActor,
|
|
18
|
-
): (editor: PortableTextSlateEditor) => PortableTextSlateEditor {
|
|
19
|
-
return function withPlaceholderBlock(
|
|
20
|
-
editor: PortableTextSlateEditor,
|
|
21
|
-
): PortableTextSlateEditor {
|
|
22
|
-
const {apply} = editor
|
|
23
|
-
|
|
24
|
-
editor.apply = (op) => {
|
|
25
|
-
if (editorActor.getSnapshot().matches({'edit mode': 'read only'})) {
|
|
26
|
-
apply(op)
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* We don't want to run any side effects when the editor is processing
|
|
32
|
-
* remote changes.
|
|
33
|
-
*/
|
|
34
|
-
if (isChangingRemotely(editor)) {
|
|
35
|
-
apply(op)
|
|
36
|
-
return
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* We don't want to run any side effects when the editor is undoing or
|
|
41
|
-
* redoing operations.
|
|
42
|
-
*/
|
|
43
|
-
if (isUndoing(editor) || isRedoing(editor)) {
|
|
44
|
-
apply(op)
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (op.type === 'remove_node') {
|
|
49
|
-
const blockIndex = op.path.at(0)
|
|
50
|
-
const isLonelyBlock =
|
|
51
|
-
op.path.length === 1 &&
|
|
52
|
-
blockIndex === 0 &&
|
|
53
|
-
editor.children.length === 1
|
|
54
|
-
const isBlockObject =
|
|
55
|
-
op.node._type !== editorActor.getSnapshot().context.schema.block.name
|
|
56
|
-
|
|
57
|
-
if (isLonelyBlock && isBlockObject) {
|
|
58
|
-
debug('Adding placeholder block')
|
|
59
|
-
Editor.insertNode(
|
|
60
|
-
editor,
|
|
61
|
-
createPlaceholderBlock(editorActor.getSnapshot().context),
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
apply(op)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return editor
|
|
70
|
-
}
|
|
71
|
-
}
|