@yorkie-js/react 0.6.49 → 0.7.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.
@@ -12497,7 +12497,7 @@ class CRDTTree extends CRDTElement {
12497
12497
  }
12498
12498
  }
12499
12499
  }
12500
- return [changes, pairs, diff];
12500
+ return [changes, pairs, diff, nodesToBeRemoved, fromIdx];
12501
12501
  }
12502
12502
  /**
12503
12503
  * `editT` edits the given range with the given value.
@@ -12935,29 +12935,46 @@ class CRDTTree extends CRDTElement {
12935
12935
  return [prev, prev.isText ? TokenType.Text : TokenType.End];
12936
12936
  }
12937
12937
  }
12938
+ function clearRemovedAt(node) {
12939
+ traverseAll(node, (n) => {
12940
+ n.removedAt = void 0;
12941
+ n.visibleSize = n.totalSize;
12942
+ });
12943
+ }
12938
12944
  class TreeEditOperation extends Operation {
12939
12945
  fromPos;
12940
12946
  toPos;
12941
12947
  contents;
12942
12948
  splitLevel;
12943
- constructor(parentCreatedAt, fromPos, toPos, contents, splitLevel, executedAt) {
12949
+ isUndoOp;
12950
+ fromIdx;
12951
+ toIdx;
12952
+ lastFromIdx;
12953
+ lastToIdx;
12954
+ constructor(parentCreatedAt, fromPos, toPos, contents, splitLevel, executedAt, isUndoOp, fromIdx, toIdx) {
12944
12955
  super(parentCreatedAt, executedAt);
12945
12956
  this.fromPos = fromPos;
12946
12957
  this.toPos = toPos;
12947
12958
  this.contents = contents;
12948
12959
  this.splitLevel = splitLevel;
12960
+ this.isUndoOp = isUndoOp;
12961
+ this.fromIdx = fromIdx;
12962
+ this.toIdx = toIdx;
12949
12963
  }
12950
12964
  /**
12951
12965
  * `create` creates a new instance of EditOperation.
12952
12966
  */
