@pixerate/editor 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +71 -1
  2. package/THIRD_PARTY_NOTICES.md +29 -0
  3. package/dist/agent/index.cjs +10 -9
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +1 -1
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +4 -3
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/canvas/index.cjs +3173 -340
  10. package/dist/canvas/index.cjs.map +1 -1
  11. package/dist/canvas/index.d.cts +617 -4
  12. package/dist/canvas/index.d.ts +617 -4
  13. package/dist/canvas/index.js +3105 -272
  14. package/dist/canvas/index.js.map +1 -1
  15. package/dist/chunk-4BVP64JJ.cjs +1406 -0
  16. package/dist/chunk-4BVP64JJ.cjs.map +1 -0
  17. package/dist/{chunk-XNORY7M6.cjs → chunk-7WISYZFO.cjs} +105 -50
  18. package/dist/chunk-7WISYZFO.cjs.map +1 -0
  19. package/dist/{chunk-OLZJXL4R.cjs → chunk-AL6JMGWW.cjs} +59 -25
  20. package/dist/chunk-AL6JMGWW.cjs.map +1 -0
  21. package/dist/chunk-BVP3TSLH.cjs +69 -0
  22. package/dist/chunk-BVP3TSLH.cjs.map +1 -0
  23. package/dist/{chunk-MCSJFWAO.cjs → chunk-C7P22VIP.cjs} +670 -96
  24. package/dist/chunk-C7P22VIP.cjs.map +1 -0
  25. package/dist/{chunk-PGNZKFQS.js → chunk-ECCCYKGL.js} +76 -21
  26. package/dist/chunk-ECCCYKGL.js.map +1 -0
  27. package/dist/{chunk-3CN2WD3X.js → chunk-FH6F67DN.js} +646 -72
  28. package/dist/chunk-FH6F67DN.js.map +1 -0
  29. package/dist/chunk-HRMEDT2L.js +1406 -0
  30. package/dist/chunk-HRMEDT2L.js.map +1 -0
  31. package/dist/{chunk-ITBSKI26.js → chunk-IXHSYOVY.js} +941 -9
  32. package/dist/chunk-IXHSYOVY.js.map +1 -0
  33. package/dist/{chunk-FODNLX5N.js → chunk-NAXVVS5I.js} +38 -4
  34. package/dist/chunk-NAXVVS5I.js.map +1 -0
  35. package/dist/chunk-O5RYH2PG.js +69 -0
  36. package/dist/chunk-O5RYH2PG.js.map +1 -0
  37. package/dist/{chunk-SBCZ6RN5.cjs → chunk-PO6A6QQH.cjs} +1039 -107
  38. package/dist/chunk-PO6A6QQH.cjs.map +1 -0
  39. package/dist/{chunk-3LV6RRPH.js → chunk-QGYDWPRM.js} +2 -2
  40. package/dist/{chunk-U5KWZU4X.js → chunk-RR7F5GUM.js} +2632 -129
  41. package/dist/chunk-RR7F5GUM.js.map +1 -0
  42. package/dist/{chunk-5S3Z4PPF.js → chunk-UAKDG62Z.js} +232 -25
  43. package/dist/chunk-UAKDG62Z.js.map +1 -0
  44. package/dist/{chunk-SML64VJG.cjs → chunk-V3CHHWOE.cjs} +4 -4
  45. package/dist/{chunk-SML64VJG.cjs.map → chunk-V3CHHWOE.cjs.map} +1 -1
  46. package/dist/chunk-WSQKHXW7.cjs +5726 -0
  47. package/dist/chunk-WSQKHXW7.cjs.map +1 -0
  48. package/dist/{chunk-D27YFC46.cjs → chunk-X4N4WUKB.cjs} +267 -60
  49. package/dist/chunk-X4N4WUKB.cjs.map +1 -0
  50. package/dist/commands/index.cjs +74 -1
  51. package/dist/commands/index.cjs.map +1 -1
  52. package/dist/commands/index.d.cts +34 -1
  53. package/dist/commands/index.d.ts +34 -1
  54. package/dist/commands/index.js +73 -0
  55. package/dist/commands/index.js.map +1 -1
  56. package/dist/compare/index.cjs +3 -3
  57. package/dist/compare/index.d.cts +1 -1
  58. package/dist/compare/index.d.ts +1 -1
  59. package/dist/compare/index.js +2 -2
  60. package/dist/controller-BIJiNoVs.d.cts +1842 -0
  61. package/dist/controller-BIJiNoVs.d.ts +1842 -0
  62. package/dist/{documents-BQjzJNe2.d.ts → documents-CHT1U5Vs.d.ts} +10 -0
  63. package/dist/{documents-KRTPhvst.d.cts → documents-Gp7wb0Me.d.cts} +10 -0
  64. package/dist/extensions/index.cjs +53 -6
  65. package/dist/extensions/index.cjs.map +1 -1
  66. package/dist/extensions/index.d.cts +12 -4
  67. package/dist/extensions/index.d.ts +12 -4
  68. package/dist/extensions/index.js +53 -6
  69. package/dist/generation/index.cjs +1013 -69
  70. package/dist/generation/index.cjs.map +1 -1
  71. package/dist/generation/index.d.cts +474 -13
  72. package/dist/generation/index.d.ts +474 -13
  73. package/dist/generation/index.js +976 -32
  74. package/dist/generation/index.js.map +1 -1
  75. package/dist/image-editor/index.cjs +3385 -1275
  76. package/dist/image-editor/index.cjs.map +1 -1
  77. package/dist/image-editor/index.d.cts +693 -128
  78. package/dist/image-editor/index.d.ts +693 -128
  79. package/dist/image-editor/index.js +3325 -1215
  80. package/dist/image-editor/index.js.map +1 -1
  81. package/dist/{index-fJrlkJCd.d.ts → index-7a6bHTLy.d.ts} +494 -5
  82. package/dist/{index-BhJBSm2d.d.cts → index-Csd5qI8u.d.cts} +494 -5
  83. package/dist/index.cjs +1491 -45
  84. package/dist/index.cjs.map +1 -1
  85. package/dist/index.d.cts +110 -19
  86. package/dist/index.d.ts +110 -19
  87. package/dist/index.js +1464 -18
  88. package/dist/index.js.map +1 -1
  89. package/dist/mention-text-CDnCFd3c.d.cts +53 -0
  90. package/dist/mention-text-CDnCFd3c.d.ts +53 -0
  91. package/dist/model-C1zApQM8.d.cts +219 -0
  92. package/dist/model-C1zApQM8.d.ts +219 -0
  93. package/dist/persistence/index.d.cts +3 -120
  94. package/dist/persistence/index.d.ts +3 -120
  95. package/dist/{registry-GJI4gToU.d.cts → registry-CEgwXED1.d.cts} +12 -1
  96. package/dist/{registry-GJI4gToU.d.ts → registry-CEgwXED1.d.ts} +12 -1
  97. package/dist/serializers/index.cjs +12 -4
  98. package/dist/serializers/index.cjs.map +1 -1
  99. package/dist/serializers/index.d.cts +39 -12
  100. package/dist/serializers/index.d.ts +39 -12
  101. package/dist/serializers/index.js +12 -4
  102. package/dist/spreadsheet/index.cjs +127 -3
  103. package/dist/spreadsheet/index.cjs.map +1 -1
  104. package/dist/spreadsheet/index.d.cts +431 -11
  105. package/dist/spreadsheet/index.d.ts +431 -11
  106. package/dist/spreadsheet/index.js +127 -3
  107. package/dist/storage-BpFfspHm.d.cts +120 -0
  108. package/dist/storage-BpFfspHm.d.ts +120 -0
  109. package/dist/tokens/index.cjs +115 -0
  110. package/dist/tokens/index.cjs.map +1 -0
  111. package/dist/tokens/index.d.cts +212 -0
  112. package/dist/tokens/index.d.ts +212 -0
  113. package/dist/tokens/index.js +115 -0
  114. package/dist/tokens/index.js.map +1 -0
  115. package/dist/{track-changes-BK5sVf4_.d.cts → track-changes-D_VAPELi.d.cts} +95 -11
  116. package/dist/{track-changes-CDjCrwKe.d.ts → track-changes-Db_fGEvx.d.ts} +95 -11
  117. package/package.json +6 -1
  118. package/dist/chunk-3CN2WD3X.js.map +0 -1
  119. package/dist/chunk-5S3Z4PPF.js.map +0 -1
  120. package/dist/chunk-D27YFC46.cjs.map +0 -1
  121. package/dist/chunk-FODNLX5N.js.map +0 -1
  122. package/dist/chunk-ITBSKI26.js.map +0 -1
  123. package/dist/chunk-MA2F5KHF.cjs +0 -3223
  124. package/dist/chunk-MA2F5KHF.cjs.map +0 -1
  125. package/dist/chunk-MCSJFWAO.cjs.map +0 -1
  126. package/dist/chunk-OLZJXL4R.cjs.map +0 -1
  127. package/dist/chunk-PGNZKFQS.js.map +0 -1
  128. package/dist/chunk-SBCZ6RN5.cjs.map +0 -1
  129. package/dist/chunk-U5KWZU4X.js.map +0 -1
  130. package/dist/chunk-XNORY7M6.cjs.map +0 -1
  131. package/dist/controller-BhLLAoi8.d.cts +0 -1000
  132. package/dist/controller-BhLLAoi8.d.ts +0 -1000
  133. /package/dist/{chunk-3LV6RRPH.js.map → chunk-QGYDWPRM.js.map} +0 -0
