@portabletext/editor 2.9.2 → 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.
Files changed (38) hide show
  1. package/lib/_chunks-cjs/util.merge-text-blocks.cjs +1 -0
  2. package/lib/_chunks-cjs/util.merge-text-blocks.cjs.map +1 -1
  3. package/lib/_chunks-cjs/util.slice-blocks.cjs +6 -1
  4. package/lib/_chunks-cjs/util.slice-blocks.cjs.map +1 -1
  5. package/lib/_chunks-dts/behavior.types.action.d.cts +132 -122
  6. package/lib/_chunks-dts/behavior.types.action.d.ts +69 -59
  7. package/lib/_chunks-es/util.merge-text-blocks.js +1 -0
  8. package/lib/_chunks-es/util.merge-text-blocks.js.map +1 -1
  9. package/lib/_chunks-es/util.slice-blocks.js +6 -1
  10. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  11. package/lib/index.cjs +232 -68
  12. package/lib/index.cjs.map +1 -1
  13. package/lib/index.js +234 -70
  14. package/lib/index.js.map +1 -1
  15. package/lib/utils/index.d.ts +2 -2
  16. package/package.json +10 -10
  17. package/src/behaviors/behavior.abstract.insert.ts +109 -24
  18. package/src/behaviors/behavior.abstract.split.ts +1 -0
  19. package/src/behaviors/behavior.perform-event.ts +89 -67
  20. package/src/behaviors/behavior.types.event.ts +9 -1
  21. package/src/converters/converter.portable-text.ts +1 -0
  22. package/src/converters/converter.text-html.ts +1 -0
  23. package/src/converters/converter.text-plain.ts +1 -0
  24. package/src/editor/Editable.tsx +1 -0
  25. package/src/editor/editor-selector.ts +10 -1
  26. package/src/editor/without-normalizing-conditional.ts +13 -0
  27. package/src/internal-utils/parse-blocks.test.ts +14 -14
  28. package/src/internal-utils/parse-blocks.ts +9 -2
  29. package/src/operations/behavior.operation.block.set.ts +4 -3
  30. package/src/operations/behavior.operation.block.unset.ts +8 -2
  31. package/src/operations/behavior.operation.insert.block.ts +4 -1
  32. package/src/operations/behavior.operation.insert.child.ts +95 -0
  33. package/src/operations/behavior.operations.ts +9 -0
  34. package/src/selectors/selector.get-trimmed-selection.test.ts +1 -0
  35. package/src/types/block-with-optional-key.ts +13 -1
  36. package/src/utils/util.merge-text-blocks.ts +1 -1
  37. package/src/utils/util.slice-blocks.ts +3 -3
  38. package/src/utils/util.slice-text-block.test.ts +54 -28
package/lib/index.cjs CHANGED
@@ -1089,6 +1089,11 @@ function getEditorSnapshot({
1089
1089
  editorActorSnapshot,
1090
1090
  slateEditorInstance
1091
1091
  }) {
1092
+ const selection = slateEditorInstance.selection ? slateRangeToSelection({
1093
+ schema: editorActorSnapshot.context.schema,
1094
+ editor: slateEditorInstance,
1095
+ range: slateEditorInstance.selection
1096
+ }) : null;
1092
1097
  return {
1093
1098
  blockIndexMap: slateEditorInstance.blockIndexMap,
1094
1099
  context: {
@@ -1098,7 +1103,7 @@ function getEditorSnapshot({
1098
1103
  "edit mode": "read only"
1099
1104
  }),
1100
1105
  schema: editorActorSnapshot.context.schema,
1101
- selection: editorActorSnapshot.context.selection,
1106
+ selection,
1102
1107
  value: slateEditorInstance.value
1103
1108
  },
1104
1109
  decoratorState: slateEditorInstance.decoratorState
@@ -1926,6 +1931,7 @@ const RelayActorContext = React.createContext({}), debug$d = debugWithName("comp
1926
1931
  },
1927
1932
  blocks: result_1.insert,
1928
1933
  options: {
1934
+ removeUnusedMarkDefs: !0,
1929
1935
  validateFields: !1
1930
1936
  }
1931
1937
  }),