12953
- static create(parentCreatedAt, fromPos, toPos, contents, splitLevel, executedAt) {
12967
+ static create(parentCreatedAt, fromPos, toPos, contents, splitLevel, executedAt, isUndoOp, fromIdx, toIdx) {
12954
12968
  return new TreeEditOperation(
12955
12969
  parentCreatedAt,
12956
12970
  fromPos,
12957
12971
  toPos,
12958
12972
  contents,
12959
12973
  splitLevel,
12960
- executedAt
12974
+ executedAt,
12975
+ isUndoOp,
12976
+ fromIdx,
12977
+ toIdx
12961
12978
  );
12962
12979
  }
12963
12980
  /**
@@ -12979,7 +12996,15 @@ class TreeEditOperation extends Operation {
12979
12996
  }
12980
12997
  const editedAt = this.getExecutedAt();
12981
12998
  const tree = parentObject;
12982
- const [changes, pairs, diff] = tree.edit(
12999
+ if (this.isUndoOp && this.fromIdx !== void 0 && this.toIdx !== void 0) {
13000
+ this.fromPos = tree.findPos(this.fromIdx);
13001
+ if (this.fromIdx === this.toIdx) {
13002
+ this.toPos = this.fromPos;
13003
+ } else {
13004
+ this.toPos = tree.findPos(this.toIdx);
13005
+ }
13006
+ }
13007
+ const [changes, pairs, diff, removedNodes, preEditFromIdx] = tree.edit(
12983
13008
  [this.fromPos, this.toPos],
12984
13009
  this.contents?.map((content) => content.deepcopy()),
12985
13010
  this.splitLevel,
@@ -13005,6 +13030,13 @@ class TreeEditOperation extends Operation {
13005
13030
  })(),
13006
13031
  versionVector
13007
13032
  );
13033
+ this.lastFromIdx = preEditFromIdx;
13034
+ const removedSize = removedNodes.reduce(
13035
+ (sum, node) => sum + node.paddedSize(),
13036
+ 0
13037
+ );
13038
+ this.lastToIdx = preEditFromIdx + removedSize;
13039
+ const reverseOp = this.splitLevel === 0 ? this.toReverseOperation(tree, removedNodes, preEditFromIdx) : void 0;
13008
13040
  root.acc(diff);
13009
13041
  for (const pair of pairs) {
13010
13042
  root.registerGCPair(pair);
@@ -13023,9 +13055,131 @@ class TreeEditOperation extends Operation {
13023
13055
  toPath
13024
13056
  };
13025
13057
  }
13026
- )
13058
+ ),
13059
+ reverseOp
13027
13060
  };
13028
13061
  }
13062
+ /**
13063
+ * `toReverseOperation` creates the reverse operation for undo.
13064
+ *
13065
+ * The reverse op stores both CRDTTreePos (for initial use) and integer
13066
+ * indices (for reconciliation adjustment when remote edits arrive).
13067
+ * At undo execution time, the integer indices take precedence and are
13068
+ * converted to CRDTTreePos via tree.findPos().
13069
+ *
13070
+ * @param tree - The CRDTTree after the edit has been applied
13071
+ * @param removedNodes - Nodes that were removed by this edit
13072
+ * @param preEditFromIdx - The from index captured BEFORE the edit
13073
+ */
13074
+ toReverseOperation(tree, removedNodes, preEditFromIdx) {
13075
+ const insertedContentSize = this.contents ? this.contents.reduce((sum, node) => sum + node.paddedSize(), 0) : 0;
13076
+ const maxNeededIdx = preEditFromIdx + insertedContentSize;
13077
+ if (maxNeededIdx > tree.getSize()) {
13078
+ return void 0;
13079
+ }
13080
+ const topLevelRemoved = removedNodes.filter(
13081
+ (node) => !node.parent || !removedNodes.includes(node.parent)
13082
+ );
13083
+ const reverseContents = topLevelRemoved.length > 0 ? topLevelRemoved.map((n) => {
13084
+ const clone = n.deepcopy();
13085
+ clearRemovedAt(clone);
13086
+ return clone;
13087
+ }) : void 0;
13088
+ const reverseFromPos = tree.findPos(preEditFromIdx);
13089
+ let reverseToPos;
13090
+ if (insertedContentSize > 0) {
13091
+ reverseToPos = tree.findPos(preEditFromIdx + insertedContentSize);
13092
+ } else {
13093
+ reverseToPos = reverseFromPos;
13094
+ }
13095
+ const reverseFromIdx = preEditFromIdx;
13096
+ const reverseToIdx = preEditFromIdx + insertedContentSize;
13097
+ return TreeEditOperation.create(
13098
+ this.getParentCreatedAt(),
13099
+ reverseFromPos,
13100
+ reverseToPos,
13101
+ reverseContents,
13102
+ 0,
13103
+ // splitLevel always 0
13104
+ void 0,
13105
+ // executedAt set during undo
13106
+ true,
13107
+ // isUndoOp
13108
+ reverseFromIdx,
13109
+ reverseToIdx
13110
+ );
13111
+ }
13112
+ /**
13113
+ * `normalizePos` returns the visible-index range of this operation.
13114
+ * For undo ops, returns the stored (possibly reconciled) indices.
13115
+ * For forward ops, returns the pre-edit indices captured during execute().
13116
+ */
13117
+ normalizePos() {
13118
+ if (this.isUndoOp && this.fromIdx !== void 0 && this.toIdx !== void 0) {
13119
+ return [this.fromIdx, this.toIdx];
13120
+ }
13121
+ if (this.lastFromIdx !== void 0 && this.lastToIdx !== void 0) {
13122
+ return [this.lastFromIdx, this.lastToIdx];
13123
+ }
13124
+ return [0, 0];
13125
+ }
13126
+ /**
13127
+ * `reconcileOperation` adjusts this undo operation's integer indices
13128
+ * when a remote edit modifies the same tree. Uses the same 6-case
13129
+ * overlap logic as EditOperation.reconcileOperation for Text.
13130
+ */
13131
+ reconcileOperation(remoteFrom, remoteTo, contentLen) {
13132
+ if (!this.isUndoOp) {
13133
+ return;
13134
+ }
13135
+ if (this.fromIdx === void 0 || this.toIdx === void 0) {
13136
+ return;
13137
+ }
13138
+ if (remoteFrom > remoteTo) {
13139
+ return;
13140
+ }
13141
+ const remoteRangeLen = remoteTo - remoteFrom;
13142
+ const localFrom = this.fromIdx;
13143
+ const localTo = this.toIdx;
13144
+ const apply = (na, nb) => {
13145
+ this.fromIdx = Math.max(0, na);
13146
+ this.toIdx = Math.max(0, nb);
13147
+ };
13148
+ if (remoteTo <= localFrom) {
13149
+ apply(
13150
+ localFrom - remoteRangeLen + contentLen,
13151
+ localTo - remoteRangeLen + contentLen
13152
+ );
13153
+ return;
13154
+ }
13155
+ if (localTo <= remoteFrom) {
13156
+ return;
13157
+ }
13158
+ if (remoteFrom <= localFrom && localTo <= remoteTo && remoteFrom !== remoteTo) {
13159
+ apply(remoteFrom, remoteFrom);
13160
+ return;
13161
+ }
13162
+ if (localFrom <= remoteFrom && remoteTo <= localTo && localFrom !== localTo) {
13163
+ apply(localFrom, localTo - remoteRangeLen + contentLen);
13164
+ return;
13165
+ }
13166
+ if (remoteFrom < localFrom && localFrom < remoteTo && remoteTo < localTo) {
13167
+ apply(remoteFrom, remoteFrom + (localTo - remoteTo));
13168
+ return;
13169
+ }
13170
+ if (localFrom < remoteFrom && remoteFrom < localTo && localTo < remoteTo) {
13171
+ apply(localFrom, remoteFrom);
13172
+ return;
13173
+ }
13174
+ }
13175
+ /**
13176
+ * `getContentSize` returns the total visible size of this operation's
13177
+ * content (for reconciliation).
13178
+ */
13179
+ getContentSize() {
13180
+ if (!this.contents) return 0;
13181
+ return this.contents.reduce((sum, node) => sum + node.paddedSize(), 0);
13182
+ }
13029
13183
  /**
13030
13184
  * `getEffectedCreatedAt` returns the creation time of the effected element.
13031
13185
  */
@@ -17953,6 +18107,24 @@ class History {
17953
18107
  replace(this.undoStack);
17954
18108
  replace(this.redoStack);
17955
18109
  }
18110
+ /**
18111
+ * `reconcileTreeEdit` reconciles the tree edit operation.
18112
+ * Scan both undo/redo stacks and adjust tree edit operations
18113
+ * when a remote edit modifies the same tree.
18114
+ */
18115
+ reconcileTreeEdit(parentCreatedAt, rangeFrom, rangeTo, contentSize) {
18116
+ const replace = (stack) => {
18117
+ for (const ops of stack) {
18118
+ for (const op of ops) {
18119
+ if (op instanceof TreeEditOperation && op.getParentCreatedAt().compare(parentCreatedAt) === 0) {
18120
+ op.reconcileOperation(rangeFrom, rangeTo, contentSize);
18121
+ }
18122
+ }
18123
+ }
18124
+ };
18125
+ replace(this.undoStack);
18126
+ replace(this.redoStack);
18127
+ }
17956
18128
  }
