@portabletext/editor 2.1.11 → 2.2.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/index.js CHANGED
@@ -4,7 +4,7 @@ import { useEditor, EditorContext } from "./_chunks-es/use-editor.js";
4
4
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
5
  import { useSelector, useActorRef } from "@xstate/react";
6
6
  import noop from "lodash/noop.js";
7
- import { Element as Element$1, Text, Range, Editor, Node, Transforms, Path, Operation, Point, createEditor, deleteText } from "slate";
7
+ import { Element as Element$1, Text, Range, Editor, Node, Transforms, Path, Operation, deleteText, setSelection, Point, createEditor } from "slate";
8
8
  import { useSelected, useSlateSelector, useSlateStatic, withReact, ReactEditor, Slate, useSlate, Editable } from "slate-react";
9
9
  import debug$f from "debug";
10
10
  import { DOMEditor, isDOMNode, EDITOR_TO_PENDING_SELECTION } from "slate-dom";
@@ -1165,7 +1165,7 @@ const converterJson = {
1165
1165
  context: snapshot.context,
1166
1166
  block,
1167
1167
  options: {
1168
- refreshKeys: !0,
1168
+ refreshKeys: !1,
1169
1169
  validateFields: !1
1170
1170
  }
1171
1171
  });
@@ -1229,7 +1229,7 @@ function createConverterTextHtml(legacySchema) {
1229
1229
  block,
1230
1230
  options: {
1231
1231
  refreshKeys: !1,
1232
- validateFields: !0
1232
+ validateFields: !1
1233
1233
  }
1234
1234
  });
1235
1235
  return parsedBlock ? [parsedBlock] : [];
@@ -1277,7 +1277,7 @@ function createConverterTextPlain(legacySchema) {
1277
1277
  block,
1278
1278
  options: {
1279
1279
  refreshKeys: !1,
1280
- validateFields: !0
1280
+ validateFields: !1
1281
1281
  }
1282
1282
  });
1283
1283
  return parsedBlock ? [parsedBlock] : [];
