Skip to content

Commit 92085a0

Browse files
QdabuliuQzombieJ
andauthored
fix: after selecting and dragging text, the table still scrolls even after releasing the mouse. (#328)
* fix: enhance useScrollDrag with unified drag state cleanup * 3.19.2 * fix: revert version to 3.19.1 in package.json The package version was changed from 3.19.2 to 3.19.1, possibly to correct a versioning error or revert a previous update. * test: add test to prevent scroll after text drop Introduces a test to verify that the list does not scroll when table text is dragged and dropped, ensuring onScroll is not triggered during drag-and-drop interactions. * chore: translate comments in scroll test to English * fix: remove blur and visibilitychange cleanup in useScrollDrag * chore: remote comment * chore: remove comments from scroll drag code and tests * fix: refactor scroll drag event handling and test helper * fix: handle drag events in useScrollDrag hook * chore: refactor scroll test for drag-and-drop behavior * chore: not block dragstart --------- Co-authored-by: 二货机器人 <[email protected]>
1 parent 5769845 commit 92085a0

File tree

2 files changed

+90
-6
lines changed

2 files changed

+90
-6
lines changed

src/hooks/useScrollDrag.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ export default function useScrollDrag(
3838
});
3939
};
4040

41+
const clearDragState = () => {
42+
mouseDownLock = false;
43+
stopScroll();
44+
};
45+
4146
const onMouseDown = (e: MouseEvent) => {
4247
// Skip if element set draggable
4348
if ((e.target as HTMLElement).draggable || e.button !== 0) {
@@ -52,10 +57,7 @@ export default function useScrollDrag(
5257
mouseDownLock = true;
5358
}
5459
};
55-
const onMouseUp = () => {
56-
mouseDownLock = false;
57-
stopScroll();
58-
};
60+
5961
const onMouseMove = (e: MouseEvent) => {
6062
if (mouseDownLock) {
6163
const mouseY = getPageXY(e, false);
@@ -76,13 +78,17 @@ export default function useScrollDrag(
7678
};
7779

7880
ele.addEventListener('mousedown', onMouseDown);
79-
ele.ownerDocument.addEventListener('mouseup', onMouseUp);
81+
ele.ownerDocument.addEventListener('mouseup', clearDragState);
8082
ele.ownerDocument.addEventListener('mousemove', onMouseMove);
8183

84+
ele.ownerDocument.addEventListener('dragend', clearDragState);
85+
8286
return () => {
8387
ele.removeEventListener('mousedown', onMouseDown);
84-
ele.ownerDocument.removeEventListener('mouseup', onMouseUp);
88+
ele.ownerDocument.removeEventListener('mouseup', clearDragState);
8589
ele.ownerDocument.removeEventListener('mousemove', onMouseMove);
90+
91+
ele.ownerDocument.removeEventListener('dragend', clearDragState);
8692
stopScroll();
8793
};
8894
}

tests/scroll.test.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,4 +731,82 @@ describe('List.Scroll', () => {
731731

732732
jest.useRealTimers();
733733
});
734+
735+
it('should not scroll after dropping selected list text', () => {
736+
const selectElementText = (element) => {
737+
const range = document.createRange();
738+
range.selectNodeContents(element);
739+
const selection = window.getSelection();
740+
selection.removeAllRanges();
741+
selection.addRange(range);
742+
};
743+
744+
const onScroll = jest.fn();
745+
const onDragStart = jest.fn();
746+
const onDragEnd = jest.fn();
747+
document.addEventListener('dragstart', onDragStart);
748+
document.addEventListener('dragend', onDragEnd);
749+
750+
const { container } = render(
751+
<List
752+
component="ul"
753+
itemKey="id"
754+
itemHeight={20}
755+
height={100}
756+
data={genData(200)}
757+
onScroll={onScroll}
758+
>
759+
{({ id }) => <li className="fixed-item">{id}</li>}
760+
</List>,
761+
);
762+
const fixedItems = container.querySelectorAll('.fixed-item');
763+
const targetItem = fixedItems[0];
764+
if (targetItem) {
765+
selectElementText(targetItem);
766+
}
767+
const listHolder = container.querySelector('.rc-virtual-list-holder');
768+
if (targetItem && listHolder) {
769+
selectElementText(targetItem);
770+
771+
fireEvent.scroll(listHolder, { target: { scrollTop: 100 } });
772+
expect(onScroll).toHaveBeenCalled();
773+
const scrollCallCountBeforeDrop = onScroll.mock.calls.length;
774+
775+
const dragStartEvent = new Event('dragstart', { bubbles: true, cancelable: true });
776+
targetItem.ownerDocument.dispatchEvent(dragStartEvent);
777+
778+
const rect = listHolder.getBoundingClientRect();
779+
fireEvent.dragOver(listHolder, {
780+
clientY: rect.bottom + 10,
781+
bubbles: true,
782+
});
783+
784+
fireEvent.drop(listHolder, {
785+
clientY: rect.bottom + 10,
786+
bubbles: true,
787+
});
788+
789+
const dragEndEvent = new Event('dragend', { bubbles: true, cancelable: true });
790+
targetItem.ownerDocument.dispatchEvent(dragEndEvent);
791+
792+
const afterRect = listHolder.getBoundingClientRect();
793+
const mouseMoveEvent = new MouseEvent('mousemove', {
794+
bubbles: true,
795+
clientY: afterRect.top - 10,
796+
});
797+
listHolder.dispatchEvent(mouseMoveEvent);
798+
act(() => {
799+
jest.advanceTimersByTime(100);
800+
});
801+
expect(onScroll.mock.calls.length).toBe(scrollCallCountBeforeDrop);
802+
}
803+
expect(onDragStart).toHaveBeenCalled();
804+
expect(onDragEnd).toHaveBeenCalled();
805+
806+
const sel = window.getSelection();
807+
sel && sel.removeAllRanges();
808+
809+
document.removeEventListener('dragstart', onDragStart);
810+
document.removeEventListener('dragend', onDragEnd);
811+
});
734812
});

0 commit comments

Comments
 (0)