17957
18129
  function validateYorkieRuleset(data, ruleset) {
17958
18130
  const errors = [];
@@ -18906,6 +19078,15 @@ class Document {
18906
19078
  op.getContent()?.length ?? 0
18907
19079
  );
18908
19080
  }
19081
+ if (op instanceof TreeEditOperation) {
19082
+ const [from, to] = op.normalizePos();
19083
+ this.internalHistory.reconcileTreeEdit(
19084
+ op.getParentCreatedAt(),
19085
+ from,
19086
+ to,
19087
+ op.getContentSize()
19088
+ );
19089
+ }
18909
19090
  }
18910
19091
  this.changeID = this.changeID.syncClocks(change.getID());
18911
19092
  if (opInfos.length) {
@@ -19451,7 +19632,7 @@ function createAuthInterceptor(apiKey, token) {
19451
19632
  };
19452
19633
  }
19453
19634
  const name$1 = "@yorkie-js/sdk";
19454
- const version$1 = "0.6.49";
19635
+ const version$1 = "0.7.0";
19455
19636
  const pkg$1 = {
19456
19637
  name: name$1,
19457
19638
  version: version$1
@@ -21306,7 +21487,7 @@ if (typeof globalThis !== "undefined") {
21306
21487
  };
21307
21488
  }
21308
21489
  const name = "@yorkie-js/react";
21309
- const version = "0.6.49";
21490
+ const version = "0.7.0";
21310
21491
  const pkg = {
21311
21492
  name,
21312
21493
  version