@@ -3305,9 +3305,17 @@ const addAnnotationOperationImplementation = ({
3305
3305
  context,
3306
3306
  operation
3307
3307
  }) => {
3308
- const anchorBlockKey = getBlockKeyFromSelectionPoint(operation.at.anchor), focusBlockKey = getBlockKeyFromSelectionPoint(operation.at.focus), endBlockKey = operation.at.backward ? anchorBlockKey : focusBlockKey, endOffset = operation.at.backward ? operation.at.focus.offset : operation.at.anchor.offset;
3308
+ const anchorBlockKey = getBlockKeyFromSelectionPoint(operation.at.anchor), focusBlockKey = getBlockKeyFromSelectionPoint(operation.at.focus), startBlockKey = operation.at.backward ? focusBlockKey : anchorBlockKey, endBlockKey = operation.at.backward ? anchorBlockKey : focusBlockKey, endOffset = operation.at.backward ? operation.at.focus.offset : operation.at.anchor.offset;
3309
+ if (!startBlockKey)
3310
+ throw new Error("Failed to get start block key");
3309
3311
  if (!endBlockKey)
3310
3312
  throw new Error("Failed to get end block key");
3313
+ const startBlockIndex = operation.editor.blockIndexMap.get(startBlockKey);
3314
+ if (startBlockIndex === void 0)
3315
+ throw new Error("Failed to get start block index");
3316
+ const startBlock = operation.editor.value.at(startBlockIndex);
3317
+ if (!startBlock)
3318
+ throw new Error("Failed to get start block");
3311
3319
  const endBlockIndex = operation.editor.blockIndexMap.get(endBlockKey);
3312
3320
  if (endBlockIndex === void 0)
3313
3321
  throw new Error("Failed to get end block index");
@@ -3338,11 +3346,14 @@ const addAnnotationOperationImplementation = ({
3338
3346
  if (!range)
3339
3347
  throw new Error(`Failed to get Slate Range for selection ${JSON.stringify(operation.at)}`);
3340
3348
  const hanging = isTextBlock(context, endBlock) && endOffset === 0;
3341
- operation.editor.delete({
3349
+ deleteText(operation.editor, {
3342
3350
  at: range,
3343
3351
  reverse: operation.direction === "backward",
3344
3352
  unit: operation.unit,
3345
3353
  hanging
3354
+ }), operation.editor.selection && isTextBlock(context, startBlock) && isTextBlock(context, endBlock) && setSelection(operation.editor, {
3355
+ anchor: operation.editor.selection.focus,
3356
+ focus: operation.editor.selection.focus
3346
3357
  });
3347
3358
  }, insertInlineObjectOperationImplementation = ({
3348
3359
  context,
@@ -3434,19 +3445,19 @@ const addAnnotationOperationImplementation = ({
3434
3445
  if (!fragment)
3435
3446
  throw new Error(`Failed to convert block to Slate fragment ${JSON.stringify(parsedBlock)}`);
3436
3447
  insertBlock({
3448
+ context,
3437
3449
  block: fragment,
3438
3450
  placement: operation.placement,
3439
3451
  select: operation.select ?? "start",
3440
- editor: operation.editor,
3441
- schema: context.schema
3452
+ editor: operation.editor
3442
3453
  });
3443
3454
  };
3444
3455
  function insertBlock({
3456
+ context,
3445
3457
  block,
3446
3458
  placement,
3447
3459
  select,
3448
- editor,
3449
- schema
3460
+ editor
3450
3461
  }) {
3451
3462
  const [startBlock, startBlockPath] = getSelectionStartBlock({
3452
3463
  editor
@@ -3468,7 +3479,7 @@ function insertBlock({
3468
3479
  at: nextPath
3469
3480
  }), select === "start" ? Transforms.select(editor, Editor.start(editor, nextPath)) : select === "end" && Transforms.select(editor, Editor.end(editor, nextPath));
3470
3481
  } else {
3471
- if (lastBlock && isEqualToEmptyEditor([lastBlock], schema)) {
3482
+ if (lastBlock && isEqualToEmptyEditor([lastBlock], context.schema)) {
3472
3483
  Transforms.removeNodes(editor, {
3473
3484
  at: lastBlockPath
3474
3485
  }), Transforms.insertNodes(editor, [block], {
@@ -3519,14 +3530,14 @@ function insertBlock({
3519
3530
  node: block,
3520
3531
  path: [newSelection.anchor.path[0]]
3521
3532
  }) : newSelection;
3522
- select === "none" && adjustedSelection && Transforms.select(editor, adjustedSelection), focusBlock && isEqualToEmptyEditor([focusBlock], schema) && Transforms.removeNodes(editor, {
3533
+ select === "none" && adjustedSelection && Transforms.select(editor, adjustedSelection), focusBlock && isEqualToEmptyEditor([focusBlock], context.schema) && Transforms.removeNodes(editor, {
3523
3534
  at: focusBlockPath
3524
3535
  });
3525
3536
  return;
3526
3537
  }
3527
3538
  if (editor.isTextBlock(endBlock) && editor.isTextBlock(block)) {
3528
3539
  const selectionStartPoint = Range.start(currentSelection);
3529
- if (isEqualToEmptyEditor([endBlock], schema)) {
3540
+ if (isEqualToEmptyEditor([endBlock], context.schema)) {
3530
3541
  const currentSelection2 = editor.selection;
3531
3542
  Transforms.insertNodes(editor, [block], {
3532
3543
  at: endBlockPath,
@@ -3536,17 +3547,46 @@ function insertBlock({
3536
3547
  }), select === "start" ? Transforms.select(editor, selectionStartPoint) : select === "end" ? Transforms.select(editor, Editor.end(editor, endBlockPath)) : Transforms.select(editor, currentSelection2);
3537
3548
  return;
3538
3549
  }
3539
- if (Transforms.setNodes(editor, {
3540
- markDefs: [...endBlock.markDefs ?? [], ...block.markDefs ?? []]
3550
+ const endBlockChildKeys = endBlock.children.map((child) => child._key), endBlockMarkDefsKeys = endBlock.markDefs?.map((markDef) => markDef._key) ?? [], markDefKeyMap = /* @__PURE__ */ new Map(), adjustedMarkDefs = block.markDefs?.map((markDef) => {
3551
+ if (endBlockMarkDefsKeys.includes(markDef._key)) {
3552
+ const newKey = context.keyGenerator();
3553
+ return markDefKeyMap.set(markDef._key, newKey), {
3554
+ ...markDef,
3555
+ _key: newKey
3556
+ };
3557
+ }
3558
+ return markDef;
3559
+ }), adjustedChildren = block.children.map((child) => {
3560
+ if (isSpan(context, child)) {
3561
+ const marks = child.marks?.map((mark) => markDefKeyMap.get(mark) || mark) ?? [];
3562
+ if (!isEqual(child.marks, marks))
3563
+ return {
3564
+ ...child,
3565
+ _key: endBlockChildKeys.includes(child._key) ? context.keyGenerator() : child._key,
3566
+ marks
3567
+ };
3568
+ }
3569
+ return endBlockChildKeys.includes(child._key) ? {
3570
+ ...child,
3571
+ _key: context.keyGenerator()
3572
+ } : child;
3573
+ });
3574
+ Transforms.setNodes(editor, {
3575
+ markDefs: [...endBlock.markDefs ?? [], ...adjustedMarkDefs ?? []]
3541
3576
  }, {
3542
3577
  at: endBlockPath
3543
- }), select === "end") {
3544
- Transforms.insertFragment(editor, [block], {
3578
+ });
3579
+ const adjustedBlock = isEqual(block.children, adjustedChildren) ? block : {
3580
+ ...block,
3581
+ children: adjustedChildren
3582
+ };
3583
+ if (select === "end") {
3584
+ Transforms.insertFragment(editor, [adjustedBlock], {
3545
3585
  voids: !0
3546
3586
  });
3547
3587
  return;
3548
3588
  }
3549
- Transforms.insertFragment(editor, [block], {
3589
+ Transforms.insertFragment(editor, [adjustedBlock], {
3550
3590
  at: currentSelection,
3551
3591
  voids: !0
3552
3592
  }), select === "start" ? Transforms.select(editor, selectionStartPoint) : Point.equals(selectionStartPoint, endBlockEndPoint) || Transforms.select(editor, selectionStartPoint);
@@ -3556,9 +3596,7 @@ function insertBlock({
3556
3596
  Transforms.insertNodes(editor, [block], {
3557
3597
  at: endBlockPath,
3558
3598
  select: !1
3559
- }), (select === "start" || select === "end") && Transforms.select(editor, Editor.start(editor, endBlockPath)), isEmptyTextBlock({
3560
- schema
3561
- }, endBlock) && Transforms.removeNodes(editor, {
3599
+ }), (select === "start" || select === "end") && Transforms.select(editor, Editor.start(editor, endBlockPath)), isEmptyTextBlock(context, endBlock) && Transforms.removeNodes(editor, {
3562
3600
  at: Path.next(endBlockPath)
3563
3601
  });
3564
3602
  else if (Range.isCollapsed(currentSelection) && Point.equals(selectionEndPoint, endBlockEndPoint2)) {
@@ -4094,6 +4132,58 @@ function createWithObjectKeys(editorActor) {
4094
4132
  });
4095
4133
  return;
4096
4134
  }
4135
+ if (operation.type === "merge_node") {
4136
+ const index = operation.path[operation.path.length - 1], prevPath = Path.previous(operation.path), prevIndex = prevPath[prevPath.length - 1];
4137
+ if (operation.path.length !== 1 || prevPath.length !== 1) {
4138
+ apply2(operation);
4139
+ return;
4140
+ }
4141
+ const block = editor.value.at(index), previousBlock = editor.value.at(prevIndex);
4142
+ if (!block || !previousBlock) {
4143
+ apply2(operation);
4144
+ return;
4145
+ }
4146
+ if (!isTextBlock(editorActor.getSnapshot().context, block) || !isTextBlock(editorActor.getSnapshot().context, previousBlock)) {
4147
+ apply2(operation);
4148
+ return;
4149
+ }
4150
+ const previousBlockChildKeys = previousBlock.children.map((child) => child._key), previousBlockMarkDefKeys = previousBlock.markDefs?.map((markDef) => markDef._key) ?? [], markDefKeyMap = /* @__PURE__ */ new Map(), adjustedMarkDefs = block.markDefs?.map((markDef) => {
4151
+ if (previousBlockMarkDefKeys.includes(markDef._key)) {
4152
+ const newKey = editorActor.getSnapshot().context.keyGenerator();
4153
+ return markDefKeyMap.set(markDef._key, newKey), {
4154
+ ...markDef,
4155
+ _key: newKey
4156
+ };
4157
+ }
4158
+ return markDef;
4159
+ });
4160
+ let childIndex = 0;
4161
+ for (const child of block.children) {
4162
+ if (isSpan(editorActor.getSnapshot().context, child)) {
4163
+ const marks = child.marks?.map((mark) => markDefKeyMap.get(mark) || mark) ?? [];
4164
+ isEqual(child.marks, marks) || Transforms.setNodes(editor, {
4165
+ marks
4166
+ }, {
4167
+ at: [index, childIndex]
4168
+ });
4169
+ }
4170
+ previousBlockChildKeys.includes(child._key) && Transforms.setNodes(editor, {
4171
+ _key: editorActor.getSnapshot().context.keyGenerator()
4172
+ }, {
4173
+ at: [index, childIndex]
4174
+ }), childIndex++;
4175
+ }
4176
+ apply2({
4177
+ ...operation,
4178
+ properties: {
4179
+ ...operation.properties,
4180
+ // Make sure the adjusted markDefs are carried along for the merge
4181
+ // operation
4182
+ markDefs: adjustedMarkDefs
4183
+ }
4184
+ });
4185
+ return;
4186
+ }
4097
4187
  apply2(operation);
4098
4188
  }, editor.normalizeNode = (entry) => {
4099
4189
  const [node, path] = entry;
@@ -6996,6 +7086,57 @@ const MAX_LIST_LEVEL = 10, clearListOnBackspace = defineBehavior({
6996
7086
  at: selection
6997
7087
  })]]
6998
7088
  }),
7089
+ defineBehavior({
7090
+ on: "split",
7091
+ guard: ({
7092
+ snapshot
7093
+ }) => {
7094
+ const selection = snapshot.context.selection;
7095
+ if (!selection || isSelectionCollapsed(selection))
7096
+ return !1;
7097
+ const selectionStartBlock = getSelectionStartBlock$1(snapshot), selectionEndBlock = getSelectionEndBlock$1(snapshot);
7098
+ if (!selectionStartBlock || !selectionEndBlock || selectionStartBlock.node._key === selectionEndBlock.node._key)
7099
+ return !1;
7100
+ const startPoint = getSelectionStartPoint(selection), startBlockEndPoint = getBlockEndPoint({
7101
+ context: snapshot.context,
7102
+ block: selectionStartBlock
7103
+ }), endPoint = getSelectionEndPoint(selection), endBlockStartPoint = getBlockStartPoint({
7104
+ context: snapshot.context,
7105
+ block: selectionEndBlock
7106
+ }), blocksInBetween = getSelectedValue(snapshot).filter((block) => block._key !== selectionStartBlock.node._key && block._key !== selectionEndBlock.node._key);
7107
+ return {
7108
+ startPoint,
7109
+ startBlockEndPoint,
7110
+ endPoint,
7111
+ endBlockStartPoint,
7112
+ blocksInBetween
7113
+ };
7114
+ },
7115
+ actions: [(_, {
7116
+ startPoint,
7117
+ startBlockEndPoint,
7118
+ endPoint,
7119
+ endBlockStartPoint,
7120
+ blocksInBetween
7121
+ }) => [raise({
7122
+ type: "delete",
7123
+ at: {
7124
+ anchor: startPoint,
7125
+ focus: startBlockEndPoint
7126
+ }
7127
+ }), ...blocksInBetween.map((block) => raise({
7128
+ type: "delete.block",
7129
+ at: [{
7130
+ _key: block._key
7131
+ }]
7132
+ })), raise({
7133
+ type: "delete",
7134
+ at: {
7135
+ anchor: endBlockStartPoint,
7136
+ focus: endPoint
7137
+ }
7138
+ })]]
7139
+ }),
6999
7140
  defineBehavior({
7000
7141
  on: "split",
7001
7142
  guard: ({
@@ -7042,8 +7183,8 @@ const MAX_LIST_LEVEL = 10, clearListOnBackspace = defineBehavior({
7042
7183
  }),
7043
7184
  context: snapshot.context,
7044
7185
  options: {
7045
- refreshKeys: !0,
7046
- validateFields: !0
7186
+ refreshKeys: !1,
7187
+ validateFields: !1
7047
7188
  }
7048
7189
  });
7049
7190
  return newTextBlock ? {
@@ -11370,8 +11511,8 @@ const debug = debugWithName("component:Editable"), PortableTextEditable = forwar
11370
11511
  },
11371
11512
  blocks: result_1.insert,
11372
11513
  options: {
11373
- refreshKeys: !0,
11374
- validateFields: !0
11514
+ refreshKeys: !1,
11515
+ validateFields: !1
11375
11516
  }
11376
11517
  }),
11377
11518
  placement: "auto"
@@ -11752,12 +11893,12 @@ function defineSchema(definition) {
11752
11893
  return definition;
11753
11894
  }
11754
11895
  const usePortableTextEditorSelection = () => {
11755
- const $ = c(3), editorActor = useContext(EditorActorContext), [selection, setSelection] = useState(null);
11896
+ const $ = c(3), editorActor = useContext(EditorActorContext), [selection, setSelection2] = useState(null);
11756
11897
  let t0, t1;
11757
11898
  return $[0] !== editorActor ? (t0 = () => {
11758
11899
  const subscription = editorActor.on("selection", (event) => {
11759
11900
  startTransition(() => {
11760
- setSelection(event.selection);
11901
+ setSelection2(event.selection);
11761
11902
  });
11762
11903
  });
11763
11904
  return () => {