@portabletext/editor 8.1.0 → 8.1.2

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
@@ -1,9 +1,9 @@
1
- import { a as getNodeChildren, i as getChildren, l as serializePath, n as parentPath, r as getNode, t as getParent, u as isKeyedSegment } from "./get-parent-Ci5241qs.js";
2
- import { C as getAncestors, S as hasNode, _ as comparePoints, a as isInline, b as isEditableContainer, c as isSpanNode, d as resolveChildEntryIndex, f as isAncestorPath, g as isAfterPoint, h as isBackwardRange, i as getEnclosingBlock, l as getSibling, m as rangeEdges, n as getEnclosingContainer, o as getBlock, p as isTextBlockNode, s as isBlock, t as getPathSubSchema, u as getNodes, v as comparePaths, x as resolveContainerAt, y as isObject } from "./get-path-sub-schema-CZd9VcVM.js";
3
- import { _ as getAncestor, a as getTextBlock, c as pathContains, d as isRange, f as isPoint, g as isLeafObject, h as getLeaf, i as getFirstChild, l as getSpan, m as isPath, n as getUnionSchema, o as rangeIntersects, p as isObject$1, r as getLastChild, s as isBeforePoint, t as getContainer, u as getText } from "./get-container-D1nM_ww9.js";
4
- import { a as parseBlocks, b as childAtTextOffset, c as parseSpan, d as getSelectionEndPoint, f as isSelectionCollapsed, g as isEqualSelectionPoints, h as getBlockKeyFromSelectionPoint, i as parseBlock, l as defaultKeyGenerator, m as getBlockEndPoint, n as isListBlock, o as parseInlineObject, p as getBlockStartPoint, r as parseAnnotation, s as parseMarkDefs, u as getSelectionStartPoint, v as blockOffsetToSpanSelectionPoint, x as textOffsetOfChild } from "./util.slice-blocks-B2fZcNok.js";
5
- import { A as getSelectionEndPoint$1, B as getFocusBlock, C as getSelectedTextBlocks, D as getPreviousSpan, F as getSelectionEndBlock, G as rangesOverlap, H as getFocusInlineObject, I as getFragment, L as getSelectedValue, M as isSelectionCollapsed$1, N as isOverlappingSelection, O as getSelectionStartPoint$1, P as getSelectionStartBlock, R as getRootAcceptedTypes, S as getActiveDecorators, T as getMarkState, U as getFocusChild, V as getFocusSpan, a as isActiveListItem, b as getActiveAnnotations, c as getSelectionEndChild, d as getLastBlock, f as getFocusListBlock, i as isActiveStyle, j as isSelectionExpanded, k as getNextSpan, l as getPreviousBlock, m as getCaretWordSelection, n as isAtTheStartOfBlock, o as isActiveDecorator, p as getFocusBlockObject, r as isAtTheEndOfBlock, s as getSelectionStartChild, t as isSelectingEntireBlocks, u as getNextBlock, w as getActiveAnnotationsMarks, x as isActiveAnnotation, z as getFocusTextBlock } from "./selector.is-selecting-entire-blocks-DPnzucrd.js";
6
- import { n as isEmptyTextBlock, r as getTextBlockText, t as isEqualSelections } from "./util.is-equal-selections-N1hxVUbE.js";
1
+ import { a as getChildren, d as isKeyedSegment, i as resolveNode, n as parentPath, o as getNodeChildren, r as getNode, t as getParent, u as serializePath } from "./get-parent-DgaKcy8-.js";
2
+ import { C as getAncestors, S as hasNode, _ as comparePoints, a as isInline, b as isEditableContainer, c as isSpanNode, d as resolveChildEntryIndex, f as isAncestorPath, g as isAfterPoint, h as isBackwardRange, i as getEnclosingBlock, l as getSibling, m as rangeEdges, n as getEnclosingContainer, o as getBlock, p as isTextBlockNode, s as isBlock, t as getPathSubSchema, u as getNodes, v as comparePaths, x as resolveContainerAt, y as isObject } from "./get-path-sub-schema-Dd0QYZ0m.js";
3
+ import { _ as getAncestor, a as getTextBlock, c as pathContains, d as isRange, f as isPoint, g as isLeafObject, h as getLeaf, i as getFirstChild, l as getSpan, m as isPath, n as getUnionSchema, o as rangeIntersects, p as isObject$1, r as getLastChild, s as isBeforePoint, t as getContainer, u as getText } from "./get-container-D2pN5Npr.js";
4
+ import { a as parseBlocks, b as childAtTextOffset, c as parseSpan, d as getSelectionEndPoint, f as isSelectionCollapsed, g as isEqualSelectionPoints, h as getBlockKeyFromSelectionPoint, i as parseBlock, l as defaultKeyGenerator, m as getBlockEndPoint, n as isListBlock, o as parseInlineObject, p as getBlockStartPoint, r as parseAnnotation, s as parseMarkDefs, u as getSelectionStartPoint, v as blockOffsetToSpanSelectionPoint, x as textOffsetOfChild } from "./util.slice-blocks-_ElaB53f.js";
5
+ import { A as getSelectionEndPoint$1, B as getFocusBlock, C as getSelectedTextBlocks, D as getPreviousSpan, F as getSelectionEndBlock, G as rangesOverlap, H as getFocusInlineObject, I as getFragment, L as getSelectedValue, M as isSelectionCollapsed$1, N as isOverlappingSelection, O as getSelectionStartPoint$1, P as getSelectionStartBlock, R as getRootAcceptedTypes, S as getActiveDecorators, T as getMarkState, U as getFocusChild, V as getFocusSpan, a as isActiveListItem, b as getActiveAnnotations, c as getSelectionEndChild, d as getLastBlock, f as getFocusListBlock, i as isActiveStyle, j as isSelectionExpanded, k as getNextSpan, l as getPreviousBlock, m as getCaretWordSelection, n as isAtTheStartOfBlock, o as isActiveDecorator, p as getFocusBlockObject, r as isAtTheEndOfBlock, s as getSelectionStartChild, t as isSelectingEntireBlocks, u as getNextBlock, w as getActiveAnnotationsMarks, x as isActiveAnnotation, z as getFocusTextBlock } from "./selector.is-selecting-entire-blocks-BFhnnkHf.js";
6
+ import { n as isEmptyTextBlock, r as getTextBlockText, t as isEqualSelections } from "./util.is-equal-selections-BdK98okY.js";
7
7
  import { a as raise$1, i as forward, n as effect, t as defineBehavior } from "./behavior.types.behavior-BxSLb73I.js";
8
8
  import { n as EditorContext$1, t as useEditor } from "./use-editor-CwNeVwVC.js";
9
9
  import { c } from "react/compiler-runtime";
@@ -465,17 +465,19 @@ const IS_IOS = typeof navigator < "u" && typeof window < "u" && /iPad|iPhone|iPo
465
465
  },
