@portabletext/editor 2.9.1 → 2.10.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/selector.is-selecting-entire-blocks.cjs +9 -1
- package/lib/_chunks-cjs/selector.is-selecting-entire-blocks.cjs.map +1 -1
- package/lib/_chunks-cjs/util.merge-text-blocks.cjs +1 -0
- package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
- package/lib/_chunks-cjs/util.slice-blocks.cjs +6 -1
- package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
- package/lib/_chunks-dts/behavior.types.action.d.cts +141 -131
- package/lib/_chunks-dts/behavior.types.action.d.ts +71 -61
- package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +9 -1
- package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +1 -1
- package/lib/_chunks-es/util.merge-text-blocks.js +1 -0
- package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -1
- package/lib/_chunks-es/util.slice-blocks.js +6 -1
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/index.cjs +419 -309
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +422 -312
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.d.cts +3 -3
- package/lib/plugins/index.d.ts +3 -3
- package/lib/utils/index.d.ts +2 -2
- package/package.json +8 -8
- package/src/behaviors/behavior.abstract.insert.ts +109 -24
- package/src/behaviors/behavior.abstract.split.ts +1 -0
- package/src/behaviors/behavior.perform-event.ts +84 -118
- package/src/behaviors/behavior.types.event.ts +9 -1
- package/src/converters/converter.portable-text.ts +1 -0
- package/src/converters/converter.text-html.ts +1 -0
- package/src/converters/converter.text-plain.ts +1 -0
- package/src/editor/Editable.tsx +1 -0
- package/src/editor/editor-selector.ts +10 -1
- package/src/editor/plugins/create-with-event-listeners.ts +13 -14
- package/src/editor/sync-machine.ts +9 -0
- package/src/editor/with-performing-behavior-operation.ts +21 -0
- package/src/editor/without-normalizing-conditional.ts +13 -0
- package/src/internal-utils/parse-blocks.test.ts +14 -14
- package/src/internal-utils/parse-blocks.ts +9 -2
- package/src/internal-utils/slate-utils.test.tsx +119 -0
- package/src/internal-utils/slate-utils.ts +14 -1
- package/src/internal-utils/text-marks.ts +1 -1
- package/src/internal-utils/values.ts +1 -55
- package/src/operations/behavior.operation.block.set.ts +18 -36
- package/src/operations/behavior.operation.block.unset.ts +8 -2
- package/src/operations/behavior.operation.insert.block.ts +4 -1
- package/src/operations/behavior.operation.insert.child.ts +95 -0
- package/src/operations/behavior.operations.ts +140 -128
- package/src/selectors/selector.get-mark-state.ts +19 -5
- package/src/selectors/selector.get-trimmed-selection.test.ts +1 -0
- package/src/types/block-with-optional-key.ts +13 -1
- package/src/utils/util.merge-text-blocks.ts +1 -1
- package/src/utils/util.slice-blocks.ts +3 -3
- package/src/utils/util.slice-text-block.test.ts +54 -28
- package/src/editor/with-applying-behavior-operations.ts +0 -18
package/lib/plugins/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Behavior, Editor, EditorEmittedEvent, EditorSchema } from "../_chunks-dts/behavior.types.action.cjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react12 from "react";
|
|
3
3
|
import React from "react";
|
|
4
4
|
/**
|
|
5
5
|
* @beta
|
|
@@ -181,7 +181,7 @@ type MarkdownPluginConfig = MarkdownBehaviorsConfig & {
|
|
|
181
181
|
*/
|
|
182
182
|
declare function MarkdownPlugin(props: {
|
|
183
183
|
config: MarkdownPluginConfig;
|
|
184
|
-
}):
|
|
184
|
+
}): react12.JSX.Element;
|
|
185
185
|
/**
|
|
186
186
|
* @beta
|
|
187
187
|
* Restrict the editor to one line. The plugin takes care of blocking
|
|
@@ -192,5 +192,5 @@ declare function MarkdownPlugin(props: {
|
|
|
192
192
|
*
|
|
193
193
|
* @deprecated Install the plugin from `@portabletext/plugin-one-line`
|
|
194
194
|
*/
|
|
195
|
-
declare function OneLinePlugin():
|
|
195
|
+
declare function OneLinePlugin(): react12.JSX.Element;
|
|
196
196
|
export { BehaviorPlugin, DecoratorShortcutPlugin, EditorRefPlugin, EventListenerPlugin, MarkdownPlugin, type MarkdownPluginConfig, OneLinePlugin };
|
package/lib/plugins/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Behavior, Editor, EditorEmittedEvent, EditorSchema } from "../_chunks-dts/behavior.types.action.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react22 from "react";
|
|
3
3
|
import React from "react";
|
|
4
4
|
/**
|
|
5
5
|
* @beta
|
|
@@ -181,7 +181,7 @@ type MarkdownPluginConfig = MarkdownBehaviorsConfig & {
|
|
|
181
181
|
*/
|
|
182
182
|
declare function MarkdownPlugin(props: {
|
|
183
183
|
config: MarkdownPluginConfig;
|
|
184
|
-
}):
|
|
184
|
+
}): react22.JSX.Element;
|
|
185
185
|
/**
|
|
186
186
|
* @beta
|
|
187
187
|
* Restrict the editor to one line. The plugin takes care of blocking
|
|
@@ -192,5 +192,5 @@ declare function MarkdownPlugin(props: {
|
|
|
192
192
|
*
|
|
193
193
|
* @deprecated Install the plugin from `@portabletext/plugin-one-line`
|
|
194
194
|
*/
|
|
195
|
-
declare function OneLinePlugin():
|
|
195
|
+
declare function OneLinePlugin(): react22.JSX.Element;
|
|
196
196
|
export { BehaviorPlugin, DecoratorShortcutPlugin, EditorRefPlugin, EventListenerPlugin, MarkdownPlugin, type MarkdownPluginConfig, OneLinePlugin };
|
package/lib/utils/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BlockOffset, BlockPath, ChildPath, EditorContext, EditorSelection, EditorSelectionPoint } from "../_chunks-dts/behavior.types.action.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as _sanity_types8 from "@sanity/types";
|
|
3
3
|
import { KeyedSegment, PortableTextBlock, PortableTextTextBlock } from "@sanity/types";
|
|
4
4
|
import { isSpan, isTextBlock } from "@portabletext/schema";
|
|
5
5
|
/**
|
|
@@ -143,7 +143,7 @@ declare function mergeTextBlocks({
|
|
|
143
143
|
context: Pick<EditorContext, 'keyGenerator' | 'schema'>;
|
|
144
144
|
targetBlock: PortableTextTextBlock;
|
|
145
145
|
incomingBlock: PortableTextTextBlock;
|
|
146
|
-
}): PortableTextTextBlock<
|
|
146
|
+
}): PortableTextTextBlock<_sanity_types8.PortableTextObject | _sanity_types8.PortableTextSpan>;
|
|
147
147
|
/**
|
|
148
148
|
* @public
|
|
149
149
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"slate-dom": "^0.118.1",
|
|
80
80
|
"slate-react": "0.117.4",
|
|
81
81
|
"xstate": "^5.21.0",
|
|
82
|
-
"@portabletext/block-tools": "^3.5.
|
|
82
|
+
"@portabletext/block-tools": "^3.5.6",
|
|
83
83
|
"@portabletext/keyboard-shortcuts": "^1.1.1",
|
|
84
84
|
"@portabletext/patches": "^1.1.8",
|
|
85
85
|
"@portabletext/schema": "^1.2.0"
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@sanity/diff-match-patch": "^3.2.0",
|
|
89
89
|
"@sanity/pkg-utils": "^8.1.4",
|
|
90
|
-
"@sanity/schema": "^4.
|
|
91
|
-
"@sanity/types": "^4.
|
|
90
|
+
"@sanity/schema": "^4.9.0",
|
|
91
|
+
"@sanity/types": "^4.9.0",
|
|
92
92
|
"@types/debug": "^4.1.12",
|
|
93
93
|
"@types/lodash": "^4.17.20",
|
|
94
94
|
"@types/lodash.startcase": "^4.4.9",
|
|
@@ -110,14 +110,14 @@
|
|
|
110
110
|
"vite": "^7.1.3",
|
|
111
111
|
"vitest": "^3.2.4",
|
|
112
112
|
"vitest-browser-react": "^1.0.1",
|
|
113
|
-
"@portabletext/sanity-bridge": "1.1.
|
|
113
|
+
"@portabletext/sanity-bridge": "1.1.10",
|
|
114
114
|
"@portabletext/test": "^0.0.0",
|
|
115
115
|
"racejar": "1.2.15"
|
|
116
116
|
},
|
|
117
117
|
"peerDependencies": {
|
|
118
|
-
"@portabletext/sanity-bridge": "^1.1.
|
|
119
|
-
"@sanity/schema": "^4.
|
|
120
|
-
"@sanity/types": "^4.
|
|
118
|
+
"@portabletext/sanity-bridge": "^1.1.10",
|
|
119
|
+
"@sanity/schema": "^4.9.0",
|
|
120
|
+
"@sanity/types": "^4.9.0",
|
|
121
121
|
"react": "^18.3 || ^19",
|
|
122
122
|
"rxjs": "^7.8.2"
|
|
123
123
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {getFocusTextBlock} from '../selectors'
|
|
1
|
+
import {getFocusTextBlock, getLastBlock} from '../selectors'
|
|
2
2
|
import {
|
|
3
3
|
getBlockEndPoint,
|
|
4
4
|
getBlockStartPoint,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
isEqualSelectionPoints,
|
|
7
7
|
} from '../utils'
|
|
8
8
|
import {sliceTextBlock} from '../utils/util.slice-text-block'
|
|
9
|
-
import {
|
|
9
|
+
import {raise} from './behavior.types.action'
|
|
10
10
|
import {defineBehavior} from './behavior.types.behavior'
|
|
11
11
|
|
|
12
12
|
export const abstractInsertBehaviors = [
|
|
@@ -328,23 +328,77 @@ export const abstractInsertBehaviors = [
|
|
|
328
328
|
actions: [() => [raise({type: 'split'})]],
|
|
329
329
|
}),
|
|
330
330
|
defineBehavior({
|
|
331
|
-
on: 'insert.
|
|
331
|
+
on: 'insert.child',
|
|
332
|
+
guard: ({snapshot}) => {
|
|
333
|
+
const lastBlock = getLastBlock(snapshot)
|
|
334
|
+
|
|
335
|
+
if (!lastBlock) {
|
|
336
|
+
return false
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (snapshot.context.selection) {
|
|
340
|
+
return false
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const lastBlockEndPoint = getBlockEndPoint({
|
|
344
|
+
context: snapshot.context,
|
|
345
|
+
block: lastBlock,
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
return {lastBlockEndPoint}
|
|
349
|
+
},
|
|
350
|
+
actions: [
|
|
351
|
+
({event}, {lastBlockEndPoint}) => [
|
|
352
|
+
raise({
|
|
353
|
+
type: 'select',
|
|
354
|
+
at: {
|
|
355
|
+
anchor: lastBlockEndPoint,
|
|
356
|
+
focus: lastBlockEndPoint,
|
|
357
|
+
},
|
|
358
|
+
}),
|
|
359
|
+
raise(event),
|
|
360
|
+
],
|
|
361
|
+
],
|
|
362
|
+
}),
|
|
363
|
+
defineBehavior({
|
|
364
|
+
on: 'insert.child',
|
|
365
|
+
guard: ({snapshot}) => {
|
|
366
|
+
const focusTextBlock = getFocusTextBlock(snapshot)
|
|
367
|
+
|
|
368
|
+
return snapshot.context.selection && !focusTextBlock
|
|
369
|
+
},
|
|
332
370
|
actions: [
|
|
333
371
|
({snapshot, event}) => [
|
|
334
|
-
|
|
372
|
+
raise({
|
|
335
373
|
type: 'insert.block',
|
|
336
374
|
block: {
|
|
337
375
|
_type: snapshot.context.schema.block.name,
|
|
338
376
|
children: [
|
|
339
377
|
{
|
|
340
|
-
_type:
|
|
341
|
-
|
|
378
|
+
_type: snapshot.context.schema.span.name,
|
|
379
|
+
text: '',
|
|
380
|
+
marks: [],
|
|
342
381
|
},
|
|
343
382
|
],
|
|
344
383
|
},
|
|
345
384
|
placement: 'auto',
|
|
346
385
|
select: 'end',
|
|
347
386
|
}),
|
|
387
|
+
raise(event),
|
|
388
|
+
],
|
|
389
|
+
],
|
|
390
|
+
}),
|
|
391
|
+
defineBehavior({
|
|
392
|
+
on: 'insert.inline object',
|
|
393
|
+
actions: [
|
|
394
|
+
({event}) => [
|
|
395
|
+
raise({
|
|
396
|
+
type: 'insert.child',
|
|
397
|
+
child: {
|
|
398
|
+
_type: event.inlineObject.name,
|
|
399
|
+
...event.inlineObject.value,
|
|
400
|
+
},
|
|
401
|
+
}),
|
|
348
402
|
],
|
|
349
403
|
],
|
|
350
404
|
}),
|
|
@@ -354,37 +408,68 @@ export const abstractInsertBehaviors = [
|
|
|
354
408
|
}),
|
|
355
409
|
defineBehavior({
|
|
356
410
|
on: 'insert.span',
|
|
357
|
-
guard: ({snapshot
|
|
358
|
-
const markDefs =
|
|
359
|
-
event.annotations?.map((annotation) => ({
|
|
360
|
-
_type: annotation.name,
|
|
361
|
-
_key: snapshot.context.keyGenerator(),
|
|
362
|
-
...annotation.value,
|
|
363
|
-
})) ?? []
|
|
364
|
-
|
|
365
|
-
return {markDefs}
|
|
366
|
-
},
|
|
411
|
+
guard: ({snapshot}) => !getFocusTextBlock(snapshot),
|
|
367
412
|
actions: [
|
|
368
|
-
({snapshot, event}
|
|
369
|
-
|
|
413
|
+
({snapshot, event}) => [
|
|
414
|
+
raise({
|
|
370
415
|
type: 'insert.block',
|
|
371
416
|
block: {
|
|
372
417
|
_type: snapshot.context.schema.block.name,
|
|
373
418
|
children: [
|
|
374
419
|
{
|
|
375
420
|
_type: snapshot.context.schema.span.name,
|
|
376
|
-
text:
|
|
377
|
-
marks: [
|
|
378
|
-
...(event.decorators ?? []),
|
|
379
|
-
...markDefs.map((markDef) => markDef._key),
|
|
380
|
-
],
|
|
421
|
+
text: '',
|
|
422
|
+
marks: [],
|
|
381
423
|
},
|
|
382
424
|
],
|
|
383
|
-
markDefs,
|
|
384
425
|
},
|
|
385
426
|
placement: 'auto',
|
|
386
427
|
select: 'end',
|
|
387
428
|
}),
|
|
429
|
+
raise(event),
|
|
430
|
+
],
|
|
431
|
+
],
|
|
432
|
+
}),
|
|
433
|
+
defineBehavior({
|
|
434
|
+
on: 'insert.span',
|
|
435
|
+
guard: ({snapshot, event}) => {
|
|
436
|
+
const focusTextBlock = getFocusTextBlock(snapshot)
|
|
437
|
+
const markDefs =
|
|
438
|
+
event.annotations?.map((annotation) => ({
|
|
439
|
+
_type: annotation.name,
|
|
440
|
+
_key: snapshot.context.keyGenerator(),
|
|
441
|
+
...annotation.value,
|
|
442
|
+
})) ?? []
|
|
443
|
+
|
|
444
|
+
return {markDefs, focusTextBlock}
|
|
445
|
+
},
|
|
446
|
+
actions: [
|
|
447
|
+
({snapshot, event}, {markDefs, focusTextBlock}) => [
|
|
448
|
+
...(focusTextBlock
|
|
449
|
+
? [
|
|
450
|
+
raise({
|
|
451
|
+
type: 'block.set',
|
|
452
|
+
at: focusTextBlock.path,
|
|
453
|
+
props: {
|
|
454
|
+
markDefs: [
|
|
455
|
+
...(focusTextBlock.node.markDefs ?? []),
|
|
456
|
+
...markDefs,
|
|
457
|
+
],
|
|
458
|
+
},
|
|
459
|
+
}),
|
|
460
|
+
]
|
|
461
|
+
: []),
|
|
462
|
+
raise({
|
|
463
|
+
type: 'insert.child',
|
|
464
|
+
child: {
|
|
465
|
+
_type: snapshot.context.schema.span.name,
|
|
466
|
+
text: event.text,
|
|
467
|
+
marks: [
|
|
468
|
+
...(event.decorators ?? []),
|
|
469
|
+
...markDefs.map((markDef) => markDef._key),
|
|
470
|
+
],
|
|
471
|
+
},
|
|
472
|
+
}),
|
|
388
473
|
],
|
|
389
474
|
],
|
|
390
475
|
}),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {createEditorDom} from '../editor/editor-dom'
|
|
2
2
|
import type {EditorSchema} from '../editor/editor-schema'
|
|
3
3
|
import type {EditorSnapshot} from '../editor/editor-snapshot'
|
|
4
|
-
import {
|
|
4
|
+
import {withPerformingBehaviorOperation} from '../editor/with-performing-behavior-operation'
|
|
5
5
|
import {clearUndoStep, createUndoStep} from '../editor/with-undo-step'
|
|
6
|
+
import {withoutNormalizingConditional} from '../editor/without-normalizing-conditional'
|
|
6
7
|
import {debugWithName} from '../internal-utils/debug'
|
|
7
8
|
import {performOperation} from '../operations/behavior.operations'
|
|
8
9
|
import type {PortableTextSlateEditor} from '../types/editor'
|
|
@@ -112,7 +113,7 @@ export function performEvent({
|
|
|
112
113
|
clearUndoStep(editor)
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
|
|
116
|
+
withPerformingBehaviorOperation(editor, () => {
|
|
116
117
|
debug(`(execute:${eventCategory(event)})`, JSON.stringify(event, null, 2))
|
|
117
118
|
|
|
118
119
|
performOperation({
|
|
@@ -198,6 +199,8 @@ export function performEvent({
|
|
|
198
199
|
(action) => action.type === 'raise' || action.type === 'execute',
|
|
199
200
|
) || !actions.some((action) => action.type === 'forward')
|
|
200
201
|
|
|
202
|
+
let undoStepCreated = false
|
|
203
|
+
|
|
201
204
|
if (actions.some((action) => action.type === 'execute')) {
|
|
202
205
|
// Since at least one action is about to `execute` changes in the editor,
|
|
203
206
|
// we set up a new undo step.
|
|
@@ -205,139 +208,102 @@ export function performEvent({
|
|
|
205
208
|
// undo step
|
|
206
209
|
createUndoStep(editor)
|
|
207
210
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
211
|
+
undoStepCreated = true
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const actionTypes = actions.map((action) => action.type)
|
|
215
|
+
const uniqueActionTypes = new Set(actionTypes)
|
|
216
|
+
|
|
217
|
+
// The set of actions are all `raise` actions
|
|
218
|
+
const raiseGroup =
|
|
219
|
+
actionTypes.length > 1 &&
|
|
220
|
+
uniqueActionTypes.size === 1 &&
|
|
221
|
+
uniqueActionTypes.has('raise')
|
|
222
|
+
|
|
223
|
+
// The set of actions are all `execute` actions
|
|
224
|
+
const executeGroup =
|
|
225
|
+
actionTypes.length > 1 &&
|
|
226
|
+
uniqueActionTypes.size === 1 &&
|
|
227
|
+
uniqueActionTypes.has('execute')
|
|
228
|
+
|
|
229
|
+
withoutNormalizingConditional(
|
|
230
|
+
editor,
|
|
231
|
+
() => raiseGroup || executeGroup,
|
|
232
|
+
() => {
|
|
233
|
+
for (const action of actions) {
|
|
234
|
+
if (action.type === 'effect') {
|
|
235
|
+
try {
|
|
236
|
+
action.effect({
|
|
237
|
+
send: sendBack,
|
|
238
|
+
})
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.error(
|
|
241
|
+
new Error(
|
|
242
|
+
`Executing effect as a result of "${event.type}" failed due to: ${error.message}`,
|
|
243
|
+
),
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
continue
|
|
220
248
|
}
|
|
221
249
|
|
|
222
|
-
|
|
223
|
-
|
|
250
|
+
if (action.type === 'forward') {
|
|
251
|
+
const remainingEventBehaviors = eventBehaviors.slice(
|
|
252
|
+
eventBehaviorIndex + 1,
|
|
253
|
+
)
|
|
224
254
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
255
|
+
performEvent({
|
|
256
|
+
mode: mode === 'execute' ? 'execute' : 'forward',
|
|
257
|
+
behaviors,
|
|
258
|
+
remainingEventBehaviors: remainingEventBehaviors,
|
|
259
|
+
event: action.event,
|
|
260
|
+
editor,
|
|
261
|
+
keyGenerator,
|
|
262
|
+
schema,
|
|
263
|
+
getSnapshot,
|
|
264
|
+
nativeEvent,
|
|
265
|
+
sendBack,
|
|
266
|
+
})
|
|
229
267
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
behaviors,
|
|
233
|
-
remainingEventBehaviors: remainingEventBehaviors,
|
|
234
|
-
event: action.event,
|
|
235
|
-
editor,
|
|
236
|
-
keyGenerator,
|
|
237
|
-
schema,
|
|
238
|
-
getSnapshot,
|
|
239
|
-
nativeEvent,
|
|
240
|
-
sendBack,
|
|
241
|
-
})
|
|
268
|
+
continue
|
|
269
|
+
}
|
|
242
270
|
|
|
243
|
-
|
|
244
|
-
|
|
271
|
+
if (action.type === 'raise') {
|
|
272
|
+
performEvent({
|
|
273
|
+
mode: mode === 'execute' ? 'execute' : 'raise',
|
|
274
|
+
behaviors,
|
|
275
|
+
remainingEventBehaviors:
|
|
276
|
+
mode === 'execute' ? remainingEventBehaviors : behaviors,
|
|
277
|
+
event: action.event,
|
|
278
|
+
editor,
|
|
279
|
+
keyGenerator,
|
|
280
|
+
schema,
|
|
281
|
+
getSnapshot,
|
|
282
|
+
nativeEvent,
|
|
283
|
+
sendBack,
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
continue
|
|
287
|
+
}
|
|
245
288
|
|
|
246
|
-
if (action.type === 'raise') {
|
|
247
289
|
performEvent({
|
|
248
|
-
mode: '
|
|
290
|
+
mode: 'execute',
|
|
249
291
|
behaviors,
|
|
250
|
-
remainingEventBehaviors:
|
|
292
|
+
remainingEventBehaviors: [],
|
|
251
293
|
event: action.event,
|
|
252
294
|
editor,
|
|
253
295
|
keyGenerator,
|
|
254
296
|
schema,
|
|
255
297
|
getSnapshot,
|
|
256
|
-
nativeEvent,
|
|
298
|
+
nativeEvent: undefined,
|
|
257
299
|
sendBack,
|
|
258
300
|
})
|
|
259
|
-
|
|
260
|
-
continue
|
|
261
301
|
}
|
|
302
|
+
},
|
|
303
|
+
)
|
|
262
304
|
|
|
263
|
-
|
|
264
|
-
mode: 'execute',
|
|
265
|
-
behaviors,
|
|
266
|
-
remainingEventBehaviors: [],
|
|
267
|
-
event: action.event,
|
|
268
|
-
editor,
|
|
269
|
-
keyGenerator,
|
|
270
|
-
schema,
|
|
271
|
-
getSnapshot,
|
|
272
|
-
nativeEvent: undefined,
|
|
273
|
-
sendBack,
|
|
274
|
-
})
|
|
275
|
-
}
|
|
276
|
-
|
|
305
|
+
if (undoStepCreated) {
|
|
277
306
|
clearUndoStep(editor)
|
|
278
|
-
|
|
279
|
-
continue
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
for (const action of actions) {
|
|
283
|
-
if (action.type === 'effect') {
|
|
284
|
-
try {
|
|
285
|
-
action.effect({
|
|
286
|
-
send: sendBack,
|
|
287
|
-
})
|
|
288
|
-
} catch (error) {
|
|
289
|
-
console.error(
|
|
290
|
-
new Error(
|
|
291
|
-
`Executing effect as a result of "${event.type}" failed due to: ${error.message}`,
|
|
292
|
-
),
|
|
293
|
-
)
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
continue
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (action.type === 'forward') {
|
|
300
|
-
const remainingEventBehaviors = eventBehaviors.slice(
|
|
301
|
-
eventBehaviorIndex + 1,
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
performEvent({
|
|
305
|
-
mode: 'forward',
|
|
306
|
-
behaviors,
|
|
307
|
-
remainingEventBehaviors: remainingEventBehaviors,
|
|
308
|
-
event: action.event,
|
|
309
|
-
editor,
|
|
310
|
-
keyGenerator,
|
|
311
|
-
schema,
|
|
312
|
-
getSnapshot,
|
|
313
|
-
nativeEvent,
|
|
314
|
-
sendBack,
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
continue
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (action.type === 'raise') {
|
|
321
|
-
performEvent({
|
|
322
|
-
mode: 'raise',
|
|
323
|
-
behaviors,
|
|
324
|
-
remainingEventBehaviors:
|
|
325
|
-
mode === 'execute' ? remainingEventBehaviors : behaviors,
|
|
326
|
-
event: action.event,
|
|
327
|
-
editor,
|
|
328
|
-
keyGenerator,
|
|
329
|
-
schema,
|
|
330
|
-
getSnapshot,
|
|
331
|
-
nativeEvent,
|
|
332
|
-
sendBack,
|
|
333
|
-
})
|
|
334
|
-
|
|
335
|
-
continue
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (action.type === 'execute') {
|
|
339
|
-
console.error('Unexpected action type: `execute`')
|
|
340
|
-
}
|
|
341
307
|
}
|
|
342
308
|
}
|
|
343
309
|
|
|
@@ -351,7 +317,7 @@ export function performEvent({
|
|
|
351
317
|
clearUndoStep(editor)
|
|
352
318
|
}
|
|
353
319
|
|
|
354
|
-
|
|
320
|
+
withPerformingBehaviorOperation(editor, () => {
|
|
355
321
|
debug(`(execute:${eventCategory(event)})`, JSON.stringify(event, null, 2))
|
|
356
322
|
|
|
357
323
|
performOperation({
|
|
@@ -3,7 +3,10 @@ import type {EventPosition} from '../internal-utils/event-position'
|
|
|
3
3
|
import type {MIMEType} from '../internal-utils/mime-type'
|
|
4
4
|
import type {OmitFromUnion, PickFromUnion, StrictExtract} from '../type-utils'
|
|
5
5
|
import type {BlockOffset} from '../types/block-offset'
|
|
6
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
BlockWithOptionalKey,
|
|
8
|
+
ChildWithOptionalKey,
|
|
9
|
+
} from '../types/block-with-optional-key'
|
|
7
10
|
import type {EditorSelection} from '../types/editor'
|
|
8
11
|
import type {AnnotationPath, BlockPath, ChildPath} from '../types/paths'
|
|
9
12
|
|
|
@@ -72,6 +75,7 @@ const syntheticBehaviorEventTypes = [
|
|
|
72
75
|
'history.redo',
|
|
73
76
|
'history.undo',
|
|
74
77
|
'insert.block',
|
|
78
|
+
'insert.child',
|
|
75
79
|
'insert.text',
|
|
76
80
|
'move.backward',
|
|
77
81
|
'move.block',
|
|
@@ -159,6 +163,10 @@ export type SyntheticBehaviorEvent =
|
|
|
159
163
|
placement: InsertPlacement
|
|
160
164
|
select?: 'start' | 'end' | 'none'
|
|
161
165
|
}
|
|
166
|
+
| {
|
|
167
|
+
type: StrictExtract<SyntheticBehaviorEventType, 'insert.child'>
|
|
168
|
+
child: ChildWithOptionalKey
|
|
169
|
+
}
|
|
162
170
|
| {
|
|
163
171
|
type: StrictExtract<SyntheticBehaviorEventType, 'insert.text'>
|
|
164
172
|
text: string
|
package/src/editor/Editable.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {useSelector} from '@xstate/react'
|
|
2
2
|
import type {Editor} from '../editor'
|
|
3
|
+
import {slateRangeToSelection} from '../internal-utils/slate-utils'
|
|
3
4
|
import type {PortableTextSlateEditor} from '../types/editor'
|
|
4
5
|
import type {InternalEditor} from './create-editor'
|
|
5
6
|
import type {EditorActor} from './editor-machine'
|
|
@@ -65,6 +66,14 @@ export function getEditorSnapshot({
|
|
|
65
66
|
editorActorSnapshot: ReturnType<EditorActor['getSnapshot']>
|
|
66
67
|
slateEditorInstance: PortableTextSlateEditor
|
|
67
68
|
}): EditorSnapshot {
|
|
69
|
+
const selection = slateEditorInstance.selection
|
|
70
|
+
? slateRangeToSelection({
|
|
71
|
+
schema: editorActorSnapshot.context.schema,
|
|
72
|
+
editor: slateEditorInstance,
|
|
73
|
+
range: slateEditorInstance.selection,
|
|
74
|
+
})
|
|
75
|
+
: null
|
|
76
|
+
|
|
68
77
|
return {
|
|
69
78
|
blockIndexMap: slateEditorInstance.blockIndexMap,
|
|
70
79
|
context: {
|
|
@@ -72,7 +81,7 @@ export function getEditorSnapshot({
|
|
|
72
81
|
keyGenerator: editorActorSnapshot.context.keyGenerator,
|
|
73
82
|
readOnly: editorActorSnapshot.matches({'edit mode': 'read only'}),
|
|
74
83
|
schema: editorActorSnapshot.context.schema,
|
|
75
|
-
selection
|
|
84
|
+
selection,
|
|
76
85
|
value: slateEditorInstance.value,
|
|
77
86
|
},
|
|
78
87
|
decoratorState: slateEditorInstance.decoratorState,
|