@os-design/use-drag 1.0.9 → 1.0.11
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/package.json +12 -5
- package/src/index.ts +162 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@os-design/use-drag",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"repository": "git@gitlab.com:os-team/libs/os-design.git",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
@@ -14,7 +14,14 @@
|
|
|
14
14
|
"./package.json": "./package.json"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
-
"dist"
|
|
17
|
+
"dist",
|
|
18
|
+
"src",
|
|
19
|
+
"!**/*.test.ts",
|
|
20
|
+
"!**/*.test.tsx",
|
|
21
|
+
"!**/__tests__",
|
|
22
|
+
"!**/*.stories.tsx",
|
|
23
|
+
"!**/*.stories.mdx",
|
|
24
|
+
"!**/*.example.tsx"
|
|
18
25
|
],
|
|
19
26
|
"sideEffects": false,
|
|
20
27
|
"scripts": {
|
|
@@ -29,11 +36,11 @@
|
|
|
29
36
|
"access": "public"
|
|
30
37
|
},
|
|
31
38
|
"dependencies": {
|
|
32
|
-
"@os-design/use-event": "^1.0.
|
|
33
|
-
"@os-design/use-long-press": "^1.0.
|
|
39
|
+
"@os-design/use-event": "^1.0.15",
|
|
40
|
+
"@os-design/use-long-press": "^1.0.11"
|
|
34
41
|
},
|
|
35
42
|
"peerDependencies": {
|
|
36
43
|
"react": ">=18"
|
|
37
44
|
},
|
|
38
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "e5d8409760608145d2c738aa5789d0465ae5416f"
|
|
39
46
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import useEvent from '@os-design/use-event';
|
|
2
|
+
import useLongPress from '@os-design/use-long-press';
|
|
3
|
+
import {
|
|
4
|
+
MouseEventHandler,
|
|
5
|
+
TouchEventHandler,
|
|
6
|
+
useCallback,
|
|
7
|
+
useEffect,
|
|
8
|
+
useRef,
|
|
9
|
+
} from 'react';
|
|
10
|
+
|
|
11
|
+
export interface Position {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type OnDragStart = (position: Position, startPosition: Position) => void;
|
|
17
|
+
export type OnDragMove = (position: Position) => void;
|
|
18
|
+
export type OnDragEnd = () => void;
|
|
19
|
+
|
|
20
|
+
export interface UseDragProps {
|
|
21
|
+
minMouseDistPx?: number;
|
|
22
|
+
longPressMs?: number;
|
|
23
|
+
onDragStart?: OnDragStart;
|
|
24
|
+
onDragMove?: OnDragMove;
|
|
25
|
+
onDragEnd?: OnDragEnd;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const userSelection = {
|
|
29
|
+
disable: () => {
|
|
30
|
+
document.body.style.userSelect = 'none';
|
|
31
|
+
},
|
|
32
|
+
enable: () => {
|
|
33
|
+
document.body.style.userSelect = '';
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export interface DragHandlers {
|
|
38
|
+
onMouseDown: MouseEventHandler;
|
|
39
|
+
onTouchStart: TouchEventHandler;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const useDrag = (props: UseDragProps): DragHandlers => {
|
|
43
|
+
const { minMouseDistPx = 10, longPressMs = 500 } = props;
|
|
44
|
+
|
|
45
|
+
const isDraggingRef = useRef(false);
|
|
46
|
+
const startMousePosRef = useRef<Position | null>(null);
|
|
47
|
+
const minMouseDistPxRef = useRef(minMouseDistPx);
|
|
48
|
+
const handlersRef = useRef({
|
|
49
|
+
onDragStart: props.onDragStart || (() => {}),
|
|
50
|
+
onDragMove: props.onDragMove || (() => {}),
|
|
51
|
+
onDragEnd: props.onDragEnd || (() => {}),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
minMouseDistPxRef.current = minMouseDistPx;
|
|
56
|
+
}, [minMouseDistPx]);
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
handlersRef.current = {
|
|
60
|
+
onDragStart: props.onDragStart || (() => {}),
|
|
61
|
+
onDragMove: props.onDragMove || (() => {}),
|
|
62
|
+
onDragEnd: props.onDragEnd || (() => {}),
|
|
63
|
+
};
|
|
64
|
+
}, [props.onDragEnd, props.onDragMove, props.onDragStart]);
|
|
65
|
+
|
|
66
|
+
const dragStartHandler = useCallback(
|
|
67
|
+
(position: Position, startPosition: Position) => {
|
|
68
|
+
const { onDragStart } = handlersRef.current;
|
|
69
|
+
onDragStart(position, startPosition);
|
|
70
|
+
isDraggingRef.current = true;
|
|
71
|
+
startMousePosRef.current = null;
|
|
72
|
+
},
|
|
73
|
+
[]
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const dragEndHandler = useCallback(() => {
|
|
77
|
+
const { onDragEnd } = handlersRef.current;
|
|
78
|
+
if (isDraggingRef.current) onDragEnd();
|
|
79
|
+
isDraggingRef.current = false;
|
|
80
|
+
startMousePosRef.current = null;
|
|
81
|
+
userSelection.enable();
|
|
82
|
+
}, []);
|
|
83
|
+
|
|
84
|
+
const onMouseDown = useCallback<MouseEventHandler>((e) => {
|
|
85
|
+
if (e.button !== 0) return; // Allow only the left mouse button
|
|
86
|
+
startMousePosRef.current = { x: e.clientX, y: e.clientY };
|
|
87
|
+
userSelection.disable();
|
|
88
|
+
}, []);
|
|
89
|
+
|
|
90
|
+
const onMouseMove = useCallback(
|
|
91
|
+
(e: MouseEvent) => {
|
|
92
|
+
const pos = { x: e.clientX, y: e.clientY };
|
|
93
|
+
if (isDraggingRef.current) {
|
|
94
|
+
const { onDragMove } = handlersRef.current;
|
|
95
|
+
onDragMove(pos);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const startPos = startMousePosRef.current;
|
|
99
|
+
if (!startPos) return;
|
|
100
|
+
const diffX = Math.abs(pos.x - startPos.x);
|
|
101
|
+
const diffY = Math.abs(pos.y - startPos.y);
|
|
102
|
+
const diff = Math.sqrt(diffX ** 2 + diffY ** 2);
|
|
103
|
+
if (diff >= minMouseDistPxRef.current) {
|
|
104
|
+
dragStartHandler(pos, startPos);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
[dragStartHandler]
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const onMouseUp = useCallback(() => {
|
|
111
|
+
dragEndHandler();
|
|
112
|
+
}, [dragEndHandler]);
|
|
113
|
+
|
|
114
|
+
const longPressHandler = useCallback<TouchEventHandler>(
|
|
115
|
+
(e) => {
|
|
116
|
+
if (e.touches.length === 0) return;
|
|
117
|
+
const pos = { x: e.touches[0].clientX, y: e.touches[0].clientY };
|
|
118
|
+
dragStartHandler(pos, pos);
|
|
119
|
+
},
|
|
120
|
+
[dragStartHandler]
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const { onTouchStart, onTouchMove, onTouchEnd } = useLongPress(
|
|
124
|
+
longPressHandler,
|
|
125
|
+
longPressMs
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const touchStartHandler = useCallback<TouchEventHandler>(
|
|
129
|
+
(e) => {
|
|
130
|
+
onTouchStart(e);
|
|
131
|
+
userSelection.disable();
|
|
132
|
+
},
|
|
133
|
+
[onTouchStart]
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const touchMoveHandler = useCallback(
|
|
137
|
+
(e: TouchEvent) => {
|
|
138
|
+
onTouchMove();
|
|
139
|
+
if (!isDraggingRef.current || e.touches.length === 0) return;
|
|
140
|
+
const { onDragMove } = handlersRef.current;
|
|
141
|
+
onDragMove({ x: e.touches[0].clientX, y: e.touches[0].clientY });
|
|
142
|
+
},
|
|
143
|
+
[onTouchMove]
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const touchEndHandler = useCallback(() => {
|
|
147
|
+
onTouchEnd();
|
|
148
|
+
dragEndHandler();
|
|
149
|
+
}, [dragEndHandler, onTouchEnd]);
|
|
150
|
+
|
|
151
|
+
useEvent(document, 'mousemove', onMouseMove);
|
|
152
|
+
useEvent(document, 'mouseup', onMouseUp);
|
|
153
|
+
useEvent(document, 'touchmove', touchMoveHandler);
|
|
154
|
+
useEvent(document, 'touchend', touchEndHandler);
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
onMouseDown,
|
|
158
|
+
onTouchStart: touchStartHandler,
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export default useDrag;
|