@@ -264,6 +264,7 @@ var INSERTION_MARK_NAME = "insertion";
264
264
  var DELETION_MARK_NAME = "deletion";
265
265
  var FORMAT_CHANGE_MARK_NAME = "formatChange";
266
266
  var BLOCK_CHANGE_ATTRIBUTE = "blockChange";
267
+ var MOVE_ID_ATTRIBUTE = "moveId";
267
268
  var REVIEW_MARK_NAMES = /* @__PURE__ */ new Set([
268
269
  INSERTION_MARK_NAME,
269
270
  DELETION_MARK_NAME,
@@ -337,6 +338,15 @@ var sharedAttributes = () => ({
337
338
  renderHTML: (attrs) => ({ "data-created-at": String(attrs.createdAt) })
338
339
  }
339
340
  });
341
+ var moveAttribute = () => ({
342
+ [MOVE_ID_ATTRIBUTE]: {
343
+ default: null,
344
+ parseHTML: (el) => el.getAttribute("data-move-id"),
345
+ renderHTML: (attrs) => attrs[MOVE_ID_ATTRIBUTE] ? { "data-move-id": attrs[MOVE_ID_ATTRIBUTE] } : {}
346
+ }
347
+ });
348
+ var MOVE_TO_CLASS = "pixerate-move-to underline decoration-double decoration-emerald-600 text-emerald-700 dark:text-emerald-400";
349
+ var MOVE_FROM_CLASS = "pixerate-move-from line-through decoration-double decoration-emerald-600 text-emerald-700 dark:text-emerald-400";
340
350
  var TrackedInsertion = _core.Mark.create({
341
351
  name: INSERTION_MARK_NAME,
342
352
  inclusive: false,
@@ -344,20 +354,22 @@ var TrackedInsertion = _core.Mark.create({
344
354
  return {
345
355
  HTMLAttributes: {
346
356
  class: "pixerate-insertion underline decoration-emerald-500 text-emerald-700 dark:text-emerald-400"
347
- }
357
+ },
358
+ moveHTMLAttributes: { class: MOVE_TO_CLASS }
348
359
  };
349
360
  },
350
361
  addStorage() {
351
362
  return { markdown: { serialize: { open: "", close: "" }, parse: {} } };
352
363
  },
353
- addAttributes: sharedAttributes,
364
+ addAttributes: () => ({ ...sharedAttributes(), ...moveAttribute() }),
354
365
  parseHTML() {
355
366
  return [{ tag: 'ins[data-change-type="insertion"]', priority: 100 }];
356
367
  },
357
- renderHTML({ HTMLAttributes }) {
368
+ renderHTML({ mark, HTMLAttributes }) {
369
+ const base = mark.attrs[MOVE_ID_ATTRIBUTE] ? this.options.moveHTMLAttributes : this.options.HTMLAttributes;
358
370
  return [
359
371
  "ins",
360
- _core.mergeAttributes.call(void 0, this.options.HTMLAttributes, HTMLAttributes, {
372
+ _core.mergeAttributes.call(void 0, base, HTMLAttributes, {
361
373
  "data-change-type": "insertion"
362
374
  }),
363
375
  0
@@ -371,7 +383,8 @@ var TrackedDeletion = _core.Mark.create({
371
383
  return {
372
384
  HTMLAttributes: {
373
385
  class: "pixerate-deletion line-through decoration-red-500 text-red-600 dark:text-red-400"
374
- }
386
+ },
387
+ moveHTMLAttributes: { class: MOVE_FROM_CLASS }
375
388
  };
376
389
  },
377
390
  addStorage() {
@@ -382,14 +395,15 @@ var TrackedDeletion = _core.Mark.create({
382
395
  }
383
396
  };
384
397
  },
385
- addAttributes: sharedAttributes,
398
+ addAttributes: () => ({ ...sharedAttributes(), ...moveAttribute() }),
386
399
  parseHTML() {
387
400
  return [{ tag: 'del[data-change-type="deletion"]', priority: 100 }];
388
401
  },
389
- renderHTML({ HTMLAttributes }) {
402
+ renderHTML({ mark, HTMLAttributes }) {
403
+ const base = mark.attrs[MOVE_ID_ATTRIBUTE] ? this.options.moveHTMLAttributes : this.options.HTMLAttributes;
390
404
  return [
391
405
  "del",
392
- _core.mergeAttributes.call(void 0, this.options.HTMLAttributes, HTMLAttributes, {
406
+ _core.mergeAttributes.call(void 0, base, HTMLAttributes, {
393
407
  "data-change-type": "deletion"
394
408
  }),
395
409
  0
@@ -539,6 +553,8 @@ function describeBlockChange(previous, current, ignoredAttributes = ["id"]) {
539
553
  keys.forEach((key) => {
540
554
  if (key === "textAlign") {
541
555
  parts.push(`Changed alignment to ${humanize(String(_nullishCoalesce(_optionalChain([current, 'access', _8 => _8.attrs, 'optionalAccess', _9 => _9.textAlign]), () => ( "default"))))}`);
556
+ } else if (key === "styleId") {
557
+ parts.push(`Changed style to ${_nullishCoalesce(_optionalChain([current, 'access', _10 => _10.attrs, 'optionalAccess', _11 => _11.styleId]), () => ( "default"))}`);
542
558
  } else {
543
559
  parts.push(`Changed ${humanize(key).toLowerCase()} of ${after}`);
544
560
  }
@@ -559,12 +575,26 @@ function describeBlockChange(previous, current, ignoredAttributes = ["id"]) {
559
575
  }
560
576
  return parts.join("; ") || `Changed ${after}`;
561
577
  }
578
+ function trackedChangeLabel(change) {
579
+ switch (change.type) {
580
+ case "insertion":
581
+ return "Inserted";
582
+ case "deletion":
583
+ return "Deleted";
584
+ case "format":
585
+ return "Formatted";
586
+ case "move":
587
+ return "Moved";
588
+ default:
589
+ return "Changed";
590
+ }
591
+ }
562
592
  function truncate(text, max = 40) {
563
593
  return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
564
594
  }
565
595
  function toDoc(source) {
566
596
  if (!source) return null;
567
- if (_optionalChain([source, 'access', _10 => _10.state, 'optionalAccess', _11 => _11.doc])) return source.state.doc;
597
+ if (_optionalChain([source, 'access', _12 => _12.state, 'optionalAccess', _13 => _13.doc])) return source.state.doc;
568
598
  if (source.doc && typeof source.doc.descendants === "function") return source.doc;
569
599
  if (typeof source.descendants === "function") return source;
570
600
  return null;
@@ -632,8 +662,8 @@ function getTrackedChanges(source) {
632
662
  };
633
663
  const blockCounts = /* @__PURE__ */ new Map();
634
664
  doc.descendants((node, pos) => {
635
- const block = _optionalChain([node, 'access', _12 => _12.attrs, 'optionalAccess', _13 => _13[BLOCK_CHANGE_ATTRIBUTE]]);
636
- if (_optionalChain([block, 'optionalAccess', _14 => _14.changeId]) && node.isTextblock) {
665
+ const block = _optionalChain([node, 'access', _14 => _14.attrs, 'optionalAccess', _15 => _15[BLOCK_CHANGE_ATTRIBUTE]]);
666
+ if (_optionalChain([block, 'optionalAccess', _16 => _16.changeId]) && node.isTextblock) {
637
667
  blockCounts.set(block.changeId, (_nullishCoalesce(blockCounts.get(block.changeId), () => ( 0))) + 1);
638
668
  const change = add(
639
669
  `block:${block.changeId}`,
@@ -657,6 +687,20 @@ function getTrackedChanges(source) {
657
687
  if (!isMarkChange(markType)) return;
658
688
  const attrs = changeAttributes(mark);
659
689
  if (!attrs.changeId) return;
690
+ const text = node.isText ? _nullishCoalesce(node.text, () => ( "")) : "";
691
+ const moveId = markType !== FORMAT_CHANGE_MARK_NAME ? attrs[MOVE_ID_ATTRIBUTE] : null;
692
+ if (moveId) {
693
+ const change2 = add(`move:${moveId}`, "move", { ...attrs, changeId: moveId }, pos, pos + node.nodeSize, text);
694
+ if (!change2.move) change2.move = { from: [], to: [], fromText: "", toText: "" };
695
+ const source2 = markType === DELETION_MARK_NAME;
696
+ const list = source2 ? change2.move.from : change2.move.to;
697
+ const last = list[list.length - 1];
698
+ if (last && last.to === pos) last.to = pos + node.nodeSize;
699
+ else list.push({ from: pos, to: pos + node.nodeSize });
700
+ if (source2) change2.move.fromText += text;
701
+ else change2.move.toText += text;
702
+ return;
703
+ }
660
704
  const type = markType === FORMAT_CHANGE_MARK_NAME ? "format" : markType;
661
705
  const change = add(
662
706
  `${type}:${attrs.changeId}`,
@@ -664,7 +708,7 @@ function getTrackedChanges(source) {
664
708
  attrs,
665
709
  pos,
666
710
  pos + node.nodeSize,
667
- node.isText ? _nullishCoalesce(node.text, () => ( "")) : ""
711
+ text
668
712
  );
669
713
  if (type === "format") {
670
714
  const summary = diffFormatting(_nullishCoalesce(mark.attrs.before, () => ( [])), _nullishCoalesce(mark.attrs.after, () => ( [])));
@@ -685,6 +729,12 @@ function getTrackedChanges(source) {
685
729
  case "format":
686
730
  change.description = describeFormatChange(change.format);
687
731
  break;
732
+ case "move": {
733
+ const move = change.move;
734
+ change.text = move.toText || move.fromText;
735
+ change.description = change.text ? `Moved "${truncate(change.text)}"` : "Moved content";
736
+ break;
737
+ }
688
738
  case "block": {
689
739
  const { previous, current, operation } = change.block;
690
740
  if (operation) {
@@ -712,15 +762,20 @@ function getTrackedChangeAt(state, pos = state.selection.from, changes = getTrac
712
762
  return _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(inline.find((c) => c.ranges.some((r) => r.from < pos && pos < r.to)), () => ( inline.find((c) => c.ranges.some((r) => r.from <= pos && pos <= r.to)))), () => ( blocks.find((c) => c.ranges.some((r) => r.from < pos && pos < r.to)))), () => ( null));
713
763
  }
714
764
  function selectionRange(change) {
715
- return change.type === "block" ? [change.from + 1, change.to - 1] : [change.from, change.to];
765
+ if (change.type === "block") return [change.from + 1, change.to - 1];
766
+ if (change.type === "move" && change.move) {
767
+ const ranges = change.move.to.length ? change.move.to : change.move.from;
768
+ if (ranges.length) return [ranges[0].from, ranges[ranges.length - 1].to];
769
+ }
770
+ return [change.from, change.to];
716
771
  }
717
772
  function isTrackChangesEnabled(source) {
718
- const state = _nullishCoalesce(_optionalChain([source, 'optionalAccess', _15 => _15.state]), () => ( source));
773
+ const state = _nullishCoalesce(_optionalChain([source, 'optionalAccess', _17 => _17.state]), () => ( source));
719
774
  if (!state || typeof state.plugins === "undefined") return false;
720
- return _nullishCoalesce(_optionalChain([trackChangesPluginKey, 'access', _16 => _16.getState, 'call', _17 => _17(state), 'optionalAccess', _18 => _18.enabled]), () => ( false));
775
+ return _nullishCoalesce(_optionalChain([trackChangesPluginKey, 'access', _18 => _18.getState, 'call', _19 => _19(state), 'optionalAccess', _20 => _20.enabled]), () => ( false));
721
776
  }
722
777
  function getTrackChangesStore(editor) {
723
- return _nullishCoalesce(_optionalChain([editor, 'optionalAccess', _19 => _19.storage, 'optionalAccess', _20 => _20.trackChanges, 'optionalAccess', _21 => _21.store]), () => ( null));
778
+ return _nullishCoalesce(_optionalChain([editor, 'optionalAccess', _21 => _21.storage, 'optionalAccess', _22 => _22.trackChanges, 'optionalAccess', _23 => _23.store]), () => ( null));
724
779
  }
725
780
  function marksFromJSON(schema, marks) {
726
781
  const result = [];
@@ -781,7 +836,7 @@ function sinkItem(tr, contentPos) {
781
836
  const itemType = $pos.node(itemDepth).type;
782
837
  if (index === 0 || list.child(index - 1).type !== itemType) return false;
783
838
  const nodeBefore = list.child(index - 1);
784
- const nestedBefore = _optionalChain([nodeBefore, 'access', _22 => _22.lastChild, 'optionalAccess', _23 => _23.type]) === list.type;
839
+ const nestedBefore = _optionalChain([nodeBefore, 'access', _24 => _24.lastChild, 'optionalAccess', _25 => _25.type]) === list.type;
785
840
  const inner = _model.Fragment.from(nestedBefore ? itemType.create() : null);
786
841
  const slice = new (0, _model.Slice)(
787
842
  _model.Fragment.from(itemType.create(null, _model.Fragment.from(list.type.create(null, inner)))),
@@ -882,10 +937,10 @@ function restoreWrappers(tr, contentPos, wrappers) {
882
937
  const wrapper = tr.doc.nodeAt(start);
883
938
  if (!wrapper) return;
884
939
  const end = start + wrapper.nodeSize;
885
- if (_optionalChain([tr, 'access', _24 => _24.doc, 'access', _25 => _25.resolve, 'call', _26 => _26(end), 'access', _27 => _27.nodeAfter, 'optionalAccess', _28 => _28.type]) === wrapper.type && _transform.canJoin.call(void 0, tr.doc, end)) {
940
+ if (_optionalChain([tr, 'access', _26 => _26.doc, 'access', _27 => _27.resolve, 'call', _28 => _28(end), 'access', _29 => _29.nodeAfter, 'optionalAccess', _30 => _30.type]) === wrapper.type && _transform.canJoin.call(void 0, tr.doc, end)) {
886
941
  step(() => tr.join(end));
887
942
  }
888
- if (_optionalChain([tr, 'access', _29 => _29.doc, 'access', _30 => _30.resolve, 'call', _31 => _31(start), 'access', _32 => _32.nodeBefore, 'optionalAccess', _33 => _33.type]) === wrapper.type && _transform.canJoin.call(void 0, tr.doc, start)) {
943
+ if (_optionalChain([tr, 'access', _31 => _31.doc, 'access', _32 => _32.resolve, 'call', _33 => _33(start), 'access', _34 => _34.nodeBefore, 'optionalAccess', _35 => _35.type]) === wrapper.type && _transform.canJoin.call(void 0, tr.doc, start)) {
889
944
  step(() => tr.join(start));
890
945
  }
891
946
  return;
@@ -899,8 +954,8 @@ function removeBlocks(tr, ids, decision) {
899
954
  if (cached !== void 0) return cached;
900
955
  let result;
901
956
  if (node.isTextblock) {
902
- const record = _optionalChain([node, 'access', _34 => _34.attrs, 'optionalAccess', _35 => _35[BLOCK_CHANGE_ATTRIBUTE]]);
903
- result = !!_optionalChain([record, 'optionalAccess', _36 => _36.changeId]) && record.operation === removed && ids.has(record.changeId);
957
+ const record = _optionalChain([node, 'access', _36 => _36.attrs, 'optionalAccess', _37 => _37[BLOCK_CHANGE_ATTRIBUTE]]);
958
+ result = !!_optionalChain([record, 'optionalAccess', _38 => _38.changeId]) && record.operation === removed && ids.has(record.changeId);
904
959
  } else if (node.isLeaf || node.childCount === 0) {
905
960
  result = false;
906
961
  } else {
@@ -912,7 +967,7 @@ function removeBlocks(tr, ids, decision) {
912
967
  };
913
968
  const doc = tr.doc;
914
969
  if (removable(doc)) {
915
- const filler = _optionalChain([doc, 'access', _37 => _37.type, 'access', _38 => _38.contentMatch, 'access', _39 => _39.defaultType, 'optionalAccess', _40 => _40.createAndFill, 'call', _41 => _41()]);
970
+ const filler = _optionalChain([doc, 'access', _39 => _39.type, 'access', _40 => _40.contentMatch, 'access', _41 => _41.defaultType, 'optionalAccess', _42 => _42.createAndFill, 'call', _43 => _43()]);
916
971
  if (filler) tr.replaceWith(0, doc.content.size, filler);
917
972
  return;
918
973
  }
@@ -943,8 +998,8 @@ function decideBlocks(tr, changes, decision) {
943
998
  removeBlocks(tr, ids, decision);
944
999
  const items = [];
945
1000
  tr.doc.descendants((node, pos) => {
946
- const record = _optionalChain([node, 'access', _42 => _42.attrs, 'optionalAccess', _43 => _43[BLOCK_CHANGE_ATTRIBUTE]]);
947
- if (node.isTextblock && _optionalChain([record, 'optionalAccess', _44 => _44.changeId]) && ids.has(record.changeId)) {
1001
+ const record = _optionalChain([node, 'access', _44 => _44.attrs, 'optionalAccess', _45 => _45[BLOCK_CHANGE_ATTRIBUTE]]);
1002
+ if (node.isTextblock && _optionalChain([record, 'optionalAccess', _46 => _46.changeId]) && ids.has(record.changeId)) {
948
1003
  items.push({ contentPos: pos + 1, record });
949
1004
  }
950
1005
  return !node.isTextblock;
@@ -982,12 +1037,36 @@ function decideBlocks(tr, changes, decision) {
982
1037
  }
983
1038
  });
984
1039
  }
1040
+ function deleteWholeBlock(tr, from, to) {
1041
+ const $from = tr.doc.resolve(from);
1042
+ const block = $from.parent;
1043
+ if ($from.depth !== 1 || !block.isTextblock || from !== $from.start() || to !== $from.end() || tr.doc.childCount < 2) {
1044
+ return false;
1045
+ }
1046
+ try {
1047
+ tr.delete($from.before(), $from.after());
1048
+ return true;
1049
+ } catch (e8) {
1050
+ return false;
1051
+ }
1052
+ }
985
1053
  function applyDecision(tr, changes, decision) {
986
1054
  const schema = tr.doc.type.schema;
987
1055
  const format = changes.filter((c) => c.type === "format");
988
1056
  if (format.length) decideFormat(tr, format, decision);
989
1057
  const deletions = [];
990
1058
  changes.forEach((change) => {
1059
+ if (change.type === "move" && change.move) {
1060
+ const accept = decision === "accept";
1061
+ const keepType = schema.marks[accept ? INSERTION_MARK_NAME : DELETION_MARK_NAME];
1062
+ (accept ? change.move.to : change.move.from).forEach(({ from, to }) => {
1063
+ if (keepType) tr.removeMark(from, to, keepType);
1064
+ });
1065
+ (accept ? change.move.from : change.move.to).forEach(
1066
+ ({ from, to }) => deletions.push({ from, to, wholeBlocks: true })
1067
+ );
1068
+ return;
1069
+ }
991
1070
  if (change.type !== "insertion" && change.type !== "deletion") return;
992
1071
  const markType = schema.marks[change.type];
993
1072
  if (!markType) return;
@@ -1000,8 +1079,11 @@ function applyDecision(tr, changes, decision) {
1000
1079
  }
1001
1080
  });
1002
1081
  });
1003
- deletions.sort((a, b) => b.from - a.from).forEach(({ from, to }) => {
1004
- tr.delete(tr.mapping.map(from), tr.mapping.map(to));
1082
+ deletions.sort((a, b) => b.from - a.from).forEach(({ from, to, wholeBlocks }) => {
1083
+ const start = tr.mapping.map(from);
1084
+ const end = tr.mapping.map(to);
1085
+ if (wholeBlocks && deleteWholeBlock(tr, start, end)) return;
1086
+ tr.delete(start, end);
1005
1087
  });
1006
1088
  const blocks = changes.filter((c) => c.type === "block");
1007
1089
  if (blocks.length) decideBlocks(tr, blocks, decision);
@@ -1036,7 +1118,7 @@ function acceptSlice(slice, schema) {
1036
1118
  if (insertion) marks = insertion.removeFromSet(marks);
1037
1119
  if (format) marks = format.removeFromSet(marks);
1038
1120
  children.push(marks === child.marks ? child : child.mark(marks));
1039
- } else if (_optionalChain([child, 'access', _45 => _45.attrs, 'optionalAccess', _46 => _46[BLOCK_CHANGE_ATTRIBUTE]])) {
1121
+ } else if (_optionalChain([child, 'access', _47 => _47.attrs, 'optionalAccess', _48 => _48[BLOCK_CHANGE_ATTRIBUTE]])) {
1040
1122
  children.push(
1041
1123
  child.type.create(
1042
1124
  { ...child.attrs, [BLOCK_CHANGE_ATTRIBUTE]: null },
@@ -1059,6 +1141,52 @@ function stripMarks(fragment) {
1059
1141
  });
1060
1142
  return _model.Fragment.fromArray(children);
1061
1143
  }
1144
+ var SENTENCE_END = /[.!?…]$/;
1145
+ var TRAILING_CLOSERS = /["'”’)]+$/;
1146
+ var TRAILING_SPACES = /[  ]+$/;
1147
+ function isMoveSized(text) {
1148
+ const trimmed = text.replace(TRAILING_SPACES, "");
1149
+ if (trimmed.includes("\n")) return true;
1150
+ const sentence = trimmed.replace(TRAILING_CLOSERS, "");
1151
+ return SENTENCE_END.test(sentence) && sentence.trim().split(/\s+/).length >= 2;
1152
+ }
1153
+ var normalizeMoveText = (text) => text.replace(/\s+/g, "");
1154
+ function deletedText(slice, ctx) {
1155
+ let text = "";
1156
+ let blocks = 0;
1157
+ slice.content.descendants((node) => {
1158
+ if (node.isTextblock) {
1159
+ if (blocks++ > 0) text += "\n";
1160
+ return true;
1161
+ }
1162
+ if (!node.isText) return true;
1163
+ const insertion = ctx.insertion.isInSet(node.marks);
1164
+ if (insertion && insertion.attrs.authorId === ctx.author.id) return false;
1165
+ if (ctx.deletion.isInSet(node.marks)) return false;
1166
+ text += _nullishCoalesce(node.text, () => ( ""));
1167
+ return false;
1168
+ });
1169
+ return text;
1170
+ }
1171
+ var rangeText = (doc, from, to) => doc.textBetween(from, to, "\n", "");
1172
+ function linkMoveSource(tr, pending, ctx) {
1173
+ const segments = [];
1174
+ tr.doc.descendants((node, pos) => {
1175
+ if (!node.isInline) return true;
1176
+ const mark = ctx.deletion.isInSet(node.marks);
1177
+ if (mark && mark.attrs.changeId === pending.id && !mark.attrs[MOVE_ID_ATTRIBUTE]) {
1178
+ segments.push({ from: pos, to: pos + node.nodeSize, mark });
1179
+ }
1180
+ return false;
1181
+ });
1182
+ if (segments.length === 0) return false;
1183
+ const text = segments.map((s) => rangeText(tr.doc, s.from, s.to)).join("");
1184
+ if (normalizeMoveText(text) !== pending.text) return false;
1185
+ segments.forEach(
1186
+ ({ from, to, mark }) => tr.addMark(from, to, ctx.deletion.create({ ...mark.attrs, [MOVE_ID_ATTRIBUTE]: pending.id }))
1187
+ );
1188
+ return true;
1189
+ }
1062
1190
  function newAttributes(ctx) {
1063
1191
  return {
1064
1192
  changeId: ctx.generateId(),
@@ -1081,7 +1209,7 @@ function adjacentAttributes(doc, from, to, type, ctx) {
1081
1209
  const candidates = [doc.resolve(from).nodeBefore, doc.resolve(to).nodeAfter];
1082
1210
  for (const node of candidates) {
1083
1211
  const mark = node && type.isInSet(node.marks);
1084
- if (mark && mark.attrs.authorId === ctx.author.id && mark.attrs.changeId) {
1212
+ if (mark && mark.attrs.authorId === ctx.author.id && mark.attrs.changeId && !mark.attrs[MOVE_ID_ATTRIBUTE]) {
1085
1213
  return changeAttributes(mark);
1086
1214
  }
1087
1215
  }
@@ -1210,8 +1338,8 @@ function trackBlocks(tr, pending, ctx) {
1210
1338
  if (!node.isTextblock || $pos.parentOffset !== 0 || $pos.depth === 0) return;
1211
1339
  if (!node.type.spec.attrs || !(BLOCK_CHANGE_ATTRIBUTE in node.type.spec.attrs)) return;
1212
1340
  const pos = $pos.before();
1213
- if (_optionalChain([existing, 'optionalAccess', _47 => _47.operation]) || _optionalChain([node, 'access', _48 => _48.attrs, 'access', _49 => _49[BLOCK_CHANGE_ATTRIBUTE], 'optionalAccess', _50 => _50.operation])) return;
1214
- const original = _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _51 => _51.previous]), () => ( previous));
1341
+ if (_optionalChain([existing, 'optionalAccess', _49 => _49.operation]) || _optionalChain([node, 'access', _50 => _50.attrs, 'access', _51 => _51[BLOCK_CHANGE_ATTRIBUTE], 'optionalAccess', _52 => _52.operation])) return;
1342
+ const original = _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _53 => _53.previous]), () => ( previous));
1215
1343
  const current = blockSnapshot(tr.doc, pos);
1216
1344
  if (sameBlock(original, current, ctx.ignoredAttributes)) {
1217
1345
  if (node.attrs[BLOCK_CHANGE_ATTRIBUTE]) {
@@ -1243,7 +1371,7 @@ function collectBlockChanges(step, docBefore, docAfter, rest, pending, ctx) {
1243
1371
  };
1244
1372
  if (step instanceof _transform.AttrStep) {
1245
1373
  const node = docBefore.nodeAt(step.pos);
1246
- if (_optionalChain([node, 'optionalAccess', _52 => _52.isTextblock]) && step.attr !== BLOCK_CHANGE_ATTRIBUTE && !ctx.ignoredAttributes.has(step.attr)) {
1374
+ if (_optionalChain([node, 'optionalAccess', _54 => _54.isTextblock]) && step.attr !== BLOCK_CHANGE_ATTRIBUTE && !ctx.ignoredAttributes.has(step.attr)) {
1247
1375
  record(step.pos, step.pos);
1248
1376
  }
1249
1377
  return;
@@ -1338,24 +1466,57 @@ function trackTransactions(transactions, oldState, newState, ctx) {
1338
1466
  if (blocks.size) {
1339
1467
  changed = trackBlocks(tr, blocks, ctx) || changed;
1340
1468
  }
1469
+ const moves = ctx.moves;
1470
+ let insertAttrs = null;
1471
+ let deleteAttrs = null;
1472
+ const moveAttrs = (id) => ({
1473
+ changeId: id,
1474
+ authorId: ctx.author.id,
1475
+ authorName: ctx.author.name,
1476
+ authorColor: _nullishCoalesce(ctx.author.color, () => ( null)),
1477
+ createdAt: ctx.now(),
1478
+ [MOVE_ID_ATTRIBUTE]: id
1479
+ });
1480
+ if (moves && inserted.length) {
1481
+ const insertedText = normalizeMoveText(
1482
+ inserted.map((r) => rangeText(tr.doc, r.from, r.to)).join("")
1483
+ );
1484
+ const pending = moves.pending;
1485
+ if (moves.event === "paste" && pending && pending.authorId === ctx.author.id && insertedText === pending.text && linkMoveSource(tr, pending, ctx)) {
1486
+ insertAttrs = moveAttrs(pending.id);
1487
+ } else if (moves.event === "drop" && restores.length) {
1488
+ const raw = restores.map((r) => deletedText(r.slice, ctx)).join("\n");
1489
+ if (insertedText && normalizeMoveText(raw) === insertedText && moves.isMove(raw)) {
1490
+ insertAttrs = deleteAttrs = moveAttrs(ctx.generateId());
1491
+ }
1492
+ }
1493
+ }
1494
+ if (_optionalChain([moves, 'optionalAccess', _55 => _55.event]) === "cut" && restores.length) {
1495
+ deleteAttrs = newAttributes(ctx);
1496
+ const raw = restores.map((r) => deletedText(r.slice, ctx)).join("\n");
1497
+ if (normalizeMoveText(raw) && moves.isMove(raw)) {
1498
+ moves.cut = { id: deleteAttrs.changeId, text: normalizeMoveText(raw), authorId: ctx.author.id };
1499
+ }
1500
+ }
1341
1501
  inserted.forEach(({ from, to }) => {
1342
1502
  tr.removeMark(from, to, ctx.deletion);
1343
1503
  tr.removeMark(from, to, ctx.insertion);
1344
1504
  if (ctx.format) tr.removeMark(from, to, ctx.format);
1345
- const attrs = _nullishCoalesce(adjacentAttributes(tr.doc, from, to, ctx.insertion, ctx), () => ( newAttributes(ctx)));
1505
+ const attrs = _nullishCoalesce(_nullishCoalesce(insertAttrs, () => ( adjacentAttributes(tr.doc, from, to, ctx.insertion, ctx))), () => ( newAttributes(ctx)));
1346
1506
  tr.addMark(from, to, ctx.insertion.create(attrs));
1347
1507
  changed = true;
1348
1508
  });
1509
+ if (insertAttrs) changed = true;
1349
1510
  let cursor = null;
1350
1511
  restores.sort((a, b) => b.pos - a.pos).forEach((restore) => {
1351
1512
  const pos = tr.mapping.map(restore.pos, -1);
1352
- const attrs = _nullishCoalesce(adjacentAttributes(tr.doc, pos, pos, ctx.deletion, ctx), () => ( newAttributes(ctx)));
1513
+ const attrs = _nullishCoalesce(_nullishCoalesce(deleteAttrs, () => ( adjacentAttributes(tr.doc, pos, pos, ctx.deletion, ctx))), () => ( newAttributes(ctx)));
1353
1514
  const marked = markDeletedSlice(restore.slice, restore.parentType, attrs, ctx);
1354
1515
  if (!marked || !marked.hasContent) return;
1355
1516
  const sizeBefore = tr.doc.content.size;
1356
1517
  try {
1357
1518
  tr.replace(pos, pos, marked.slice);
1358
- } catch (e8) {
1519
+ } catch (e9) {
1359
1520
  return;
1360
1521
  }
1361
1522
  changed = true;
@@ -1367,7 +1528,7 @@ function trackTransactions(transactions, oldState, newState, ctx) {
1367
1528
  if (cursor !== null) {
1368
1529
  try {
1369
1530
  tr.setSelection(_state.TextSelection.create(tr.doc, cursor));
1370
- } catch (e9) {
1531
+ } catch (e10) {
1371
1532
  }
1372
1533
  }
1373
1534
  tr.setMeta(TRACK_CHANGES_SKIP_META, true);
@@ -1377,10 +1538,10 @@ function buildSnapshot(state, author) {
1377
1538
  const plugin = trackChangesPluginKey.getState(state);
1378
1539
  const changes = getTrackedChanges(state.doc);
1379
1540
  return {
1380
- enabled: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _53 => _53.enabled]), () => ( false)),
1381
- author: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _54 => _54.author]), () => ( author)),
1541
+ enabled: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _56 => _56.enabled]), () => ( false)),
1542
+ author: _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _57 => _57.author]), () => ( author)),
1382
1543
  changes,
1383
- currentChangeId: _nullishCoalesce(_optionalChain([getTrackedChangeAt, 'call', _55 => _55(state, state.selection.from, changes), 'optionalAccess', _56 => _56.id]), () => ( null))
1544
+ currentChangeId: _nullishCoalesce(_optionalChain([getTrackedChangeAt, 'call', _58 => _58(state, state.selection.from, changes), 'optionalAccess', _59 => _59.id]), () => ( null))
1384
1545
  };
1385
1546
  }
1386
1547
  function allowTrackingInCodeBlocks(schema) {
@@ -1415,7 +1576,10 @@ var TrackChanges = _core.Extension.create({
1415
1576
  trackCodeBlocks: true,
1416
1577
  blockTypes: ["paragraph", "heading", "codeBlock"],
1417
1578
  ignoredMarks: [],
1418
- ignoredBlockAttributes: ["id"]
1579
+ ignoredBlockAttributes: ["id"],
1580
+ trackMoves: true,
1581
+ isMove: isMoveSized,
1582
+ moveHTMLAttributes: {}
1419
1583
  };
1420
1584
  },
1421
1585
  addStorage() {
@@ -1429,13 +1593,13 @@ var TrackChanges = _core.Extension.create({
1429
1593
  };
1430
1594
  },
1431
1595
  addGlobalAttributes() {
1432
- if (_optionalChain([this, 'access', _57 => _57.options, 'optionalAccess', _58 => _58.trackBlocks]) === false) return [];
1433
- const blockClass = _nullishCoalesce(_optionalChain([this, 'access', _59 => _59.options, 'optionalAccess', _60 => _60.blockChangeClass]), () => ( ""));
1434
- const insertedClass = _nullishCoalesce(_optionalChain([this, 'access', _61 => _61.options, 'optionalAccess', _62 => _62.blockInsertedClass]), () => ( ""));
1435
- const deletedClass = _nullishCoalesce(_optionalChain([this, 'access', _63 => _63.options, 'optionalAccess', _64 => _64.blockDeletedClass]), () => ( ""));
1596
+ if (_optionalChain([this, 'access', _60 => _60.options, 'optionalAccess', _61 => _61.trackBlocks]) === false) return [];
1597
+ const blockClass = _nullishCoalesce(_optionalChain([this, 'access', _62 => _62.options, 'optionalAccess', _63 => _63.blockChangeClass]), () => ( ""));
1598
+ const insertedClass = _nullishCoalesce(_optionalChain([this, 'access', _64 => _64.options, 'optionalAccess', _65 => _65.blockInsertedClass]), () => ( ""));
1599
+ const deletedClass = _nullishCoalesce(_optionalChain([this, 'access', _66 => _66.options, 'optionalAccess', _67 => _67.blockDeletedClass]), () => ( ""));
1436
1600
  return [
1437
1601
  {
1438
- types: _nullishCoalesce(_optionalChain([this, 'access', _65 => _65.options, 'optionalAccess', _66 => _66.blockTypes]), () => ( ["paragraph", "heading", "codeBlock"])),
1602
+ types: _nullishCoalesce(_optionalChain([this, 'access', _68 => _68.options, 'optionalAccess', _69 => _69.blockTypes]), () => ( ["paragraph", "heading", "codeBlock"])),
1439
1603
  attributes: {
1440
1604
  [BLOCK_CHANGE_ATTRIBUTE]: {
1441
1605
  default: null,
@@ -1459,12 +1623,21 @@ var TrackChanges = _core.Extension.create({
1459
1623
  ];
1460
1624
  },
1461
1625
  addExtensions() {
1462
- const insertionAttrs = _nullishCoalesce(_optionalChain([this, 'access', _67 => _67.options, 'optionalAccess', _68 => _68.insertionHTMLAttributes]), () => ( {}));
1463
- const deletionAttrs = _nullishCoalesce(_optionalChain([this, 'access', _69 => _69.options, 'optionalAccess', _70 => _70.deletionHTMLAttributes]), () => ( {}));
1464
- const formatAttrs = _nullishCoalesce(_optionalChain([this, 'access', _71 => _71.options, 'optionalAccess', _72 => _72.formatChangeHTMLAttributes]), () => ( {}));
1626
+ const insertionAttrs = _nullishCoalesce(_optionalChain([this, 'access', _70 => _70.options, 'optionalAccess', _71 => _71.insertionHTMLAttributes]), () => ( {}));
1627
+ const deletionAttrs = _nullishCoalesce(_optionalChain([this, 'access', _72 => _72.options, 'optionalAccess', _73 => _73.deletionHTMLAttributes]), () => ( {}));
1628
+ const formatAttrs = _nullishCoalesce(_optionalChain([this, 'access', _74 => _74.options, 'optionalAccess', _75 => _75.formatChangeHTMLAttributes]), () => ( {}));
1629
+ const moveAttrs = _nullishCoalesce(_optionalChain([this, 'access', _76 => _76.options, 'optionalAccess', _77 => _77.moveHTMLAttributes]), () => ( {}));
1630
+ const markOptions = (attrs) => ({
1631
+ ...Object.keys(attrs).length ? { HTMLAttributes: attrs } : {},
1632
+ ...Object.keys(moveAttrs).length ? { moveHTMLAttributes: moveAttrs } : {}
1633
+ });
1634
+ const configured = (mark, attrs) => {
1635
+ const options = markOptions(attrs);
1636
+ return Object.keys(options).length ? mark.configure(options) : mark;
1637
+ };
1465
1638
  return [
1466
- Object.keys(insertionAttrs).length ? TrackedInsertion.configure({ HTMLAttributes: insertionAttrs }) : TrackedInsertion,
1467
- Object.keys(deletionAttrs).length ? TrackedDeletion.configure({ HTMLAttributes: deletionAttrs }) : TrackedDeletion,
1639
+ configured(TrackedInsertion, insertionAttrs),
1640
+ configured(TrackedDeletion, deletionAttrs),
1468
1641
  Object.keys(formatAttrs).length ? TrackedFormatChange.configure({ HTMLAttributes: formatAttrs }) : TrackedFormatChange
1469
1642
  ];
1470
1643
  },
@@ -1472,9 +1645,9 @@ var TrackChanges = _core.Extension.create({
1472
1645
  if (this.options.trackCodeBlocks) allowTrackingInCodeBlocks(this.editor.schema);
1473
1646
  },
1474
1647
  addCommands() {
1475
- const decide = (decision, id) => ({ state, tr, dispatch }) => {
1648
+ const decide = (decision, id, onlyMoves = false) => ({ state, tr, dispatch }) => {
1476
1649
  const all = getTrackedChanges(state.doc);
1477
- const changes = id === null ? all : all.filter((c) => c.id === id);
1650
+ const changes = id === null ? all : all.filter((c) => c.id === id && (!onlyMoves || c.type === "move"));
1478
1651
  if (changes.length === 0) return false;
1479
1652
  if (dispatch) {
1480
1653
  applyDecision(tr, changes, decision);
@@ -1511,11 +1684,22 @@ var TrackChanges = _core.Extension.create({
1511
1684
  return true;
1512
1685
  },
1513
1686
  acceptChange: (id) => decide("accept", id),
1687
+ acceptMove: (id) => decide("accept", id, true),
1688
+ rejectMove: (id) => decide("reject", id, true),
1514
1689
  rejectChange: (id) => decide("reject", id),
1515
1690
  acceptAllChanges: () => decide("accept", null),
1516
1691
  rejectAllChanges: () => decide("reject", null),
1517
1692
  selectNextChange: () => select(1),
1518
- selectPreviousChange: () => select(-1)
1693
+ selectPreviousChange: () => select(-1),
1694
+ selectChange: (id) => ({ state, tr, dispatch }) => {
1695
+ const change = getTrackedChanges(state.doc).find((c) => c.id === id);
1696
+ if (!change) return false;
1697
+ if (dispatch) {
1698
+ const [anchor, head] = selectionRange(change);
1699
+ tr.setSelection(_state.TextSelection.create(tr.doc, anchor, head)).scrollIntoView();
1700
+ }
1701
+ return true;
1702
+ }
1519
1703
  };
1520
1704
  },
1521
1705
  addProseMirrorPlugins() {
@@ -1526,6 +1710,8 @@ var TrackChanges = _core.Extension.create({
1526
1710
  let editorView = null;
1527
1711
  let pending = null;
1528
1712
  let flushTimer = null;
1713
+ let pendingMove = null;
1714
+ const isMove = _nullishCoalesce(options.isMove, () => ( isMoveSized));
1529
1715
  const scheduleFlush = () => {
1530
1716
  if (flushTimer) clearTimeout(flushTimer);
1531
1717
  flushTimer = setTimeout(() => {
@@ -1555,9 +1741,12 @@ var TrackChanges = _core.Extension.create({
1555
1741
  },
1556
1742
  appendTransaction: (transactions, oldState, newState) => {
1557
1743
  const plugin = trackChangesPluginKey.getState(oldState);
1558
- const tracking = !!_optionalChain([plugin, 'optionalAccess', _73 => _73.enabled]);
1559
- if (!tracking && !pending) return null;
1560
- if (_optionalChain([editorView, 'optionalAccess', _74 => _74.composing]) && transactions.some((t) => t.docChanged)) {
1744
+ const tracking = !!_optionalChain([plugin, 'optionalAccess', _78 => _78.enabled]);
1745
+ if (!tracking && !pending) {
1746
+ if (transactions.some((t) => t.docChanged)) pendingMove = null;
1747
+ return null;
1748
+ }
1749
+ if (_optionalChain([editorView, 'optionalAccess', _79 => _79.composing]) && transactions.some((t) => t.docChanged)) {
1561
1750
  if (tracking) {
1562
1751
  if (!pending) pending = { oldState, transactions: [] };
1563
1752
  pending.transactions.push(...transactions);
@@ -1572,8 +1761,18 @@ var TrackChanges = _core.Extension.create({
1572
1761
  pending = null;
1573
1762
  }
1574
1763
  if (!tracking && trs === transactions) return null;
1575
- const author = _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _75 => _75.author]), () => ( options.author));
1576
- return trackTransactions(trs, fromState, newState, {
1764
+ const author = _nullishCoalesce(_optionalChain([plugin, 'optionalAccess', _80 => _80.author]), () => ( options.author));
1765
+ const userTransactions = trs.filter((t) => !shouldSkip(t));
1766
+ let moves;
1767
+ if (userTransactions.length) {
1768
+ const uiEvent = userTransactions.length === 1 ? userTransactions[0].getMeta("uiEvent") : null;
1769
+ const event = uiEvent === "cut" || uiEvent === "paste" || uiEvent === "drop" ? uiEvent : null;
1770
+ if (options.trackMoves !== false) {
1771
+ moves = { event, pending: event === "paste" ? pendingMove : null, isMove };
1772
+ }
1773
+ pendingMove = null;
1774
+ }
1775
+ const result = trackTransactions(trs, fromState, newState, {
1577
1776
  author,
1578
1777
  now: options.now,
1579
1778
  generateId: options.generateId,
@@ -1582,8 +1781,11 @@ var TrackChanges = _core.Extension.create({
1582
1781
  format: options.trackFormatting !== false ? newState.schema.marks[FORMAT_CHANGE_MARK_NAME] : void 0,
1583
1782
  trackBlocks: options.trackBlocks !== false,
1584
1783
  ignoredMarks,
1585
- ignoredAttributes
1784
+ ignoredAttributes,
1785
+ moves
1586
1786
  });
1787
+ if (_optionalChain([moves, 'optionalAccess', _81 => _81.cut])) pendingMove = moves.cut;
1788
+ return result;
1587
1789
  },
1588
1790
  props: {
1589
1791
  transformPasted: (slice, view) => acceptSlice(slice, view.state.schema),
@@ -1639,5 +1841,10 @@ var TrackChanges = _core.Extension.create({
1639
1841
 
1640
1842
 
1641
1843
 
1642
- exports.createReviewId = createReviewId; exports.CommentStore = CommentStore; exports.createCommentStore = createCommentStore; exports.formatReviewTime = formatReviewTime; exports.INSERTION_MARK_NAME = INSERTION_MARK_NAME; exports.DELETION_MARK_NAME = DELETION_MARK_NAME; exports.FORMAT_CHANGE_MARK_NAME = FORMAT_CHANGE_MARK_NAME; exports.BLOCK_CHANGE_ATTRIBUTE = BLOCK_CHANGE_ATTRIBUTE; exports.TRACK_CHANGES_SKIP_META = TRACK_CHANGES_SKIP_META; exports.TrackChangesStore = TrackChangesStore; exports.trackChangesPluginKey = trackChangesPluginKey; exports.TrackedInsertion = TrackedInsertion; exports.TrackedDeletion = TrackedDeletion; exports.TrackedFormatChange = TrackedFormatChange; exports.describeFormatChange = describeFormatChange; exports.describeBlockChange = describeBlockChange; exports.getTrackedChanges = getTrackedChanges; exports.getTrackedChangeAt = getTrackedChangeAt; exports.isTrackChangesEnabled = isTrackChangesEnabled; exports.getTrackChangesStore = getTrackChangesStore; exports.resolveTrackedChanges = resolveTrackedChanges; exports.TrackChanges = TrackChanges;
1643
- //# sourceMappingURL=chunk-D27YFC46.cjs.map
1844
+
1845
+
1846
+
1847
+
1848
+
1849
+ exports.createReviewId = createReviewId; exports.CommentStore = CommentStore; exports.createCommentStore = createCommentStore; exports.formatReviewTime = formatReviewTime; exports.INSERTION_MARK_NAME = INSERTION_MARK_NAME; exports.DELETION_MARK_NAME = DELETION_MARK_NAME; exports.FORMAT_CHANGE_MARK_NAME = FORMAT_CHANGE_MARK_NAME; exports.BLOCK_CHANGE_ATTRIBUTE = BLOCK_CHANGE_ATTRIBUTE; exports.MOVE_ID_ATTRIBUTE = MOVE_ID_ATTRIBUTE; exports.TRACK_CHANGES_SKIP_META = TRACK_CHANGES_SKIP_META; exports.TrackChangesStore = TrackChangesStore; exports.trackChangesPluginKey = trackChangesPluginKey; exports.MOVE_TO_CLASS = MOVE_TO_CLASS; exports.MOVE_FROM_CLASS = MOVE_FROM_CLASS; exports.TrackedInsertion = TrackedInsertion; exports.TrackedDeletion = TrackedDeletion; exports.TrackedFormatChange = TrackedFormatChange; exports.describeFormatChange = describeFormatChange; exports.describeBlockChange = describeBlockChange; exports.trackedChangeLabel = trackedChangeLabel; exports.getTrackedChanges = getTrackedChanges; exports.getTrackedChangeAt = getTrackedChangeAt; exports.isTrackChangesEnabled = isTrackChangesEnabled; exports.getTrackChangesStore = getTrackChangesStore; exports.resolveTrackedChanges = resolveTrackedChanges; exports.isMoveSized = isMoveSized; exports.TrackChanges = TrackChanges;
1850
+ //# sourceMappingURL=chunk-X4N4WUKB.cjs.map