466
466
  toEditorSelection: (editor, domRange, options) => {
467
467
  let { exactMatch, suppressThrow } = options, el = isDOMSelection(domRange) ? domRange.anchorNode : domRange.startContainer, anchorNode = null, anchorOffset = 0, focusNode = null, focusOffset = 0, isCollapsed = !1;
468
- if (el) if (isDOMSelection(domRange)) {
469
- if (IS_FIREFOX && domRange.rangeCount > 1) {
470
- focusNode = domRange.focusNode;
471
- let firstRange = domRange.getRangeAt(0), lastRange = domRange.getRangeAt(domRange.rangeCount - 1);
472
- if (focusNode instanceof HTMLTableRowElement && firstRange.startContainer instanceof HTMLTableRowElement && lastRange.startContainer instanceof HTMLTableRowElement) {
473
- let getLastChildren = (element) => element.childElementCount > 0 ? getLastChildren(element.children[0]) : element, firstNodeRow = firstRange.startContainer, lastNodeRow = lastRange.startContainer, firstNode = getLastChildren(firstNodeRow.children[firstRange.startOffset]), lastNode = getLastChildren(lastNodeRow.children[lastRange.startOffset]);
474
- focusOffset = 0, anchorNode = lastNode.childNodes.length > 0 ? lastNode.childNodes[0] ?? null : lastNode, focusNode = firstNode.childNodes.length > 0 ? firstNode.childNodes[0] ?? null : firstNode, anchorOffset = lastNode instanceof HTMLElement ? lastNode.innerHTML.length : 0;
475
- } else firstRange.startContainer === focusNode ? (anchorNode = lastRange.endContainer, anchorOffset = lastRange.endOffset, focusOffset = firstRange.startOffset) : (anchorNode = firstRange.startContainer, anchorOffset = firstRange.endOffset, focusOffset = lastRange.startOffset);
476
- } else anchorNode = domRange.anchorNode, anchorOffset = domRange.anchorOffset, focusNode = domRange.focusNode, focusOffset = domRange.focusOffset;
477
- isCollapsed = IS_CHROME && hasShadowRoot(anchorNode) || IS_FIREFOX ? domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset : domRange.isCollapsed;
478
- } else anchorNode = domRange.startContainer, anchorOffset = domRange.startOffset, focusNode = domRange.endContainer, focusOffset = domRange.endOffset, isCollapsed = domRange.collapsed;
468
+ if (el) {
469
+ if (isDOMSelection(domRange)) {
470
+ if (IS_FIREFOX && domRange.rangeCount > 1) {
471
+ focusNode = domRange.focusNode;
472
+ let firstRange = domRange.getRangeAt(0), lastRange = domRange.getRangeAt(domRange.rangeCount - 1);
473
+ if (focusNode instanceof HTMLTableRowElement && firstRange.startContainer instanceof HTMLTableRowElement && lastRange.startContainer instanceof HTMLTableRowElement) {
474
+ let getLastChildren = (element) => element.childElementCount > 0 ? getLastChildren(element.children[0]) : element, firstNodeRow = firstRange.startContainer, lastNodeRow = lastRange.startContainer, firstNode = getLastChildren(firstNodeRow.children[firstRange.startOffset]), lastNode = getLastChildren(lastNodeRow.children[lastRange.startOffset]);
475
+ focusOffset = 0, anchorNode = lastNode.childNodes.length > 0 ? lastNode.childNodes[0] ?? null : lastNode, focusNode = firstNode.childNodes.length > 0 ? firstNode.childNodes[0] ?? null : firstNode, anchorOffset = lastNode instanceof HTMLElement ? lastNode.innerHTML.length : 0;
476
+ } else firstRange.startContainer === focusNode ? (anchorNode = lastRange.endContainer, anchorOffset = lastRange.endOffset, focusOffset = firstRange.startOffset) : (anchorNode = firstRange.startContainer, anchorOffset = firstRange.endOffset, focusOffset = lastRange.startOffset);
477
+ } else anchorNode = domRange.anchorNode, anchorOffset = domRange.anchorOffset, focusNode = domRange.focusNode, focusOffset = domRange.focusOffset;
478
+ isCollapsed = IS_CHROME && hasShadowRoot(anchorNode) || IS_FIREFOX ? domRange.anchorNode === domRange.focusNode && domRange.anchorOffset === domRange.focusOffset : domRange.isCollapsed;
479
+ } else anchorNode = domRange.startContainer, anchorOffset = domRange.startOffset, focusNode = domRange.endContainer, focusOffset = domRange.endOffset, isCollapsed = domRange.collapsed;
480
+ }
479
481
  if (anchorNode == null || focusNode == null || anchorOffset == null || focusOffset == null) {
480
482
  if (suppressThrow) return null;
481
483
  throw Error(`Cannot map DOM range to an editor selection: ${domRange}`);
@@ -2863,12 +2865,14 @@ const RestoreDOM = IS_ANDROID ? RestoreDOMComponent : ({ children }) => /* @__PU
2863
2865
  exactMatch: !1,
2864
2866
  suppressThrow: !0
2865
2867
  });
2866
- if (range) if (!editor.composing && !androidInputManager?.hasPendingChanges() && !androidInputManager?.isFlushing()) {
2867
- if (editor.select(range), domSelection.isCollapsed && anchorNode && anchorNode.nodeType === Node.ELEMENT_NODE) try {
2868
- let canonicalRange = DOMEditor.toDOMRange(editor, range);
2869
- domSelection.setBaseAndExtent(canonicalRange.startContainer, canonicalRange.startOffset, canonicalRange.startContainer, canonicalRange.startOffset);
2870
- } catch {}
2871
- } else androidInputManager?.handleUserSelect(range);
2868
+ if (range) {
2869
+ if (!editor.composing && !androidInputManager?.hasPendingChanges() && !androidInputManager?.isFlushing()) {
2870
+ if (editor.select(range), domSelection.isCollapsed && anchorNode && anchorNode.nodeType === Node.ELEMENT_NODE) try {
2871
+ let canonicalRange = DOMEditor.toDOMRange(editor, range);
2872
+ domSelection.setBaseAndExtent(canonicalRange.startContainer, canonicalRange.startOffset, canonicalRange.startContainer, canonicalRange.startOffset);
2873
+ } catch {}
2874
+ } else androidInputManager?.handleUserSelect(range);
2875
+ }
2872
2876
  }
2873
2877
  readOnly && (!anchorNodeSelectable || !focusNodeInEditor) && deselect(editor);
2874
2878
  }
@@ -5644,11 +5648,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5644
5648
  }, $[105] = editorActor, $[106] = editorEngine, $[107] = onDragStart, $[108] = readOnly, $[109] = t28) : t28 = $[109];
5645
5649
  let handleDragStart = t28, t29;
5646
5650
  $[110] !== editorActor || $[111] !== editorEngine || $[112] !== onDrag ? (t29 = (event_9) => {
5647
- if (onDrag?.(event_9), !(event_9.isDefaultPrevented() || event_9.isPropagationStopped()) && getEventPosition({
5648
- editorActor,
5649
- editorEngine,
5650
- event: event_9.nativeEvent
5651
- })) return editorActor.send({
5651
+ if (onDrag?.(event_9), !(event_9.isDefaultPrevented() || event_9.isPropagationStopped()) && !(editorActor.getSnapshot().matches({ setup: "setting up" }) || !DOMEditor.hasTarget(editorEngine, event_9.target))) return editorActor.send({
5652
5652
  type: "behavior event",
5653
5653
  behaviorEvent: {
5654
5654
  type: "drag.drag",
@@ -5671,17 +5671,17 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5671
5671
  let handleDragEnd = t30, t31;
5672
5672
  $[118] !== editorActor || $[119] !== editorEngine || $[120] !== onDragEnter ? (t31 = (event_11) => {
5673
5673
  if (onDragEnter?.(event_11), event_11.isDefaultPrevented() || event_11.isPropagationStopped()) return;
5674
- let position_6 = getEventPosition({
5674
+ let position_5 = getEventPosition({
5675
5675
  editorActor,
5676
5676
  editorEngine,
5677
5677
  event: event_11.nativeEvent
5678
5678
  });
5679
- if (position_6) return editorActor.send({
5679
+ if (position_5) return editorActor.send({
5680
5680
  type: "behavior event",
5681
5681
  behaviorEvent: {
5682
5682
  type: "drag.dragenter",
5683
5683
  originEvent: { dataTransfer: event_11.dataTransfer },
5684
- position: position_6
5684
+ position: position_5
5685
5685
  },
5686
5686
  editor: editorEngine
5687
5687
  }), !0;
@@ -5689,18 +5689,18 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5689
5689
  let handleDragEnter = t31, t32;
5690
5690
  $[122] !== editorActor || $[123] !== editorEngine || $[124] !== onDragOver ? (t32 = (event_12) => {
5691
5691
  if (onDragOver?.(event_12), event_12.isDefaultPrevented() || event_12.isPropagationStopped()) return;
5692
- let position_7 = getEventPosition({
5692
+ let position_6 = getEventPosition({
5693
5693
  editorActor,
5694
5694
  editorEngine,
5695
5695
  event: event_12.nativeEvent
5696
5696
  });
5697
- if (position_7) return editorActor.send({
5697
+ if (position_6) return editorActor.send({
5698
5698
  type: "behavior event",
5699
5699
  behaviorEvent: {
5700
5700
  type: "drag.dragover",
5701
5701
  originEvent: { dataTransfer: event_12.dataTransfer },
5702
5702
  dragOrigin: editorActor.getSnapshot().context.internalDrag?.origin,
5703
- position: position_7
5703
+ position: position_6
5704
5704
  },
5705
5705
  editor: editorEngine,
5706
5706
  nativeEvent: event_12
@@ -5709,12 +5709,12 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5709
5709
  let handleDragOver = t32, t33;
5710
5710
  $[126] !== editorActor || $[127] !== editorEngine || $[128] !== onDrop ? (t33 = (event_13) => {
5711
5711
  if (onDrop?.(event_13), event_13.isDefaultPrevented() || event_13.isPropagationStopped()) return;
5712
- let position_8 = getEventPosition({
5712
+ let position_7 = getEventPosition({
5713
5713
  editorActor,
5714
5714
  editorEngine,
5715
5715
  event: event_13.nativeEvent
5716
5716
  });
5717
- if (!position_8) {
5717
+ if (!position_7) {
5718
5718
  console.warn("Could not find position for drop event");
5719
5719
  return;
5720
5720
  }
@@ -5724,7 +5724,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5724
5724
  type: "drag.drop",
5725
5725
  originEvent: { dataTransfer: event_13.dataTransfer },
5726
5726
  dragOrigin: editorActor.getSnapshot().context.internalDrag?.origin,
5727
- position: position_8
5727
+ position: position_7
5728
5728
  },
5729
5729
  editor: editorEngine,
5730
5730
  nativeEvent: event_13
@@ -5732,11 +5732,7 @@ const PortableTextEditable = forwardRef(function PortableTextEditable(props, for
5732
5732
  }, $[126] = editorActor, $[127] = editorEngine, $[128] = onDrop, $[129] = t33) : t33 = $[129];
5733
5733
  let handleDrop = t33, t34;
5734
5734
  $[130] !== editorActor || $[131] !== editorEngine || $[132] !== onDragLeave ? (t34 = (event_14) => {
5735
- if (onDragLeave?.(event_14), !(event_14.isDefaultPrevented() || event_14.isPropagationStopped()) && getEventPosition({
5736
- editorActor,
5737
- editorEngine,
5738
- event: event_14.nativeEvent
5739
- })) return editorActor.send({
5735
+ if (onDragLeave?.(event_14), !(event_14.isDefaultPrevented() || event_14.isPropagationStopped()) && !(editorActor.getSnapshot().matches({ setup: "setting up" }) || !DOMEditor.hasTarget(editorEngine, event_14.target))) return editorActor.send({
5740
5736
  type: "behavior event",
5741
5737
  behaviorEvent: {
5742
5738
  type: "drag.dragleave",
@@ -6945,14 +6941,15 @@ function applyOperation(editor, op) {
6945
6941
  typeof value == "object" && value && !Array.isArray(value) && modifyDescendant(editor, setNodePath, () => value), transformSelection = !0;
6946
6942
  break;
6947
6943
  }
6948
- if (getNode(editor.snapshot, setNodePath)) if (setPropertyPath.length === 1) {
6949
- let propertyName = setPropertyPath[0];
6950
- modifyDescendant(editor, setNodePath, (node) => ({
6951
- ...node,
6952
- [propertyName]: value
6953
- }));
6954
- } else modifyDescendant(editor, setNodePath, (node) => deepSet(node, setPropertyPath, value));
6955
- else {
6944
+ if (getNode(editor.snapshot, setNodePath)) {
6945
+ if (setPropertyPath.length === 1) {
6946
+ let propertyName = setPropertyPath[0];
6947
+ modifyDescendant(editor, setNodePath, (node) => ({
6948
+ ...node,
6949
+ [propertyName]: value
6950
+ }));
6951
+ } else modifyDescendant(editor, setNodePath, (node) => deepSet(node, setPropertyPath, value));
6952
+ } else {
6956
6953
  let blockSegment = findBlockSegment(path);
6957
6954
  if (!blockSegment) break;
6958
6955
  let blockIndex = resolveBlockIndex(editor, blockSegment);
@@ -7042,14 +7039,15 @@ function applyOperation(editor, op) {
7042
7039
  value: previousValue
7043
7040
  };
7044
7041
  }
7045
- if (getNode(editor.snapshot, unsetNodePath)) if (unsetPropertyPath.length === 1) {
7046
- let propertyName = unsetPropertyPath[0];
7047
- modifyDescendant(editor, unsetNodePath, (node) => {
7048
- let newNode = { ...node };
7049
- return delete newNode[propertyName], newNode;
7050
- });
7051
- } else modifyDescendant(editor, unsetNodePath, (node) => deepUnset(node, unsetPropertyPath));
7052
- else {
7042
+ if (getNode(editor.snapshot, unsetNodePath)) {
7043
+ if (unsetPropertyPath.length === 1) {
7044
+ let propertyName = unsetPropertyPath[0];
7045
+ modifyDescendant(editor, unsetNodePath, (node) => {
7046
+ let newNode = { ...node };
7047
+ return delete newNode[propertyName], newNode;
7048
+ });
7049
+ } else modifyDescendant(editor, unsetNodePath, (node) => deepUnset(node, unsetPropertyPath));
7050
+ } else {
7053
7051
  let blockSegment = findBlockSegment(path);
7054
7052
  if (!blockSegment) break;
7055
7053
  let blockIndex = resolveBlockIndex(editor, blockSegment);
@@ -7253,23 +7251,25 @@ const apply$1 = (editor, op) => {
7253
7251
  for (let ref of editor.pathRefs) PathRef.transform(ref, op);
7254
7252
  for (let ref of editor.pointRefs) PointRef.transform(ref, op);
7255
7253
  for (let ref of editor.rangeRefs) transformRangeRef(ref, op, editor.snapshot.context);
7256
- if (applyOperation(editor, op), updateDirtyPaths(editor, getDirtyPaths(editor.snapshot.context, op)), editor.operations.push(op), normalize(editor, { operation: op }), op.type === "set.selection") if (op.properties && op.newProperties && op.properties.anchor && op.properties.focus && op.newProperties.anchor && op.newProperties.focus) {
7257
- let previousSelectionIsCollapsed = isCollapsedRange({
7258
- anchor: op.properties.anchor,
7259
- focus: op.properties.focus
7260
- }), newSelectionIsCollapsed = isCollapsedRange({
7261
- anchor: op.newProperties.anchor,
7262
- focus: op.newProperties.focus
7263
- });
7264
- if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
7265
- let focusSpan = getSpan(editor.snapshot, op.properties.focus.path)?.node, newFocusSpan = getSpan(editor.snapshot, op.newProperties.focus.path)?.node, sameParent = pathEquals(parentPath(op.properties.focus.path), parentPath(op.newProperties.focus.path)), movedToNextSpan = !1, movedToPreviousSpan = !1;
7266
- if (sameParent && focusSpan && newFocusSpan) {
7267
- let nextSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "next" }), previousSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "previous" });
7268
- movedToNextSpan = nextSibling !== void 0 && pathEquals(nextSibling.path, op.newProperties.focus.path) && focusSpan.text.length === op.properties.focus.offset && op.newProperties.focus.offset === 0, movedToPreviousSpan = previousSibling !== void 0 && pathEquals(previousSibling.path, op.newProperties.focus.path) && op.properties.focus.offset === 0 && newFocusSpan.text.length === op.newProperties.focus.offset;
7254
+ if (applyOperation(editor, op), updateDirtyPaths(editor, getDirtyPaths(editor.snapshot.context, op)), editor.operations.push(op), normalize(editor, { operation: op }), op.type === "set.selection") {
7255
+ if (op.properties && op.newProperties && op.properties.anchor && op.properties.focus && op.newProperties.anchor && op.newProperties.focus) {
7256
+ let previousSelectionIsCollapsed = isCollapsedRange({
7257
+ anchor: op.properties.anchor,
7258
+ focus: op.properties.focus
7259
+ }), newSelectionIsCollapsed = isCollapsedRange({
7260
+ anchor: op.newProperties.anchor,
7261
+ focus: op.newProperties.focus
7262
+ });
7263
+ if (previousSelectionIsCollapsed && newSelectionIsCollapsed) {
7264
+ let focusSpan = getSpan(editor.snapshot, op.properties.focus.path)?.node, newFocusSpan = getSpan(editor.snapshot, op.newProperties.focus.path)?.node, sameParent = pathEquals(parentPath(op.properties.focus.path), parentPath(op.newProperties.focus.path)), movedToNextSpan = !1, movedToPreviousSpan = !1;
7265
+ if (sameParent && focusSpan && newFocusSpan) {
7266
+ let nextSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "next" }), previousSibling = getSibling(editor.snapshot, op.properties.focus.path, { direction: "previous" });
7267
+ movedToNextSpan = nextSibling !== void 0 && pathEquals(nextSibling.path, op.newProperties.focus.path) && focusSpan.text.length === op.properties.focus.offset && op.newProperties.focus.offset === 0, movedToPreviousSpan = previousSibling !== void 0 && pathEquals(previousSibling.path, op.newProperties.focus.path) && op.properties.focus.offset === 0 && newFocusSpan.text.length === op.newProperties.focus.offset;
7268
+ }
7269
+ !movedToNextSpan && !movedToPreviousSpan && (editor.snapshot.decoratorState = {});
7269
7270
  }
7270
- !movedToNextSpan && !movedToPreviousSpan && (editor.snapshot.decoratorState = {});
7271
- }
7272
- } else editor.snapshot.decoratorState = {};
7271
+ } else editor.snapshot.decoratorState = {};
7272
+ }
7273
7273
  editor.flushing || (editor.flushing = !0, Promise.resolve().then(() => {
7274
7274
  editor.flushing = !1, editor.onChange({ operation: op }), editor.operations = [];
7275
7275
  })), operationEvent && emitOperationEvent(editor.operationListeners.after, operationEvent);
@@ -7662,6 +7662,49 @@ function transformPointForMerge(point, mergePath, prevKey, position) {
7662
7662
  };
7663
7663
  }
7664
7664
  /**
7665
+ * Apply property changes at a known path using primitive `set` and `unset`
7666
+ * operations.
7667
+ *
7668
+ * Properties set to `null` are treated as deletions.
7669
+ * When `_key` is among the properties, it is processed first so that
7670
+ * downstream patch consumers see the key change before any property
7671
+ * mutations that reference the new key.
7672
+ */
7673
+ function applyNodeProperties(editor, props, path) {
7674
+ let result = resolveNode(editor.snapshot, path);
7675
+ if (result.status === "unreachable") throw Error(`Unable to apply properties at structurally unreachable path ${safeStringify(path)}`);
7676
+ if (result.status === "missing") return;
7677
+ let nodeRecord = result.entry.node, propsRecord = props, keys = Object.keys(propsRecord), keyIndex = keys.indexOf("_key");
7678
+ keyIndex !== -1 && (keys.splice(keyIndex, 1), keys.unshift("_key"));
7679
+ let currentPath = path;
7680
+ for (let key of keys) if (propsRecord[key] !== nodeRecord[key]) {
7681
+ if (propsRecord[key] != null) {
7682
+ let hadProperty = nodeRecord.hasOwnProperty(key), lastSegment = currentPath[currentPath.length - 1], renamedPath = key === "_key" && typeof propsRecord[key] == "string" && isKeyedSegment(lastSegment) ? [...currentPath.slice(0, -1), { _key: propsRecord[key] }] : void 0, inversePath = renamedPath ? [...renamedPath, key] : [...currentPath, key];
7683
+ editor.apply({
7684
+ type: "set",
7685
+ path: [...currentPath, key],
7686
+ value: propsRecord[key],
7687
+ inverse: hadProperty ? {
7688
+ type: "set",
7689
+ path: inversePath,
7690
+ value: nodeRecord[key]
7691
+ } : {
7692
+ type: "unset",
7693
+ path: inversePath
7694
+ }
7695
+ }), renamedPath && (currentPath = renamedPath);
7696
+ } else nodeRecord.hasOwnProperty(key) && editor.apply({
7697
+ type: "unset",
7698
+ path: [...currentPath, key],
7699
+ inverse: {
7700
+ type: "set",
7701
+ path: [...currentPath, key],
7702
+ value: nodeRecord[key]
7703
+ }
7704
+ });
7705
+ }
7706
+ }
7707
+ /**
7665
7708
  * Create a placeholder text block -- the empty initial block used when the
7666
7709
  * editor value is empty or when a container needs a default child.
7667
7710
  *
@@ -7689,46 +7732,6 @@ function resolveDefaultStyle(snapshot, path) {
7689
7732
  return path ? getPathSubSchema(snapshot, path).styles[0]?.name ?? rootFallback : rootFallback;
7690
7733
  }
7691
7734
  /**
7692
- * Apply property changes at a known path using primitive `set` and `unset`
7693
- * operations.
7694
- *
7695
- * Properties set to `null` are treated as deletions.
7696
- * When `_key` is among the properties, it is processed first so that
7697
- * downstream patch consumers see the key change before any property
7698
- * mutations that reference the new key.
7699
- */
7700
- function setNodeProperties(editor, props, path) {
7701
- let nodeEntry = getNode(editor.snapshot, path);
7702
- if (!nodeEntry) return;
7703
- let nodeRecord = nodeEntry.node, propsRecord = props, keys = Object.keys(propsRecord), keyIndex = keys.indexOf("_key");
7704
- keyIndex !== -1 && (keys.splice(keyIndex, 1), keys.unshift("_key"));
7705
- let currentPath = path;
7706
- for (let key of keys) if (propsRecord[key] !== nodeRecord[key]) if (propsRecord[key] != null) {
7707
- let hadProperty = nodeRecord.hasOwnProperty(key), lastSegment = currentPath[currentPath.length - 1], renamedPath = key === "_key" && typeof propsRecord[key] == "string" && isKeyedSegment(lastSegment) ? [...currentPath.slice(0, -1), { _key: propsRecord[key] }] : void 0, inversePath = renamedPath ? [...renamedPath, key] : [...currentPath, key];
7708
- editor.apply({
7709
- type: "set",
7710
- path: [...currentPath, key],
7711
- value: propsRecord[key],
7712
- inverse: hadProperty ? {
7713
- type: "set",
7714
- path: inversePath,
7715
- value: nodeRecord[key]
7716
- } : {
7717
- type: "unset",
7718
- path: inversePath
7719
- }
7720
- }), renamedPath && (currentPath = renamedPath);
7721
- } else nodeRecord.hasOwnProperty(key) && editor.apply({
7722
- type: "unset",
7723
- path: [...currentPath, key],
7724
- inverse: {
7725
- type: "set",
7726
- path: [...currentPath, key],
7727
- value: nodeRecord[key]
7728
- }
7729
- });
7730
- }
7731
- /**
7732
7735
  * Read the `_type` from a pre-resolved `of` entry.
7733
7736
  */
7734
7737
  function entryType(entry) {
@@ -7818,7 +7821,7 @@ function richDescentToParent(input, path) {
7818
7821
  * 3. **Global fallback with position-validity.** Falls back to the
7819
7822
  * top-level rich `containers` map keyed by `_type`. Activates only
7820
7823
  * when schema-at-position permits the registered `arrayField`
7821
- * (for containers) or simply declares `_type` (for leaves).
7824
+ * (for containers) or declares `_type` (for leaves).
7822
7825
  * Registration is type-keyed; activation is position-gated.
7823
7826
  */
7824
7827
  function resolveContainerByPath(input, path, node) {
@@ -7959,7 +7962,7 @@ const normalizeNode = (editor, entry) => {
7959
7962
  * Add missing .markDefs to text block nodes
7960
7963
  */
7961
7964
  if (!editor.isProcessingRemoteChanges && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.markDefs)) {
7962
- debug.normalization("adding .markDefs to block node"), setNodeProperties(editor, { markDefs: [] }, path);
7965
+ debug.normalization("adding .markDefs to block node"), applyNodeProperties(editor, { markDefs: [] }, path);
7963
7966
  return;
7964
7967
  }
7965
7968
  /**
@@ -7968,7 +7971,7 @@ const normalizeNode = (editor, entry) => {
7968
7971
  if (!editor.isProcessingRemoteChanges && isTextBlockNode({ schema: editor.snapshot.context.schema }, node) && node.style === void 0) {
7969
7972
  let defaultStyle = getPathSubSchema(editor.snapshot, path).styles.at(0)?.name;
7970
7973
  if (defaultStyle) {
7971
- debug.normalization("adding .style to block node"), setNodeProperties(editor, { style: defaultStyle }, path);
7974
+ debug.normalization("adding .style to block node"), applyNodeProperties(editor, { style: defaultStyle }, path);
7972
7975
  return;
7973
7976
  }
7974
7977
  }
@@ -7991,7 +7994,7 @@ const normalizeNode = (editor, entry) => {
7991
7994
  * Add missing .marks to span nodes
7992
7995
  */
7993
7996
  if (!editor.isProcessingRemoteChanges && isSpan({ schema: editor.snapshot.context.schema }, node) && !Array.isArray(node.marks)) {
7994
- debug.normalization("Adding .marks to span node"), setNodeProperties(editor, { marks: [] }, path);
7997
+ debug.normalization("Adding .marks to span node"), applyNodeProperties(editor, { marks: [] }, path);
7995
7998
  return;
7996
7999
  }
7997
8000
  /**
@@ -8002,7 +8005,7 @@ const normalizeNode = (editor, entry) => {
8002
8005
  if (!blockEntry) return;
8003
8006
  let annotations = node.marks?.filter((mark) => blockEntry.node.markDefs?.some((markDef) => markDef._key === mark));
8004
8007
  if (node.text === "" && annotations && annotations.length > 0) {
8005
- debug.normalization("removing annotations from empty span node"), setNodeProperties(editor, { marks: node.marks?.filter((mark) => !annotations.includes(mark)) }, path);
8008
+ debug.normalization("removing annotations from empty span node"), applyNodeProperties(editor, { marks: node.marks?.filter((mark) => !annotations.includes(mark)) }, path);
8006
8009
  return;
8007
8010
  }
8008
8011
  }
@@ -8013,7 +8016,7 @@ const normalizeNode = (editor, entry) => {
8013
8016
  let markDefs = node.markDefs ?? [], markDefKeys = /* @__PURE__ */ new Set(), newMarkDefs = [];
8014
8017
  for (let markDef of markDefs) markDefKeys.has(markDef._key) || (markDefKeys.add(markDef._key), newMarkDefs.push(markDef));
8015
8018
  if (markDefs.length !== newMarkDefs.length) {
8016
- debug.normalization("removing duplicate markDefs"), setNodeProperties(editor, { markDefs: newMarkDefs }, path);
8019
+ debug.normalization("removing duplicate markDefs"), applyNodeProperties(editor, { markDefs: newMarkDefs }, path);
8017
8020
  return;
8018
8021
  }
8019
8022
  }
@@ -8023,7 +8026,7 @@ const normalizeNode = (editor, entry) => {
8023
8026
  if (!editor.isProcessingRemoteChanges && isTextBlock({ schema: editor.snapshot.context.schema }, node)) {
8024
8027
  let newMarkDefs = (node.markDefs || []).filter((def) => node.children.find((child) => isSpan({ schema: editor.snapshot.context.schema }, child) && Array.isArray(child.marks) && child.marks.includes(def._key)));
8025
8028
  if (node.markDefs && !isEqualMarkDefs(newMarkDefs, node.markDefs)) {
8026
- debug.normalization("removing markDef not in use"), setNodeProperties(editor, { markDefs: newMarkDefs }, path);
8029
+ debug.normalization("removing markDef not in use"), applyNodeProperties(editor, { markDefs: newMarkDefs }, path);
8027
8030
  return;
8028
8031
  }
8029
8032
  }
@@ -8063,11 +8066,11 @@ const normalizeNode = (editor, entry) => {
8063
8066
  _type: firstChildType.type === "object" && "name" in firstChildType ? firstChildType.name : firstChildType.type,
8064
8067
  _key: editor.snapshot.context.keyGenerator()
8065
8068
  }), needsField && childNode) {
8066
- setNodeProperties(editor, { [arrayField.name]: [childNode] }, path);
8069
+ applyNodeProperties(editor, { [arrayField.name]: [childNode] }, path);
8067
8070
  return;
8068
8071
  }
8069
8072
  if (needsField) {
8070
- setNodeProperties(editor, { [arrayField.name]: [] }, path);
8073
+ applyNodeProperties(editor, { [arrayField.name]: [] }, path);
8071
8074
  return;
8072
8075
  }
8073
8076
  if (childNode) {
@@ -8758,8 +8761,10 @@ function bitap(text, pattern, loc, opts = {}) {
8758
8761
  let charMatch = s[text.charAt(j - 1)];
8759
8762
  if (d === 0 ? rd[j] = (rd[j + 1] << 1 | 1) & charMatch : rd[j] = (rd[j + 1] << 1 | 1) & charMatch | (lastRd[j + 1] | lastRd[j]) << 1 | 1 | lastRd[j + 1], rd[j] & matchmask) {
8760
8763
  let score = getBitapScore(d, j - 1);
8761
- if (score <= scoreThreshold) if (scoreThreshold = score, bestLoc = j - 1, bestLoc > loc) start = Math.max(1, 2 * loc - bestLoc);
8762
- else break;
8764
+ if (score <= scoreThreshold) {
8765
+ if (scoreThreshold = score, bestLoc = j - 1, bestLoc > loc) start = Math.max(1, 2 * loc - bestLoc);
8766
+ else break;
8767
+ }
8763
8768
  }
8764
8769
  }
8765
8770
  if (getBitapScore(d + 1, loc) > scoreThreshold) break;
@@ -10386,9 +10391,9 @@ function isBlockLike(value) {
10386
10391
  * drag origin in a way that would make the drop a no-op.
10387
10392
  *
10388
10393
  * Two expanded selections that only touch at a single endpoint are not treated
10389
- * as a self-drop the drop position covers an adjacent block (typical when
10394
+ * as a self-drop: the drop position covers an adjacent block (typical when
10390
10395
  * dragging a block-object onto the next block via the expanded fallback in
10391
- * `getEventPosition`), and the user genuinely wants the drop to happen.
10396
+ * `getEventPosition`), so the drop should go through.
10392
10397
  *
10393
10398
  * Chrome drags emit a collapsed selection pointing AT the dragged container.
10394
10399
  * A drop position whose path descends into that container is dropping the
@@ -11189,7 +11194,7 @@ const addAnnotationOperationImplementation = ({ snapshot, operation }) => {
11189
11194
  for (let { node: block, path: blockPath } of selectedBlocks) {
11190
11195
  if (!isTextBlock({ schema: editor.snapshot.context.schema }, block) || block.children.length === 0 || block.children.length === 1 && block.children[0]?.text === "" || !getPathSubSchema(snapshot, blockPath).annotations.some((annotation) => annotation.name === parsedAnnotation._type)) continue;
11191
11196
  let annotationKey = blockIndex === 0 ? parsedAnnotation._key : context.keyGenerator(), markDefs = block.markDefs ?? [];
11192
- markDefs.find((markDef) => markDef._type === parsedAnnotation._type && markDef._key === annotationKey) === void 0 && setNodeProperties(editor, { markDefs: [...markDefs, {
11197
+ markDefs.find((markDef) => markDef._type === parsedAnnotation._type && markDef._key === annotationKey) === void 0 && applyNodeProperties(editor, { markDefs: [...markDefs, {
11193
11198
  ...parsedAnnotation,
11194
11199
  _key: annotationKey
11195
11200
  }] }, blockPath);
@@ -11207,7 +11212,7 @@ const addAnnotationOperationImplementation = ({ snapshot, operation }) => {
11207
11212
  for (let { node: span, path: spanPath } of children) {
11208
11213
  if (!isSpan({ schema: editor.snapshot.context.schema }, span) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, spanPath)) continue;
11209
11214
  let marks = span.marks ?? [];
11210
- setNodeProperties(editor, { marks: [...marks, annotationKey] }, spanPath);
11215
+ applyNodeProperties(editor, { marks: [...marks, annotationKey] }, spanPath);
11211
11216
  }
11212
11217
  blockIndex++;
11213
11218
  }
@@ -11221,59 +11226,65 @@ function isBeforePath(path, another, root) {
11221
11226
  }
11222
11227
  const removeAnnotationOperationImplementation = ({ snapshot, operation }) => {
11223
11228
  let editor = operation.editor, at = operation.at ? resolveSelection(operation.editor, operation.at) : null, effectiveSelection = at ?? editor.snapshot.context.selection;
11224
- if (effectiveSelection) if (isCollapsedRange(effectiveSelection)) {
11225
- let blockEntry = getParent(snapshot, effectiveSelection.focus.path, { match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node) });
11226
- if (!blockEntry) return;
11227
- let { node: block, path: blockPath } = blockEntry, potentialAnnotations = (block.markDefs ?? []).filter((markDef) => markDef._type === operation.annotation.name), selectedChildEntry = getNode(editor.snapshot, effectiveSelection.focus.path);
11228
- if (!selectedChildEntry) return;
11229
- let { node: selectedChild, path: selectedChildPath } = selectedChildEntry;
11230
- if (!isSpan({ schema: editor.snapshot.context.schema }, selectedChild)) return;
11231
- let annotationToRemove = selectedChild.marks?.find((mark) => potentialAnnotations.some((markDef) => markDef._key === mark));
11232
- if (!annotationToRemove) return;
11233
- let previousSpansWithSameAnnotation = [], reversedChildren = getChildren(editor.snapshot, blockPath);
11234
- for (let index = reversedChildren.length - 1; index >= 0; index--) {
11235
- let entry = reversedChildren[index];
11236
- if (!entry) continue;
11237
- let { node: child, path: childPath } = entry;
11238
- if (isSpan({ schema: editor.snapshot.context.schema }, child) && isBeforePath(childPath, selectedChildPath, editor.snapshot.context)) if (child.marks?.includes(annotationToRemove)) previousSpansWithSameAnnotation.push([child, childPath]);
11239
- else break;
11240
- }
11241
- let nextSpansWithSameAnnotation = [];
11242
- for (let { node: child, path: childPath } of getChildren(editor.snapshot, blockPath)) if (isSpan({ schema: editor.snapshot.context.schema }, child) && isAfterPath(childPath, selectedChildPath, editor.snapshot.context)) if (child.marks?.includes(annotationToRemove)) nextSpansWithSameAnnotation.push([child, childPath]);
11243
- else break;
11244
- for (let [child, childPath] of [
11245
- ...previousSpansWithSameAnnotation,
11246
- [selectedChild, selectedChildPath],
11247
- ...nextSpansWithSameAnnotation
11248
- ]) setNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
11249
- } else {
11250
- let ref = at ? rangeRef(editor, at, { affinity: "inward" }) : null;
11251
- withoutNormalizing(editor, () => {
11252
- let splitRange = at ?? editor.snapshot.context.selection;
11253
- if (splitRange && isRange(splitRange)) {
11254
- let splitLeaf = getNode(editor.snapshot, splitRange.anchor.path)?.node;
11255
- if (!(splitLeaf && isCollapsedRange(splitRange) && isSpan({ schema: editor.snapshot.context.schema }, splitLeaf) && splitLeaf.text.length > 0)) {
11256
- let splitRangeRef = rangeRef(editor, splitRange, { affinity: "inward" }), [splitStart, splitEnd] = rangeEdges(splitRange, editor.snapshot.context);
11257
- (!isEnd(editor, splitEnd, splitEnd.path) || !isEdge(editor, splitEnd, splitEnd.path)) && applySplitNode(editor, splitEnd.path, splitEnd.offset), (!isStart(editor, splitStart, splitStart.path) || !isEdge(editor, splitStart, splitStart.path)) && applySplitNode(editor, splitStart.path, splitStart.offset);
11258
- let updatedSplitRange = splitRangeRef.unref();
11259
- !at && updatedSplitRange && applySelect(editor, updatedSplitRange);
11229
+ if (effectiveSelection) {
11230
+ if (isCollapsedRange(effectiveSelection)) {
11231
+ let blockEntry = getParent(snapshot, effectiveSelection.focus.path, { match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node) });
11232
+ if (!blockEntry) return;
11233
+ let { node: block, path: blockPath } = blockEntry, potentialAnnotations = (block.markDefs ?? []).filter((markDef) => markDef._type === operation.annotation.name), selectedChildEntry = getNode(editor.snapshot, effectiveSelection.focus.path);
11234
+ if (!selectedChildEntry) return;
11235
+ let { node: selectedChild, path: selectedChildPath } = selectedChildEntry;
11236
+ if (!isSpan({ schema: editor.snapshot.context.schema }, selectedChild)) return;
11237
+ let annotationToRemove = selectedChild.marks?.find((mark) => potentialAnnotations.some((markDef) => markDef._key === mark));
11238
+ if (!annotationToRemove) return;
11239
+ let previousSpansWithSameAnnotation = [], reversedChildren = getChildren(editor.snapshot, blockPath);
11240
+ for (let index = reversedChildren.length - 1; index >= 0; index--) {
11241
+ let entry = reversedChildren[index];
11242
+ if (!entry) continue;
11243
+ let { node: child, path: childPath } = entry;
11244
+ if (isSpan({ schema: editor.snapshot.context.schema }, child) && isBeforePath(childPath, selectedChildPath, editor.snapshot.context)) {
11245
+ if (child.marks?.includes(annotationToRemove)) previousSpansWithSameAnnotation.push([child, childPath]);
11246
+ else break;
11260
11247
  }
11261
11248
  }
11262
- let blocks = Array.from(getNodes(editor.snapshot, {
11263
- from: rangeStart(effectiveSelection, editor.snapshot.context).path,
11264
- to: rangeEnd(effectiveSelection, editor.snapshot.context).path,
11265
- match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node)
11266
- })), selectionRange = ref?.current ?? editor.snapshot.context.selection;
11267
- for (let { node: block, path: blockPath } of blocks) {
11268
- if (!isTextBlock({ schema: editor.snapshot.context.schema }, block)) continue;
11269
- let children = getChildren(editor.snapshot, blockPath);
11270
- for (let { node: child, path: childPath } of children) {
11271
- if (!isSpan({ schema: editor.snapshot.context.schema }, child) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, childPath)) continue;
11272
- let markDefs = block.markDefs ?? [], marks = child.marks ?? [], marksWithoutAnnotation = marks.filter((mark) => markDefs.find((markDef) => markDef._key === mark)?._type !== operation.annotation.name);
11273
- marksWithoutAnnotation.length !== marks.length && setNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
11274
- }
11249
+ let nextSpansWithSameAnnotation = [];
11250
+ for (let { node: child, path: childPath } of getChildren(editor.snapshot, blockPath)) if (isSpan({ schema: editor.snapshot.context.schema }, child) && isAfterPath(childPath, selectedChildPath, editor.snapshot.context)) {
11251
+ if (child.marks?.includes(annotationToRemove)) nextSpansWithSameAnnotation.push([child, childPath]);
11252
+ else break;
11275
11253
  }
11276
- }), ref?.unref();
11254
+ for (let [child, childPath] of [
11255
+ ...previousSpansWithSameAnnotation,
11256
+ [selectedChild, selectedChildPath],
11257
+ ...nextSpansWithSameAnnotation
11258
+ ]) applyNodeProperties(editor, { marks: child.marks?.filter((mark) => mark !== annotationToRemove) }, childPath);
11259
+ } else {
11260
+ let ref = at ? rangeRef(editor, at, { affinity: "inward" }) : null;
11261
+ withoutNormalizing(editor, () => {
11262
+ let splitRange = at ?? editor.snapshot.context.selection;
11263
+ if (splitRange && isRange(splitRange)) {
11264
+ let splitLeaf = getNode(editor.snapshot, splitRange.anchor.path)?.node;
11265
+ if (!(splitLeaf && isCollapsedRange(splitRange) && isSpan({ schema: editor.snapshot.context.schema }, splitLeaf) && splitLeaf.text.length > 0)) {
11266
+ let splitRangeRef = rangeRef(editor, splitRange, { affinity: "inward" }), [splitStart, splitEnd] = rangeEdges(splitRange, editor.snapshot.context);
11267
+ (!isEnd(editor, splitEnd, splitEnd.path) || !isEdge(editor, splitEnd, splitEnd.path)) && applySplitNode(editor, splitEnd.path, splitEnd.offset), (!isStart(editor, splitStart, splitStart.path) || !isEdge(editor, splitStart, splitStart.path)) && applySplitNode(editor, splitStart.path, splitStart.offset);
11268
+ let updatedSplitRange = splitRangeRef.unref();
11269
+ !at && updatedSplitRange && applySelect(editor, updatedSplitRange);
11270
+ }
11271
+ }
11272
+ let blocks = Array.from(getNodes(editor.snapshot, {
11273
+ from: rangeStart(effectiveSelection, editor.snapshot.context).path,
11274
+ to: rangeEnd(effectiveSelection, editor.snapshot.context).path,
11275
+ match: (node) => isTextBlock({ schema: editor.snapshot.context.schema }, node)
11276
+ })), selectionRange = ref?.current ?? editor.snapshot.context.selection;
11277
+ for (let { node: block, path: blockPath } of blocks) {
11278
+ if (!isTextBlock({ schema: editor.snapshot.context.schema }, block)) continue;
11279
+ let children = getChildren(editor.snapshot, blockPath);
11280
+ for (let { node: child, path: childPath } of children) {
11281
+ if (!isSpan({ schema: editor.snapshot.context.schema }, child) || !selectionRange || !rangeIntersects(editor.snapshot, selectionRange, childPath)) continue;
11282
+ let markDefs = block.markDefs ?? [], marks = child.marks ?? [], marksWithoutAnnotation = marks.filter((mark) => markDefs.find((markDef) => markDef._key === mark)?._type !== operation.annotation.name);
11283
+ marksWithoutAnnotation.length !== marks.length && applyNodeProperties(editor, { marks: marksWithoutAnnotation }, childPath);
11284
+ }
11285
+ }
11286
+ }), ref?.unref();
11287
+ }
11277
11288
  }
11278
11289
  };
11279
11290
  /**
@@ -11333,7 +11344,7 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
11333
11344
  }
11334
11345
  context.schema.block.fields?.some((field) => field.name === key) && (filteredProps[key] = operation.props[key]);
11335
11346
  }
11336
- setNodeProperties(operation.editor, filteredProps, blockEntry.path);
11347
+ applyNodeProperties(operation.editor, filteredProps, blockEntry.path);
11337
11348
  } else {
11338
11349
  let schemaDefinition = getBlockObjectSchema(snapshot, engineBlock, blockEntry.path), filteredProps = {};
11339
11350
  for (let key of Object.keys(operation.props)) if (key !== "_type") {
@@ -11344,7 +11355,7 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
11344
11355
  schemaDefinition?.fields?.some((field) => field.name === key) && (filteredProps[key] = operation.props[key]);
11345
11356
  }
11346
11357
  let patches = Object.entries(filteredProps).map(([key, value]) => set(value, [key])), updatedEngineBlock = applyAll(engineBlock, patches);
11347
- setNodeProperties(operation.editor, updatedEngineBlock, blockEntry.path);
11358
+ applyNodeProperties(operation.editor, updatedEngineBlock, blockEntry.path);
11348
11359
  }
11349
11360
  }, blockUnsetOperationImplementation = ({ snapshot, operation }) => {
11350
11361
  let { context } = snapshot, blockEntry = getNode(operation.editor.snapshot, operation.at);
@@ -11353,12 +11364,12 @@ const blockSetOperationImplementation = ({ snapshot, operation }) => {
11353
11364
  if (isTextBlockNode(context, engineBlock)) {
11354
11365
  let propsToRemove = operation.props.filter((prop) => prop !== "_type" && prop !== "_key"), unsetProps = {};
11355
11366
  for (let prop of propsToRemove) unsetProps[prop] = null;
11356
- setNodeProperties(operation.editor, unsetProps, blockEntry.path), operation.props.includes("_key") && setNodeProperties(operation.editor, { _key: context.keyGenerator() }, blockEntry.path);
11367
+ applyNodeProperties(operation.editor, unsetProps, blockEntry.path), operation.props.includes("_key") && applyNodeProperties(operation.editor, { _key: context.keyGenerator() }, blockEntry.path);
11357
11368
  return;
11358
11369
  }
11359
11370
  let unsetProps = {};
11360
11371
  for (let key of operation.props) key !== "_type" && (key === "_key" ? unsetProps._key = context.keyGenerator() : unsetProps[key] = null);
11361
- setNodeProperties(operation.editor, unsetProps, blockEntry.path);
11372
+ applyNodeProperties(operation.editor, unsetProps, blockEntry.path);
11362
11373
  };
11363
11374
  /**
11364
11375
  * Compute the canonical path that a new node will have when inserted as a
@@ -11385,7 +11396,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11385
11396
  let { node: child, path: childPath } = childEntry;
11386
11397
  if (isSpan({ schema: operation.editor.snapshot.context.schema }, child)) {
11387
11398
  let { _type, text, ...rest } = operation.props;
11388
- setNodeProperties(operation.editor, {
11399
+ applyNodeProperties(operation.editor, {
11389
11400
  ...child,
11390
11401
  ...rest
11391
11402
  }, childPath);
@@ -11408,7 +11419,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11408
11419
  if (!definition) return;
11409
11420
  let { _type, _key, ...rest } = operation.props;
11410
11421
  for (let prop in rest) definition.fields.some((field) => field.name === prop) || delete rest[prop];
11411
- setNodeProperties(operation.editor, {
11422
+ applyNodeProperties(operation.editor, {
11412
11423
  ...child,
11413
11424
  _key: typeof _key == "string" ? _key : child._key,
11414
11425
  ...rest
@@ -11429,13 +11440,13 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11429
11440
  }
11430
11441
  newNode[prop] = null;
11431
11442
  }
11432
- setNodeProperties(operation.editor, newNode, childPath);
11443
+ applyNodeProperties(operation.editor, newNode, childPath);
11433
11444
  return;
11434
11445
  }
11435
11446
  if (isObject(operation.editor.snapshot, child)) {
11436
11447
  let unsetProps = {};
11437
11448
  for (let prop of operation.props) prop !== "_type" && (prop === "_key" ? unsetProps._key = context.keyGenerator() : unsetProps[prop] = null);
11438
- setNodeProperties(operation.editor, unsetProps, childPath);
11449
+ applyNodeProperties(operation.editor, unsetProps, childPath);
11439
11450
  return;
11440
11451
  }
11441
11452
  throw Error(`Unable to determine the type of child at ${safeStringify(operation.at)}`);
@@ -11458,7 +11469,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11458
11469
  let blockPath = parentPath(spanPath);
11459
11470
  if (!getPathSubSchema(snapshot, blockPath).decorators.some((decorator) => decorator.name === mark)) continue;
11460
11471
  let marks = [...(Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark), mark];
11461
- setNodeProperties(editor, { marks }, spanPath);
11472
+ applyNodeProperties(editor, { marks }, spanPath);
11462
11473
  }
11463
11474
  });
11464
11475
  } else {
@@ -11477,7 +11488,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11477
11488
  for (let { path: spanPath } of Array.from(getNodes(editor.snapshot, {
11478
11489
  at: blockPath,
11479
11490
  match: (node) => isSpan({ schema: editor.snapshot.context.schema }, node)
11480
- }))) setNodeProperties(editor, { marks: newMarks }, spanPath);
11491
+ }))) applyNodeProperties(editor, { marks: newMarks }, spanPath);
11481
11492
  } else editor.snapshot.decoratorState[mark] = !0;
11482
11493
  }
11483
11494
  if (editor.snapshot.context.selection) {
@@ -11506,7 +11517,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11506
11517
  for (let { node, path: nodePath } of splitTextNodes) {
11507
11518
  if (!isSpan({ schema: editor.snapshot.context.schema }, node)) continue;
11508
11519
  let blockPath = parentPath(nodePath), block = getNode(editor.snapshot, blockPath)?.node;
11509
- isTextBlock({ schema: editor.snapshot.context.schema }, block) && block.children.includes(node) && setNodeProperties(editor, {
11520
+ isTextBlock({ schema: editor.snapshot.context.schema }, block) && block.children.includes(node) && applyNodeProperties(editor, {
11510
11521
  marks: (Array.isArray(node.marks) ? node.marks : []).filter((eMark) => eMark !== mark),
11511
11522
  _type: context.schema.span.name
11512
11523
  }, nodePath);
@@ -11522,7 +11533,7 @@ const childSetOperationImplementation = ({ snapshot, operation }) => {
11522
11533
  for (let { path: spanPath } of Array.from(getNodes(editor.snapshot, {
11523
11534
  at: blockPath,
11524
11535
  match: (node) => isSpan({ schema: editor.snapshot.context.schema }, node)
11525
- }))) setNodeProperties(editor, { marks: existingMarksWithoutDecorator }, spanPath);
11536
+ }))) applyNodeProperties(editor, { marks: existingMarksWithoutDecorator }, spanPath);
11526
11537
  } else editor.snapshot.decoratorState[mark] = !1;
11527
11538
  }
11528
11539
  if (editor.snapshot.context.selection) {
@@ -11637,21 +11648,31 @@ function fieldAcceptsTextBlock(editor, node, _path) {
11637
11648
  * `destinationBlock` by key. Any child key the merging block shares with
11638
11649
  * the destination has to be renamed before the merge, or the engine's own
11639
11650
  * collision handling mints a fresh key for it, which reads on the wire as
11640
- * that node being destroyed and a new one created instead of moved. There
11641
- * is no such backstop for markDefs: an unrenamed collision either loses
11642
- * one of the two defs to last-wins replacement, or, on the `insert.block`
11643
- * path, gets silently re-minted by `adjustFragmentKeys` (see
11644
- * `dedupeEqualMarkDefs` below).
11651
+ * that node being destroyed and a new one created instead of moved.
11652
+ *
11653
+ * A colliding markDef that is deeply equal to the destination's is left
11654
+ * unrenamed and reported in `dedupedMarkDefKeys` instead: the merge keeps
11655
+ * a single copy under the original `_key` rather than duplicating
11656
+ * identical content under two keys. A colliding markDef that differs gets
11657
+ * renamed like a child would.
11658
+ *
11659
+ * `renamedBlock` keeps every deduped def in its own `markDefs`, even
11660
+ * though the destination already carries it: `renamedBlock` feeds
11661
+ * `insert.block` on some callers' paths, and that path parses the block
11662
+ * standalone, stripping any mark that doesn't resolve in the block's own
11663
+ * `markDefs`. A caller that appends `renamedBlock.markDefs` onto the
11664
+ * destination's must skip the keys listed in `dedupedMarkDefKeys`, or the
11665
+ * def duplicates.
11645
11666
  *
11646
11667
  * Pure: computes the renames and the block they produce without touching
11647
11668
  * an editor. Callers raise or apply the renames themselves, ahead of the
11648
11669
  * merge, against the still-living `mergingBlock`.
11649
11670
  */
11650
11671
  function planMergeKeyRenames(args) {
11651
- let { context, mergingBlock, destinationBlock, dedupeEqualMarkDefs } = args, destinationChildKeys = new Set(destinationBlock.children.map((child) => child._key)), destinationMarkDefsByKey = new Map((destinationBlock.markDefs ?? []).map((markDef) => [markDef._key, markDef])), markDefKeyMap = /* @__PURE__ */ new Map(), renamedMarkDefs = mergingBlock.markDefs?.flatMap((markDef) => {
11672
+ let { context, mergingBlock, destinationBlock } = args, destinationChildKeys = new Set(destinationBlock.children.map((child) => child._key)), destinationMarkDefsByKey = new Map((destinationBlock.markDefs ?? []).map((markDef) => [markDef._key, markDef])), markDefKeyMap = /* @__PURE__ */ new Map(), dedupedMarkDefKeys = [], renamedMarkDefs = mergingBlock.markDefs?.flatMap((markDef) => {
11652
11673
  let destinationMarkDef = destinationMarkDefsByKey.get(markDef._key);
11653
11674
  if (!destinationMarkDef) return [markDef];
11654
- if (dedupeEqualMarkDefs && isDeepEqual(markDef, destinationMarkDef)) return [];
11675
+ if (isDeepEqual(markDef, destinationMarkDef)) return dedupedMarkDefKeys.push(markDef._key), [markDef];
11655
11676
  let newKey = context.keyGenerator();
11656
11677
  return markDefKeyMap.set(markDef._key, newKey), [{
11657
11678
  ...markDef,
@@ -11686,7 +11707,8 @@ function planMergeKeyRenames(args) {
11686
11707
  ...mergingBlock.markDefs ? { markDefs: renamedMarkDefs } : {}
11687
11708
  },
11688
11709
  childRenames,
11689
- markDefRenames
11710
+ markDefRenames,
11711
+ dedupedMarkDefKeys
11690
11712
  };
11691
11713
  }
11692
11714
  /**
@@ -12022,11 +12044,10 @@ function mergeBlock(editor, startBlockPath, endBlockPath, removeEmptyStartBlock)
12022
12044
  removeNodeAt(editor, startBlockPath);
12023
12045
  return;
12024
12046
  }
12025
- let { renamedBlock, childRenames, markDefRenames } = planMergeKeyRenames({
12047
+ let { renamedBlock, childRenames, markDefRenames, dedupedMarkDefKeys } = planMergeKeyRenames({
12026
12048
  context: editor.snapshot.context,
12027
12049
  mergingBlock: endBlock.node,
12028
- destinationBlock: startBlock.node,
12029
- dedupeEqualMarkDefs: !0
12050
+ destinationBlock: startBlock.node
12030
12051
  });
12031
12052
  for (let { markDefKey, newKey } of markDefRenames) editor.apply({
12032
12053
  type: "set",
@@ -12038,13 +12059,13 @@ function mergeBlock(editor, startBlockPath, endBlockPath, removeEmptyStartBlock)
12038
12059
  ],
12039
12060
  value: newKey
12040
12061
  });
12041
- for (let { childKey, props } of childRenames) setNodeProperties(editor, props, [
12062
+ for (let { childKey, props } of childRenames) applyNodeProperties(editor, props, [
12042
12063
  ...endBlockPath,
12043
12064
  "children",
12044
12065
  { _key: childKey }
12045
12066
  ]);
12046
- let endMarkDefs = renamedBlock.markDefs;
12047
- Array.isArray(endMarkDefs) && endMarkDefs.length > 0 && setNodeProperties(editor, { markDefs: [...startBlock.node.markDefs ?? [], ...endMarkDefs] }, startBlockPath), applyMergeNode(editor, endBlockPath, startBlock.node.children.length);
12067
+ let endMarkDefs = renamedBlock.markDefs?.filter((markDef) => !dedupedMarkDefKeys.includes(markDef._key));
12068
+ Array.isArray(endMarkDefs) && endMarkDefs.length > 0 && applyNodeProperties(editor, { markDefs: [...startBlock.node.markDefs ?? [], ...endMarkDefs] }, startBlockPath), applyMergeNode(editor, endBlockPath, startBlock.node.children.length);
12048
12069
  }
12049
12070
  function removeNodeAt(editor, path) {
12050
12071
  getNode(editor.snapshot, path) && editor.apply({
@@ -12733,7 +12754,7 @@ function mergeTextBlockFragment(args) {
12733
12754
  block,
12734
12755
  endBlock
12735
12756
  });
12736
- setNodeProperties(editor, { markDefs: [...endBlock.markDefs ?? [], ...adjustedMarkDefs ?? []] }, endBlockPath);
12757
+ applyNodeProperties(editor, { markDefs: [...endBlock.markDefs ?? [], ...adjustedMarkDefs ?? []] }, endBlockPath);
12737
12758
  let atPathRef = pathRef(editor, at.path), atBlockStart = pointEquals(at, start(editor, endBlockPath)), firstInsertedKey = insertFragmentChildren(editor, adjustedBlock, at), resolvedAtPath = atPathRef.unref();
12738
12759
  if (select === "none") {
12739
12760
  (wasCrossBlock || !atBlockStart) && applySelect(editor, at);
@@ -12841,8 +12862,12 @@ function resolveChildIndex(children, segment) {
12841
12862
  }
12842
12863
  /**
12843
12864
  * Reassign keys on spans, inline objects and markDefs that collide with the
12844
- * end block's existing keys. Returns the adjusted block and the adjusted
12845
- * markDefs (to be merged into the end block).
12865
+ * end block's existing keys. A colliding markDef that is deeply equal to
12866
+ * the end block's is left out of the returned `adjustedMarkDefs` instead
12867
+ * of renamed, since the end block already carries it; its key isn't
12868
+ * remapped, so the fragment's marks keep pointing at it unchanged. The
12869
+ * caller must merge the returned `adjustedMarkDefs` into the end block's
12870
+ * own `markDefs`, or the deduped defs are lost.
12846
12871
  */
12847
12872
  function adjustFragmentKeys(args) {
12848
12873
  let { context, block, endBlock } = args;
@@ -12854,15 +12879,15 @@ function adjustFragmentKeys(args) {
12854
12879
  adjustedBlock: block,
12855
12880
  adjustedMarkDefs: block.markDefs
12856
12881
  };
12857
- let endBlockChildKeys = endBlock.children.map((child) => child._key), endBlockMarkDefsKeys = endBlock.markDefs?.map((markDef) => markDef._key) ?? [], markDefKeyMap = /* @__PURE__ */ new Map(), adjustedMarkDefs = block.markDefs?.map((markDef) => {
12858
- if (endBlockMarkDefsKeys.includes(markDef._key)) {
12859
- let newKey = context.keyGenerator();
12860
- return markDefKeyMap.set(markDef._key, newKey), {
12861
- ...markDef,
12862
- _key: newKey
12863
- };
12864
- }
12865
- return markDef;
12882
+ let endBlockChildKeys = endBlock.children.map((child) => child._key), endBlockMarkDefsByKey = new Map((endBlock.markDefs ?? []).map((markDef) => [markDef._key, markDef])), markDefKeyMap = /* @__PURE__ */ new Map(), adjustedMarkDefs = block.markDefs?.flatMap((markDef) => {
12883
+ let endBlockMarkDef = endBlockMarkDefsByKey.get(markDef._key);
12884
+ if (!endBlockMarkDef) return [markDef];
12885
+ if (isDeepEqual(markDef, endBlockMarkDef)) return [];
12886
+ let newKey = context.keyGenerator();
12887
+ return markDefKeyMap.set(markDef._key, newKey), [{
12888
+ ...markDef,
12889
+ _key: newKey
12890
+ }];
12866
12891
  }), adjustedChildren = block.children.map((child) => {
12867
12892
  if (isSpan(context, child)) {
12868
12893
  let marks = child.marks?.map((mark) => markDefKeyMap.get(mark) ?? mark) ?? [];
@@ -12999,12 +13024,13 @@ const insertChildOperationImplementation = ({ snapshot, operation }) => {
12999
13024
  let node = nodeEntry.node;
13000
13025
  if (isLeafObject(editor.snapshot, node, nodeEntry.path)) {
13001
13026
  let nextSibling = getSibling(editor.snapshot, nodeEntry.path, { direction: "next" });
13002
- if (nextSibling) if (getSpan(editor.snapshot, nextSibling.path)) path = nextSibling.path, offset = 0, applySelect(editor, {
13003
- path,
13004
- offset
13005
- });
13006
- else return;
13007
- else return;
13027
+ if (nextSibling) {
13028
+ if (getSpan(editor.snapshot, nextSibling.path)) path = nextSibling.path, offset = 0, applySelect(editor, {
13029
+ path,
13030
+ offset
13031
+ });
13032
+ else return;
13033
+ } else return;
13008
13034
  }
13009
13035
  operation.text.length > 0 && editor.apply({
13010
13036
  type: "insert.text",
@@ -13437,8 +13463,7 @@ function planMergeKeyRenameActions(args) {
13437
13463
  let { context, mergingBlockPath, mergingBlock, destinationBlock } = args, { renamedBlock, childRenames, markDefRenames } = planMergeKeyRenames({
13438
13464
  context,
13439
13465
  mergingBlock,
13440
- destinationBlock,
13441
- dedupeEqualMarkDefs: !1
13466
+ destinationBlock
13442
13467
  }), renameActions = [];
13443
13468
  for (let { markDefKey, newKey } of markDefRenames) renameActions.push(raise$1({
13444
13469
  type: "set",
@@ -16128,49 +16153,51 @@ async function updateValue({ context, sendBack, editorEngine, streamBlocks, valu
16128
16153
  if ((!value || value.length === 0) && (clearEditor({
16129
16154
  editorEngine,
16130
16155
  doneSyncing
16131
- }), isChanged = !0), value && value.length > 0) if (streamBlocks) await new Promise((resolve) => {
16132
- if (doneSyncing) {
16133
- resolve();
16134
- return;
16135
- }
16136
- isChanged = removeExtraBlocks({
16137
- editorEngine,
16138
- value
16156
+ }), isChanged = !0), value && value.length > 0) {
16157
+ if (streamBlocks) await new Promise((resolve) => {
16158
+ if (doneSyncing) {
16159
+ resolve();
16160
+ return;
16161
+ }
16162
+ isChanged = removeExtraBlocks({
16163
+ editorEngine,
16164
+ value
16165
+ });
16166
+ let processBlocks = async () => {
16167
+ for await (let [currentBlock, currentBlockIndex] of getStreamedBlocks({ value })) {
16168
+ let { blockChanged, blockValid } = syncBlock({
16169
+ context,
16170
+ sendBack,
16171
+ block: currentBlock,
16172
+ index: currentBlockIndex,
16173
+ editorEngine,
16174
+ value
16175
+ });
16176
+ if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !isValid) break;
16177
+ }
16178
+ resolve();
16179
+ };
16180
+ processBlocks();
16139
16181
  });
16140
- let processBlocks = async () => {
16141
- for await (let [currentBlock, currentBlockIndex] of getStreamedBlocks({ value })) {
16182
+ else {
16183
+ if (doneSyncing) return;
16184
+ isChanged = removeExtraBlocks({
16185
+ editorEngine,
16186
+ value
16187
+ });
16188
+ let index = 0;
16189
+ for (let block of value) {
16142
16190
  let { blockChanged, blockValid } = syncBlock({
16143
16191
  context,
16144
16192
  sendBack,
16145
- block: currentBlock,
16146
- index: currentBlockIndex,
16193
+ block,
16194
+ index,
16147
16195
  editorEngine,
16148
16196
  value
16149
16197
  });
16150
- if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !isValid) break;
16198
+ if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !blockValid) break;
16199
+ index++;
16151
16200
  }
16152
- resolve();
16153
- };
16154
- processBlocks();
16155
- });
16156
- else {
16157
- if (doneSyncing) return;
16158
- isChanged = removeExtraBlocks({
16159
- editorEngine,
16160
- value
16161
- });
16162
- let index = 0;
16163
- for (let block of value) {
16164
- let { blockChanged, blockValid } = syncBlock({
16165
- context,
16166
- sendBack,
16167
- block,
16168
- index,
16169
- editorEngine,
16170
- value
16171
- });
16172
- if (isChanged = blockChanged || isChanged, isValid &&= blockValid, !blockValid) break;
16173
- index++;
16174
16201
  }
16175
16202
  }
16176
16203
  if (!isValid) {
@@ -16369,13 +16396,13 @@ function replaceBlock({ context, editorEngine, block, index }) {
16369
16396
  }
16370
16397
  function updateBlock({ context, editorEngine, oldEngineBlock, block, index: _index }) {
16371
16398
  let engineBlock = toEngineBlock(block, { schemaTypes: context.schema }), { children: _children, ...blockProps } = engineBlock;
16372
- setNodeProperties(editorEngine, blockProps, [{ _key: oldEngineBlock._key }]);
16399
+ applyNodeProperties(editorEngine, blockProps, [{ _key: oldEngineBlock._key }]);
16373
16400
  let oldRecord = oldEngineBlock, newRecord = engineBlock, removedProperties = {};
16374
16401
  for (let key of Object.keys(oldRecord)) key !== "children" && key !== "text" && (newRecord.hasOwnProperty(key) || (removedProperties[key] = null));
16375
- if (Object.keys(removedProperties).length > 0 && setNodeProperties(editorEngine, removedProperties, [{ _key: oldEngineBlock._key }]), isTextBlock({ schema: editorEngine.snapshot.context.schema }, engineBlock) && isTextBlock({ schema: editorEngine.snapshot.context.schema }, oldEngineBlock)) {
16402
+ if (Object.keys(removedProperties).length > 0 && applyNodeProperties(editorEngine, removedProperties, [{ _key: oldEngineBlock._key }]), isTextBlock({ schema: editorEngine.snapshot.context.schema }, engineBlock) && isTextBlock({ schema: editorEngine.snapshot.context.schema }, oldEngineBlock)) {
16376
16403
  let oldKeys = oldEngineBlock.children.map((c) => c._key), newKeys = engineBlock.children.map((c) => c._key), oldKeySet = new Set(oldKeys), hasSharedKeys = newKeys.some((key) => oldKeySet.has(key));
16377
16404
  if (oldKeys.length === newKeys.length && oldKeys.length > 0 && oldKeySet.size === oldKeys.length && oldKeys.some((key, i) => key !== newKeys[i]) && newKeys.every((key) => oldKeySet.has(key)) || newKeys.length > 0 && !hasSharedKeys) {
16378
- debug.syncValue("Replacing children via set"), setNodeProperties(editorEngine, { children: engineBlock.children }, [{ _key: oldEngineBlock._key }]), editorEngine.onChange();
16405
+ debug.syncValue("Replacing children via set"), applyNodeProperties(editorEngine, { children: engineBlock.children }, [{ _key: oldEngineBlock._key }]), editorEngine.onChange();
16379
16406
  return;
16380
16407
  }
16381
16408
  let oldBlockChildrenLength = oldEngineBlock.children.length;
@@ -16404,7 +16431,7 @@ function updateBlock({ context, editorEngine, oldEngineBlock, block, index: _ind
16404
16431
  if (currentBlockChild._key === oldBlockChild?._key && currentBlockChild._type === oldBlockChild?._type) {
16405
16432
  debug.syncValue("Updating changed child", currentBlockChild, oldBlockChild);
16406
16433
  let isSpanNode = isSpan({ schema: context.schema }, currentBlockChild) && isSpan({ schema: context.schema }, oldBlockChild), childProps = { ...currentBlockChild };
16407
- isSpanNode && delete childProps.text, setNodeProperties(editorEngine, childProps, path), isSpanNode && isTextChanged ? (oldBlockChild.text.length > 0 && deleteRange(editorEngine, {
16434
+ isSpanNode && delete childProps.text, applyNodeProperties(editorEngine, childProps, path), isSpanNode && isTextChanged ? (oldBlockChild.text.length > 0 && deleteRange(editorEngine, {
16408
16435
  focus: {
16409
16436
  path,
16410
16437
  offset: 0