@portabletext/editor 1.36.5 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/behavior.markdown.cjs +1 -1
- package/lib/_chunks-cjs/editor-provider.cjs +104 -7
- package/lib/_chunks-cjs/editor-provider.cjs.map +1 -1
- package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/behavior.markdown.js +1 -1
- package/lib/_chunks-es/editor-provider.js +108 -11
- package/lib/_chunks-es/editor-provider.js.map +1 -1
- package/lib/_chunks-es/util.block-offsets-to-selection.js.map +1 -1
- package/lib/behaviors/index.d.cts +59 -0
- package/lib/behaviors/index.d.ts +59 -0
- package/lib/index.d.cts +59 -0
- package/lib/index.d.ts +59 -0
- package/lib/plugins/index.cjs +1 -1
- package/lib/plugins/index.d.cts +59 -0
- package/lib/plugins/index.d.ts +59 -0
- package/lib/plugins/index.js +1 -1
- package/lib/selectors/index.cjs +69 -14
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.d.cts +75 -0
- package/lib/selectors/index.d.ts +75 -0
- package/lib/selectors/index.js +63 -8
- package/lib/selectors/index.js.map +1 -1
- package/lib/utils/index.d.cts +59 -0
- package/lib/utils/index.d.ts +59 -0
- package/package.json +7 -7
- package/src/behavior-actions/behavior.action.decorator.add.ts +1 -0
- package/src/behavior-actions/behavior.action.delete.text.ts +1 -0
- package/src/behavior-actions/behavior.action.delete.ts +1 -3
- package/src/behavior-actions/behavior.action.insert-blocks.ts +98 -2
- package/src/behavior-actions/behavior.actions.ts +1 -0
- package/src/behaviors/behavior.default.ts +1 -0
- package/src/behaviors/behavior.types.ts +1 -0
- package/src/editor/editor-machine.ts +16 -3
- package/src/editor/editor-selector.ts +1 -0
- package/src/editor/editor-snapshot.ts +4 -0
- package/src/internal-utils/create-test-snapshot.ts +1 -0
- package/src/internal-utils/parse-blocks.ts +22 -0
- package/src/selectors/index.ts +2 -0
- package/src/selectors/selector.get-focus-inline-object.ts +21 -0
- package/src/selectors/selector.is-overlapping-selection.test.ts +171 -0
- package/src/selectors/selector.is-overlapping-selection.ts +108 -4
- package/src/selectors/selector.is-point-after-selection.ts +3 -1
- package/src/selectors/selector.is-point-before-selection.ts +3 -1
- package/src/selectors/selector.is-selecting-entire-blocks.ts +34 -0
|
@@ -360,7 +360,10 @@ export const editorMachine = setup({
|
|
|
360
360
|
withApplyingBehaviorActions(event.editor, () => {
|
|
361
361
|
try {
|
|
362
362
|
performAction({
|
|
363
|
-
context
|
|
363
|
+
context: {
|
|
364
|
+
keyGenerator: context.keyGenerator,
|
|
365
|
+
schema: context.schema,
|
|
366
|
+
},
|
|
364
367
|
action: defaultAction,
|
|
365
368
|
})
|
|
366
369
|
} catch (error) {
|
|
@@ -379,6 +382,7 @@ export const editorMachine = setup({
|
|
|
379
382
|
converters: [...context.converters],
|
|
380
383
|
editor: event.editor,
|
|
381
384
|
keyGenerator: context.keyGenerator,
|
|
385
|
+
readOnly: self.getSnapshot().matches({'edit mode': 'read only'}),
|
|
382
386
|
schema: context.schema,
|
|
383
387
|
hasTag: (tag) => self.getSnapshot().hasTag(tag),
|
|
384
388
|
})
|
|
@@ -440,7 +444,13 @@ export const editorMachine = setup({
|
|
|
440
444
|
}
|
|
441
445
|
|
|
442
446
|
try {
|
|
443
|
-
performAction({
|
|
447
|
+
performAction({
|
|
448
|
+
context: {
|
|
449
|
+
keyGenerator: context.keyGenerator,
|
|
450
|
+
schema: context.schema,
|
|
451
|
+
},
|
|
452
|
+
action: internalAction,
|
|
453
|
+
})
|
|
444
454
|
} catch (error) {
|
|
445
455
|
console.error(
|
|
446
456
|
new Error(
|
|
@@ -483,7 +493,10 @@ export const editorMachine = setup({
|
|
|
483
493
|
withApplyingBehaviorActions(event.editor, () => {
|
|
484
494
|
try {
|
|
485
495
|
performAction({
|
|
486
|
-
context
|
|
496
|
+
context: {
|
|
497
|
+
keyGenerator: context.keyGenerator,
|
|
498
|
+
schema: context.schema,
|
|
499
|
+
},
|
|
487
500
|
action: defaultAction,
|
|
488
501
|
})
|
|
489
502
|
} catch (error) {
|
|
@@ -73,6 +73,7 @@ export function getEditorSnapshot({
|
|
|
73
73
|
slateEditorInstance,
|
|
74
74
|
}),
|
|
75
75
|
keyGenerator: editorActorSnapshot.context.keyGenerator,
|
|
76
|
+
readOnly: editorActorSnapshot.matches({'edit mode': 'read only'}),
|
|
76
77
|
schema: editorActorSnapshot.context.schema,
|
|
77
78
|
selection: editorActorSnapshot.context.selection,
|
|
78
79
|
value: getValue({editorActorSnapshot, slateEditorInstance}),
|
|
@@ -15,6 +15,7 @@ export type EditorContext = {
|
|
|
15
15
|
activeDecorators: Array<string>
|
|
16
16
|
converters: Array<Converter>
|
|
17
17
|
keyGenerator: () => string
|
|
18
|
+
readOnly: boolean
|
|
18
19
|
schema: EditorSchema
|
|
19
20
|
selection: EditorSelection
|
|
20
21
|
value: Array<PortableTextBlock>
|
|
@@ -38,12 +39,14 @@ export function createEditorSnapshot({
|
|
|
38
39
|
converters,
|
|
39
40
|
editor,
|
|
40
41
|
keyGenerator,
|
|
42
|
+
readOnly,
|
|
41
43
|
schema,
|
|
42
44
|
hasTag,
|
|
43
45
|
}: {
|
|
44
46
|
converters: Array<Converter>
|
|
45
47
|
editor: PortableTextSlateEditor
|
|
46
48
|
keyGenerator: () => string
|
|
49
|
+
readOnly: boolean
|
|
47
50
|
schema: EditorSchema
|
|
48
51
|
hasTag: HasTag
|
|
49
52
|
}) {
|
|
@@ -61,6 +64,7 @@ export function createEditorSnapshot({
|
|
|
61
64
|
}),
|
|
62
65
|
converters,
|
|
63
66
|
keyGenerator,
|
|
67
|
+
readOnly,
|
|
64
68
|
schema,
|
|
65
69
|
selection,
|
|
66
70
|
value,
|
|
@@ -13,6 +13,7 @@ export function createTestSnapshot(snapshot: {
|
|
|
13
13
|
snapshot.context?.schema ?? compileSchemaDefinition(defineSchema({})),
|
|
14
14
|
keyGenerator: snapshot.context?.keyGenerator ?? createTestKeyGenerator(),
|
|
15
15
|
activeDecorators: snapshot.context?.activeDecorators ?? [],
|
|
16
|
+
readOnly: snapshot.context?.readOnly ?? false,
|
|
16
17
|
value: snapshot.context?.value ?? [],
|
|
17
18
|
selection: snapshot.context?.selection ?? null,
|
|
18
19
|
},
|
|
@@ -8,6 +8,28 @@ import type {EditorSchema} from '../editor/define-schema'
|
|
|
8
8
|
import type {EditorContext} from '../editor/editor-snapshot'
|
|
9
9
|
import {isTypedObject} from './asserters'
|
|
10
10
|
|
|
11
|
+
export function parseBlocks({
|
|
12
|
+
context,
|
|
13
|
+
blocks,
|
|
14
|
+
options,
|
|
15
|
+
}: {
|
|
16
|
+
context: Pick<EditorContext, 'keyGenerator' | 'schema'>
|
|
17
|
+
blocks: unknown
|
|
18
|
+
options: {
|
|
19
|
+
refreshKeys: boolean
|
|
20
|
+
}
|
|
21
|
+
}): Array<PortableTextBlock> {
|
|
22
|
+
if (!Array.isArray(blocks)) {
|
|
23
|
+
return []
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return blocks.flatMap((block) => {
|
|
27
|
+
const parsedBlock = parseBlock({context, block, options})
|
|
28
|
+
|
|
29
|
+
return parsedBlock ? [parsedBlock] : []
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
11
33
|
export function parseBlock({
|
|
12
34
|
context,
|
|
13
35
|
block,
|
package/src/selectors/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export {isSelectingEntireBlocks} from './selector.is-selecting-entire-blocks'
|
|
1
2
|
export {getActiveAnnotations} from './selector.get-active-annotations'
|
|
2
3
|
export {getActiveListItem} from './selector.get-active-list-item'
|
|
3
4
|
export {getActiveStyle} from './selector.get-active-style'
|
|
@@ -7,6 +8,7 @@ export {getAnchorSpan} from './selector.get-anchor-span'
|
|
|
7
8
|
export {getAnchorTextBlock} from './selector.get-anchor-text-block'
|
|
8
9
|
export {getBlockOffsets} from './selector.get-block-offsets'
|
|
9
10
|
export {getCaretWordSelection} from './selector.get-caret-word-selection'
|
|
11
|
+
export {getFocusInlineObject} from './selector.get-focus-inline-object'
|
|
10
12
|
export {getNextInlineObject} from './selector.get-next-inline-object'
|
|
11
13
|
export {getPreviousInlineObject} from './selector.get-previous-inline-object'
|
|
12
14
|
export {getSelectedSlice} from './selector.get-selected-slice'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isPortableTextSpan,
|
|
3
|
+
type KeyedSegment,
|
|
4
|
+
type PortableTextObject,
|
|
5
|
+
} from '@sanity/types'
|
|
6
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
7
|
+
import {getFocusChild} from './selectors'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export const getFocusInlineObject: EditorSelector<
|
|
13
|
+
| {node: PortableTextObject; path: [KeyedSegment, 'children', KeyedSegment]}
|
|
14
|
+
| undefined
|
|
15
|
+
> = (snapshot) => {
|
|
16
|
+
const focusChild = getFocusChild(snapshot)
|
|
17
|
+
|
|
18
|
+
return focusChild && !isPortableTextSpan(focusChild.node)
|
|
19
|
+
? {node: focusChild.node, path: focusChild.path}
|
|
20
|
+
: undefined
|
|
21
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {describe, expect, test} from 'vitest'
|
|
2
|
+
import {createTestSnapshot} from '../internal-utils/create-test-snapshot'
|
|
3
|
+
import type {EditorSelection} from '../types/editor'
|
|
4
|
+
import {isOverlappingSelection} from './selector.is-overlapping-selection'
|
|
5
|
+
|
|
6
|
+
function snapshot(selection: EditorSelection) {
|
|
7
|
+
return createTestSnapshot({
|
|
8
|
+
context: {
|
|
9
|
+
selection,
|
|
10
|
+
value: [
|
|
11
|
+
{_type: 'image', _key: 'k0'},
|
|
12
|
+
{
|
|
13
|
+
_type: 'block',
|
|
14
|
+
_key: 'k1',
|
|
15
|
+
children: [
|
|
16
|
+
{_type: 'span', _key: 'k3', text: 'foo'},
|
|
17
|
+
{_type: 'stock-ticker', _key: 'k4'},
|
|
18
|
+
{_type: 'span', _key: 'k5', text: 'bar'},
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{_type: 'image', _key: 'k2'},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe(isOverlappingSelection.name, () => {
|
|
28
|
+
test('null', () => {
|
|
29
|
+
expect(isOverlappingSelection(null)(snapshot(null))).toBe(false)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('fully selected block object', () => {
|
|
33
|
+
expect(
|
|
34
|
+
isOverlappingSelection({
|
|
35
|
+
anchor: {path: [{_key: 'k0'}], offset: 0},
|
|
36
|
+
focus: {path: [{_key: 'k0'}], offset: 0},
|
|
37
|
+
})(
|
|
38
|
+
snapshot({
|
|
39
|
+
anchor: {path: [{_key: 'k0'}], offset: 0},
|
|
40
|
+
focus: {path: [{_key: 'k0'}], offset: 0},
|
|
41
|
+
}),
|
|
42
|
+
),
|
|
43
|
+
).toBe(true)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('block object inside selection', () => {
|
|
47
|
+
expect(
|
|
48
|
+
isOverlappingSelection({
|
|
49
|
+
anchor: {path: [{_key: 'k0'}], offset: 0},
|
|
50
|
+
focus: {path: [{_key: 'k0'}], offset: 0},
|
|
51
|
+
})(
|
|
52
|
+
snapshot({
|
|
53
|
+
anchor: {path: [{_key: 'k0'}], offset: 0},
|
|
54
|
+
focus: {path: [{_key: 'k2'}], offset: 0},
|
|
55
|
+
}),
|
|
56
|
+
),
|
|
57
|
+
).toBe(true)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('fully selected inline object', () => {
|
|
61
|
+
expect(
|
|
62
|
+
isOverlappingSelection({
|
|
63
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
64
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
65
|
+
})(
|
|
66
|
+
snapshot({
|
|
67
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
68
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
69
|
+
}),
|
|
70
|
+
),
|
|
71
|
+
).toBe(true)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test('inline object inside selection', () => {
|
|
75
|
+
expect(
|
|
76
|
+
isOverlappingSelection({
|
|
77
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
78
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
79
|
+
})(
|
|
80
|
+
snapshot({
|
|
81
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
|
|
82
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
|
|
83
|
+
}),
|
|
84
|
+
),
|
|
85
|
+
).toBe(true)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('selection right before', () => {
|
|
89
|
+
expect(
|
|
90
|
+
isOverlappingSelection({
|
|
91
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 0},
|
|
92
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
|
|
93
|
+
})(
|
|
94
|
+
snapshot({
|
|
95
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
|
|
96
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
|
|
97
|
+
}),
|
|
98
|
+
),
|
|
99
|
+
).toBe(false)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test('selection overlapping from the start', () => {
|
|
103
|
+
expect(
|
|
104
|
+
isOverlappingSelection({
|
|
105
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 0},
|
|
106
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 3},
|
|
107
|
+
})(
|
|
108
|
+
snapshot({
|
|
109
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
|
|
110
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
|
|
111
|
+
}),
|
|
112
|
+
),
|
|
113
|
+
).toBe(true)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('selection right after', () => {
|
|
117
|
+
expect(
|
|
118
|
+
isOverlappingSelection({
|
|
119
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
|
|
120
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 2},
|
|
121
|
+
})(
|
|
122
|
+
snapshot({
|
|
123
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
|
|
124
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
|
|
125
|
+
}),
|
|
126
|
+
),
|
|
127
|
+
).toBe(false)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
test('selection overlapping from the end', () => {
|
|
131
|
+
expect(
|
|
132
|
+
isOverlappingSelection({
|
|
133
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 0},
|
|
134
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 2},
|
|
135
|
+
})(
|
|
136
|
+
snapshot({
|
|
137
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
|
|
138
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 1},
|
|
139
|
+
}),
|
|
140
|
+
),
|
|
141
|
+
).toBe(true)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
test('before inline object', () => {
|
|
145
|
+
expect(
|
|
146
|
+
isOverlappingSelection({
|
|
147
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
|
|
148
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k3'}], offset: 2},
|
|
149
|
+
})(
|
|
150
|
+
snapshot({
|
|
151
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
152
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
153
|
+
}),
|
|
154
|
+
),
|
|
155
|
+
).toBe(false)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
test('after inline object', () => {
|
|
159
|
+
expect(
|
|
160
|
+
isOverlappingSelection({
|
|
161
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 2},
|
|
162
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k5'}], offset: 2},
|
|
163
|
+
})(
|
|
164
|
+
snapshot({
|
|
165
|
+
anchor: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
166
|
+
focus: {path: [{_key: 'k1'}, 'children', {_key: 'k4'}], offset: 0},
|
|
167
|
+
}),
|
|
168
|
+
),
|
|
169
|
+
).toBe(false)
|
|
170
|
+
})
|
|
171
|
+
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {EditorSelection} from '../types/editor'
|
|
2
|
+
import {isEqualSelectionPoints} from '../utils'
|
|
2
3
|
import type {EditorSelector} from './../editor/editor-selector'
|
|
3
4
|
import {getSelectionEndPoint} from './selector.get-selection-end-point'
|
|
4
5
|
import {getSelectionStartPoint} from './selector.get-selection-start-point'
|
|
@@ -31,18 +32,121 @@ export function isOverlappingSelection(
|
|
|
31
32
|
},
|
|
32
33
|
})
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
const originalSelectionStartPoint = getSelectionStartPoint(snapshot)
|
|
36
|
+
const originalSelectionEndPoint = getSelectionEndPoint(snapshot)
|
|
37
|
+
|
|
38
|
+
if (
|
|
39
|
+
!selectionStartPoint ||
|
|
40
|
+
!selectionEndPoint ||
|
|
41
|
+
!originalSelectionStartPoint ||
|
|
42
|
+
!originalSelectionEndPoint
|
|
43
|
+
) {
|
|
35
44
|
return false
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
|
|
47
|
+
const startPointBeforeSelection =
|
|
48
|
+
isPointBeforeSelection(selectionStartPoint)(snapshot)
|
|
49
|
+
const startPointAfterSelection =
|
|
50
|
+
isPointAfterSelection(selectionStartPoint)(snapshot)
|
|
51
|
+
const endPointBeforeSelection =
|
|
52
|
+
isPointBeforeSelection(selectionEndPoint)(snapshot)
|
|
53
|
+
const endPointAfterSelection =
|
|
54
|
+
isPointAfterSelection(selectionEndPoint)(snapshot)
|
|
55
|
+
|
|
56
|
+
const originalStartPointBeforeStartPoint = isPointBeforeSelection(
|
|
57
|
+
originalSelectionStartPoint,
|
|
58
|
+
)({
|
|
59
|
+
...snapshot,
|
|
60
|
+
context: {
|
|
61
|
+
...snapshot.context,
|
|
62
|
+
selection: {
|
|
63
|
+
anchor: selectionStartPoint,
|
|
64
|
+
focus: selectionStartPoint,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
})
|
|
68
|
+
const originalStartPointAfterStartPoint = isPointAfterSelection(
|
|
69
|
+
originalSelectionStartPoint,
|
|
70
|
+
)({
|
|
71
|
+
...snapshot,
|
|
72
|
+
context: {
|
|
73
|
+
...snapshot.context,
|
|
74
|
+
selection: {
|
|
75
|
+
anchor: selectionStartPoint,
|
|
76
|
+
focus: selectionStartPoint,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const originalEndPointBeforeEndPoint = isPointBeforeSelection(
|
|
82
|
+
originalSelectionEndPoint,
|
|
83
|
+
)({
|
|
84
|
+
...snapshot,
|
|
85
|
+
context: {
|
|
86
|
+
...snapshot.context,
|
|
87
|
+
selection: {
|
|
88
|
+
anchor: selectionEndPoint,
|
|
89
|
+
focus: selectionEndPoint,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
})
|
|
93
|
+
const originalEndPointAfterEndPoint = isPointAfterSelection(
|
|
94
|
+
originalSelectionEndPoint,
|
|
95
|
+
)({
|
|
96
|
+
...snapshot,
|
|
97
|
+
context: {
|
|
98
|
+
...snapshot.context,
|
|
99
|
+
selection: {
|
|
100
|
+
anchor: selectionEndPoint,
|
|
101
|
+
focus: selectionEndPoint,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
const endPointEqualToOriginalStartPoint = isEqualSelectionPoints(
|
|
107
|
+
selectionEndPoint,
|
|
108
|
+
originalSelectionStartPoint,
|
|
109
|
+
)
|
|
110
|
+
const startPointEqualToOriginalEndPoint = isEqualSelectionPoints(
|
|
111
|
+
selectionStartPoint,
|
|
112
|
+
originalSelectionEndPoint,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if (endPointBeforeSelection && !endPointEqualToOriginalStartPoint) {
|
|
39
116
|
return false
|
|
40
117
|
}
|
|
41
118
|
|
|
42
|
-
if (!
|
|
119
|
+
if (startPointAfterSelection && !startPointEqualToOriginalEndPoint) {
|
|
43
120
|
return false
|
|
44
121
|
}
|
|
45
122
|
|
|
46
|
-
|
|
123
|
+
if (
|
|
124
|
+
!originalStartPointBeforeStartPoint &&
|
|
125
|
+
originalStartPointAfterStartPoint &&
|
|
126
|
+
!originalEndPointBeforeEndPoint &&
|
|
127
|
+
originalEndPointAfterEndPoint
|
|
128
|
+
) {
|
|
129
|
+
return !endPointEqualToOriginalStartPoint
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (
|
|
133
|
+
originalStartPointBeforeStartPoint &&
|
|
134
|
+
!originalStartPointAfterStartPoint &&
|
|
135
|
+
originalEndPointBeforeEndPoint &&
|
|
136
|
+
!originalEndPointAfterEndPoint
|
|
137
|
+
) {
|
|
138
|
+
return !startPointEqualToOriginalEndPoint
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (
|
|
142
|
+
!startPointAfterSelection ||
|
|
143
|
+
!startPointBeforeSelection ||
|
|
144
|
+
!endPointAfterSelection ||
|
|
145
|
+
!endPointBeforeSelection
|
|
146
|
+
) {
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return false
|
|
47
151
|
}
|
|
48
152
|
}
|
|
@@ -14,7 +14,9 @@ export function isPointAfterSelection(
|
|
|
14
14
|
return false
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const selection =
|
|
17
|
+
const selection = snapshot.context.selection.backward
|
|
18
|
+
? reverseSelection(snapshot.context.selection)
|
|
19
|
+
: snapshot.context.selection
|
|
18
20
|
|
|
19
21
|
const pointBlockKey = isKeySegment(point.path[0])
|
|
20
22
|
? point.path[0]._key
|
|
@@ -14,7 +14,9 @@ export function isPointBeforeSelection(
|
|
|
14
14
|
return false
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const selection =
|
|
17
|
+
const selection = snapshot.context.selection.backward
|
|
18
|
+
? reverseSelection(snapshot.context.selection)
|
|
19
|
+
: snapshot.context.selection
|
|
18
20
|
|
|
19
21
|
const pointBlockKey = isKeySegment(point.path[0])
|
|
20
22
|
? point.path[0]._key
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
2
|
+
import * as utils from '../utils'
|
|
3
|
+
import {getSelectionEndBlock, getSelectionStartBlock} from './selectors'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export const isSelectingEntireBlocks: EditorSelector<boolean> = (snapshot) => {
|
|
9
|
+
if (!snapshot.context.selection) {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const startPoint = snapshot.context.selection.backward
|
|
14
|
+
? snapshot.context.selection.focus
|
|
15
|
+
: snapshot.context.selection.anchor
|
|
16
|
+
const endPoint = snapshot.context.selection.backward
|
|
17
|
+
? snapshot.context.selection.anchor
|
|
18
|
+
: snapshot.context.selection.focus
|
|
19
|
+
|
|
20
|
+
const startBlock = getSelectionStartBlock(snapshot)
|
|
21
|
+
const endBlock = getSelectionEndBlock(snapshot)
|
|
22
|
+
|
|
23
|
+
if (!startBlock || !endBlock) {
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const startBlockStartPoint = utils.getBlockStartPoint(startBlock)
|
|
28
|
+
const endBlockEndPoint = utils.getBlockEndPoint(endBlock)
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
utils.isEqualSelectionPoints(startBlockStartPoint, startPoint) &&
|
|
32
|
+
utils.isEqualSelectionPoints(endBlockEndPoint, endPoint)
|
|
33
|
+
)
|
|
34
|
+
}
|