@portabletext/editor 1.33.2 → 1.33.4
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 +11 -204
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/behavior.markdown.cjs +7 -7
- package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -1
- package/lib/_chunks-cjs/plugin.event-listener.cjs +208 -33
- package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.get-text-before.cjs +3 -3
- package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-active-style.cjs +246 -0
- package/lib/_chunks-cjs/selector.is-active-style.cjs.map +1 -0
- package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +31 -200
- package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -1
- package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs +7 -5
- package/lib/_chunks-cjs/util.block-offsets-to-selection.cjs.map +1 -1
- package/lib/_chunks-cjs/util.reverse-selection.cjs +0 -116
- package/lib/_chunks-cjs/util.reverse-selection.cjs.map +1 -1
- package/lib/_chunks-cjs/util.slice-blocks.cjs +138 -1
- package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js +9 -202
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/behavior.markdown.js +1 -1
- package/lib/_chunks-es/plugin.event-listener.js +205 -31
- package/lib/_chunks-es/plugin.event-listener.js.map +1 -1
- package/lib/_chunks-es/selector.get-text-before.js +2 -1
- package/lib/_chunks-es/selector.get-text-before.js.map +1 -1
- package/lib/_chunks-es/selector.is-active-style.js +249 -0
- package/lib/_chunks-es/selector.is-active-style.js.map +1 -0
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js +20 -189
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
- package/lib/_chunks-es/util.block-offsets-to-selection.js +5 -3
- package/lib/_chunks-es/util.block-offsets-to-selection.js.map +1 -1
- package/lib/_chunks-es/util.reverse-selection.js +1 -117
- package/lib/_chunks-es/util.reverse-selection.js.map +1 -1
- package/lib/_chunks-es/util.slice-blocks.js +140 -3
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/index.d.cts +1 -115
- package/lib/index.d.ts +1 -115
- package/lib/plugins/index.cjs +19 -15
- package/lib/plugins/index.cjs.map +1 -1
- package/lib/plugins/index.d.cts +1 -115
- package/lib/plugins/index.d.ts +1 -115
- package/lib/plugins/index.js +9 -5
- package/lib/plugins/index.js.map +1 -1
- package/lib/selectors/index.cjs +16 -21
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.d.cts +2 -0
- package/lib/selectors/index.d.ts +2 -0
- package/lib/selectors/index.js +7 -11
- package/lib/selectors/index.js.map +1 -1
- package/lib/utils/index.cjs +13 -13
- package/lib/utils/index.cjs.map +1 -1
- package/lib/utils/index.d.cts +2 -0
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +3 -3
- package/package.json +2 -2
- package/src/behaviors/behavior.core.annotations.ts +0 -24
- package/src/behaviors/behavior.core.decorators.ts +0 -19
- package/src/behaviors/behavior.core.insert-break.ts +4 -4
- package/src/behaviors/behavior.core.lists.ts +0 -30
- package/src/behaviors/behavior.core.ts +2 -17
- package/src/behaviors/behavior.default.ts +198 -0
- package/src/behaviors/behavior.foundational.ts +12 -12
- package/src/behaviors/behavior.markdown-emphasis.ts +4 -0
- package/src/converters/converter.text-html.serialize.test.ts +1 -1
- package/src/editor/PortableTextEditor.tsx +1 -1
- package/src/editor/editor-machine.ts +8 -8
- package/src/plugins/plugin.event-listener.tsx +1 -1
- package/src/selectors/selector.get-caret-word-selection.ts +9 -0
- package/src/selectors/selector.get-selection-text.test.ts +383 -36
- package/src/selectors/selector.get-selection-text.ts +13 -73
- package/src/utils/util.block-offset.test.ts +312 -0
- package/src/utils/util.block-offset.ts +39 -7
- package/src/utils/util.block-offsets-to-selection.ts +2 -0
- package/src/utils/util.slice-blocks.ts +12 -1
- package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs +0 -97
- package/lib/_chunks-cjs/selector.get-trimmed-selection.cjs.map +0 -1
- package/lib/_chunks-es/selector.get-trimmed-selection.js +0 -100
- package/lib/_chunks-es/selector.get-trimmed-selection.js.map +0 -1
- package/src/behaviors/behavior.core.deserialize.ts +0 -60
- package/src/behaviors/behavior.core.serialize.ts +0 -44
- package/src/behaviors/behavior.core.style.ts +0 -19
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import * as selectors from '../selectors'
|
|
2
|
+
import {defineBehavior, raise} from './behavior.types'
|
|
3
|
+
|
|
4
|
+
const toggleAnnotationOff = defineBehavior({
|
|
5
|
+
on: 'annotation.toggle',
|
|
6
|
+
guard: ({context, event}) =>
|
|
7
|
+
selectors.isActiveAnnotation(event.annotation.name)({context}),
|
|
8
|
+
actions: [
|
|
9
|
+
({event}) => [
|
|
10
|
+
raise({type: 'annotation.remove', annotation: event.annotation}),
|
|
11
|
+
],
|
|
12
|
+
],
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const toggleAnnotationOn = defineBehavior({
|
|
16
|
+
on: 'annotation.toggle',
|
|
17
|
+
guard: ({context, event}) =>
|
|
18
|
+
!selectors.isActiveAnnotation(event.annotation.name)({context}),
|
|
19
|
+
actions: [
|
|
20
|
+
({event}) => [
|
|
21
|
+
raise({type: 'annotation.add', annotation: event.annotation}),
|
|
22
|
+
],
|
|
23
|
+
],
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const toggleDecoratorOff = defineBehavior({
|
|
27
|
+
on: 'decorator.toggle',
|
|
28
|
+
guard: ({context, event}) =>
|
|
29
|
+
selectors.isActiveDecorator(event.decorator)({context}),
|
|
30
|
+
actions: [
|
|
31
|
+
({event}) => [
|
|
32
|
+
raise({type: 'decorator.remove', decorator: event.decorator}),
|
|
33
|
+
],
|
|
34
|
+
],
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const toggleDecoratorOn = defineBehavior({
|
|
38
|
+
on: 'decorator.toggle',
|
|
39
|
+
guard: ({context, event}) =>
|
|
40
|
+
!selectors.isActiveDecorator(event.decorator)({context}),
|
|
41
|
+
actions: [
|
|
42
|
+
({event}) => [raise({type: 'decorator.add', decorator: event.decorator})],
|
|
43
|
+
],
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const toggleListItemOff = defineBehavior({
|
|
47
|
+
on: 'list item.toggle',
|
|
48
|
+
guard: ({context, event}) =>
|
|
49
|
+
selectors.isActiveListItem(event.listItem)({context}),
|
|
50
|
+
actions: [
|
|
51
|
+
({event}) => [
|
|
52
|
+
raise({
|
|
53
|
+
type: 'list item.remove',
|
|
54
|
+
listItem: event.listItem,
|
|
55
|
+
}),
|
|
56
|
+
],
|
|
57
|
+
],
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const toggleListItemOn = defineBehavior({
|
|
61
|
+
on: 'list item.toggle',
|
|
62
|
+
guard: ({context, event}) =>
|
|
63
|
+
!selectors.isActiveListItem(event.listItem)({context}),
|
|
64
|
+
actions: [
|
|
65
|
+
({event}) => [
|
|
66
|
+
raise({
|
|
67
|
+
type: 'list item.add',
|
|
68
|
+
listItem: event.listItem,
|
|
69
|
+
}),
|
|
70
|
+
],
|
|
71
|
+
],
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const toggleStyleOff = defineBehavior({
|
|
75
|
+
on: 'style.toggle',
|
|
76
|
+
guard: ({context, event}) => selectors.isActiveStyle(event.style)({context}),
|
|
77
|
+
actions: [({event}) => [raise({type: 'style.remove', style: event.style})]],
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const toggleStyleOn = defineBehavior({
|
|
81
|
+
on: 'style.toggle',
|
|
82
|
+
guard: ({context, event}) => !selectors.isActiveStyle(event.style)({context}),
|
|
83
|
+
actions: [({event}) => [raise({type: 'style.add', style: event.style})]],
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const raiseDeserializationSuccessOrFailure = defineBehavior({
|
|
87
|
+
on: 'deserialize',
|
|
88
|
+
guard: ({context, event}) => {
|
|
89
|
+
const deserializeEvents = context.converters.flatMap((converter) => {
|
|
90
|
+
const data = event.dataTransfer.getData(converter.mimeType)
|
|
91
|
+
|
|
92
|
+
if (!data) {
|
|
93
|
+
return []
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return [
|
|
97
|
+
converter.deserialize({context, event: {type: 'deserialize', data}}),
|
|
98
|
+
]
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
const firstSuccess = deserializeEvents.find(
|
|
102
|
+
(deserializeEvent) => deserializeEvent.type === 'deserialization.success',
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
if (!firstSuccess) {
|
|
106
|
+
return {
|
|
107
|
+
type: 'deserialization.failure',
|
|
108
|
+
mimeType: '*/*',
|
|
109
|
+
reason: deserializeEvents
|
|
110
|
+
.map((deserializeEvent) =>
|
|
111
|
+
deserializeEvent.type === 'deserialization.failure'
|
|
112
|
+
? deserializeEvent.reason
|
|
113
|
+
: '',
|
|
114
|
+
)
|
|
115
|
+
.join(', '),
|
|
116
|
+
} as const
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return firstSuccess
|
|
120
|
+
},
|
|
121
|
+
actions: [
|
|
122
|
+
({event}, deserializeEvent) => [
|
|
123
|
+
raise({
|
|
124
|
+
...deserializeEvent,
|
|
125
|
+
dataTransfer: event.dataTransfer,
|
|
126
|
+
}),
|
|
127
|
+
],
|
|
128
|
+
],
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
const raiseInsertBlocks = defineBehavior({
|
|
132
|
+
on: 'deserialization.success',
|
|
133
|
+
actions: [
|
|
134
|
+
({event}) => [
|
|
135
|
+
raise({
|
|
136
|
+
type: 'insert.blocks',
|
|
137
|
+
blocks: event.data,
|
|
138
|
+
}),
|
|
139
|
+
],
|
|
140
|
+
],
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const raiseSerializationSuccessOrFailure = defineBehavior({
|
|
144
|
+
on: 'serialize',
|
|
145
|
+
guard: ({context, event}) => {
|
|
146
|
+
if (context.converters.length === 0) {
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const serializeEvents = context.converters.map((converter) =>
|
|
151
|
+
converter.serialize({context, event}),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if (serializeEvents.length === 0) {
|
|
155
|
+
return false
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return serializeEvents
|
|
159
|
+
},
|
|
160
|
+
actions: [
|
|
161
|
+
({event}, serializeEvents) =>
|
|
162
|
+
serializeEvents.map((serializeEvent) =>
|
|
163
|
+
raise({
|
|
164
|
+
...serializeEvent,
|
|
165
|
+
dataTransfer: event.dataTransfer,
|
|
166
|
+
}),
|
|
167
|
+
),
|
|
168
|
+
],
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
const raiseDataTransferSet = defineBehavior({
|
|
172
|
+
on: 'serialization.success',
|
|
173
|
+
actions: [
|
|
174
|
+
({event}) => [
|
|
175
|
+
raise({
|
|
176
|
+
type: 'data transfer.set',
|
|
177
|
+
data: event.data,
|
|
178
|
+
dataTransfer: event.dataTransfer,
|
|
179
|
+
mimeType: event.mimeType,
|
|
180
|
+
}),
|
|
181
|
+
],
|
|
182
|
+
],
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
export const defaultBehaviors = [
|
|
186
|
+
toggleAnnotationOff,
|
|
187
|
+
toggleAnnotationOn,
|
|
188
|
+
toggleDecoratorOff,
|
|
189
|
+
toggleDecoratorOn,
|
|
190
|
+
toggleListItemOff,
|
|
191
|
+
toggleListItemOn,
|
|
192
|
+
toggleStyleOff,
|
|
193
|
+
toggleStyleOn,
|
|
194
|
+
raiseDeserializationSuccessOrFailure,
|
|
195
|
+
raiseInsertBlocks,
|
|
196
|
+
raiseSerializationSuccessOrFailure,
|
|
197
|
+
raiseDataTransferSet,
|
|
198
|
+
]
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {keyIs} from '../internal-utils/key-is'
|
|
2
2
|
import {defineBehavior, raise} from './behavior.types'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
]
|
|
4
|
+
/**
|
|
5
|
+
* On WebKit, Shift+Enter results in an `insertParagraph` input event rather
|
|
6
|
+
* than an `insertLineBreak` input event. This Behavior makes sure we catch
|
|
7
|
+
* that `key.down` event beforehand and raise an `insert.soft break` manually.
|
|
8
|
+
*/
|
|
9
|
+
const raiseSoftBreak = defineBehavior({
|
|
10
|
+
on: 'key.down',
|
|
11
|
+
guard: ({event}) => keyIs.lineBreak(event.keyboardEvent),
|
|
12
|
+
actions: [() => [raise({type: 'insert.soft break'})]],
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export const foundationalBehaviors = [raiseSoftBreak]
|
|
@@ -125,10 +125,12 @@ const emphasisListener: CallbackLogicFunction<
|
|
|
125
125
|
const anchor = utils.blockOffsetToSpanSelectionPoint({
|
|
126
126
|
value: context.value,
|
|
127
127
|
blockOffset: prefixOffsets.focus,
|
|
128
|
+
direction: 'backward',
|
|
128
129
|
})
|
|
129
130
|
const focus = utils.blockOffsetToSpanSelectionPoint({
|
|
130
131
|
value: context.value,
|
|
131
132
|
blockOffset: suffixOffsets.anchor,
|
|
133
|
+
direction: 'forward',
|
|
132
134
|
})
|
|
133
135
|
|
|
134
136
|
if (!anchor || !focus) {
|
|
@@ -169,10 +171,12 @@ const emphasisListener: CallbackLogicFunction<
|
|
|
169
171
|
const anchor = utils.blockOffsetToSpanSelectionPoint({
|
|
170
172
|
value: context.value,
|
|
171
173
|
blockOffset: prefixOffsets.focus,
|
|
174
|
+
direction: 'backward',
|
|
172
175
|
})
|
|
173
176
|
const focus = utils.blockOffsetToSpanSelectionPoint({
|
|
174
177
|
value: context.value,
|
|
175
178
|
blockOffset: suffixOffsets.anchor,
|
|
179
|
+
direction: 'forward',
|
|
176
180
|
})
|
|
177
181
|
|
|
178
182
|
if (!anchor || !focus) {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from 'xstate'
|
|
12
12
|
import {performAction} from '../behavior-actions/behavior.actions'
|
|
13
13
|
import {coreBehaviors} from '../behaviors/behavior.core'
|
|
14
|
+
import {defaultBehaviors} from '../behaviors/behavior.default'
|
|
14
15
|
import {foundationalBehaviors} from '../behaviors/behavior.foundational'
|
|
15
16
|
import {
|
|
16
17
|
isCustomBehaviorEvent,
|
|
@@ -255,7 +256,7 @@ export const editorMachine = setup({
|
|
|
255
256
|
'assign behaviors': assign({
|
|
256
257
|
behaviors: ({event}) => {
|
|
257
258
|
assertEvent(event, 'update behaviors')
|
|
258
|
-
return new Set([...
|
|
259
|
+
return new Set([...event.behaviors])
|
|
259
260
|
},
|
|
260
261
|
}),
|
|
261
262
|
'assign schema': assign({
|
|
@@ -310,9 +311,11 @@ export const editorMachine = setup({
|
|
|
310
311
|
? event.defaultActionCallback
|
|
311
312
|
: undefined
|
|
312
313
|
|
|
313
|
-
const eventBehaviors = [
|
|
314
|
-
|
|
315
|
-
|
|
314
|
+
const eventBehaviors = [
|
|
315
|
+
...foundationalBehaviors,
|
|
316
|
+
...context.behaviors.values(),
|
|
317
|
+
...defaultBehaviors,
|
|
318
|
+
].filter((behavior) => behavior.on === event.behaviorEvent.type)
|
|
316
319
|
|
|
317
320
|
if (eventBehaviors.length === 0) {
|
|
318
321
|
if (defaultActionCallback) {
|
|
@@ -474,10 +477,7 @@ export const editorMachine = setup({
|
|
|
474
477
|
}).createMachine({
|
|
475
478
|
id: 'editor',
|
|
476
479
|
context: ({input}) => ({
|
|
477
|
-
behaviors: new Set([
|
|
478
|
-
...foundationalBehaviors,
|
|
479
|
-
...(input.behaviors ?? coreBehaviors),
|
|
480
|
-
]),
|
|
480
|
+
behaviors: new Set([...(input.behaviors ?? coreBehaviors)]),
|
|
481
481
|
converters: new Set(input.converters ?? []),
|
|
482
482
|
keyGenerator: input.keyGenerator,
|
|
483
483
|
pendingEvents: [],
|
|
@@ -74,6 +74,13 @@ export const getCaretWordSelection: EditorSelector<EditorSelection> = ({
|
|
|
74
74
|
})
|
|
75
75
|
const textDirectlyAfter = textAfter.split(/\s+/).at(0)
|
|
76
76
|
|
|
77
|
+
if (
|
|
78
|
+
(textDirectlyBefore === undefined || textDirectlyBefore === '') &&
|
|
79
|
+
(textDirectlyAfter === undefined || textDirectlyAfter === '')
|
|
80
|
+
) {
|
|
81
|
+
return null
|
|
82
|
+
}
|
|
83
|
+
|
|
77
84
|
const caretWordStartOffset: BlockOffset = textDirectlyBefore
|
|
78
85
|
? {
|
|
79
86
|
...selectionStartOffset,
|
|
@@ -90,10 +97,12 @@ export const getCaretWordSelection: EditorSelector<EditorSelection> = ({
|
|
|
90
97
|
const caretWordStartSelectionPoint = blockOffsetToSpanSelectionPoint({
|
|
91
98
|
value: context.value,
|
|
92
99
|
blockOffset: caretWordStartOffset,
|
|
100
|
+
direction: 'backward',
|
|
93
101
|
})
|
|
94
102
|
const caretWordEndSelectionPoint = blockOffsetToSpanSelectionPoint({
|
|
95
103
|
value: context.value,
|
|
96
104
|
blockOffset: caretWordEndOffset,
|
|
105
|
+
direction: 'forward',
|
|
97
106
|
})
|
|
98
107
|
|
|
99
108
|
if (!caretWordStartSelectionPoint || !caretWordEndSelectionPoint) {
|