@portabletext/editor 1.24.0 → 1.26.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 +283 -64
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.get-text-before.cjs +8 -8
- package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +412 -0
- package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -0
- package/lib/_chunks-cjs/util.is-empty-text-block.cjs +2 -2
- package/lib/_chunks-cjs/util.is-empty-text-block.cjs.map +1 -1
- package/lib/_chunks-cjs/util.is-equal-selection-points.cjs +46 -0
- package/lib/_chunks-cjs/util.is-equal-selection-points.cjs.map +1 -0
- package/lib/_chunks-cjs/util.reverse-selection.cjs +0 -16
- package/lib/_chunks-cjs/util.reverse-selection.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js +259 -40
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/selector.get-text-before.js +2 -2
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js +414 -0
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -0
- package/lib/_chunks-es/util.is-empty-text-block.js +1 -1
- package/lib/_chunks-es/util.is-equal-selection-points.js +47 -0
- package/lib/_chunks-es/util.is-equal-selection-points.js.map +1 -0
- package/lib/_chunks-es/util.reverse-selection.js +0 -16
- package/lib/_chunks-es/util.reverse-selection.js.map +1 -1
- package/lib/behaviors/index.cjs +27 -27
- package/lib/behaviors/index.cjs.map +1 -1
- package/lib/behaviors/index.d.cts +2208 -171
- package/lib/behaviors/index.d.ts +2208 -171
- package/lib/behaviors/index.js +1 -1
- package/lib/index.cjs +306 -298
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +10499 -521
- package/lib/index.d.ts +10499 -521
- package/lib/index.js +302 -294
- package/lib/index.js.map +1 -1
- package/lib/selectors/index.cjs +26 -171
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.d.cts +16 -0
- package/lib/selectors/index.d.ts +16 -0
- package/lib/selectors/index.js +5 -151
- package/lib/selectors/index.js.map +1 -1
- package/lib/utils/index.cjs +5 -3
- package/lib/utils/index.cjs.map +1 -1
- package/lib/utils/index.d.cts +19 -0
- package/lib/utils/index.d.ts +19 -0
- package/lib/utils/index.js +4 -2
- package/package.json +6 -6
- package/src/behavior-actions/behavior.action-utils.insert-block.ts +3 -3
- package/src/behavior-actions/behavior.action.block.set.ts +23 -0
- package/src/behavior-actions/behavior.action.block.unset.ts +21 -0
- package/src/behavior-actions/behavior.action.insert-break.ts +2 -69
- package/src/behavior-actions/behavior.action.insert.block.ts +29 -0
- package/src/behavior-actions/behavior.actions.ts +116 -96
- package/src/behaviors/behavior.core.annotations.ts +29 -0
- package/src/behaviors/behavior.core.block-objects.ts +13 -13
- package/src/behaviors/behavior.core.decorators.ts +19 -0
- package/src/behaviors/behavior.core.insert-break.ts +122 -0
- package/src/behaviors/behavior.core.lists.ts +57 -23
- package/src/behaviors/behavior.core.style.ts +19 -0
- package/src/behaviors/behavior.core.ts +18 -2
- package/src/behaviors/behavior.types.ts +103 -88
- package/src/converters/converter.json.ts +4 -4
- package/src/converters/converter.portable-text.deserialize.test.ts +1 -1
- package/src/converters/converter.portable-text.ts +4 -4
- package/src/converters/converter.text-html.deserialize.test.ts +1 -1
- package/src/converters/converter.text-html.serialize.test.ts +1 -1
- package/src/converters/converter.text-html.ts +4 -4
- package/src/converters/converter.text-plain.test.ts +1 -1
- package/src/converters/converter.text-plain.ts +3 -3
- package/src/converters/{converter.ts → converter.types.ts} +6 -0
- package/src/editor/create-editor.ts +50 -7
- package/src/editor/editor-machine.ts +46 -3
- package/src/editor/editor-snapshot.ts +1 -1
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +2 -2
- package/src/editor/plugins/create-with-event-listeners.ts +41 -106
- package/src/selectors/index.ts +2 -0
- package/src/selectors/selector.is-at-the-end-of-block.ts +22 -0
- package/src/selectors/selector.is-at-the-start-of-block.ts +25 -0
- package/src/selectors/selector.is-selection-collapsed.ts +6 -2
- package/src/utils/index.ts +2 -0
- package/src/utils/util.get-block-end-point.ts +34 -0
- package/src/utils/util.is-equal-selection-points.ts +13 -0
- package/lib/_chunks-cjs/selector.is-selection-collapsed.cjs +0 -231
- package/lib/_chunks-cjs/selector.is-selection-collapsed.cjs.map +0 -1
- package/lib/_chunks-cjs/util.is-keyed-segment.cjs +0 -6
- package/lib/_chunks-cjs/util.is-keyed-segment.cjs.map +0 -1
- package/lib/_chunks-es/selector.is-selection-collapsed.js +0 -232
- package/lib/_chunks-es/selector.is-selection-collapsed.js.map +0 -1
- package/lib/_chunks-es/util.is-keyed-segment.js +0 -7
- package/lib/_chunks-es/util.is-keyed-segment.js.map +0 -1
- /package/src/converters/{converters.ts → converters.core.ts} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {htmlToBlocks} from '@portabletext/block-tools'
|
|
2
2
|
import {isPortableTextTextBlock, type PortableTextBlock} from '@sanity/types'
|
|
3
3
|
import {sliceBlocks} from '../utils'
|
|
4
|
-
import
|
|
4
|
+
import {defineConverter} from './converter.types'
|
|
5
5
|
|
|
6
|
-
export const converterTextPlain
|
|
6
|
+
export const converterTextPlain = defineConverter({
|
|
7
7
|
mimeType: 'text/plain',
|
|
8
8
|
serialize: ({context, event}) => {
|
|
9
9
|
if (!context.selection) {
|
|
@@ -73,7 +73,7 @@ export const converterTextPlain: Converter<'text/plain'> = {
|
|
|
73
73
|
mimeType: 'text/plain',
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
|
-
}
|
|
76
|
+
})
|
|
77
77
|
|
|
78
78
|
const entityMap: Record<string, string> = {
|
|
79
79
|
'&': '&',
|
|
@@ -9,6 +9,12 @@ export type Converter<TMIMEType extends MIMEType = MIMEType> = {
|
|
|
9
9
|
deserialize: Deserializer<TMIMEType>
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
export function defineConverter<TMIMEType extends MIMEType>(
|
|
13
|
+
converter: Converter<TMIMEType>,
|
|
14
|
+
): Converter<TMIMEType> {
|
|
15
|
+
return converter
|
|
16
|
+
}
|
|
17
|
+
|
|
12
18
|
export type ConverterEvent<TMIMEType extends MIMEType = MIMEType> =
|
|
13
19
|
| {
|
|
14
20
|
type: 'serialize'
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
type Snapshot,
|
|
13
13
|
} from 'xstate'
|
|
14
14
|
import type {Behavior, CustomBehaviorEvent} from '../behaviors/behavior.types'
|
|
15
|
-
import {coreConverters} from '../converters/converters'
|
|
15
|
+
import {coreConverters} from '../converters/converters.core'
|
|
16
16
|
import {compileType} from '../internal-utils/schema'
|
|
17
17
|
import type {PickFromUnion} from '../type-utils'
|
|
18
18
|
import type {EditableAPI} from '../types/editor'
|
|
@@ -65,14 +65,40 @@ export type EditorEvent =
|
|
|
65
65
|
'type',
|
|
66
66
|
| 'annotation.add'
|
|
67
67
|
| 'annotation.remove'
|
|
68
|
+
| 'annotation.toggle'
|
|
69
|
+
| 'block.set'
|
|
70
|
+
| 'block.unset'
|
|
68
71
|
| 'blur'
|
|
72
|
+
| 'data transfer.set'
|
|
73
|
+
| 'decorator.add'
|
|
74
|
+
| 'decorator.remove'
|
|
69
75
|
| 'decorator.toggle'
|
|
76
|
+
| 'delete.block'
|
|
77
|
+
| 'delete.text'
|
|
78
|
+
| 'deserialization.failure'
|
|
79
|
+
| 'deserialization.success'
|
|
70
80
|
| 'focus'
|
|
81
|
+
| 'insert.block'
|
|
71
82
|
| 'insert.block object'
|
|
72
83
|
| 'insert.inline object'
|
|
84
|
+
| 'insert.span'
|
|
85
|
+
| 'insert.text block'
|
|
86
|
+
| 'list item.add'
|
|
87
|
+
| 'list item.remove'
|
|
73
88
|
| 'list item.toggle'
|
|
89
|
+
| 'move.block'
|
|
90
|
+
| 'move.block down'
|
|
91
|
+
| 'move.block up'
|
|
74
92
|
| 'select'
|
|
93
|
+
| 'select.next block'
|
|
94
|
+
| 'select.previous block'
|
|
95
|
+
| 'serialization.failure'
|
|
96
|
+
| 'serialization.success'
|
|
97
|
+
| 'style.add'
|
|
98
|
+
| 'style.remove'
|
|
75
99
|
| 'style.toggle'
|
|
100
|
+
| 'text block.set'
|
|
101
|
+
| 'text block.unset'
|
|
76
102
|
| 'patches'
|
|
77
103
|
| 'update behaviors'
|
|
78
104
|
| 'update key generator'
|
|
@@ -160,12 +186,29 @@ function createEditorFromActor(editorActor: EditorActor): Editor {
|
|
|
160
186
|
send: (event) => {
|
|
161
187
|
editorActor.send(event)
|
|
162
188
|
},
|
|
163
|
-
on: (event, listener) =>
|
|
164
|
-
editorActor.on(
|
|
165
|
-
event
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
189
|
+
on: (event, listener) => {
|
|
190
|
+
const subscription = editorActor.on(event, (event) => {
|
|
191
|
+
switch (event.type) {
|
|
192
|
+
case 'blurred':
|
|
193
|
+
case 'done loading':
|
|
194
|
+
case 'editable':
|
|
195
|
+
case 'error':
|
|
196
|
+
case 'focused':
|
|
197
|
+
case 'invalid value':
|
|
198
|
+
case 'loading':
|
|
199
|
+
case 'mutation':
|
|
200
|
+
case 'patch':
|
|
201
|
+
case 'read only':
|
|
202
|
+
case 'ready':
|
|
203
|
+
case 'selection':
|
|
204
|
+
case 'value changed':
|
|
205
|
+
listener(event)
|
|
206
|
+
break
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
return subscription
|
|
211
|
+
},
|
|
169
212
|
_internal: {
|
|
170
213
|
editable,
|
|
171
214
|
editorActor,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
type NativeBehaviorEvent,
|
|
21
21
|
type SyntheticBehaviorEvent,
|
|
22
22
|
} from '../behaviors/behavior.types'
|
|
23
|
-
import type {Converter} from '../converters/converter'
|
|
23
|
+
import type {Converter} from '../converters/converter.types'
|
|
24
24
|
import type {OmitFromUnion, PickFromUnion} from '../type-utils'
|
|
25
25
|
import type {
|
|
26
26
|
EditorSelection,
|
|
@@ -172,7 +172,6 @@ export type InternalEditorEmittedEvent =
|
|
|
172
172
|
description: string
|
|
173
173
|
data: unknown
|
|
174
174
|
}
|
|
175
|
-
| {type: 'select'; selection: EditorSelection}
|
|
176
175
|
| {type: 'selection'; selection: EditorSelection}
|
|
177
176
|
| {type: 'blurred'; event: FocusEvent<HTMLDivElement, Element>}
|
|
178
177
|
| {type: 'focused'; event: FocusEvent<HTMLDivElement, Element>}
|
|
@@ -185,13 +184,42 @@ export type InternalEditorEmittedEvent =
|
|
|
185
184
|
'type',
|
|
186
185
|
| 'annotation.add'
|
|
187
186
|
| 'annotation.remove'
|
|
187
|
+
| 'annotation.toggle'
|
|
188
|
+
| 'block.set'
|
|
189
|
+
| 'block.unset'
|
|
188
190
|
| 'blur'
|
|
191
|
+
| 'data transfer.set'
|
|
192
|
+
| 'decorator.add'
|
|
193
|
+
| 'decorator.remove'
|
|
189
194
|
| 'decorator.toggle'
|
|
195
|
+
| 'delete.backward'
|
|
196
|
+
| 'delete.block'
|
|
197
|
+
| 'delete.forward'
|
|
198
|
+
| 'delete.text'
|
|
199
|
+
| 'deserialization.failure'
|
|
200
|
+
| 'deserialization.success'
|
|
201
|
+
| 'focus'
|
|
202
|
+
| 'insert.block'
|
|
190
203
|
| 'insert.block object'
|
|
191
204
|
| 'insert.inline object'
|
|
205
|
+
| 'insert.span'
|
|
206
|
+
| 'insert.text block'
|
|
207
|
+
| 'list item.add'
|
|
208
|
+
| 'list item.remove'
|
|
192
209
|
| 'list item.toggle'
|
|
193
|
-
| '
|
|
210
|
+
| 'move.block'
|
|
211
|
+
| 'move.block down'
|
|
212
|
+
| 'move.block up'
|
|
213
|
+
| 'select'
|
|
214
|
+
| 'select.next block'
|
|
215
|
+
| 'select.previous block'
|
|
216
|
+
| 'serialization.failure'
|
|
217
|
+
| 'serialization.success'
|
|
218
|
+
| 'style.add'
|
|
219
|
+
| 'style.remove'
|
|
194
220
|
| 'style.toggle'
|
|
221
|
+
| 'text block.set'
|
|
222
|
+
| 'text block.unset'
|
|
195
223
|
>
|
|
196
224
|
| {
|
|
197
225
|
type: 'custom.*'
|
|
@@ -571,6 +599,9 @@ export const editorMachine = setup({
|
|
|
571
599
|
'annotation.*': {
|
|
572
600
|
actions: emit(({event}) => event),
|
|
573
601
|
},
|
|
602
|
+
'block.*': {
|
|
603
|
+
actions: emit(({event}) => event),
|
|
604
|
+
},
|
|
574
605
|
'blur': {
|
|
575
606
|
actions: emit(({event}) => event),
|
|
576
607
|
},
|
|
@@ -580,6 +611,9 @@ export const editorMachine = setup({
|
|
|
580
611
|
'decorator.*': {
|
|
581
612
|
actions: emit(({event}) => event),
|
|
582
613
|
},
|
|
614
|
+
'delete.*': {
|
|
615
|
+
actions: emit(({event}) => event),
|
|
616
|
+
},
|
|
583
617
|
'focus': {
|
|
584
618
|
actions: emit(({event}) => event),
|
|
585
619
|
},
|
|
@@ -589,12 +623,21 @@ export const editorMachine = setup({
|
|
|
589
623
|
'list item.*': {
|
|
590
624
|
actions: emit(({event}) => event),
|
|
591
625
|
},
|
|
626
|
+
'move.*': {
|
|
627
|
+
actions: emit(({event}) => event),
|
|
628
|
+
},
|
|
592
629
|
'select': {
|
|
593
630
|
actions: emit(({event}) => event),
|
|
594
631
|
},
|
|
632
|
+
'select.*': {
|
|
633
|
+
actions: emit(({event}) => event),
|
|
634
|
+
},
|
|
595
635
|
'style.*': {
|
|
596
636
|
actions: emit(({event}) => event),
|
|
597
637
|
},
|
|
638
|
+
'text block.*': {
|
|
639
|
+
actions: emit(({event}) => event),
|
|
640
|
+
},
|
|
598
641
|
},
|
|
599
642
|
},
|
|
600
643
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type {PortableTextBlock} from '@sanity/types'
|
|
2
|
-
import type {Converter} from '../converters/converter'
|
|
2
|
+
import type {Converter} from '../converters/converter.types'
|
|
3
3
|
import {toPortableTextRange} from '../internal-utils/ranges'
|
|
4
4
|
import {fromSlateValue} from '../internal-utils/values'
|
|
5
5
|
import {KEY_TO_VALUE_ELEMENT} from '../internal-utils/weakMaps'
|
|
@@ -461,11 +461,11 @@ describe('plugin:withPortableTextMarksModel', () => {
|
|
|
461
461
|
style: 'normal',
|
|
462
462
|
},
|
|
463
463
|
{
|
|
464
|
-
_key: '
|
|
464
|
+
_key: '5',
|
|
465
465
|
_type: 'myTestBlockType',
|
|
466
466
|
children: [
|
|
467
467
|
{
|
|
468
|
-
_key: '
|
|
468
|
+
_key: '3',
|
|
469
469
|
_type: 'span',
|
|
470
470
|
marks: [],
|
|
471
471
|
text: '',
|
|
@@ -17,123 +17,58 @@ export function createWithEventListeners(
|
|
|
17
17
|
subscriptions.push(() => {
|
|
18
18
|
const subscription = editorActor.on('*', (event) => {
|
|
19
19
|
switch (event.type) {
|
|
20
|
-
case '
|
|
21
|
-
editorActor.send({
|
|
22
|
-
type: 'behavior event',
|
|
23
|
-
behaviorEvent: {
|
|
24
|
-
type: 'annotation.add',
|
|
25
|
-
annotation: event.annotation,
|
|
26
|
-
},
|
|
27
|
-
editor,
|
|
28
|
-
})
|
|
29
|
-
break
|
|
30
|
-
}
|
|
31
|
-
case 'annotation.remove': {
|
|
32
|
-
editorActor.send({
|
|
33
|
-
type: 'behavior event',
|
|
34
|
-
behaviorEvent: {
|
|
35
|
-
type: 'annotation.remove',
|
|
36
|
-
annotation: event.annotation,
|
|
37
|
-
},
|
|
38
|
-
editor,
|
|
39
|
-
})
|
|
40
|
-
break
|
|
41
|
-
}
|
|
42
|
-
case 'blur': {
|
|
43
|
-
editorActor.send({
|
|
44
|
-
type: 'behavior event',
|
|
45
|
-
behaviorEvent: {
|
|
46
|
-
type: 'blur',
|
|
47
|
-
},
|
|
48
|
-
editor,
|
|
49
|
-
})
|
|
50
|
-
break
|
|
51
|
-
}
|
|
52
|
-
case 'custom.*': {
|
|
20
|
+
case 'custom.*':
|
|
53
21
|
editorActor.send({
|
|
54
22
|
type: 'custom behavior event',
|
|
55
23
|
behaviorEvent: event.event,
|
|
56
24
|
editor,
|
|
57
25
|
})
|
|
58
26
|
break
|
|
59
|
-
|
|
60
|
-
case '
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
case '
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
case 'insert.block
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
case '
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
inlineObject: event.inlineObject,
|
|
99
|
-
},
|
|
100
|
-
editor,
|
|
101
|
-
})
|
|
102
|
-
break
|
|
103
|
-
}
|
|
104
|
-
case 'list item.toggle': {
|
|
105
|
-
editorActor.send({
|
|
106
|
-
type: 'behavior event',
|
|
107
|
-
behaviorEvent: {
|
|
108
|
-
type: 'list item.toggle',
|
|
109
|
-
listItem: event.listItem,
|
|
110
|
-
},
|
|
111
|
-
editor,
|
|
112
|
-
})
|
|
113
|
-
break
|
|
114
|
-
}
|
|
115
|
-
case 'select': {
|
|
116
|
-
editorActor.send({
|
|
117
|
-
type: 'behavior event',
|
|
118
|
-
behaviorEvent: {
|
|
119
|
-
type: 'select',
|
|
120
|
-
selection: event.selection,
|
|
121
|
-
},
|
|
122
|
-
editor,
|
|
123
|
-
})
|
|
124
|
-
break
|
|
125
|
-
}
|
|
126
|
-
case 'style.toggle': {
|
|
27
|
+
|
|
28
|
+
case 'annotation.add':
|
|
29
|
+
case 'annotation.remove':
|
|
30
|
+
case 'annotation.toggle':
|
|
31
|
+
case 'block.set':
|
|
32
|
+
case 'block.unset':
|
|
33
|
+
case 'blur':
|
|
34
|
+
case 'data transfer.set':
|
|
35
|
+
case 'decorator.add':
|
|
36
|
+
case 'decorator.remove':
|
|
37
|
+
case 'decorator.toggle':
|
|
38
|
+
case 'delete.backward':
|
|
39
|
+
case 'delete.block':
|
|
40
|
+
case 'delete.forward':
|
|
41
|
+
case 'delete.text':
|
|
42
|
+
case 'deserialization.failure':
|
|
43
|
+
case 'deserialization.success':
|
|
44
|
+
case 'focus':
|
|
45
|
+
case 'insert.block':
|
|
46
|
+
case 'insert.block object':
|
|
47
|
+
case 'insert.inline object':
|
|
48
|
+
case 'insert.span':
|
|
49
|
+
case 'insert.text block':
|
|
50
|
+
case 'list item.add':
|
|
51
|
+
case 'list item.remove':
|
|
52
|
+
case 'list item.toggle':
|
|
53
|
+
case 'move.block':
|
|
54
|
+
case 'move.block down':
|
|
55
|
+
case 'move.block up':
|
|
56
|
+
case 'select':
|
|
57
|
+
case 'select.next block':
|
|
58
|
+
case 'select.previous block':
|
|
59
|
+
case 'serialization.failure':
|
|
60
|
+
case 'serialization.success':
|
|
61
|
+
case 'style.add':
|
|
62
|
+
case 'style.remove':
|
|
63
|
+
case 'style.toggle':
|
|
64
|
+
case 'text block.set':
|
|
65
|
+
case 'text block.unset':
|
|
127
66
|
editorActor.send({
|
|
128
67
|
type: 'behavior event',
|
|
129
|
-
behaviorEvent:
|
|
130
|
-
type: 'style.toggle',
|
|
131
|
-
style: event.style,
|
|
132
|
-
},
|
|
68
|
+
behaviorEvent: event,
|
|
133
69
|
editor,
|
|
134
70
|
})
|
|
135
71
|
break
|
|
136
|
-
}
|
|
137
72
|
}
|
|
138
73
|
})
|
|
139
74
|
|
package/src/selectors/index.ts
CHANGED
|
@@ -17,6 +17,8 @@ export {isActiveAnnotation} from './selector.is-active-annotation'
|
|
|
17
17
|
export {isActiveDecorator} from './selector.is-active-decorator'
|
|
18
18
|
export {isActiveListItem} from './selector.is-active-list-item'
|
|
19
19
|
export {isActiveStyle} from './selector.is-active-style'
|
|
20
|
+
export {isAtTheEndOfBlock} from './selector.is-at-the-end-of-block'
|
|
21
|
+
export {isAtTheStartOfBlock} from './selector.is-at-the-start-of-block'
|
|
20
22
|
export {isPointAfterSelection} from './selector.is-point-after-selection'
|
|
21
23
|
export {isPointBeforeSelection} from './selector.is-point-before-selection'
|
|
22
24
|
export {isSelectionCollapsed} from './selector.is-selection-collapsed'
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type {KeyedSegment, PortableTextBlock} from '@sanity/types'
|
|
2
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import * as utils from '../utils'
|
|
4
|
+
import {isSelectionCollapsed} from './selector.is-selection-collapsed'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export function isAtTheEndOfBlock(block: {
|
|
10
|
+
node: PortableTextBlock
|
|
11
|
+
path: [KeyedSegment]
|
|
12
|
+
}): EditorSelector<boolean> {
|
|
13
|
+
return ({context}) => {
|
|
14
|
+
if (!context.selection || !isSelectionCollapsed({context})) {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const blockEndPoint = utils.getBlockEndPoint(block)
|
|
19
|
+
|
|
20
|
+
return utils.isEqualSelectionPoints(context.selection.focus, blockEndPoint)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type {KeyedSegment, PortableTextBlock} from '@sanity/types'
|
|
2
|
+
import type {EditorSelector} from '../editor/editor-selector'
|
|
3
|
+
import * as utils from '../utils'
|
|
4
|
+
import {isSelectionCollapsed} from './selector.is-selection-collapsed'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export function isAtTheStartOfBlock(block: {
|
|
10
|
+
node: PortableTextBlock
|
|
11
|
+
path: [KeyedSegment]
|
|
12
|
+
}): EditorSelector<boolean> {
|
|
13
|
+
return ({context}) => {
|
|
14
|
+
if (!context.selection || !isSelectionCollapsed({context})) {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const blockStartPoint = utils.getBlockStartPoint(block)
|
|
19
|
+
|
|
20
|
+
return utils.isEqualSelectionPoints(
|
|
21
|
+
context.selection.focus,
|
|
22
|
+
blockStartPoint,
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -4,9 +4,13 @@ import type {EditorSelector} from '../editor/editor-selector'
|
|
|
4
4
|
* @public
|
|
5
5
|
*/
|
|
6
6
|
export const isSelectionCollapsed: EditorSelector<boolean> = ({context}) => {
|
|
7
|
+
if (!context.selection) {
|
|
8
|
+
return false
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
return (
|
|
8
|
-
JSON.stringify(context.selection
|
|
9
|
-
JSON.stringify(context.selection
|
|
12
|
+
JSON.stringify(context.selection.anchor.path) ===
|
|
13
|
+
JSON.stringify(context.selection.focus.path) &&
|
|
10
14
|
context.selection?.anchor.offset === context.selection?.focus.offset
|
|
11
15
|
)
|
|
12
16
|
}
|
package/src/utils/index.ts
CHANGED
|
@@ -4,9 +4,11 @@ export {
|
|
|
4
4
|
blockOffsetToSpanSelectionPoint,
|
|
5
5
|
spanSelectionPointToBlockOffset,
|
|
6
6
|
} from './util.block-offset'
|
|
7
|
+
export {getBlockEndPoint} from './util.get-block-end-point'
|
|
7
8
|
export {getBlockStartPoint} from './util.get-block-start-point'
|
|
8
9
|
export {getTextBlockText} from './util.get-text-block-text'
|
|
9
10
|
export {isEmptyTextBlock} from './util.is-empty-text-block'
|
|
11
|
+
export {isEqualSelectionPoints} from './util.is-equal-selection-points'
|
|
10
12
|
export {isKeyedSegment} from './util.is-keyed-segment'
|
|
11
13
|
export {reverseSelection} from './util.reverse-selection'
|
|
12
14
|
export {sliceBlocks} from './util.slice-blocks'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isPortableTextSpan,
|
|
3
|
+
isPortableTextTextBlock,
|
|
4
|
+
type KeyedSegment,
|
|
5
|
+
type PortableTextBlock,
|
|
6
|
+
} from '@sanity/types'
|
|
7
|
+
import type {EditorSelectionPoint} from '../types/editor'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export function getBlockEndPoint({
|
|
13
|
+
node,
|
|
14
|
+
path,
|
|
15
|
+
}: {
|
|
16
|
+
node: PortableTextBlock
|
|
17
|
+
path: [KeyedSegment]
|
|
18
|
+
}): EditorSelectionPoint {
|
|
19
|
+
if (isPortableTextTextBlock(node)) {
|
|
20
|
+
const lastChild = node.children[node.children.length - 1]
|
|
21
|
+
|
|
22
|
+
if (lastChild) {
|
|
23
|
+
return {
|
|
24
|
+
path: [...path, 'children', {_key: lastChild._key}],
|
|
25
|
+
offset: isPortableTextSpan(lastChild) ? lastChild.text.length : 0,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
path,
|
|
32
|
+
offset: 0,
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type {EditorSelectionPoint} from '../types/editor'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export function isEqualSelectionPoints(
|
|
7
|
+
a: EditorSelectionPoint,
|
|
8
|
+
b: EditorSelectionPoint,
|
|
9
|
+
) {
|
|
10
|
+
return (
|
|
11
|
+
a.offset === b.offset && JSON.stringify(a.path) === JSON.stringify(b.path)
|
|
12
|
+
)
|
|
13
|
+
}
|