1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | import {getOffset} from './getOffset';
|
16 | import {Orientation} from '@react-types/shared';
|
17 | import React, {HTMLAttributes, MutableRefObject, useRef} from 'react';
|
18 |
|
19 | interface UseDrag1DProps {
|
20 | containerRef: MutableRefObject<HTMLElement>,
|
21 | reverse?: boolean,
|
22 | orientation?: Orientation,
|
23 | onHover?: (hovered: boolean) => void,
|
24 | onDrag?: (dragging: boolean) => void,
|
25 | onPositionChange?: (position: number) => void,
|
26 | onIncrement?: () => void,
|
27 | onDecrement?: () => void,
|
28 | onIncrementToMax?: () => void,
|
29 | onDecrementToMin?: () => void,
|
30 | onCollapseToggle?: () => void
|
31 | }
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | const draggingElements: HTMLElement[] = [];
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | export function useDrag1D(props: UseDrag1DProps): HTMLAttributes<HTMLElement> {
|
44 | console.warn('useDrag1D is deprecated, please use `useMove` instead https://react-spectrum.adobe.com/react-aria/useMove.html');
|
45 | let {containerRef, reverse, orientation, onHover, onDrag, onPositionChange, onIncrement, onDecrement, onIncrementToMax, onDecrementToMin, onCollapseToggle} = props;
|
46 | let getPosition = (e) => orientation === 'horizontal' ? e.clientX : e.clientY;
|
47 | let getNextOffset = (e: MouseEvent) => {
|
48 | let containerOffset = getOffset(containerRef.current, reverse, orientation);
|
49 | let mouseOffset = getPosition(e);
|
50 | let nextOffset = reverse ? containerOffset - mouseOffset : mouseOffset - containerOffset;
|
51 | return nextOffset;
|
52 | };
|
53 | let dragging = useRef(false);
|
54 | let prevPosition = useRef(0);
|
55 |
|
56 |
|
57 | let handlers = useRef({onPositionChange, onDrag});
|
58 | handlers.current.onDrag = onDrag;
|
59 | handlers.current.onPositionChange = onPositionChange;
|
60 |
|
61 | let onMouseDragged = (e: MouseEvent) => {
|
62 | e.preventDefault();
|
63 | let nextOffset = getNextOffset(e);
|
64 | if (!dragging.current) {
|
65 | dragging.current = true;
|
66 | if (handlers.current.onDrag) {
|
67 | handlers.current.onDrag(true);
|
68 | }
|
69 | if (handlers.current.onPositionChange) {
|
70 | handlers.current.onPositionChange(nextOffset);
|
71 | }
|
72 | }
|
73 | if (prevPosition.current === nextOffset) {
|
74 | return;
|
75 | }
|
76 | prevPosition.current = nextOffset;
|
77 | if (onPositionChange) {
|
78 | onPositionChange(nextOffset);
|
79 | }
|
80 | };
|
81 |
|
82 | let onMouseUp = (e: MouseEvent) => {
|
83 | const target = e.target as HTMLElement;
|
84 | dragging.current = false;
|
85 | let nextOffset = getNextOffset(e);
|
86 | if (handlers.current.onDrag) {
|
87 | handlers.current.onDrag(false);
|
88 | }
|
89 | if (handlers.current.onPositionChange) {
|
90 | handlers.current.onPositionChange(nextOffset);
|
91 | }
|
92 |
|
93 | draggingElements.splice(draggingElements.indexOf(target), 1);
|
94 | window.removeEventListener('mouseup', onMouseUp, false);
|
95 | window.removeEventListener('mousemove', onMouseDragged, false);
|
96 | };
|
97 |
|
98 | let onMouseDown = (e: React.MouseEvent<HTMLElement>) => {
|
99 | const target = e.currentTarget;
|
100 |
|
101 |
|
102 | if (draggingElements.some(elt => target.contains(elt))) {
|
103 | return;
|
104 | }
|
105 | draggingElements.push(target);
|
106 | window.addEventListener('mousemove', onMouseDragged, false);
|
107 | window.addEventListener('mouseup', onMouseUp, false);
|
108 | };
|
109 |
|
110 | let onMouseEnter = () => {
|
111 | if (onHover) {
|
112 | onHover(true);
|
113 | }
|
114 | };
|
115 |
|
116 | let onMouseOut = () => {
|
117 | if (onHover) {
|
118 | onHover(false);
|
119 | }
|
120 | };
|
121 |
|
122 | let onKeyDown = (e) => {
|
123 | switch (e.key) {
|
124 | case 'Left':
|
125 | case 'ArrowLeft':
|
126 | if (orientation === 'horizontal') {
|
127 | e.preventDefault();
|
128 | if (onDecrement && !reverse) {
|
129 | onDecrement();
|
130 | } else if (onIncrement && reverse) {
|
131 | onIncrement();
|
132 | }
|
133 | }
|
134 | break;
|
135 | case 'Up':
|
136 | case 'ArrowUp':
|
137 | if (orientation === 'vertical') {
|
138 | e.preventDefault();
|
139 | if (onDecrement && !reverse) {
|
140 | onDecrement();
|
141 | } else if (onIncrement && reverse) {
|
142 | onIncrement();
|
143 | }
|
144 | }
|
145 | break;
|
146 | case 'Right':
|
147 | case 'ArrowRight':
|
148 | if (orientation === 'horizontal') {
|
149 | e.preventDefault();
|
150 | if (onIncrement && !reverse) {
|
151 | onIncrement();
|
152 | } else if (onDecrement && reverse) {
|
153 | onDecrement();
|
154 | }
|
155 | }
|
156 | break;
|
157 | case 'Down':
|
158 | case 'ArrowDown':
|
159 | if (orientation === 'vertical') {
|
160 | e.preventDefault();
|
161 | if (onIncrement && !reverse) {
|
162 | onIncrement();
|
163 | } else if (onDecrement && reverse) {
|
164 | onDecrement();
|
165 | }
|
166 | }
|
167 | break;
|
168 | case 'Home':
|
169 | e.preventDefault();
|
170 | if (onDecrementToMin) {
|
171 | onDecrementToMin();
|
172 | }
|
173 | break;
|
174 | case 'End':
|
175 | e.preventDefault();
|
176 | if (onIncrementToMax) {
|
177 | onIncrementToMax();
|
178 | }
|
179 | break;
|
180 | case 'Enter':
|
181 | e.preventDefault();
|
182 | if (onCollapseToggle) {
|
183 | onCollapseToggle();
|
184 | }
|
185 | break;
|
186 | }
|
187 | };
|
188 |
|
189 | return {onMouseDown, onMouseEnter, onMouseOut, onKeyDown};
|
190 | }
|