UNPKG

8.36 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7var React = _interopDefault(require('react'));
8var PropTypes = _interopDefault(require('prop-types'));
9
10function _extends() {
11 _extends = Object.assign || function (target) {
12 for (var i = 1; i < arguments.length; i++) {
13 var source = arguments[i];
14
15 for (var key in source) {
16 if (Object.prototype.hasOwnProperty.call(source, key)) {
17 target[key] = source[key];
18 }
19 }
20 }
21
22 return target;
23 };
24
25 return _extends.apply(this, arguments);
26}
27
28function _inheritsLoose(subClass, superClass) {
29 subClass.prototype = Object.create(superClass.prototype);
30 subClass.prototype.constructor = subClass;
31 subClass.__proto__ = superClass;
32}
33
34function _objectWithoutPropertiesLoose(source, excluded) {
35 if (source == null) return {};
36 var target = {};
37 var sourceKeys = Object.keys(source);
38 var key, i;
39
40 for (i = 0; i < sourceKeys.length; i++) {
41 key = sourceKeys[i];
42 if (excluded.indexOf(key) >= 0) continue;
43 target[key] = source[key];
44 }
45
46 return target;
47}
48
49var defaultProps = {
50 preventDefaultTouchmoveEvent: false,
51 delta: 10,
52 rotationAngle: 0,
53 trackMouse: false,
54 trackTouch: true
55};
56var initialState = {
57 xy: [0, 0],
58 swiping: false,
59 lastEventData: undefined,
60 start: undefined
61};
62var LEFT = 'Left';
63var RIGHT = 'Right';
64var UP = 'Up';
65var DOWN = 'Down';
66var touchMove = 'touchmove';
67var touchEnd = 'touchend';
68var mouseMove = 'mousemove';
69var mouseUp = 'mouseup';
70
71function getDirection(absX, absY, deltaX, deltaY) {
72 if (absX > absY) {
73 if (deltaX > 0) {
74 return LEFT;
75 }
76
77 return RIGHT;
78 } else if (deltaY > 0) {
79 return UP;
80 }
81
82 return DOWN;
83}
84
85function rotateXYByAngle(pos, angle) {
86 if (angle === 0) return pos;
87 var angleInRadians = Math.PI / 180 * angle;
88 var x = pos[0] * Math.cos(angleInRadians) + pos[1] * Math.sin(angleInRadians);
89 var y = pos[1] * Math.cos(angleInRadians) - pos[0] * Math.sin(angleInRadians);
90 return [x, y];
91}
92
93var getTouchHandlerOption = function getTouchHandlerOption(props) {
94 if (props.touchHandlerOption) return props.touchHandlerOption;
95 return props.preventDefaultTouchmoveEvent ? {
96 passive: false
97 } : {
98 passive: true
99 };
100};
101
102function getHandlers(set, props) {
103 var onStart = function onStart(event) {
104 // if more than a single touch don't track, for now...
105 if (event.touches && event.touches.length > 1) return;
106 set(function () {
107 var _ref = event.touches ? event.touches[0] : event,
108 clientX = _ref.clientX,
109 clientY = _ref.clientY;
110
111 var xy = rotateXYByAngle([clientX, clientY], props.rotationAngle);
112 return _extends({}, initialState, {
113 xy: xy,
114 start: event.timeStamp || 0
115 });
116 });
117 };
118
119 var onMove = function onMove(event) {
120 set(function (state) {
121 if (!state.xy[0] || !state.xy[1] || event.touches && event.touches.length > 1) {
122 return state;
123 }
124
125 var _ref2 = event.touches ? event.touches[0] : event,
126 clientX = _ref2.clientX,
127 clientY = _ref2.clientY;
128
129 var _rotateXYByAngle = rotateXYByAngle([clientX, clientY], props.rotationAngle),
130 x = _rotateXYByAngle[0],
131 y = _rotateXYByAngle[1];
132
133 var deltaX = state.xy[0] - x;
134 var deltaY = state.xy[1] - y;
135 var absX = Math.abs(deltaX);
136 var absY = Math.abs(deltaY);
137 var time = (event.timeStamp || 0) - state.start;
138 var velocity = Math.sqrt(absX * absX + absY * absY) / (time || 1); // if swipe is under delta and we have not started to track a swipe: skip update
139
140 if (absX < props.delta && absY < props.delta && !state.swiping) return state;
141 var dir = getDirection(absX, absY, deltaX, deltaY);
142 var eventData = {
143 event: event,
144 absX: absX,
145 absY: absY,
146 deltaX: deltaX,
147 deltaY: deltaY,
148 velocity: velocity,
149 dir: dir
150 };
151 props.onSwiping && props.onSwiping(eventData); // track if a swipe is cancelable(handler for swiping or swiped(dir) exists)
152 // so we can call preventDefault if needed
153
154 var cancelablePageSwipe = false;
155
156 if (props.onSwiping || props.onSwiped || props["onSwiped" + dir]) {
157 cancelablePageSwipe = true;
158 }
159
160 if (cancelablePageSwipe && props.preventDefaultTouchmoveEvent && props.trackTouch) event.preventDefault();
161 return _extends({}, state, {
162 lastEventData: eventData,
163 swiping: true
164 });
165 });
166 };
167
168 var onEnd = function onEnd(event) {
169 set(function (state) {
170 if (state.swiping) {
171 var eventData = _extends({}, state.lastEventData, {
172 event: event
173 });
174
175 props.onSwiped && props.onSwiped(eventData);
176 props["onSwiped" + eventData.dir] && props["onSwiped" + eventData.dir](eventData);
177 }
178
179 return _extends({}, initialState);
180 });
181 };
182
183 var onDown = function onDown(e) {
184 if (props.trackMouse) {
185 document.addEventListener(mouseMove, onMove);
186 document.addEventListener(mouseUp, onUp);
187 }
188
189 if (props.trackTouch) {
190 var touchHandlerOption = getTouchHandlerOption(props);
191 document.addEventListener(touchMove, onMove, touchHandlerOption);
192 document.addEventListener(touchEnd, onUp, touchHandlerOption);
193 }
194
195 onStart(e);
196 };
197
198 var stop = function stop() {
199 if (props.trackMouse) {
200 document.removeEventListener(mouseMove, onMove);
201 document.removeEventListener(mouseUp, onUp);
202 }
203
204 if (props.trackTouch) {
205 var touchHandlerOption = getTouchHandlerOption(props);
206 document.removeEventListener(touchMove, onMove, touchHandlerOption);
207 document.removeEventListener(touchEnd, onUp, touchHandlerOption);
208 }
209 };
210
211 var onUp = function onUp(e) {
212 stop();
213 onEnd(e);
214 };
215
216 var output = {};
217
218 if (props.trackMouse) {
219 output.onMouseDown = onDown;
220 }
221
222 if (props.trackTouch) {
223 output.onTouchStart = onDown;
224 }
225
226 return output;
227}
228
229function useSwipeable(props) {
230 var transientState = React.useRef(initialState);
231
232 var _React$useState = React.useState(function () {
233 return function (currentProps) {
234 return getHandlers(function (cb) {
235 return transientState.current = cb(transientState.current);
236 }, _extends({}, defaultProps, currentProps));
237 };
238 }),
239 spread = _React$useState[0];
240
241 return spread(props);
242}
243var Swipeable =
244/*#__PURE__*/
245function (_React$PureComponent) {
246 _inheritsLoose(Swipeable, _React$PureComponent);
247
248 function Swipeable(props) {
249 var _this;
250
251 _this = _React$PureComponent.call(this, props) || this;
252 _this._state = initialState;
253
254 _this._set = function (cb) {
255 return _this._state = cb(_this._state);
256 };
257
258 return _this;
259 }
260
261 var _proto = Swipeable.prototype;
262
263 _proto.render = function render() {
264 var _this$props = this.props,
265 className = _this$props.className,
266 style = _this$props.style,
267 _this$props$nodeName = _this$props.nodeName,
268 nodeName = _this$props$nodeName === void 0 ? 'div' : _this$props$nodeName,
269 innerRef = _this$props.innerRef,
270 children = _this$props.children,
271 rest = _objectWithoutPropertiesLoose(_this$props, ["className", "style", "nodeName", "innerRef", "children"]);
272
273 var handlers = getHandlers(this._set, rest);
274 return React.createElement(nodeName, _extends({}, handlers, {
275 className: className,
276 style: style,
277 ref: innerRef
278 }), children);
279 };
280
281 return Swipeable;
282}(React.PureComponent);
283Swipeable.propTypes = {
284 onSwiped: PropTypes.func,
285 onSwiping: PropTypes.func,
286 onSwipedUp: PropTypes.func,
287 onSwipedRight: PropTypes.func,
288 onSwipedDown: PropTypes.func,
289 onSwipedLeft: PropTypes.func,
290 delta: PropTypes.number,
291 preventDefaultTouchmoveEvent: PropTypes.bool,
292 nodeName: PropTypes.string,
293 trackMouse: PropTypes.bool,
294 trackTouch: PropTypes.bool,
295 innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
296 current: PropTypes.any
297 })]),
298 rotationAngle: PropTypes.number
299};
300Swipeable.defaultProps = defaultProps;
301
302exports.LEFT = LEFT;
303exports.RIGHT = RIGHT;
304exports.UP = UP;
305exports.DOWN = DOWN;
306exports.useSwipeable = useSwipeable;
307exports.Swipeable = Swipeable;