@portabletext/editor 1.12.3 → 1.14.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/README.md +1 -1
- package/lib/_chunks-cjs/selector.get-text-before.cjs +320 -0
- package/lib/_chunks-cjs/selector.get-text-before.cjs.map +1 -0
- package/lib/_chunks-es/selector.get-text-before.js +321 -0
- package/lib/_chunks-es/selector.get-text-before.js.map +1 -0
- package/lib/{index.esm.js → index.cjs} +1954 -1513
- package/lib/index.cjs.map +1 -0
- package/lib/{index.d.mts → index.d.cts} +4249 -304
- package/lib/index.d.ts +4249 -304
- package/lib/index.js +1974 -1488
- package/lib/index.js.map +1 -1
- package/lib/selectors/index.cjs +35 -0
- package/lib/selectors/index.cjs.map +1 -0
- package/lib/selectors/index.d.cts +243 -0
- package/lib/selectors/index.d.ts +243 -0
- package/lib/selectors/index.js +36 -0
- package/lib/selectors/index.js.map +1 -0
- package/package.json +25 -17
- package/src/editor/Editable.tsx +61 -6
- package/src/editor/PortableTextEditor.tsx +19 -4
- package/src/editor/__tests__/handleClick.test.tsx +4 -4
- package/src/editor/behavior/behavior.action.insert-block-object.ts +1 -1
- package/src/editor/behavior/behavior.action.insert-break.ts +24 -27
- package/src/editor/behavior/behavior.action.insert-inline-object.ts +58 -0
- package/src/editor/behavior/behavior.action.insert-span.ts +1 -1
- package/src/editor/behavior/behavior.action.list-item.ts +100 -0
- package/src/editor/behavior/behavior.action.style.ts +108 -0
- package/src/editor/behavior/behavior.action.text-block.set.ts +25 -0
- package/src/editor/behavior/behavior.action.text-block.unset.ts +17 -0
- package/src/editor/behavior/behavior.actions.ts +266 -75
- package/src/editor/behavior/behavior.code-editor.ts +76 -0
- package/src/editor/behavior/behavior.core.block-objects.ts +52 -19
- package/src/editor/behavior/behavior.core.decorators.ts +9 -6
- package/src/editor/behavior/behavior.core.lists.ts +139 -17
- package/src/editor/behavior/behavior.core.ts +7 -2
- package/src/editor/behavior/behavior.guards.ts +28 -0
- package/src/editor/behavior/behavior.links.ts +9 -9
- package/src/editor/behavior/behavior.markdown.ts +69 -80
- package/src/editor/behavior/behavior.types.ts +121 -60
- package/src/editor/{use-editor.ts → create-editor.ts} +13 -8
- package/src/editor/editor-event-listener.tsx +2 -2
- package/src/editor/editor-machine.ts +57 -15
- package/src/editor/editor-provider.tsx +5 -5
- package/src/editor/editor-selector.ts +49 -0
- package/src/editor/editor-snapshot.ts +22 -0
- package/src/editor/get-value.ts +11 -0
- package/src/editor/plugins/create-with-event-listeners.ts +93 -5
- package/src/editor/plugins/createWithEditableAPI.ts +69 -20
- package/src/editor/plugins/createWithHotKeys.ts +0 -101
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +1 -55
- package/src/editor/plugins/with-plugins.ts +4 -8
- package/src/editor/{behavior/behavior.utils.block-offset.test.ts → utils/utils.block-offset.test.ts} +1 -1
- package/src/editor/{behavior/behavior.utils.block-offset.ts → utils/utils.block-offset.ts} +1 -8
- package/src/editor/{behavior/behavior.utils.reverse-selection.ts → utils/utils.reverse-selection.ts} +3 -5
- package/src/editor/utils/utils.ts +21 -0
- package/src/index.ts +13 -9
- package/src/selectors/index.ts +15 -0
- package/src/selectors/selector.get-active-list-item.ts +37 -0
- package/src/{editor/behavior/behavior.utils.get-selection-text.ts → selectors/selector.get-selection-text.ts} +10 -15
- package/src/selectors/selector.get-text-before.ts +41 -0
- package/src/selectors/selectors.ts +329 -0
- package/src/types/editor.ts +0 -60
- package/src/utils/is-hotkey.test.ts +99 -46
- package/src/utils/is-hotkey.ts +1 -1
- package/src/utils/operationToPatches.ts +5 -0
- package/src/utils/paths.ts +4 -11
- package/src/utils/ranges.ts +3 -3
- package/lib/index.esm.js.map +0 -1
- package/lib/index.mjs +0 -7372
- package/lib/index.mjs.map +0 -1
- package/src/editor/behavior/behavior.utils.ts +0 -218
- package/src/editor/behavior/behavior.utilts.get-text-before.ts +0 -31
- package/src/editor/plugins/createWithPortableTextLists.ts +0 -172
- /package/src/editor/{behavior/behavior.utils.get-start-point.ts → utils/utils.get-start-point.ts} +0 -0
- /package/src/editor/{behavior/behavior.utils.is-keyed-segment.ts → utils/utils.is-keyed-segment.ts} +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {isPortableTextTextBlock} from '@sanity/types'
|
|
2
|
-
import
|
|
3
|
-
import {defineBehavior} from './behavior.types'
|
|
2
|
+
import {getBlockTextBefore} from '../../selectors/selector.get-text-before'
|
|
4
3
|
import {
|
|
5
4
|
getFocusBlock,
|
|
6
5
|
getFocusSpan,
|
|
7
6
|
getFocusTextBlock,
|
|
8
|
-
getTextBlockText,
|
|
9
7
|
selectionIsCollapsed,
|
|
10
|
-
} from '
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
8
|
+
} from '../../selectors/selectors'
|
|
9
|
+
import type {PortableTextMemberSchemaTypes} from '../../types/editor'
|
|
10
|
+
import {getTextBlockText} from '../utils/utils'
|
|
11
|
+
import {spanSelectionPointToBlockOffset} from '../utils/utils.block-offset'
|
|
12
|
+
import {defineBehavior} from './behavior.types'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @alpha
|
|
@@ -41,7 +41,7 @@ export type MarkdownBehaviorsConfig = {
|
|
|
41
41
|
*/
|
|
42
42
|
export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
43
43
|
const automaticBlockquoteOnSpace = defineBehavior({
|
|
44
|
-
on: 'insert
|
|
44
|
+
on: 'insert.text',
|
|
45
45
|
guard: ({context, event}) => {
|
|
46
46
|
const isSpace = event.text === ' '
|
|
47
47
|
|
|
@@ -49,9 +49,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
49
49
|
return false
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const selectionCollapsed = selectionIsCollapsed(context)
|
|
53
|
-
const focusTextBlock = getFocusTextBlock(context)
|
|
54
|
-
const focusSpan = getFocusSpan(context)
|
|
52
|
+
const selectionCollapsed = selectionIsCollapsed({context})
|
|
53
|
+
const focusTextBlock = getFocusTextBlock({context})
|
|
54
|
+
const focusSpan = getFocusSpan({context})
|
|
55
55
|
|
|
56
56
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
|
|
57
57
|
return false
|
|
@@ -76,7 +76,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
76
76
|
const blockText = getTextBlockText(focusTextBlock.node)
|
|
77
77
|
const caretAtTheEndOfQuote = blockOffset.offset === 1
|
|
78
78
|
const looksLikeMarkdownQuote = /^>/.test(blockText)
|
|
79
|
-
const blockquoteStyle = config.blockquoteStyle?.(
|
|
79
|
+
const blockquoteStyle = config.blockquoteStyle?.(context)
|
|
80
80
|
|
|
81
81
|
if (
|
|
82
82
|
caretAtTheEndOfQuote &&
|
|
@@ -91,23 +91,23 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
91
91
|
actions: [
|
|
92
92
|
() => [
|
|
93
93
|
{
|
|
94
|
-
type: 'insert
|
|
94
|
+
type: 'insert.text',
|
|
95
95
|
text: ' ',
|
|
96
96
|
},
|
|
97
97
|
],
|
|
98
|
-
(
|
|
98
|
+
({focusTextBlock, style}) => [
|
|
99
99
|
{
|
|
100
|
-
type: '
|
|
100
|
+
type: 'text block.unset',
|
|
101
101
|
props: ['listItem', 'level'],
|
|
102
|
-
|
|
102
|
+
at: focusTextBlock.path,
|
|
103
103
|
},
|
|
104
104
|
{
|
|
105
|
-
type: '
|
|
105
|
+
type: 'text block.set',
|
|
106
106
|
style,
|
|
107
|
-
|
|
107
|
+
at: focusTextBlock.path,
|
|
108
108
|
},
|
|
109
109
|
{
|
|
110
|
-
type: 'delete
|
|
110
|
+
type: 'delete.text',
|
|
111
111
|
anchor: {
|
|
112
112
|
path: focusTextBlock.path,
|
|
113
113
|
offset: 0,
|
|
@@ -121,7 +121,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
121
121
|
],
|
|
122
122
|
})
|
|
123
123
|
const automaticHr = defineBehavior({
|
|
124
|
-
on: 'insert
|
|
124
|
+
on: 'insert.text',
|
|
125
125
|
guard: ({context, event}) => {
|
|
126
126
|
const hrCharacter =
|
|
127
127
|
event.text === '-'
|
|
@@ -136,20 +136,15 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
136
136
|
return false
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
const hrObject = config.horizontalRuleObject?.(
|
|
140
|
-
|
|
141
|
-
})
|
|
142
|
-
const focusBlock = getFocusTextBlock(context)
|
|
143
|
-
const selectionCollapsed = selectionIsCollapsed(context)
|
|
139
|
+
const hrObject = config.horizontalRuleObject?.(context)
|
|
140
|
+
const focusBlock = getFocusTextBlock({context})
|
|
141
|
+
const selectionCollapsed = selectionIsCollapsed({context})
|
|
144
142
|
|
|
145
143
|
if (!hrObject || !focusBlock || !selectionCollapsed) {
|
|
146
144
|
return false
|
|
147
145
|
}
|
|
148
146
|
|
|
149
|
-
const textBefore = getBlockTextBefore({
|
|
150
|
-
value: context.value,
|
|
151
|
-
point: context.selection.focus,
|
|
152
|
-
})
|
|
147
|
+
const textBefore = getBlockTextBefore({context})
|
|
153
148
|
const hrBlockOffsets = {
|
|
154
149
|
anchor: {
|
|
155
150
|
path: focusBlock.path,
|
|
@@ -168,20 +163,20 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
168
163
|
return false
|
|
169
164
|
},
|
|
170
165
|
actions: [
|
|
171
|
-
(
|
|
166
|
+
({hrCharacter}) => [
|
|
172
167
|
{
|
|
173
|
-
type: 'insert
|
|
168
|
+
type: 'insert.text',
|
|
174
169
|
text: hrCharacter,
|
|
175
170
|
},
|
|
176
171
|
],
|
|
177
|
-
(
|
|
172
|
+
({hrObject, hrBlockOffsets}) => [
|
|
178
173
|
{
|
|
179
|
-
type: 'insert
|
|
174
|
+
type: 'insert.block object',
|
|
180
175
|
placement: 'before',
|
|
181
176
|
blockObject: hrObject,
|
|
182
177
|
},
|
|
183
178
|
{
|
|
184
|
-
type: 'delete
|
|
179
|
+
type: 'delete.text',
|
|
185
180
|
...hrBlockOffsets,
|
|
186
181
|
},
|
|
187
182
|
],
|
|
@@ -190,13 +185,11 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
190
185
|
const automaticHrOnPaste = defineBehavior({
|
|
191
186
|
on: 'paste',
|
|
192
187
|
guard: ({context, event}) => {
|
|
193
|
-
const text = event.
|
|
188
|
+
const text = event.data.getData('text/plain')
|
|
194
189
|
const hrRegExp = /^(---)$|(___)$|(\*\*\*)$/gm
|
|
195
190
|
const hrCharacters = text.match(hrRegExp)?.[0]
|
|
196
|
-
const hrObject = config.horizontalRuleObject?.(
|
|
197
|
-
|
|
198
|
-
})
|
|
199
|
-
const focusBlock = getFocusBlock(context)
|
|
191
|
+
const hrObject = config.horizontalRuleObject?.(context)
|
|
192
|
+
const focusBlock = getFocusBlock({context})
|
|
200
193
|
|
|
201
194
|
if (!hrCharacters || !hrObject || !focusBlock) {
|
|
202
195
|
return false
|
|
@@ -205,30 +198,30 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
205
198
|
return {hrCharacters, hrObject, focusBlock}
|
|
206
199
|
},
|
|
207
200
|
actions: [
|
|
208
|
-
(
|
|
201
|
+
({hrCharacters}) => [
|
|
209
202
|
{
|
|
210
|
-
type: 'insert
|
|
203
|
+
type: 'insert.text',
|
|
211
204
|
text: hrCharacters,
|
|
212
205
|
},
|
|
213
206
|
],
|
|
214
|
-
(
|
|
207
|
+
({hrObject, focusBlock}) =>
|
|
215
208
|
isPortableTextTextBlock(focusBlock.node)
|
|
216
209
|
? [
|
|
217
210
|
{
|
|
218
|
-
type: 'insert
|
|
211
|
+
type: 'insert.text block',
|
|
219
212
|
textBlock: {children: focusBlock.node.children},
|
|
220
213
|
placement: 'after',
|
|
221
214
|
},
|
|
222
215
|
{
|
|
223
|
-
type: 'insert
|
|
216
|
+
type: 'insert.block object',
|
|
224
217
|
blockObject: hrObject,
|
|
225
218
|
placement: 'after',
|
|
226
219
|
},
|
|
227
|
-
{type: 'delete
|
|
220
|
+
{type: 'delete.block', blockPath: focusBlock.path},
|
|
228
221
|
]
|
|
229
222
|
: [
|
|
230
223
|
{
|
|
231
|
-
type: 'insert
|
|
224
|
+
type: 'insert.block object',
|
|
232
225
|
blockObject: hrObject,
|
|
233
226
|
placement: 'after',
|
|
234
227
|
},
|
|
@@ -236,7 +229,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
236
229
|
],
|
|
237
230
|
})
|
|
238
231
|
const automaticHeadingOnSpace = defineBehavior({
|
|
239
|
-
on: 'insert
|
|
232
|
+
on: 'insert.text',
|
|
240
233
|
guard: ({context, event}) => {
|
|
241
234
|
const isSpace = event.text === ' '
|
|
242
235
|
|
|
@@ -244,9 +237,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
244
237
|
return false
|
|
245
238
|
}
|
|
246
239
|
|
|
247
|
-
const selectionCollapsed = selectionIsCollapsed(context)
|
|
248
|
-
const focusTextBlock = getFocusTextBlock(context)
|
|
249
|
-
const focusSpan = getFocusSpan(context)
|
|
240
|
+
const selectionCollapsed = selectionIsCollapsed({context})
|
|
241
|
+
const focusTextBlock = getFocusTextBlock({context})
|
|
242
|
+
const focusSpan = getFocusSpan({context})
|
|
250
243
|
|
|
251
244
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
|
|
252
245
|
return false
|
|
@@ -297,23 +290,23 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
297
290
|
actions: [
|
|
298
291
|
() => [
|
|
299
292
|
{
|
|
300
|
-
type: 'insert
|
|
293
|
+
type: 'insert.text',
|
|
301
294
|
text: ' ',
|
|
302
295
|
},
|
|
303
296
|
],
|
|
304
|
-
(
|
|
297
|
+
({focusTextBlock, style, level}) => [
|
|
305
298
|
{
|
|
306
|
-
type: '
|
|
299
|
+
type: 'text block.unset',
|
|
307
300
|
props: ['listItem', 'level'],
|
|
308
|
-
|
|
301
|
+
at: focusTextBlock.path,
|
|
309
302
|
},
|
|
310
303
|
{
|
|
311
|
-
type: '
|
|
304
|
+
type: 'text block.set',
|
|
312
305
|
style,
|
|
313
|
-
|
|
306
|
+
at: focusTextBlock.path,
|
|
314
307
|
},
|
|
315
308
|
{
|
|
316
|
-
type: 'delete
|
|
309
|
+
type: 'delete.text',
|
|
317
310
|
anchor: {
|
|
318
311
|
path: focusTextBlock.path,
|
|
319
312
|
offset: 0,
|
|
@@ -327,11 +320,11 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
327
320
|
],
|
|
328
321
|
})
|
|
329
322
|
const clearStyleOnBackspace = defineBehavior({
|
|
330
|
-
on: 'delete
|
|
323
|
+
on: 'delete.backward',
|
|
331
324
|
guard: ({context}) => {
|
|
332
|
-
const selectionCollapsed = selectionIsCollapsed(context)
|
|
333
|
-
const focusTextBlock = getFocusTextBlock(context)
|
|
334
|
-
const focusSpan = getFocusSpan(context)
|
|
325
|
+
const selectionCollapsed = selectionIsCollapsed({context})
|
|
326
|
+
const focusTextBlock = getFocusTextBlock({context})
|
|
327
|
+
const focusSpan = getFocusSpan({context})
|
|
335
328
|
|
|
336
329
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
|
|
337
330
|
return false
|
|
@@ -341,7 +334,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
341
334
|
focusTextBlock.node.children[0]._key === focusSpan.node._key &&
|
|
342
335
|
context.selection.focus.offset === 0
|
|
343
336
|
|
|
344
|
-
const defaultStyle = config.defaultStyle?.(
|
|
337
|
+
const defaultStyle = config.defaultStyle?.(context)
|
|
345
338
|
|
|
346
339
|
if (
|
|
347
340
|
atTheBeginningOfBLock &&
|
|
@@ -354,17 +347,17 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
354
347
|
return false
|
|
355
348
|
},
|
|
356
349
|
actions: [
|
|
357
|
-
(
|
|
350
|
+
({defaultStyle, focusTextBlock}) => [
|
|
358
351
|
{
|
|
359
|
-
type: '
|
|
352
|
+
type: 'text block.set',
|
|
360
353
|
style: defaultStyle,
|
|
361
|
-
|
|
354
|
+
at: focusTextBlock.path,
|
|
362
355
|
},
|
|
363
356
|
],
|
|
364
357
|
],
|
|
365
358
|
})
|
|
366
359
|
const automaticListOnSpace = defineBehavior({
|
|
367
|
-
on: 'insert
|
|
360
|
+
on: 'insert.text',
|
|
368
361
|
guard: ({context, event}) => {
|
|
369
362
|
const isSpace = event.text === ' '
|
|
370
363
|
|
|
@@ -372,9 +365,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
372
365
|
return false
|
|
373
366
|
}
|
|
374
367
|
|
|
375
|
-
const selectionCollapsed = selectionIsCollapsed(context)
|
|
376
|
-
const focusTextBlock = getFocusTextBlock(context)
|
|
377
|
-
const focusSpan = getFocusSpan(context)
|
|
368
|
+
const selectionCollapsed = selectionIsCollapsed({context})
|
|
369
|
+
const focusTextBlock = getFocusTextBlock({context})
|
|
370
|
+
const focusSpan = getFocusSpan({context})
|
|
378
371
|
|
|
379
372
|
if (!selectionCollapsed || !focusTextBlock || !focusSpan) {
|
|
380
373
|
return false
|
|
@@ -397,11 +390,9 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
397
390
|
}
|
|
398
391
|
|
|
399
392
|
const blockText = getTextBlockText(focusTextBlock.node)
|
|
400
|
-
const defaultStyle = config.defaultStyle?.(
|
|
393
|
+
const defaultStyle = config.defaultStyle?.(context)
|
|
401
394
|
const looksLikeUnorderedList = /^(-|\*)/.test(blockText)
|
|
402
|
-
const unorderedListStyle = config.unorderedListStyle?.(
|
|
403
|
-
schema: context.schema,
|
|
404
|
-
})
|
|
395
|
+
const unorderedListStyle = config.unorderedListStyle?.(context)
|
|
405
396
|
const caretAtTheEndOfUnorderedList = blockOffset.offset === 1
|
|
406
397
|
|
|
407
398
|
if (
|
|
@@ -419,9 +410,7 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
419
410
|
}
|
|
420
411
|
|
|
421
412
|
const looksLikeOrderedList = /^1\./.test(blockText)
|
|
422
|
-
const orderedListStyle = config.orderedListStyle?.(
|
|
423
|
-
schema: context.schema,
|
|
424
|
-
})
|
|
413
|
+
const orderedListStyle = config.orderedListStyle?.(context)
|
|
425
414
|
const caretAtTheEndOfOrderedList = blockOffset.offset === 2
|
|
426
415
|
|
|
427
416
|
if (
|
|
@@ -443,20 +432,20 @@ export function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {
|
|
|
443
432
|
actions: [
|
|
444
433
|
() => [
|
|
445
434
|
{
|
|
446
|
-
type: 'insert
|
|
435
|
+
type: 'insert.text',
|
|
447
436
|
text: ' ',
|
|
448
437
|
},
|
|
449
438
|
],
|
|
450
|
-
(
|
|
439
|
+
({focusTextBlock, style, listItem, listItemLength}) => [
|
|
451
440
|
{
|
|
452
|
-
type: '
|
|
441
|
+
type: 'text block.set',
|
|
453
442
|
listItem,
|
|
454
443
|
level: 1,
|
|
455
444
|
style,
|
|
456
|
-
|
|
445
|
+
at: focusTextBlock.path,
|
|
457
446
|
},
|
|
458
447
|
{
|
|
459
|
-
type: 'delete
|
|
448
|
+
type: 'delete.text',
|
|
460
449
|
anchor: {
|
|
461
450
|
path: focusTextBlock.path,
|
|
462
451
|
offset: 0,
|
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
KeyedSegment,
|
|
3
|
-
PortableTextBlock,
|
|
4
|
-
PortableTextTextBlock,
|
|
5
|
-
} from '@sanity/types'
|
|
1
|
+
import type {KeyedSegment, PortableTextTextBlock} from '@sanity/types'
|
|
6
2
|
import type {TextUnit} from 'slate'
|
|
7
3
|
import type {TextInsertTextOptions} from 'slate/dist/interfaces/transforms/text'
|
|
8
|
-
import type {
|
|
9
|
-
|
|
10
|
-
PortableTextMemberSchemaTypes,
|
|
11
|
-
PortableTextSlateEditor,
|
|
12
|
-
} from '../../types/editor'
|
|
13
|
-
import type {BlockOffset} from './behavior.utils.block-offset'
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @alpha
|
|
17
|
-
*/
|
|
18
|
-
export type BehaviorContext = {
|
|
19
|
-
schema: PortableTextMemberSchemaTypes
|
|
20
|
-
value: Array<PortableTextBlock>
|
|
21
|
-
selection: NonNullable<EditorSelection>
|
|
22
|
-
}
|
|
4
|
+
import type {EditorSelection, PortableTextSlateEditor} from '../../types/editor'
|
|
5
|
+
import type {EditorContext} from '../editor-snapshot'
|
|
23
6
|
|
|
24
7
|
/**
|
|
25
8
|
* @alpha
|
|
@@ -45,6 +28,13 @@ export type BehaviorEvent =
|
|
|
45
28
|
value: {[prop: string]: unknown}
|
|
46
29
|
}
|
|
47
30
|
}
|
|
31
|
+
| {
|
|
32
|
+
type: 'blur'
|
|
33
|
+
}
|
|
34
|
+
| {
|
|
35
|
+
type: 'copy'
|
|
36
|
+
data: DataTransfer
|
|
37
|
+
}
|
|
48
38
|
| {
|
|
49
39
|
type: 'decorator.add'
|
|
50
40
|
decorator: string
|
|
@@ -58,30 +48,67 @@ export type BehaviorEvent =
|
|
|
58
48
|
decorator: string
|
|
59
49
|
}
|
|
60
50
|
| {
|
|
61
|
-
type: 'delete
|
|
51
|
+
type: 'delete.backward'
|
|
62
52
|
unit: TextUnit
|
|
63
53
|
}
|
|
64
54
|
| {
|
|
65
|
-
type: 'delete
|
|
55
|
+
type: 'delete.forward'
|
|
66
56
|
unit: TextUnit
|
|
67
57
|
}
|
|
68
58
|
| {
|
|
69
59
|
type: 'focus'
|
|
70
60
|
}
|
|
71
61
|
| {
|
|
72
|
-
type: 'insert
|
|
62
|
+
type: 'insert.block object'
|
|
63
|
+
placement: 'auto' | 'after' | 'before'
|
|
64
|
+
blockObject: {
|
|
65
|
+
name: string
|
|
66
|
+
value?: {[prop: string]: unknown}
|
|
67
|
+
}
|
|
73
68
|
}
|
|
74
69
|
| {
|
|
75
|
-
type: 'insert
|
|
70
|
+
type: 'insert.inline object'
|
|
71
|
+
inlineObject: {
|
|
72
|
+
name: string
|
|
73
|
+
value?: {[prop: string]: unknown}
|
|
74
|
+
}
|
|
76
75
|
}
|
|
77
76
|
| {
|
|
78
|
-
type: 'insert
|
|
77
|
+
type: 'insert.soft break'
|
|
78
|
+
}
|
|
79
|
+
| {
|
|
80
|
+
type: 'insert.break'
|
|
81
|
+
}
|
|
82
|
+
| {
|
|
83
|
+
type: 'insert.text'
|
|
79
84
|
text: string
|
|
80
85
|
options?: TextInsertTextOptions
|
|
81
86
|
}
|
|
82
87
|
| {
|
|
83
88
|
type: 'paste'
|
|
84
|
-
|
|
89
|
+
data: DataTransfer
|
|
90
|
+
}
|
|
91
|
+
| {
|
|
92
|
+
type: 'key.down'
|
|
93
|
+
keyboardEvent: Pick<
|
|
94
|
+
KeyboardEvent,
|
|
95
|
+
'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
|
|
96
|
+
>
|
|
97
|
+
}
|
|
98
|
+
| {
|
|
99
|
+
type: 'key.up'
|
|
100
|
+
keyboardEvent: Pick<
|
|
101
|
+
KeyboardEvent,
|
|
102
|
+
'key' | 'code' | 'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey'
|
|
103
|
+
>
|
|
104
|
+
}
|
|
105
|
+
| {
|
|
106
|
+
type: 'list item.toggle'
|
|
107
|
+
listItem: string
|
|
108
|
+
}
|
|
109
|
+
| {
|
|
110
|
+
type: 'style.toggle'
|
|
111
|
+
style: string
|
|
85
112
|
}
|
|
86
113
|
|
|
87
114
|
/**
|
|
@@ -94,8 +121,8 @@ export type BehaviorGuard<
|
|
|
94
121
|
context,
|
|
95
122
|
event,
|
|
96
123
|
}: {
|
|
124
|
+
context: EditorContext
|
|
97
125
|
event: TBehaviorEvent
|
|
98
|
-
context: BehaviorContext
|
|
99
126
|
}) => TGuardResponse | false
|
|
100
127
|
|
|
101
128
|
/**
|
|
@@ -104,15 +131,7 @@ export type BehaviorGuard<
|
|
|
104
131
|
export type BehaviorActionIntend =
|
|
105
132
|
| BehaviorEvent
|
|
106
133
|
| {
|
|
107
|
-
type: 'insert
|
|
108
|
-
placement: 'auto' | 'after' | 'before'
|
|
109
|
-
blockObject: {
|
|
110
|
-
name: string
|
|
111
|
-
value?: {[prop: string]: unknown}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
| {
|
|
115
|
-
type: 'insert span'
|
|
134
|
+
type: 'insert.span'
|
|
116
135
|
text: string
|
|
117
136
|
annotations?: Array<{
|
|
118
137
|
name: string
|
|
@@ -121,30 +140,42 @@ export type BehaviorActionIntend =
|
|
|
121
140
|
decorators?: Array<string>
|
|
122
141
|
}
|
|
123
142
|
| {
|
|
124
|
-
type: 'insert
|
|
143
|
+
type: 'insert.text block'
|
|
125
144
|
placement: 'auto' | 'after' | 'before'
|
|
126
145
|
textBlock?: {
|
|
127
146
|
children?: PortableTextTextBlock['children']
|
|
128
147
|
}
|
|
129
148
|
}
|
|
130
149
|
| {
|
|
131
|
-
type: '
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
150
|
+
type: 'list item.add'
|
|
151
|
+
listItem: string
|
|
152
|
+
}
|
|
153
|
+
| {
|
|
154
|
+
type: 'list item.remove'
|
|
155
|
+
listItem: string
|
|
156
|
+
}
|
|
157
|
+
| {
|
|
158
|
+
type: 'move.block'
|
|
159
|
+
at: [KeyedSegment]
|
|
160
|
+
to: [KeyedSegment]
|
|
161
|
+
}
|
|
162
|
+
| {
|
|
163
|
+
type: 'move.block down'
|
|
164
|
+
at: [KeyedSegment]
|
|
165
|
+
}
|
|
166
|
+
| {
|
|
167
|
+
type: 'move.block up'
|
|
168
|
+
at: [KeyedSegment]
|
|
136
169
|
}
|
|
137
170
|
| {
|
|
138
|
-
type: '
|
|
139
|
-
paths: Array<[KeyedSegment]>
|
|
140
|
-
props: Array<'style' | 'listItem' | 'level'>
|
|
171
|
+
type: 'noop'
|
|
141
172
|
}
|
|
142
173
|
| {
|
|
143
|
-
type: 'delete
|
|
174
|
+
type: 'delete.block'
|
|
144
175
|
blockPath: [KeyedSegment]
|
|
145
176
|
}
|
|
146
177
|
| {
|
|
147
|
-
type: 'delete
|
|
178
|
+
type: 'delete.text'
|
|
148
179
|
anchor: BlockOffset
|
|
149
180
|
focus: BlockOffset
|
|
150
181
|
}
|
|
@@ -156,9 +187,35 @@ export type BehaviorActionIntend =
|
|
|
156
187
|
type: 'select'
|
|
157
188
|
selection: EditorSelection
|
|
158
189
|
}
|
|
190
|
+
| {
|
|
191
|
+
type: 'select previous block'
|
|
192
|
+
}
|
|
193
|
+
| {
|
|
194
|
+
type: 'select next block'
|
|
195
|
+
}
|
|
159
196
|
| {
|
|
160
197
|
type: 'reselect'
|
|
161
198
|
}
|
|
199
|
+
| {
|
|
200
|
+
type: 'style.add'
|
|
201
|
+
style: string
|
|
202
|
+
}
|
|
203
|
+
| {
|
|
204
|
+
type: 'style.remove'
|
|
205
|
+
style: string
|
|
206
|
+
}
|
|
207
|
+
| {
|
|
208
|
+
type: 'text block.set'
|
|
209
|
+
at: [KeyedSegment]
|
|
210
|
+
level?: number
|
|
211
|
+
listItem?: string
|
|
212
|
+
style?: string
|
|
213
|
+
}
|
|
214
|
+
| {
|
|
215
|
+
type: 'text block.unset'
|
|
216
|
+
at: [KeyedSegment]
|
|
217
|
+
props: Array<'level' | 'listItem' | 'style'>
|
|
218
|
+
}
|
|
162
219
|
|
|
163
220
|
/**
|
|
164
221
|
* @alpha
|
|
@@ -190,25 +247,21 @@ export type Behavior<
|
|
|
190
247
|
/**
|
|
191
248
|
* Array of behavior action sets.
|
|
192
249
|
*/
|
|
193
|
-
actions: Array<BehaviorActionIntendSet<
|
|
250
|
+
actions: Array<BehaviorActionIntendSet<TGuardResponse>>
|
|
194
251
|
}
|
|
195
252
|
|
|
196
253
|
/**
|
|
197
254
|
* @alpha
|
|
198
255
|
*/
|
|
199
|
-
export type BehaviorActionIntendSet<
|
|
200
|
-
TBehaviorEventType extends BehaviorEvent['type'] = BehaviorEvent['type'],
|
|
201
|
-
TGuardResponse = true,
|
|
202
|
-
> = (
|
|
203
|
-
{
|
|
204
|
-
context,
|
|
205
|
-
event,
|
|
206
|
-
}: {
|
|
207
|
-
context: BehaviorContext
|
|
208
|
-
event: PickFromUnion<BehaviorEvent, 'type', TBehaviorEventType>
|
|
209
|
-
},
|
|
256
|
+
export type BehaviorActionIntendSet<TGuardResponse = true> = (
|
|
210
257
|
guardResponse: TGuardResponse,
|
|
211
|
-
) => Array<
|
|
258
|
+
) => Array<
|
|
259
|
+
OmitFromUnion<
|
|
260
|
+
BehaviorActionIntend,
|
|
261
|
+
'type',
|
|
262
|
+
'copy' | 'key.down' | 'key.up' | 'paste'
|
|
263
|
+
>
|
|
264
|
+
>
|
|
212
265
|
|
|
213
266
|
/**
|
|
214
267
|
* @alpha
|
|
@@ -220,6 +273,14 @@ export function defineBehavior<
|
|
|
220
273
|
return behavior as unknown as Behavior
|
|
221
274
|
}
|
|
222
275
|
|
|
276
|
+
/**
|
|
277
|
+
* @alpha
|
|
278
|
+
*/
|
|
279
|
+
export type BlockOffset = {
|
|
280
|
+
path: [KeyedSegment]
|
|
281
|
+
offset: number
|
|
282
|
+
}
|
|
283
|
+
|
|
223
284
|
/**
|
|
224
285
|
* @alpha
|
|
225
286
|
*/
|
|
@@ -53,7 +53,15 @@ export type EditorEvent = PickFromUnion<
|
|
|
53
53
|
InternalEditorEvent,
|
|
54
54
|
'type',
|
|
55
55
|
| 'annotation.toggle'
|
|
56
|
+
| 'blur'
|
|
57
|
+
| 'decorator.add'
|
|
58
|
+
| 'decorator.remove'
|
|
59
|
+
| 'decorator.toggle'
|
|
56
60
|
| 'focus'
|
|
61
|
+
| 'insert.block object'
|
|
62
|
+
| 'insert.inline object'
|
|
63
|
+
| 'list item.toggle'
|
|
64
|
+
| 'style.toggle'
|
|
57
65
|
| 'patches'
|
|
58
66
|
| 'toggle readOnly'
|
|
59
67
|
| 'update behaviors'
|
|
@@ -66,15 +74,15 @@ export type EditorEvent = PickFromUnion<
|
|
|
66
74
|
export type Editor = {
|
|
67
75
|
send: (event: EditorEvent) => void
|
|
68
76
|
on: ActorRef<Snapshot<unknown>, EventObject, EditorEmittedEvent>['on']
|
|
69
|
-
editable: EditableAPI
|
|
70
77
|
_internal: {
|
|
78
|
+
editable: EditableAPI
|
|
71
79
|
editorActor: EditorActor
|
|
72
80
|
slateEditor: SlateEditor
|
|
73
81
|
}
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
/**
|
|
77
|
-
* @
|
|
85
|
+
* @internal
|
|
78
86
|
*/
|
|
79
87
|
export function createEditor(config: EditorConfig): Editor {
|
|
80
88
|
const editorActor = createActor(editorMachine, {
|
|
@@ -96,18 +104,15 @@ export function createEditor(config: EditorConfig): Editor {
|
|
|
96
104
|
// @ts-ignore
|
|
97
105
|
listener,
|
|
98
106
|
),
|
|
99
|
-
editable,
|
|
100
107
|
_internal: {
|
|
108
|
+
editable,
|
|
101
109
|
editorActor,
|
|
102
110
|
slateEditor,
|
|
103
111
|
},
|
|
104
112
|
}
|
|
105
113
|
}
|
|
106
114
|
|
|
107
|
-
|
|
108
|
-
* @alpha
|
|
109
|
-
*/
|
|
110
|
-
export function useEditor(config: EditorConfig): Editor {
|
|
115
|
+
export function useCreateEditor(config: EditorConfig): Editor {
|
|
111
116
|
const editorActor = useActorRef(editorMachine, {
|
|
112
117
|
input: editorConfigToMachineInput(config),
|
|
113
118
|
})
|
|
@@ -135,8 +140,8 @@ export function useEditor(config: EditorConfig): Editor {
|
|
|
135
140
|
() => ({
|
|
136
141
|
send,
|
|
137
142
|
on,
|
|
138
|
-
editable,
|
|
139
143
|
_internal: {
|
|
144
|
+
editable,
|
|
140
145
|
editorActor,
|
|
141
146
|
slateEditor,
|
|
142
147
|
},
|