@@ -2394,6 +2400,7 @@ const converterJson = {
2394
2400
  context: snapshot.context,
2395
2401
  block,
2396
2402
  options: {
2403
+ removeUnusedMarkDefs: !0,
2397
2404
  validateFields: !1
2398
2405
  }
2399
2406
  });
@@ -2456,6 +2463,7 @@ function createConverterTextHtml(legacySchema) {
2456
2463
  context: snapshot.context,
2457
2464
  block,
2458
2465
  options: {
2466
+ removeUnusedMarkDefs: !0,
2459
2467
  validateFields: !1
2460
2468
  }
2461
2469
  });
@@ -2503,6 +2511,7 @@ function createConverterTextPlain(legacySchema) {
2503
2511
  context: snapshot.context,
2504
2512
  block,
2505
2513
  options: {
2514
+ removeUnusedMarkDefs: !0,
2506
2515
  validateFields: !1
2507
2516
  }
2508
2517
  });
@@ -4050,12 +4059,12 @@ const addAnnotationOperationImplementation = ({
4050
4059
  context,
4051
4060
  block: updatedBlock,
4052
4061
  options: {
4062
+ removeUnusedMarkDefs: !1,
4053
4063
  validateFields: !0
4054
4064
  }
4055
4065
  });
4056
4066
  if (!parsedBlock)
4057
4067
  throw new Error(`Unable to update block at ${JSON.stringify(operation.at)}`);
4058
- parsedBlock.markDefs = updatedBlock.markDefs;
4059
4068
  const slateBlock = toSlateValue([parsedBlock], {
4060
4069
  schemaTypes: context.schema
4061
4070
  })?.at(0);
@@ -4100,6 +4109,7 @@ const addAnnotationOperationImplementation = ({
4100
4109
  context,
4101
4110
  block: omit__default.default(parsedBlock, propsToRemove),
4102
4111
  options: {
4112
+ removeUnusedMarkDefs: !0,
4103
4113
  validateFields: !0
4104
4114
  }
4105
4115
  });
@@ -4117,6 +4127,7 @@ const addAnnotationOperationImplementation = ({
4117
4127
  context,
4118
4128
  block: omit__default.default(parsedBlock, operation.props.filter((prop) => prop !== "_type")),
4119
4129
  options: {
4130
+ removeUnusedMarkDefs: !0,
4120
4131
  validateFields: !0
4121
4132
  }
4122
4133
  });
@@ -4505,6 +4516,7 @@ const insertBlockOperationImplementation = ({
4505
4516
  block: operation.block,
4506
4517
  context,
4507
4518
  options: {
4519
+ removeUnusedMarkDefs: !0,
4508
4520
  validateFields: !0
4509
4521
  }
4510
4522
  });
@@ -4715,7 +4727,76 @@ function insertBlock({
4715
4727
  }
4716
4728
  }
4717
4729
  }
