@seafile/sdoc-editor 3.0.248 → 3.0.249

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.
@@ -40,11 +40,18 @@ var SideToolbar = function SideToolbar() {
40
40
  var menuRef = (0, _react.useRef)(null);
41
41
  var sideToolbarContainerRef = (0, _react.useRef)(null);
42
42
  var sourceElementRef = (0, _react.useRef)(null);
43
- var isEventInCurrentEditor = (0, _react.useCallback)(function (event) {
43
+ var isDraggingEditorElementRef = (0, _react.useRef)(false);
44
+ var getEditorContainer = (0, _react.useCallback)(function () {
44
45
  var _sideToolbarContainer;
45
- var editorContainer = (_sideToolbarContainer = sideToolbarContainerRef.current) === null || _sideToolbarContainer === void 0 ? void 0 : _sideToolbarContainer.closest('.sdoc-article-container');
46
+ return (_sideToolbarContainer = sideToolbarContainerRef.current) === null || _sideToolbarContainer === void 0 ? void 0 : _sideToolbarContainer.closest('.sdoc-article-container');
47
+ }, []);
48
+ var isEventInCurrentEditor = (0, _react.useCallback)(function (event) {
49
+ var editorContainer = getEditorContainer();
46
50
  var eventTarget = event.target || event.currentTarget;
47
51
  return Boolean(editorContainer && eventTarget && editorContainer.contains(eventTarget));
52
+ }, [getEditorContainer]);
53
+ var isEditorDrag = (0, _react.useCallback)(function () {
54
+ return isDraggingEditorElementRef.current;
48
55
  }, []);
49
56
  var _useState = (0, _react.useState)(null),
50
57
  _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
@@ -80,6 +87,7 @@ var SideToolbar = function SideToolbar() {
80
87
  var showSelectedNodesRef = (0, _react.useRef)(null);
81
88
  var draggedPreviewContainer = (0, _react.useRef)(null);
82
89
  var activeDragElRef = (0, _react.useRef)(null);
90
+ var pendingSideDropRef = (0, _react.useRef)(null);
83
91
  var onReset = (0, _react.useCallback)(function () {
84
92
  setShowSideMenu(false);
85
93
  setMenuPosition({});
@@ -269,6 +277,7 @@ var SideToolbar = function SideToolbar() {
269
277
  var dragStart = (0, _react.useCallback)(function (event) {
270
278
  event.stopPropagation();
271
279
  sourceElementRef.current = null;
280
+ isDraggingEditorElementRef.current = true;
272
281
  // Create the preview container when dragging more than one listNodes
273
282
  var noDrag = _slate.Path.equals(editor.selection.focus.path, editor.selection.anchor.path);
274
283
  if (showSelectedNodesRef.current && showSelectedNodesRef.current.length > 1 && !noDrag) {
@@ -314,25 +323,24 @@ var SideToolbar = function SideToolbar() {
314
323
  }, [editor, slateNode]);
315
324
  var dragOver = (0, _react.useCallback)(function (event) {
316
325
  if (!isEventInCurrentEditor(event)) return;
317
- var dragTypes = event.dataTransfer.types;
318
- if (!dragTypes.includes(_event.DRAG_SDOC_EDITOR_ELEMENT)) return;
326
+ if (!isEditorDrag()) return;
319
327
  var overElement = event.currentTarget;
320
328
  if (!overElement.classList.contains('sdoc-dragging')) {
321
329
  overElement.classList.add('sdoc-dragging');
322
330
  }
323
- }, [isEventInCurrentEditor]);
331
+ }, [isEditorDrag, isEventInCurrentEditor]);
324
332
  var dragLeave = (0, _react.useCallback)(function (event) {
325
333
  if (!isEventInCurrentEditor(event)) return;
326
334
  var leaveElement = event.currentTarget;
327
335
  leaveElement.classList.remove('sdoc-dragging');
328
336
  }, [isEventInCurrentEditor]);
329
337
  var drop = (0, _react.useCallback)(function (event) {
330
- var _parentNode$children$;
338
+ var _event$dataTransfer, _parentNode$children$;
331
339
  if (!isEventInCurrentEditor(event)) return;
332
340
  var targetElement = event.currentTarget;
333
341
  targetElement.classList.remove('sdoc-dragging');
334
- var dragTypes = event.dataTransfer.types;
335
- if (!dragTypes.includes(_event.DRAG_SDOC_EDITOR_ELEMENT) && dragTypes[0] !== 'Files') return;
342
+ var dragTypes = ((_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.types) || [];
343
+ if (!isEditorDrag() && dragTypes[0] !== 'Files') return;
336
344
 
337
345
  // Prevent dragging table data to the editor
338
346
  if (dragTypes.includes(_constants2.TABLE_DRAG_KEY)) return;
@@ -608,7 +616,7 @@ var SideToolbar = function SideToolbar() {
608
616
 
609
617
  // reset
610
618
  sourceElementRef.current = null;
611
- }, [editor, isEventInCurrentEditor]);
619
+ }, [editor, isEditorDrag, isEventInCurrentEditor]);
612
620
  (0, _react.useEffect)(function () {
613
621
  var eventBus = _eventBus["default"].getInstance();
614
622
  var unSubscribeDragOver = eventBus.subscribe(_constants.INTERNAL_EVENT.ON_DRAG_OVER_BLOCK, dragOver);
@@ -629,15 +637,17 @@ var SideToolbar = function SideToolbar() {
629
637
  var clearAllDragStyles = (0, _react.useCallback)(function () {
630
638
  (0, _helpers2.clearDragClass)(activeDragElRef.current);
631
639
  activeDragElRef.current = null;
640
+ pendingSideDropRef.current = null;
632
641
  }, []);
642
+ var resetDragState = (0, _react.useCallback)(function () {
643
+ clearAllDragStyles();
644
+ sourceElementRef.current = null;
645
+ isDraggingEditorElementRef.current = false;
646
+ }, [clearAllDragStyles]);
633
647
  var handleDragover = (0, _react.useCallback)(function (event) {
634
- var _event$dataTransfer, _target;
648
+ var _target;
649
+ if (!isEditorDrag()) return;
635
650
  event.preventDefault();
636
- var dragTypes = (_event$dataTransfer = event.dataTransfer) === null || _event$dataTransfer === void 0 ? void 0 : _event$dataTransfer.types;
637
- if (!(dragTypes !== null && dragTypes !== void 0 && dragTypes.includes(_event.DRAG_SDOC_EDITOR_ELEMENT))) {
638
- clearAllDragStyles();
639
- return;
640
- }
641
651
  var _getSafeNodeEntry7 = getSafeNodeEntry(editor, sourceElementRef.current),
642
652
  _getSafeNodeEntry8 = (0, _slicedToArray2["default"])(_getSafeNodeEntry7, 2),
643
653
  sourceNode = _getSafeNodeEntry8[0],
@@ -662,7 +672,11 @@ var SideToolbar = function SideToolbar() {
662
672
  // Cursor position
663
673
  var x = event.clientX;
664
674
  var y = event.clientY;
665
- var editorContainer = event.currentTarget;
675
+ var editorContainer = getEditorContainer();
676
+ if (!editorContainer) {
677
+ clearAllDragStyles();
678
+ return;
679
+ }
666
680
  var containerRect = editorContainer.getBoundingClientRect();
667
681
 
668
682
  // Current visible area of editor container
@@ -757,6 +771,10 @@ var SideToolbar = function SideToolbar() {
757
771
  if (activeColumn) {
758
772
  activeColumn.classList.add("sdoc-dragging-".concat(activeDirection));
759
773
  activeDragElRef.current = activeColumn;
774
+ pendingSideDropRef.current = {
775
+ element: activeColumn,
776
+ direction: activeDirection
777
+ };
760
778
  } else {
761
779
  clearAllDragStyles();
762
780
  }
@@ -773,19 +791,38 @@ var SideToolbar = function SideToolbar() {
773
791
  target.el.classList.remove('sdoc-dragging-right');
774
792
  target.el.classList.remove('sdoc-dragging');
775
793
  activeDragElRef.current = target.el;
794
+ pendingSideDropRef.current = {
795
+ element: target.el,
796
+ direction: 'left'
797
+ };
776
798
  } else if (isRightDropZone) {
777
799
  target.el.classList.add('sdoc-dragging-right');
778
800
  target.el.classList.remove('sdoc-dragging-left');
779
801
  target.el.classList.remove('sdoc-dragging');
780
802
  activeDragElRef.current = target.el;
803
+ pendingSideDropRef.current = {
804
+ element: target.el,
805
+ direction: 'right'
806
+ };
781
807
  } else {
782
808
  clearAllDragStyles();
783
809
  }
784
- }, [clearAllDragStyles, editor]);
810
+ }, [clearAllDragStyles, editor, getEditorContainer, isEditorDrag]);
811
+ var handleDragLeave = (0, _react.useCallback)(function (event) {
812
+ var editorContainer = event.currentTarget;
813
+ var relatedTarget = event.relatedTarget;
814
+
815
+ // Ignore dragleave events from descendants. Some browsers report a null
816
+ // relatedTarget when moving between block elements, so clearing here
817
+ // would remove the active drop zone before the drop event arrives.
818
+ var isLeavingEditor = event.target === editorContainer && (!relatedTarget || !editorContainer.contains(relatedTarget));
819
+ if (isLeavingEditor) clearAllDragStyles();
820
+ }, [clearAllDragStyles]);
785
821
  var handleDrop = (0, _react.useCallback)(function () {
786
- var targetEl = activeDragElRef.current;
787
- var hasSideDropClass = (targetEl === null || targetEl === void 0 ? void 0 : targetEl.classList.contains('sdoc-dragging-left')) || (targetEl === null || targetEl === void 0 ? void 0 : targetEl.classList.contains('sdoc-dragging-right'));
788
- if (!hasSideDropClass) return false;
822
+ var pendingDrop = pendingSideDropRef.current;
823
+ var targetEl = (pendingDrop === null || pendingDrop === void 0 ? void 0 : pendingDrop.element) || activeDragElRef.current;
824
+ var direction = (pendingDrop === null || pendingDrop === void 0 ? void 0 : pendingDrop.direction) || (targetEl !== null && targetEl !== void 0 && targetEl.classList.contains('sdoc-dragging-left') ? 'left' : null) || (targetEl !== null && targetEl !== void 0 && targetEl.classList.contains('sdoc-dragging-right') ? 'right' : null);
825
+ if (!targetEl || !direction) return false;
789
826
  var _getSafeNodeEntry1 = getSafeNodeEntry(editor, targetEl),
790
827
  _getSafeNodeEntry10 = (0, _slicedToArray2["default"])(_getSafeNodeEntry1, 2),
791
828
  targetNode = _getSafeNodeEntry10[0],
@@ -806,7 +843,7 @@ var SideToolbar = function SideToolbar() {
806
843
  if (_constants2.COLUMN === targetNode.type) {
807
844
  var topTargetNode = _slate.Node.get(editor, [targetPath[0]]); // Top multi column Node
808
845
  // Insert source node into last of multi column
809
- if (targetEl.classList.contains('sdoc-dragging-right')) {
846
+ if (direction === 'right') {
810
847
  (0, _helper2.addLastColumnInMultiColumn)(editor, topTargetNode, targetPath);
811
848
  _slate.Transforms.moveNodes(editor, {
812
849
  at: [sourcePath[0]],
@@ -815,7 +852,7 @@ var SideToolbar = function SideToolbar() {
815
852
  return true;
816
853
  }
817
854
  // Insert source node into middle of multi column
818
- if (targetEl.classList.contains('sdoc-dragging-left')) {
855
+ if (direction === 'left') {
819
856
  (0, _helper2.addMiddleColumnInMultiColumn)(editor, topTargetNode, targetPath);
820
857
  _slate.Transforms.moveNodes(editor, {
821
858
  at: [sourcePath[0]],
@@ -834,10 +871,10 @@ var SideToolbar = function SideToolbar() {
834
871
  if (_slate.Path.equals([sourcePath[0]], [targetPath[0]])) return true;
835
872
  var leftNode = null;
836
873
  var rightNode = null;
837
- if (targetEl.classList.contains('sdoc-dragging-left')) {
874
+ if (direction === 'left') {
838
875
  leftNode = sourceNode;
839
876
  rightNode = targetNode;
840
- } else if (targetEl.classList.contains('sdoc-dragging-right')) {
877
+ } else if (direction === 'right') {
841
878
  leftNode = targetNode;
842
879
  rightNode = sourceNode;
843
880
  } else {
@@ -855,42 +892,50 @@ var SideToolbar = function SideToolbar() {
855
892
  return true;
856
893
  }, [editor]);
857
894
  var handleDropCapture = (0, _react.useCallback)(function (event) {
858
- var _event$dataTransfer2;
859
- var dragTypes = (_event$dataTransfer2 = event.dataTransfer) === null || _event$dataTransfer2 === void 0 ? void 0 : _event$dataTransfer2.types;
860
- if (!(dragTypes !== null && dragTypes !== void 0 && dragTypes.includes(_event.DRAG_SDOC_EDITOR_ELEMENT))) return;
861
- var targetEl = activeDragElRef.current;
862
- var hasSideDropClass = (targetEl === null || targetEl === void 0 ? void 0 : targetEl.classList.contains('sdoc-dragging-left')) || (targetEl === null || targetEl === void 0 ? void 0 : targetEl.classList.contains('sdoc-dragging-right'));
863
- if (!hasSideDropClass) return;
895
+ if (!isEditorDrag() || !pendingSideDropRef.current) return;
896
+
897
+ // Stop the normal block drop before mutating Slate. The actual target and
898
+ // direction were recorded during dragover, so this path does not depend
899
+ // on the final drop event target or on a final dragover being delivered.
900
+ event.preventDefault();
901
+ event.stopPropagation();
864
902
  var handled = handleDrop();
865
903
  if (!handled) {
866
- clearAllDragStyles();
904
+ resetDragState();
867
905
  return;
868
906
  }
869
-
870
- // Only side drops create/extend a multi-column. Stop before the block
871
- // handlers can process the same drop and mutate Slate a second time.
872
- event.preventDefault();
873
- event.stopPropagation();
874
- clearAllDragStyles();
875
- sourceElementRef.current = null;
876
- }, [clearAllDragStyles, handleDrop]);
907
+ resetDragState();
908
+ }, [handleDrop, isEditorDrag, resetDragState]);
909
+ var handleDragEnd = (0, _react.useCallback)(function () {
910
+ // Both the document listener and React's onDragEnd can observe the same
911
+ // native event. Only the first one owns the drag session and may commit it.
912
+ if (!isDraggingEditorElementRef.current) return;
913
+
914
+ // Some deployed browsers do not deliver the drop event to the editor.
915
+ // The source draggable still receives dragend, so commit a pending side
916
+ // drop here as a fallback.
917
+ if (pendingSideDropRef.current) {
918
+ handleDrop();
919
+ }
920
+ resetDragState();
921
+ }, [handleDrop, resetDragState]);
877
922
  (0, _react.useEffect)(function () {
878
- var _sideToolbarContainer2;
879
- var editorContainer = (_sideToolbarContainer2 = sideToolbarContainerRef.current) === null || _sideToolbarContainer2 === void 0 ? void 0 : _sideToolbarContainer2.closest('.sdoc-article-container');
923
+ var editorContainer = getEditorContainer();
880
924
  if (!editorContainer) return undefined;
881
925
 
882
- // Capture dragover/drop because block-level handlers stop propagation.
926
+ // Keep drag events scoped to the current editor container. Capture phase
927
+ // still lets this handler run before block-level handlers in the editor.
883
928
  editorContainer.addEventListener('dragover', handleDragover, true);
884
- editorContainer.addEventListener('dragend', clearAllDragStyles, true);
885
- editorContainer.addEventListener('dragleave', clearAllDragStyles, true);
929
+ editorContainer.addEventListener('dragend', handleDragEnd, true);
930
+ editorContainer.addEventListener('dragleave', handleDragLeave, true);
886
931
  editorContainer.addEventListener('drop', handleDropCapture, true);
887
932
  return function () {
888
933
  editorContainer.removeEventListener('dragover', handleDragover, true);
889
- editorContainer.removeEventListener('dragend', clearAllDragStyles, true);
890
- editorContainer.removeEventListener('dragleave', clearAllDragStyles, true);
934
+ editorContainer.removeEventListener('dragend', handleDragEnd, true);
935
+ editorContainer.removeEventListener('dragleave', handleDragLeave, true);
891
936
  editorContainer.removeEventListener('drop', handleDropCapture, true);
892
937
  };
893
- }, [clearAllDragStyles, handleDragover, handleDropCapture]);
938
+ }, [getEditorContainer, handleDragEnd, handleDragLeave, handleDragover, handleDropCapture]);
894
939
  return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, !_commonUtils.isMobile && /*#__PURE__*/_react["default"].createElement("div", {
895
940
  onAnimationEnd: function onAnimationEnd() {
896
941
  return setIsMoving(false);
@@ -905,6 +950,7 @@ var SideToolbar = function SideToolbar() {
905
950
  onMouseDown: onMouseDown,
906
951
  draggable: true,
907
952
  onDragStart: dragStart,
953
+ onDragEnd: handleDragEnd,
908
954
  className: "sdoc-side-op-icon",
909
955
  onClick: onShowSideMenuToggle,
910
956
  onMouseEnter: onMouseEnter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seafile/sdoc-editor",
3
- "version": "3.0.248",
3
+ "version": "3.0.249",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "test": "jest",
@@ -71,5 +71,5 @@
71
71
  "publishConfig": {
72
72
  "access": "public"
73
73
  },
74
- "gitHead": "28da2fee93d686e9cf936d227566c47084d3ebf8"
74
+ "gitHead": "c7f6bb39019dd763b4a9bc3f55f04e397d09b04a"
75
75
  }