@tiptap/extension-drag-handle 3.27.0 → 3.27.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/dist/index.cjs +126 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +126 -68
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
- package/src/drag-handle-plugin.ts +59 -39
- package/src/helpers/cloneElement.ts +3 -2
- package/src/helpers/dragHandler.ts +19 -1
- package/src/helpers/findNextElementFromCursor.ts +57 -13
- package/src/helpers/nodeRangeDrop.ts +47 -0
package/dist/index.cjs
CHANGED
|
@@ -48,7 +48,7 @@ var import_state = require("@tiptap/pm/state");
|
|
|
48
48
|
function getCSSText(element, properties) {
|
|
49
49
|
const style = getComputedStyle(element);
|
|
50
50
|
if (properties) {
|
|
51
|
-
return properties.
|
|
51
|
+
return properties.map((property) => property.trim()).filter((property) => property.length > 0).map((property) => `${property}:${style.getPropertyValue(property)};`).join("");
|
|
52
52
|
}
|
|
53
53
|
let value = "";
|
|
54
54
|
for (let i = 0; i < style.length; i += 1) {
|
|
@@ -306,28 +306,41 @@ function findBestDragTarget(view, coords, options) {
|
|
|
306
306
|
|
|
307
307
|
// src/helpers/findNextElementFromCursor.ts
|
|
308
308
|
function findClosestTopLevelBlock(element, view) {
|
|
309
|
+
var _a;
|
|
309
310
|
let current = element;
|
|
310
311
|
while ((current == null ? void 0 : current.parentElement) && current.parentElement !== view.dom) {
|
|
311
312
|
current = current.parentElement;
|
|
312
313
|
}
|
|
313
|
-
|
|
314
|
+
if ((current == null ? void 0 : current.parentElement) !== view.dom) {
|
|
315
|
+
return void 0;
|
|
316
|
+
}
|
|
317
|
+
if (!((_a = current.pmViewDesc) == null ? void 0 : _a.node)) {
|
|
318
|
+
return void 0;
|
|
319
|
+
}
|
|
320
|
+
return current;
|
|
314
321
|
}
|
|
315
322
|
function isValidRect(rect) {
|
|
316
323
|
return Number.isFinite(rect.top) && Number.isFinite(rect.bottom) && Number.isFinite(rect.left) && Number.isFinite(rect.right) && rect.width > 0 && rect.height > 0;
|
|
317
324
|
}
|
|
325
|
+
function edgeBlockRect(container, edge) {
|
|
326
|
+
let current = edge === "first" ? container.firstElementChild : container.lastElementChild;
|
|
327
|
+
while (current) {
|
|
328
|
+
const rect = current.getBoundingClientRect();
|
|
329
|
+
if (isValidRect(rect)) {
|
|
330
|
+
return rect;
|
|
331
|
+
}
|
|
332
|
+
current = edge === "first" ? current.nextElementSibling : current.previousElementSibling;
|
|
333
|
+
}
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
318
336
|
function clampToContent(view, x, y, inset = 5) {
|
|
319
337
|
if (!Number.isFinite(x) || !Number.isFinite(y)) {
|
|
320
338
|
return null;
|
|
321
339
|
}
|
|
322
340
|
const container = view.dom;
|
|
323
|
-
const
|
|
324
|
-
const
|
|
325
|
-
if (!
|
|
326
|
-
return null;
|
|
327
|
-
}
|
|
328
|
-
const topRect = firstBlock.getBoundingClientRect();
|
|
329
|
-
const botRect = lastBlock.getBoundingClientRect();
|
|
330
|
-
if (!isValidRect(topRect) || !isValidRect(botRect)) {
|
|
341
|
+
const topRect = edgeBlockRect(container, "first");
|
|
342
|
+
const botRect = edgeBlockRect(container, "last");
|
|
343
|
+
if (!topRect || !botRect) {
|
|
331
344
|
return null;
|
|
332
345
|
}
|
|
333
346
|
const clampedY = Math.min(Math.max(topRect.top + inset, y), botRect.bottom - inset);
|
|
@@ -453,6 +466,15 @@ function removeNode(node) {
|
|
|
453
466
|
function getDragImageOffset(direction, wrapperWidth) {
|
|
454
467
|
return direction === "rtl" ? wrapperWidth : 0;
|
|
455
468
|
}
|
|
469
|
+
function shouldResetMargin(dragImageProperties) {
|
|
470
|
+
if (!dragImageProperties) {
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
return !dragImageProperties.some((property) => {
|
|
474
|
+
const p = property.trim().toLowerCase();
|
|
475
|
+
return p === "margin" || p.startsWith("margin-");
|
|
476
|
+
});
|
|
477
|
+
}
|
|
456
478
|
function getDragHandleRanges(event, editor, nestedOptions, dragContext) {
|
|
457
479
|
const { doc } = editor.view.state;
|
|
458
480
|
if ((nestedOptions == null ? void 0 : nestedOptions.enabled) && (dragContext == null ? void 0 : dragContext.node) && dragContext.pos >= 0) {
|
|
@@ -514,13 +536,16 @@ function dragHandler(event, editor, nestedOptions, dragContext, dragImagePropert
|
|
|
514
536
|
selection = import_extension_node_range.NodeRangeSelection.create(view.state.doc, from, to);
|
|
515
537
|
slice = selection.content();
|
|
516
538
|
}
|
|
539
|
+
const resetMargin = shouldResetMargin(dragImageProperties);
|
|
517
540
|
ranges.forEach((range) => {
|
|
518
541
|
const element = getDraggedBlockElement(view, range.$from.pos);
|
|
519
542
|
if (!element) {
|
|
520
543
|
return;
|
|
521
544
|
}
|
|
522
545
|
const clonedElement = cloneElement(element, dragImageProperties);
|
|
523
|
-
|
|
546
|
+
if (resetMargin) {
|
|
547
|
+
clonedElement.style.margin = "0";
|
|
548
|
+
}
|
|
524
549
|
wrapper.append(clonedElement);
|
|
525
550
|
});
|
|
526
551
|
wrapper.style.position = "absolute";
|
|
@@ -548,8 +573,56 @@ function dragHandler(event, editor, nestedOptions, dragContext, dragImagePropert
|
|
|
548
573
|
document.addEventListener("dragend", cleanupDragPreview);
|
|
549
574
|
}
|
|
550
575
|
|
|
576
|
+
// src/helpers/getOuterNode.ts
|
|
577
|
+
var getOuterNodePos = (doc, pos) => {
|
|
578
|
+
const resolvedPos = doc.resolve(pos);
|
|
579
|
+
const { depth } = resolvedPos;
|
|
580
|
+
if (depth === 0) {
|
|
581
|
+
return pos;
|
|
582
|
+
}
|
|
583
|
+
const a = resolvedPos.pos - resolvedPos.parentOffset;
|
|
584
|
+
return a - 1;
|
|
585
|
+
};
|
|
586
|
+
var getOuterNode = (doc, pos) => {
|
|
587
|
+
const node = doc.nodeAt(pos);
|
|
588
|
+
const resolvedPos = doc.resolve(pos);
|
|
589
|
+
let { depth } = resolvedPos;
|
|
590
|
+
let parent = node;
|
|
591
|
+
while (depth > 0) {
|
|
592
|
+
const currentNode = resolvedPos.node(depth);
|
|
593
|
+
depth -= 1;
|
|
594
|
+
if (depth === 0) {
|
|
595
|
+
parent = currentNode;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return parent;
|
|
599
|
+
};
|
|
600
|
+
|
|
551
601
|
// src/helpers/nodeRangeDrop.ts
|
|
552
602
|
var import_extension_node_range2 = require("@tiptap/extension-node-range");
|
|
603
|
+
function mapPendingRestoreAnchor(pendingRestore, tr, options) {
|
|
604
|
+
if (!tr.docChanged) {
|
|
605
|
+
return pendingRestore;
|
|
606
|
+
}
|
|
607
|
+
if (options.isChangeOrigin && pendingRestore.relativeAnchorPos != null) {
|
|
608
|
+
const newPos = options.getAbsolutePos(pendingRestore.relativeAnchorPos);
|
|
609
|
+
if (!Number.isFinite(newPos) || newPos <= 0) {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
return {
|
|
613
|
+
...pendingRestore,
|
|
614
|
+
anchorPos: newPos
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
const mappedResult = tr.mapping.mapResult(pendingRestore.anchorPos, 1);
|
|
618
|
+
if (mappedResult.deleted) {
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
return {
|
|
622
|
+
...pendingRestore,
|
|
623
|
+
anchorPos: mappedResult.pos
|
|
624
|
+
};
|
|
625
|
+
}
|
|
553
626
|
function sumNodeSizes(parent, from, to) {
|
|
554
627
|
let size = 0;
|
|
555
628
|
for (let i = from; i < to; i += 1) {
|
|
@@ -596,31 +669,6 @@ function createDroppedNodeRangeSelection(doc, anchorPos, nodeCount, depth) {
|
|
|
596
669
|
}
|
|
597
670
|
}
|
|
598
671
|
|
|
599
|
-
// src/helpers/getOuterNode.ts
|
|
600
|
-
var getOuterNodePos = (doc, pos) => {
|
|
601
|
-
const resolvedPos = doc.resolve(pos);
|
|
602
|
-
const { depth } = resolvedPos;
|
|
603
|
-
if (depth === 0) {
|
|
604
|
-
return pos;
|
|
605
|
-
}
|
|
606
|
-
const a = resolvedPos.pos - resolvedPos.parentOffset;
|
|
607
|
-
return a - 1;
|
|
608
|
-
};
|
|
609
|
-
var getOuterNode = (doc, pos) => {
|
|
610
|
-
const node = doc.nodeAt(pos);
|
|
611
|
-
const resolvedPos = doc.resolve(pos);
|
|
612
|
-
let { depth } = resolvedPos;
|
|
613
|
-
let parent = node;
|
|
614
|
-
while (depth > 0) {
|
|
615
|
-
const currentNode = resolvedPos.node(depth);
|
|
616
|
-
depth -= 1;
|
|
617
|
-
if (depth === 0) {
|
|
618
|
-
parent = currentNode;
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
return parent;
|
|
622
|
-
};
|
|
623
|
-
|
|
624
672
|
// src/drag-handle-plugin.ts
|
|
625
673
|
var getRelativePos = (state, absolutePos) => {
|
|
626
674
|
const ystate = import_y_tiptap.ySyncPluginKey.getState(state);
|
|
@@ -670,10 +718,40 @@ var DragHandlePlugin = ({
|
|
|
670
718
|
let currentNodePos = -1;
|
|
671
719
|
let currentNodeRelPos;
|
|
672
720
|
let rafId = null;
|
|
673
|
-
let restoreRafId = null;
|
|
674
721
|
let pendingMouseCoords = null;
|
|
675
722
|
let activeDragRange = null;
|
|
676
723
|
let pendingRestore = null;
|
|
724
|
+
function clearDragRangeState() {
|
|
725
|
+
activeDragRange = null;
|
|
726
|
+
pendingRestore = null;
|
|
727
|
+
}
|
|
728
|
+
function remapPendingRestore(tr, state) {
|
|
729
|
+
if (!pendingRestore) {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
pendingRestore = mapPendingRestoreAnchor(pendingRestore, tr, {
|
|
733
|
+
isChangeOrigin: (0, import_extension_collaboration.isChangeOrigin)(tr),
|
|
734
|
+
getAbsolutePos: (relativePos) => getAbsolutePos(state, relativePos)
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
function buildRestoreTransaction(state) {
|
|
738
|
+
if (!pendingRestore) {
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
const nodeRangeSelection = createDroppedNodeRangeSelection(
|
|
742
|
+
state.doc,
|
|
743
|
+
pendingRestore.anchorPos,
|
|
744
|
+
pendingRestore.nodeCount,
|
|
745
|
+
pendingRestore.depth
|
|
746
|
+
);
|
|
747
|
+
if (!nodeRangeSelection) {
|
|
748
|
+
pendingRestore = null;
|
|
749
|
+
activeDragRange = null;
|
|
750
|
+
return null;
|
|
751
|
+
}
|
|
752
|
+
clearDragRangeState();
|
|
753
|
+
return state.tr.setSelection(nodeRangeSelection);
|
|
754
|
+
}
|
|
677
755
|
function hideHandle() {
|
|
678
756
|
if (!element) {
|
|
679
757
|
return;
|
|
@@ -732,17 +810,6 @@ var DragHandlePlugin = ({
|
|
|
732
810
|
element.dataset.dragging = "false";
|
|
733
811
|
}
|
|
734
812
|
}
|
|
735
|
-
function restoreNodeRangeSelection({ nodeCount, depth, anchorPos }) {
|
|
736
|
-
const nodeRangeSelection = createDroppedNodeRangeSelection(
|
|
737
|
-
editor.state.doc,
|
|
738
|
-
anchorPos,
|
|
739
|
-
nodeCount,
|
|
740
|
-
depth
|
|
741
|
-
);
|
|
742
|
-
if (nodeRangeSelection) {
|
|
743
|
-
editor.view.dispatch(editor.state.tr.setSelection(nodeRangeSelection));
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
813
|
function onDrop(e) {
|
|
747
814
|
if (!e.target || !editor.view.dom.contains(e.target)) {
|
|
748
815
|
return;
|
|
@@ -759,17 +826,14 @@ var DragHandlePlugin = ({
|
|
|
759
826
|
if (!activeDragRange || editor.view.state.selection.empty) {
|
|
760
827
|
return;
|
|
761
828
|
}
|
|
829
|
+
const anchorPos = editor.state.selection.from;
|
|
830
|
+
const relativeAnchorPos = getRelativePos(editor.state, anchorPos);
|
|
762
831
|
pendingRestore = {
|
|
763
832
|
...activeDragRange,
|
|
764
|
-
anchorPos
|
|
833
|
+
anchorPos,
|
|
834
|
+
relativeAnchorPos: relativeAnchorPos != null ? relativeAnchorPos : void 0
|
|
765
835
|
};
|
|
766
|
-
|
|
767
|
-
restoreRafId = null;
|
|
768
|
-
if (pendingRestore) {
|
|
769
|
-
restoreNodeRangeSelection(pendingRestore);
|
|
770
|
-
pendingRestore = null;
|
|
771
|
-
}
|
|
772
|
-
});
|
|
836
|
+
editor.view.dispatch(editor.state.tr.setMeta("addToHistory", false));
|
|
773
837
|
}
|
|
774
838
|
function cleanup() {
|
|
775
839
|
element.removeEventListener("dragstart", onDragStart);
|
|
@@ -780,10 +844,7 @@ var DragHandlePlugin = ({
|
|
|
780
844
|
rafId = null;
|
|
781
845
|
pendingMouseCoords = null;
|
|
782
846
|
}
|
|
783
|
-
|
|
784
|
-
cancelAnimationFrame(restoreRafId);
|
|
785
|
-
restoreRafId = null;
|
|
786
|
-
}
|
|
847
|
+
clearDragRangeState();
|
|
787
848
|
}
|
|
788
849
|
wrapper.appendChild(element);
|
|
789
850
|
return {
|
|
@@ -797,14 +858,7 @@ var DragHandlePlugin = ({
|
|
|
797
858
|
return { locked: false };
|
|
798
859
|
},
|
|
799
860
|
apply(tr, value, _oldState, state) {
|
|
800
|
-
|
|
801
|
-
const mappedResult = tr.mapping.mapResult(pendingRestore.anchorPos, 1);
|
|
802
|
-
if (mappedResult.deleted) {
|
|
803
|
-
pendingRestore = null;
|
|
804
|
-
} else {
|
|
805
|
-
pendingRestore.anchorPos = mappedResult.pos;
|
|
806
|
-
}
|
|
807
|
-
}
|
|
861
|
+
remapPendingRestore(tr, state);
|
|
808
862
|
const isLocked = tr.getMeta("lockDragHandle");
|
|
809
863
|
const hideDragHandle = tr.getMeta("hideDragHandle");
|
|
810
864
|
if (isLocked !== void 0) {
|
|
@@ -835,6 +889,9 @@ var DragHandlePlugin = ({
|
|
|
835
889
|
return value;
|
|
836
890
|
}
|
|
837
891
|
},
|
|
892
|
+
appendTransaction(_transactions, _oldState, newState) {
|
|
893
|
+
return buildRestoreTransaction(newState);
|
|
894
|
+
},
|
|
838
895
|
view: (view) => {
|
|
839
896
|
var _a;
|
|
840
897
|
element.draggable = true;
|
|
@@ -845,6 +902,7 @@ var DragHandlePlugin = ({
|
|
|
845
902
|
wrapper.style.position = "absolute";
|
|
846
903
|
wrapper.style.top = "0";
|
|
847
904
|
wrapper.style.left = "0";
|
|
905
|
+
wrapper.style.zIndex = "10";
|
|
848
906
|
element.addEventListener("dragstart", onDragStart);
|
|
849
907
|
element.addEventListener("dragend", onDragEnd);
|
|
850
908
|
document.addEventListener("drop", onDrop);
|