4718
- const insertTextOperationImplementation = ({
4730
+ const insertChildOperationImplementation = ({
4731
+ context,
4732
+ operation
4733
+ }) => {
4734
+ const focus = operation.editor.selection?.focus, focusBlockIndex = focus?.path.at(0), focusChildIndex = focus?.path.at(1);
4735
+ if (focusBlockIndex === void 0 || focusChildIndex === void 0)
4736
+ throw new Error("Unable to insert child without a focus");
4737
+ const [focusBlock, focusBlockPath] = getFocusBlock({
4738
+ editor: operation.editor
4739
+ });
4740
+ if (!focus || !focusBlock || !focusBlockPath)
4741
+ throw new Error("Unable to insert child without a focus block");
4742
+ if (!schema.isTextBlock(context, focusBlock))
4743
+ throw new Error("Unable to insert child into a non-text block");
4744
+ const markDefs = focusBlock.markDefs ?? [], markDefKeyMap = /* @__PURE__ */ new Map();
4745
+ for (const markDef of markDefs)
4746
+ markDefKeyMap.set(markDef._key, markDef._key);
4747
+ const span = util_sliceBlocks.parseSpan({
4748
+ span: operation.child,
4749
+ context,
4750
+ markDefKeyMap,
4751
+ options: {
4752
+ validateFields: !0
4753
+ }
4754
+ });
4755
+ if (span) {
4756
+ const [focusSpan] = getFocusSpan({
4757
+ editor: operation.editor
4758
+ });
4759
+ focusSpan ? slate.Transforms.insertNodes(operation.editor, span, {
4760
+ at: focus,
4761
+ select: !0
4762
+ }) : slate.Transforms.insertNodes(operation.editor, span, {
4763
+ at: [focusBlockIndex, focusChildIndex + 1],
4764
+ select: !0
4765
+ });
4766
+ return;
4767
+ }
4768
+ const inlineObject = util_sliceBlocks.parseInlineObject({
4769
+ inlineObject: operation.child,
4770
+ context,
4771
+ options: {
4772
+ validateFields: !0
4773
+ }
4774
+ });
4775
+ if (inlineObject) {
4776
+ const {
4777
+ _key,
4778
+ _type,
4779
+ ...rest
4780
+ } = inlineObject;
4781
+ slate.Transforms.insertNodes(operation.editor, {
4782
+ _key,
4783
+ _type,
4784
+ children: [{
4785
+ _key: VOID_CHILD_KEY,
4786
+ _type: "span",
4787
+ text: "",
4788
+ marks: []
4789
+ }],
4790
+ value: rest,
4791
+ __inline: !0
4792
+ }, {
4793
+ at: [focusBlockIndex, focusChildIndex + 1],
4794
+ select: !0
4795
+ });
4796
+ return;
4797
+ }
4798
+ throw new Error("Unable to parse child");
4799
+ }, insertTextOperationImplementation = ({
4719
4800
  context,
4720
4801
  operation
4721
4802
  }) => {
@@ -4819,6 +4900,7 @@ const insertTextOperationImplementation = ({
4819
4900
  "history.redo": historyRedoOperationImplementation,
4820
4901
  "history.undo": historyUndoOperationImplementation,
4821
4902
  "insert.block": insertBlockOperationImplementation,
4903
+ "insert.child": insertChildOperationImplementation,
4822
4904
  "insert.text": insertTextOperationImplementation,
4823
4905
  "move.backward": moveBackwardOperationImplementation,
4824
4906
  "move.block": moveBlockOperationImplementation,
@@ -4916,6 +4998,13 @@ function performOperation({
4916
4998
  });
4917
4999
  break;
4918
5000
  }
5001
+ case "insert.child": {
5002
+ behaviorOperationImplementations["insert.child"]({
5003
+ context,
5004
+ operation
5005
+ });
5006
+ break;
5007
+ }
4919
5008
  case "insert.text": {
4920
5009
  behaviorOperationImplementations["insert.text"]({
4921
5010
  context,
@@ -7693,7 +7782,11 @@ const MAX_LIST_LEVEL = 10, clearListOnBackspace = behaviors_index.defineBehavior
7693
7782
  }, coreBehaviorsConfig = [...coreAnnotationBehaviors, coreDecoratorBehaviors.strongShortcut, coreDecoratorBehaviors.emShortcut, coreDecoratorBehaviors.underlineShortcut, coreDecoratorBehaviors.codeShortcut, ...coreDndBehaviors, coreBlockObjectBehaviors.clickingAboveLonelyBlockObject, coreBlockObjectBehaviors.clickingBelowLonelyBlockObject, coreBlockObjectBehaviors.arrowDownOnLonelyBlockObject, coreBlockObjectBehaviors.arrowUpOnLonelyBlockObject, coreBlockObjectBehaviors.breakingBlockObject, coreBlockObjectBehaviors.deletingEmptyTextBlockAfterBlockObject, coreBlockObjectBehaviors.deletingEmptyTextBlockBeforeBlockObject, coreListBehaviors.clearListOnBackspace, coreListBehaviors.unindentListOnBackspace, coreListBehaviors.mergeTextIntoListOnDelete, coreListBehaviors.mergeTextIntoListOnBackspace, coreListBehaviors.deletingListFromStart, coreListBehaviors.clearListOnEnter, coreListBehaviors.indentListOnTab, coreListBehaviors.unindentListOnShiftTab, coreListBehaviors.inheritListLevel, coreListBehaviors.inheritListItem, coreListBehaviors.inheritListProperties, coreInsertBreakBehaviors.breakingAtTheEndOfTextBlock, coreInsertBreakBehaviors.breakingAtTheStartOfTextBlock, coreInsertBreakBehaviors.breakingEntireDocument, coreInsertBreakBehaviors.breakingEntireBlocks, coreInsertBreakBehaviors.breakingInlineObject].map((behavior) => ({
7694
7783
  behavior,
7695
7784
  priority: corePriority
7696
- })), abstractAnnotationBehaviors = [behaviors_index.defineBehavior({
7785
+ }));
7786
+ function withoutNormalizingConditional(editor, predicate, fn) {
7787
+ predicate() ? slate.Editor.withoutNormalizing(editor, fn) : fn();
7788
+ }
7789
+ const abstractAnnotationBehaviors = [behaviors_index.defineBehavior({
7697
7790
  on: "annotation.set",
7698
7791
  guard: ({
7699
7792
  snapshot,
@@ -8475,21 +8568,63 @@ const MAX_LIST_LEVEL = 10, clearListOnBackspace = behaviors_index.defineBehavior
8475
8568
  type: "split"
8476
8569
  })]]
8477
8570
  }), behaviors_index.defineBehavior({
8478
- on: "insert.inline object",
8571
+ on: "insert.child",
8572
+ guard: ({
8573
+ snapshot
8574
+ }) => {
8575
+ const lastBlock = selector_isSelectingEntireBlocks.getLastBlock(snapshot);
8576
+ return !lastBlock || snapshot.context.selection ? !1 : {
8577
+ lastBlockEndPoint: util_isSelectionCollapsed.getBlockEndPoint({
8578
+ context: snapshot.context,
8579
+ block: lastBlock
8580
+ })
8581
+ };
8582
+ },
8583
+ actions: [({
8584
+ event
8585
+ }, {
8586
+ lastBlockEndPoint
8587
+ }) => [behaviors_index.raise({
8588
+ type: "select",
8589
+ at: {
8590
+ anchor: lastBlockEndPoint,
8591
+ focus: lastBlockEndPoint
8592
+ }
8593
+ }), behaviors_index.raise(event)]]
8594
+ }), behaviors_index.defineBehavior({
8595
+ on: "insert.child",
8596
+ guard: ({
8597
+ snapshot
8598
+ }) => {
8599
+ const focusTextBlock = selector_isSelectionExpanded.getFocusTextBlock(snapshot);
8600
+ return snapshot.context.selection && !focusTextBlock;
8601
+ },
8479
8602
  actions: [({
8480
8603
  snapshot,
8481
8604
  event
8482
- }) => [behaviors_index.execute({
8605
+ }) => [behaviors_index.raise({
8483
8606
  type: "insert.block",
8484
8607
  block: {
8485
8608
  _type: snapshot.context.schema.block.name,
8486
8609
  children: [{
8487
- _type: event.inlineObject.name,
8488
- ...event.inlineObject.value
8610
+ _type: snapshot.context.schema.span.name,
8611
+ text: "",
8612
+ marks: []
8489
8613
  }]
8490
8614
  },
8491
8615
  placement: "auto",
8492
8616
  select: "end"
8617
+ }), behaviors_index.raise(event)]]
8618
+ }), behaviors_index.defineBehavior({
8619
+ on: "insert.inline object",
8620
+ actions: [({
8621
+ event
8622
+ }) => [behaviors_index.raise({
8623
+ type: "insert.child",
8624
+ child: {
8625
+ _type: event.inlineObject.name,
8626
+ ...event.inlineObject.value
8627
+ }
8493
8628
  })]]
8494
8629
  }), behaviors_index.defineBehavior({
8495
8630
  on: "insert.soft break",
@@ -8501,33 +8636,59 @@ const MAX_LIST_LEVEL = 10, clearListOnBackspace = behaviors_index.defineBehavior
8501
8636
  }), behaviors_index.defineBehavior({
8502
8637
  on: "insert.span",
8503
8638
  guard: ({
8504
- snapshot,
8505
- event
8506
- }) => ({
8507
- markDefs: event.annotations?.map((annotation) => ({
8508
- _type: annotation.name,
8509
- _key: snapshot.context.keyGenerator(),
8510
- ...annotation.value
8511
- })) ?? []
8512
- }),
8639
+ snapshot
8640
+ }) => !selector_isSelectionExpanded.getFocusTextBlock(snapshot),
8513
8641
  actions: [({
8514
8642
  snapshot,
8515
8643
  event
8516
- }, {
8517
- markDefs
8518
- }) => [behaviors_index.execute({
8644
+ }) => [behaviors_index.raise({
8519
8645
  type: "insert.block",
8520
8646
  block: {
8521
8647
  _type: snapshot.context.schema.block.name,
8522
8648
  children: [{
8523
8649
  _type: snapshot.context.schema.span.name,
8524
- text: event.text,
8525
- marks: [...event.decorators ?? [], ...markDefs.map((markDef) => markDef._key)]
8526
- }],
8527
- markDefs
8650
+ text: "",
8651
+ marks: []
8652
+ }]
8528
8653
  },
8529
8654
  placement: "auto",
8530
8655
  select: "end"
8656
+ }), behaviors_index.raise(event)]]
8657
+ }), behaviors_index.defineBehavior({
8658
+ on: "insert.span",
8659
+ guard: ({
8660
+ snapshot,
8661
+ event
8662
+ }) => {
8663
+ const focusTextBlock = selector_isSelectionExpanded.getFocusTextBlock(snapshot);
8664
+ return {
8665
+ markDefs: event.annotations?.map((annotation) => ({
8666
+ _type: annotation.name,
8667
+ _key: snapshot.context.keyGenerator(),
8668
+ ...annotation.value
8669
+ })) ?? [],
8670
+ focusTextBlock
8671
+ };
8672
+ },
8673
+ actions: [({
8674
+ snapshot,
8675
+ event
8676
+ }, {
8677
+ markDefs,
8678
+ focusTextBlock
8679
+ }) => [...focusTextBlock ? [behaviors_index.raise({
8680
+ type: "block.set",
8681
+ at: focusTextBlock.path,
8682
+ props: {
8683
+ markDefs: [...focusTextBlock.node.markDefs ?? [], ...markDefs]
8684
+ }
8685
+ })] : [], behaviors_index.raise({
8686
+ type: "insert.child",
8687
+ child: {
8688
+ _type: snapshot.context.schema.span.name,
8689
+ text: event.text,
8690
+ marks: [...event.decorators ?? [], ...markDefs.map((markDef) => markDef._key)]
8691
+ }
8531
8692
  })]]
8532
8693
  })], abstractKeyboardBehaviors = [
8533
8694
  /**
@@ -9005,6 +9166,7 @@ const MAX_LIST_LEVEL = 10, clearListOnBackspace = behaviors_index.defineBehavior
9005
9166
  }),
9006
9167
  context: snapshot.context,
9007
9168
  options: {
9169
+ removeUnusedMarkDefs: !0,
9008
9170
  validateFields: !1
9009
9171
  }
9010
9172
  });
@@ -9259,62 +9421,64 @@ function performEvent({
9259
9421
  nativeEventPrevented = actions.some((action) => action.type === "raise" || action.type === "execute") || !actions.some((action) => action.type === "forward");
9260
9422
  let undoStepCreated = !1;
9261
9423
  actions.some((action) => action.type === "execute") && (createUndoStep(editor), undoStepCreated = !0);
9262
- for (const action of actions) {
9263
- if (action.type === "effect") {
9264
- try {
9265
- action.effect({
9266
- send: sendBack
9424
+ const actionTypes = actions.map((action) => action.type), uniqueActionTypes = new Set(actionTypes), raiseGroup = actionTypes.length > 1 && uniqueActionTypes.size === 1 && uniqueActionTypes.has("raise"), executeGroup = actionTypes.length > 1 && uniqueActionTypes.size === 1 && uniqueActionTypes.has("execute");
9425
+ withoutNormalizingConditional(editor, () => raiseGroup || executeGroup, () => {
9426
+ for (const action of actions) {
9427
+ if (action.type === "effect") {
9428
+ try {
9429
+ action.effect({
9430
+ send: sendBack
9431
+ });
9432
+ } catch (error) {
9433
+ console.error(new Error(`Executing effect as a result of "${event.type}" failed due to: ${error.message}`));
9434
+ }
9435
+ continue;
9436
+ }
9437
+ if (action.type === "forward") {
9438
+ const remainingEventBehaviors2 = eventBehaviors.slice(eventBehaviorIndex + 1);
9439
+ performEvent({
9440
+ mode: mode === "execute" ? "execute" : "forward",
9441
+ behaviors,
9442
+ remainingEventBehaviors: remainingEventBehaviors2,
9443
+ event: action.event,
9444
+ editor,
9445
+ keyGenerator,
9446
+ schema: schema2,
9447
+ getSnapshot,
9448
+ nativeEvent,
9449
+ sendBack
9267
9450
  });
9268
- } catch (error) {
9269
- console.error(new Error(`Executing effect as a result of "${event.type}" failed due to: ${error.message}`));
9451
+ continue;
9452
+ }
9453
+ if (action.type === "raise") {
9454
+ performEvent({
9455
+ mode: mode === "execute" ? "execute" : "raise",
9456
+ behaviors,
9457
+ remainingEventBehaviors: mode === "execute" ? remainingEventBehaviors : behaviors,
9458
+ event: action.event,
9459
+ editor,
9460
+ keyGenerator,
9461
+ schema: schema2,
9462
+ getSnapshot,
9463
+ nativeEvent,
9464
+ sendBack
9465
+ });
9466
+ continue;
9270
9467
  }
9271
- continue;
9272
- }
9273
- if (action.type === "forward") {
9274
- const remainingEventBehaviors2 = eventBehaviors.slice(eventBehaviorIndex + 1);
9275
- performEvent({
9276
- mode: mode === "execute" ? "execute" : "forward",
9277
- behaviors,
9278
- remainingEventBehaviors: remainingEventBehaviors2,
9279
- event: action.event,
9280
- editor,
9281
- keyGenerator,
9282
- schema: schema2,
9283
- getSnapshot,
9284
- nativeEvent,
9285
- sendBack
9286
- });
9287
- continue;
9288
- }
9289
- if (action.type === "raise") {
9290
9468
  performEvent({
9291
- mode: mode === "execute" ? "execute" : "raise",
9469
+ mode: "execute",
9292
9470
  behaviors,
9293
- remainingEventBehaviors: mode === "execute" ? remainingEventBehaviors : behaviors,
9471
+ remainingEventBehaviors: [],
9294
9472
  event: action.event,
9295
9473
  editor,
9296
9474
  keyGenerator,
9297
9475
  schema: schema2,
9298
9476
  getSnapshot,
9299
- nativeEvent,
9477
+ nativeEvent: void 0,
9300
9478
  sendBack
9301
9479
  });
9302
- continue;
9303
9480
  }
9304
- performEvent({
9305
- mode: "execute",
9306
- behaviors,
9307
- remainingEventBehaviors: [],
9308
- event: action.event,
9309
- editor,
9310
- keyGenerator,
9311
- schema: schema2,
9312
- getSnapshot,
9313
- nativeEvent: void 0,
9314
- sendBack
9315
- });
9316
- }
9317
- undoStepCreated && clearUndoStep(editor);
9481
+ }), undoStepCreated && clearUndoStep(editor);
9318
9482
  }
9319
9483
  break;
9320
9484
  }