UNPKG

11.1 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.DraggableZone = void 0;
4var tslib_1 = require("tslib");
5var React = require("react");
6var DraggableZone_styles_1 = require("./DraggableZone.styles");
7var Utilities_1 = require("../../Utilities");
8var eventMapping = {
9 touch: {
10 start: 'touchstart',
11 move: 'touchmove',
12 stop: 'touchend',
13 },
14 mouse: {
15 start: 'mousedown',
16 move: 'mousemove',
17 stop: 'mouseup',
18 },
19};
20var DraggableZone = /** @class */ (function (_super) {
21 tslib_1.__extends(DraggableZone, _super);
22 function DraggableZone(props) {
23 var _this = _super.call(this, props) || this;
24 _this._currentEventType = eventMapping.mouse;
25 _this._events = [];
26 _this._onMouseDown = function (event) {
27 var onMouseDown = React.Children.only(_this.props.children).props.onMouseDown;
28 if (onMouseDown) {
29 onMouseDown(event);
30 }
31 _this._currentEventType = eventMapping.mouse;
32 return _this._onDragStart(event);
33 };
34 _this._onMouseUp = function (event) {
35 var onMouseUp = React.Children.only(_this.props.children).props.onMouseUp;
36 if (onMouseUp) {
37 onMouseUp(event);
38 }
39 _this._currentEventType = eventMapping.mouse;
40 return _this._onDragStop(event);
41 };
42 _this._onTouchStart = function (event) {
43 var onTouchStart = React.Children.only(_this.props.children).props.onTouchStart;
44 if (onTouchStart) {
45 onTouchStart(event);
46 }
47 _this._currentEventType = eventMapping.touch;
48 return _this._onDragStart(event);
49 };
50 _this._onTouchEnd = function (event) {
51 var onTouchEnd = React.Children.only(_this.props.children).props.onTouchEnd;
52 if (onTouchEnd) {
53 onTouchEnd(event);
54 }
55 _this._currentEventType = eventMapping.touch;
56 _this._onDragStop(event);
57 };
58 _this._onDragStart = function (event) {
59 // Only handle left click for dragging
60 if (typeof event.button === 'number' && event.button !== 0) {
61 return false;
62 }
63 // If the target doesn't match the handleSelector OR
64 // if the target does match the preventDragSelector, bail out
65 if ((_this.props.handleSelector && !_this._matchesSelector(event.target, _this.props.handleSelector)) ||
66 (_this.props.preventDragSelector &&
67 _this._matchesSelector(event.target, _this.props.preventDragSelector))) {
68 return;
69 }
70 // Remember the touch identifier if this is a touch event so we can
71 // distinguish between individual touches in multitouch scenarios
72 // by remembering which touch point we were given
73 _this._touchId = _this._getTouchId(event);
74 var position = _this._getControlPosition(event);
75 if (position === undefined) {
76 return;
77 }
78 var dragData = _this._createDragDataFromPosition(position);
79 _this.props.onStart && _this.props.onStart(event, dragData);
80 _this.setState({
81 isDragging: true,
82 lastPosition: position,
83 });
84 // hook up the appropriate mouse/touch events to the body to ensure
85 // smooth dragging
86 _this._events = [
87 Utilities_1.on(document.body, _this._currentEventType.move, _this._onDrag, true /* use capture phase */),
88 Utilities_1.on(document.body, _this._currentEventType.stop, _this._onDragStop, true /* use capture phase */),
89 ];
90 };
91 _this._onDrag = function (event) {
92 // Prevent scrolling on mobile devices
93 if (event.type === 'touchmove') {
94 event.preventDefault();
95 }
96 var position = _this._getControlPosition(event);
97 if (!position) {
98 return;
99 }
100 // create the updated drag data from the position data
101 var updatedData = _this._createUpdatedDragData(_this._createDragDataFromPosition(position));
102 var updatedPosition = updatedData.position;
103 _this.props.onDragChange && _this.props.onDragChange(event, updatedData);
104 _this.setState({
105 position: updatedPosition,
106 lastPosition: position,
107 });
108 };
109 _this._onDragStop = function (event) {
110 if (!_this.state.isDragging) {
111 return;
112 }
113 var position = _this._getControlPosition(event);
114 if (!position) {
115 return;
116 }
117 var baseDragData = _this._createDragDataFromPosition(position);
118 // Set dragging to false and reset the lastPosition
119 _this.setState({
120 isDragging: false,
121 lastPosition: undefined,
122 });
123 _this.props.onStop && _this.props.onStop(event, baseDragData);
124 if (_this.props.position) {
125 _this.setState({
126 position: _this.props.position,
127 });
128 }
129 // Remove event handlers
130 _this._events.forEach(function (dispose) { return dispose(); });
131 };
132 _this.state = {
133 isDragging: false,
134 position: _this.props.position || { x: 0, y: 0 },
135 lastPosition: undefined,
136 };
137 return _this;
138 }
139 DraggableZone.prototype.componentDidUpdate = function (prevProps) {
140 if (this.props.position && (!prevProps.position || this.props.position !== prevProps.position)) {
141 this.setState({ position: this.props.position });
142 }
143 };
144 DraggableZone.prototype.componentWillUnmount = function () {
145 this._events.forEach(function (dispose) { return dispose(); });
146 };
147 DraggableZone.prototype.render = function () {
148 var child = React.Children.only(this.props.children);
149 var props = child.props;
150 var position = this.props.position;
151 var _a = this.state, statePosition = _a.position, isDragging = _a.isDragging;
152 var x = statePosition.x;
153 var y = statePosition.y;
154 if (position && !isDragging) {
155 x = position.x;
156 y = position.y;
157 }
158 return React.cloneElement(child, {
159 style: tslib_1.__assign(tslib_1.__assign({}, props.style), { transform: "translate(" + x + "px, " + y + "px)" }),
160 className: DraggableZone_styles_1.getClassNames(props.className, this.state.isDragging).root,
161 onMouseDown: this._onMouseDown,
162 onMouseUp: this._onMouseUp,
163 onTouchStart: this._onTouchStart,
164 onTouchEnd: this._onTouchEnd,
165 });
166 };
167 /**
168 * Get the control position based off the event that fired
169 * @param event - The event to get offsets from
170 */
171 DraggableZone.prototype._getControlPosition = function (event) {
172 var touchObj = this._getActiveTouch(event);
173 // did we get the right touch?
174 if (this._touchId !== undefined && !touchObj) {
175 return undefined;
176 }
177 var eventToGetOffset = touchObj || event;
178 return {
179 x: eventToGetOffset.clientX,
180 y: eventToGetOffset.clientY,
181 };
182 };
183 /**
184 * Get the active touch point that we have saved from the event's TouchList
185 * @param event - The event used to get the TouchList for the active touch point
186 */
187 DraggableZone.prototype._getActiveTouch = function (event) {
188 return ((event.targetTouches && this._findTouchInTouchList(event.targetTouches)) ||
189 (event.changedTouches && this._findTouchInTouchList(event.changedTouches)));
190 };
191 /**
192 * Get the initial touch identifier associated with the given event
193 * @param event - The event that contains the TouchList
194 */
195 DraggableZone.prototype._getTouchId = function (event) {
196 var touch = (event.targetTouches && event.targetTouches[0]) || (event.changedTouches && event.changedTouches[0]);
197 if (touch) {
198 return touch.identifier;
199 }
200 };
201 /**
202 * Returns if an element (or any of the element's parents) match the given selector
203 */
204 DraggableZone.prototype._matchesSelector = function (element, selector) {
205 if (!element || element === document.body) {
206 return false;
207 }
208 var matchesSelectorFn = element.matches || element.webkitMatchesSelector || element.msMatchesSelector; /* for IE */
209 if (!matchesSelectorFn) {
210 return false;
211 }
212 return matchesSelectorFn.call(element, selector) || this._matchesSelector(element.parentElement, selector);
213 };
214 /**
215 * Attempts to find the Touch that matches the identifier we stored in dragStart
216 * @param touchList The TouchList to look for the stored identifier from dragStart
217 */
218 DraggableZone.prototype._findTouchInTouchList = function (touchList) {
219 if (this._touchId === undefined) {
220 return;
221 }
222 for (var i = 0; i < touchList.length; i++) {
223 if (touchList[i].identifier === this._touchId) {
224 return touchList[i];
225 }
226 }
227 return undefined;
228 };
229 /**
230 * Create DragData based off of the last known position and the new position passed in
231 * @param position The new position as part of the drag
232 */
233 DraggableZone.prototype._createDragDataFromPosition = function (position) {
234 var lastPosition = this.state.lastPosition;
235 // If we have no lastPosition, use the given position
236 // for last position
237 if (lastPosition === undefined) {
238 return {
239 delta: { x: 0, y: 0 },
240 lastPosition: position,
241 position: position,
242 };
243 }
244 return {
245 delta: {
246 x: position.x - lastPosition.x,
247 y: position.y - lastPosition.y,
248 },
249 lastPosition: lastPosition,
250 position: position,
251 };
252 };
253 /**
254 * Creates an updated DragData based off the current position and given baseDragData
255 * @param baseDragData The base DragData (from _createDragDataFromPosition) used to calculate the updated positions
256 */
257 DraggableZone.prototype._createUpdatedDragData = function (baseDragData) {
258 var position = this.state.position;
259 return {
260 position: {
261 x: position.x + baseDragData.delta.x,
262 y: position.y + baseDragData.delta.y,
263 },
264 delta: baseDragData.delta,
265 lastPosition: position,
266 };
267 };
268 return DraggableZone;
269}(React.Component));
270exports.DraggableZone = DraggableZone;
271//# sourceMappingURL=DraggableZone.js.map
\No newline at end of file