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