react-swipeable
Advanced tools
Comparing version 4.0.1 to 4.1.0
@@ -0,1 +1,8 @@ | ||
# 4.1.0 | ||
* add `disabled` prop. [#83](https://github.com/dogfessional/react-swipeable/pull/83) | ||
* add `innerRef` prop that allows user to access to `<Swipeable>`'s inner dom node react ref. [#82](https://github.com/dogfessional/react-swipeable/pull/82) | ||
# 4.0.1 | ||
* fixed bug where delta was causing a swipe to not be tracked correctly, #74 , thanks @mctep | ||
# 4.0.0 | ||
@@ -2,0 +9,0 @@ |
@@ -61,2 +61,4 @@ 'use strict'; | ||
_this.mouseUp = _this.mouseUp.bind(_this); | ||
_this.cleanupMouseListeners = _this.cleanupMouseListeners.bind(_this); | ||
_this.setupMouseListeners = _this.setupMouseListeners.bind(_this); | ||
return _this; | ||
@@ -69,9 +71,24 @@ } | ||
Swipeable.prototype.componentWillUnmount = function componentWillUnmount() { | ||
if (this.props.trackMouse) { | ||
document.removeEventListener('mousemove', this.mouseMove); | ||
document.removeEventListener('mouseup', this.mouseUp); | ||
Swipeable.prototype.componentDidUpdate = function componentDidUpdate(prevProps) { | ||
if (prevProps.disabled !== this.props.disabled) { | ||
this.cleanupMouseListeners(); | ||
this.swipeable = getInitialState(); | ||
} | ||
}; | ||
Swipeable.prototype.componentWillUnmount = function componentWillUnmount() { | ||
this.cleanupMouseListeners(); | ||
}; | ||
Swipeable.prototype.setupMouseListeners = function setupMouseListeners() { | ||
document.addEventListener('mousemove', this.mouseMove); | ||
document.addEventListener('mouseup', this.mouseUp); | ||
}; | ||
Swipeable.prototype.cleanupMouseListeners = function cleanupMouseListeners() { | ||
document.removeEventListener('mousemove', this.mouseMove); | ||
document.removeEventListener('mouseup', this.mouseUp); | ||
}; | ||
Swipeable.prototype.mouseDown = function mouseDown(e) { | ||
@@ -84,6 +101,5 @@ if (!this.props.trackMouse || e.type !== 'mousedown') { | ||
this.setupMouseListeners(); | ||
this.eventStart(e); | ||
document.addEventListener('mousemove', this.mouseMove); | ||
document.addEventListener('mouseup', this.mouseUp); | ||
}; | ||
@@ -96,5 +112,3 @@ | ||
Swipeable.prototype.mouseUp = function mouseUp(e) { | ||
document.removeEventListener('mousemove', this.mouseMove); | ||
document.removeEventListener('mouseup', this.mouseUp); | ||
this.cleanupMouseListeners(); | ||
this.eventEnd(e); | ||
@@ -211,9 +225,17 @@ }; | ||
Swipeable.prototype.render = function render() { | ||
var newProps = _extends({}, this.props, { | ||
onTouchStart: this.eventStart, | ||
onTouchMove: this.eventMove, | ||
onTouchEnd: this.eventEnd, | ||
onMouseDown: this.mouseDown | ||
}); | ||
var _props3 = this.props, | ||
disabled = _props3.disabled, | ||
innerRef = _props3.innerRef; | ||
var newProps = _extends({}, this.props); | ||
if (!disabled) { | ||
newProps.onTouchStart = this.eventStart; | ||
newProps.onTouchMove = this.eventMove; | ||
newProps.onTouchEnd = this.eventEnd; | ||
newProps.onMouseDown = this.mouseDown; | ||
} | ||
if (innerRef) { | ||
newProps.ref = innerRef; | ||
} | ||
delete newProps.onSwiped; | ||
@@ -237,2 +259,4 @@ delete newProps.onSwiping; | ||
delete newProps.trackMouse; | ||
delete newProps.disabled; | ||
delete newProps.innerRef; | ||
@@ -263,2 +287,4 @@ return React.createElement(this.props.nodeName, newProps, this.props.children); | ||
trackMouse: PropTypes.bool, | ||
disabled: PropTypes.bool, | ||
innerRef: PropTypes.func, | ||
children: PropTypes.node | ||
@@ -272,5 +298,6 @@ }; | ||
stopPropagation: false, | ||
nodeName: 'div' | ||
nodeName: 'div', | ||
disabled: false | ||
}; | ||
module.exports = Swipeable; |
{ | ||
"name": "react-swipeable", | ||
"version": "4.0.1", | ||
"version": "4.1.0", | ||
"description": "Swipe bindings for react", | ||
@@ -5,0 +5,0 @@ "main": "lib/Swipeable.js", |
@@ -1,2 +0,2 @@ | ||
# Swipeable [![npm version](https://img.shields.io/npm/v/react-swipeable.svg?style=flat-square)](https://www.npmjs.com/package/react-swipeable) [![npm downloads](https://img.shields.io/npm/dm/react-swipeable.svg?style=flat-square)](https://www.npmjs.com/package/react-swipeable) | ||
# Swipeable [![build status](https://img.shields.io/travis/dogfessional/react-swipeable/master.svg?style=flat-square)](https://travis-ci.org/dogfessional/react-swipeable) [![npm version](https://img.shields.io/npm/v/react-swipeable.svg?style=flat-square)](https://www.npmjs.com/package/react-swipeable) [![npm downloads](https://img.shields.io/npm/dm/react-swipeable.svg?style=flat-square)](https://www.npmjs.com/package/react-swipeable) | ||
React swipe component - Swipe bindings for react | ||
@@ -19,9 +19,17 @@ | ||
swiping(e, deltaX, deltaY, absX, absY, velocity) { | ||
console.log('Swiping...', e, deltaX, deltaY, absX, absY, velocity) | ||
console.log("You're Swiping...", e, deltaX, deltaY, absX, absY, velocity) | ||
} | ||
swipingLeft(e, absX) { | ||
console.log("You're Swiping to the Left...", e, absX) | ||
} | ||
swiped(e, deltaX, deltaY, isFlick, velocity) { | ||
console.log('Swiped...', e, deltaX, deltaY, isFlick, velocity) | ||
console.log("You Swiped...", e, deltaX, deltaY, isFlick, velocity) | ||
} | ||
swipedUp(e, deltaY, isFlick) { | ||
console.log("You Swiped Up...", e, deltaY, isFlick) | ||
} | ||
render() { | ||
@@ -31,3 +39,5 @@ return ( | ||
onSwiping={this.swiping} | ||
onSwiped={this.swiped} > | ||
onSwipingLeft={this.swipingLeft} | ||
onSwiped={this.swiped} | ||
onSwipedUp={this.swipedRight} > | ||
You can swipe here! | ||
@@ -39,3 +49,3 @@ </Swipeable> | ||
``` | ||
react-swipeable generates a React element(`<div>` by default) under the hood and binds touch events to it which in turn are used to fire the `swiped` and `swiping` props. | ||
react-swipeable(`<Swipeable>`) generates a new React element(`<div>` by default) under the hood and binds touch events to it that are used to fire the `swiping` and `swiped` props. | ||
@@ -56,3 +66,3 @@ ## Props / Config Options | ||
**`onTap`** is called with the onTouchEnd event when the element has been tapped. `this.props.onTap(e)` | ||
**`onTap`** is triggered when a tap happens, specifically when a swipe/touch moves less than the `delta`. Is called with the onTouchEnd event `this.props.onTap(e)` | ||
@@ -74,4 +84,8 @@ ### Configuration Props | ||
**`trackMouse`** will allow mouse 'swipes' to be tracked(click, hold, move, let go). See [#51](https://github.com/dogfessional/react-swipeable/issues/51) for more details. The default value is `false`. | ||
**`trackMouse`** will allow mouse 'swipes' to ***additonally*** be tracked(click, hold, move, let go). See [#51](https://github.com/dogfessional/react-swipeable/issues/51) for more details. The default value is `false`. | ||
**`disabled`** will disable `<Swipeable>`: swipes will not be tracked and this stops current active swipes from triggering anymore prop callbacks. The default value is `false`. | ||
**`innerRef`** will allow access to the Swipeable's inner dom node element react ref. See [#81](https://github.com/dogfessional/react-swipeable/issues/81) for more details. Example usage `<Swipeable innerRef={(el) => this.swipeableEl = el} >`. Then you'll have access to the dom element that Swipeable uses internally. | ||
**None of the props are required.** | ||
@@ -102,2 +116,4 @@ ### PropType Definitions | ||
trackMouse: PropTypes.bool, // default: false | ||
disabled: PropTypes.bool, // default: false | ||
innerRef: PropTypes.func, | ||
``` | ||
@@ -104,0 +120,0 @@ |
@@ -26,5 +26,7 @@ /* global document */ | ||
let origEventListener; | ||
let origRemoveEventListener; | ||
let eventListenerMap; | ||
beforeAll(() => { | ||
origEventListener = document.eventListener; | ||
origRemoveEventListener = document.removeEventListener; | ||
}); | ||
@@ -38,5 +40,9 @@ beforeEach(() => { | ||
}); | ||
document.removeEventListener = jest.fn((event, cb) => { | ||
if (eventListenerMap[event] === cb) delete eventListenerMap[event]; | ||
}); | ||
}); | ||
afterAll(() => { | ||
document.eventListener = origEventListener; | ||
document.removeEventListener = origRemoveEventListener; | ||
}); | ||
@@ -208,2 +214,72 @@ | ||
it('disables swipeable with disabled prop using touch swipe', () => { | ||
const onSwiping = jest.fn(); | ||
const onSwipedRight = jest.fn(); | ||
const onSwipedLeft = jest.fn(); | ||
const wrapper = mount(( | ||
<Swipeable | ||
onSwiping={onSwiping} | ||
onSwipedRight={onSwipedRight} | ||
onSwipedLeft={onSwipedLeft} | ||
> | ||
<span>Touch Here</span> | ||
</Swipeable> | ||
)); | ||
const touchHere = wrapper.find('span'); | ||
touchHere.simulate('touchStart', createStartTouchEventObject({ x: 100, y: 100 })); | ||
touchHere.simulate('touchMove', createMoveTouchEventObject({ x: 125, y: 100 })); | ||
// DISABLE swipeable "mid swipe action" | ||
wrapper.setProps({ disabled: true }); | ||
// no longer tracking a 'swipe' | ||
const swipeableInstance = wrapper.instance(); | ||
// check internal saved state | ||
expect(swipeableInstance.swipeable.swiping).toBe(false); | ||
touchHere.simulate('touchMove', createMoveTouchEventObject({ x: 150, y: 100 })); | ||
touchHere.simulate('touchEnd', createMoveTouchEventObject({ x: 175, y: 100 })); | ||
expect(onSwiping).toHaveBeenCalledTimes(1); | ||
expect(onSwipedLeft).not.toHaveBeenCalled(); | ||
expect(onSwipedRight).not.toHaveBeenCalled(); | ||
}); | ||
it('disables swipeable with disabled prop using "mouse swipe"', () => { | ||
const onSwiping = jest.fn(); | ||
const onSwipedRight = jest.fn(); | ||
const onSwipedLeft = jest.fn(); | ||
const wrapper = mount(( | ||
<Swipeable | ||
onSwiping={onSwiping} | ||
onSwipedRight={onSwipedRight} | ||
onSwipedLeft={onSwipedLeft} | ||
trackMouse={true} | ||
> | ||
<span>Touch Here</span> | ||
</Swipeable> | ||
)); | ||
const touchHere = wrapper.find('span'); | ||
touchHere.simulate('mouseDown', createMouseEventObject({ x: 100, y: 100 })); | ||
eventListenerMap.mousemove(createMouseEventObject({ x: 125, y: 100 })); | ||
// DISABLE swipeable "mid swipe action" | ||
wrapper.setProps({ disabled: true }); | ||
// no longer tracking a 'swipe' | ||
const swipeableInstance = wrapper.instance(); | ||
// check internal saved state | ||
expect(swipeableInstance.swipeable.swiping).toBe(false); | ||
expect(eventListenerMap.mousemove).toBe(undefined); | ||
expect(eventListenerMap.mouseup).toBe(undefined); | ||
expect(onSwiping).toHaveBeenCalledTimes(1); | ||
expect(onSwipedLeft).not.toHaveBeenCalled(); | ||
expect(onSwipedRight).not.toHaveBeenCalled(); | ||
}); | ||
it('does not check delta when swiping in progress', () => { | ||
@@ -234,2 +310,13 @@ const onSwiping = jest.fn(); | ||
}); | ||
it('should pass ref to the component via innerRef prop', () => { | ||
const WrapperComp = class extends React.Component { | ||
render() { | ||
return <Swipeable innerRef={el => this.testRef = el} /> // eslint-disable-line | ||
} | ||
}; | ||
const wrapper = mount((<WrapperComp />)); | ||
const swipeableDiv = wrapper.find('div').getNode(); | ||
expect(wrapper.node.testRef).toBe(swipeableDiv); | ||
}); | ||
}); |
@@ -51,2 +51,4 @@ /* global document */ | ||
this.mouseUp = this.mouseUp.bind(this); | ||
this.cleanupMouseListeners = this.cleanupMouseListeners.bind(this); | ||
this.setupMouseListeners = this.setupMouseListeners.bind(this); | ||
} | ||
@@ -58,10 +60,27 @@ | ||
} | ||
componentWillUnmount() { | ||
if (this.props.trackMouse) { | ||
// just to be safe attempt removal | ||
document.removeEventListener('mousemove', this.mouseMove); | ||
document.removeEventListener('mouseup', this.mouseUp); | ||
componentDidUpdate(prevProps) { | ||
// swipeable toggled either on/off, so stop tracking swipes and clean up | ||
if (prevProps.disabled !== this.props.disabled) { | ||
this.cleanupMouseListeners(); | ||
// reset internal swipeable state | ||
this.swipeable = getInitialState(); | ||
} | ||
} | ||
componentWillUnmount() { | ||
this.cleanupMouseListeners(); | ||
} | ||
setupMouseListeners() { | ||
document.addEventListener('mousemove', this.mouseMove); | ||
document.addEventListener('mouseup', this.mouseUp); | ||
} | ||
cleanupMouseListeners() { | ||
// safe to call, if no match is found has no effect | ||
document.removeEventListener('mousemove', this.mouseMove); | ||
document.removeEventListener('mouseup', this.mouseUp); | ||
} | ||
mouseDown(e) { | ||
@@ -71,11 +90,10 @@ if (!this.props.trackMouse || e.type !== 'mousedown') { | ||
} | ||
// allow 'orig' onMouseDown's to fire also | ||
// allow 'orig' props.onMouseDown to fire also | ||
// eslint-disable-next-line react/prop-types | ||
if (typeof this.props.onMouseDown === 'function') this.props.onMouseDown(e); | ||
// setup document listeners to track mouse movement outside <Swipeable>'s area | ||
this.setupMouseListeners(); | ||
this.eventStart(e); | ||
// setup document listeners to track mouse movement outside <Swipeable>'s area | ||
document.addEventListener('mousemove', this.mouseMove); | ||
document.addEventListener('mouseup', this.mouseUp); | ||
} | ||
@@ -88,5 +106,3 @@ | ||
mouseUp(e) { | ||
document.removeEventListener('mousemove', this.mouseMove); | ||
document.removeEventListener('mouseup', this.mouseUp); | ||
this.cleanupMouseListeners(); | ||
this.eventEnd(e); | ||
@@ -200,9 +216,13 @@ } | ||
render() { | ||
const newProps = { | ||
...this.props, | ||
onTouchStart: this.eventStart, | ||
onTouchMove: this.eventMove, | ||
onTouchEnd: this.eventEnd, | ||
onMouseDown: this.mouseDown, | ||
}; | ||
const { disabled, innerRef } = this.props; | ||
const newProps = { ...this.props }; | ||
if (!disabled) { | ||
newProps.onTouchStart = this.eventStart; | ||
newProps.onTouchMove = this.eventMove; | ||
newProps.onTouchEnd = this.eventEnd; | ||
newProps.onMouseDown = this.mouseDown; | ||
} | ||
if (innerRef) { | ||
newProps.ref = innerRef; | ||
} | ||
@@ -228,2 +248,4 @@ // clean up swipeable's props to avoid react warning | ||
delete newProps.trackMouse; | ||
delete newProps.disabled; | ||
delete newProps.innerRef; | ||
@@ -256,2 +278,4 @@ return React.createElement( | ||
trackMouse: PropTypes.bool, | ||
disabled: PropTypes.bool, | ||
innerRef: PropTypes.func, | ||
children: PropTypes.node, | ||
@@ -266,4 +290,5 @@ }; | ||
nodeName: 'div', | ||
disabled: false, | ||
}; | ||
module.exports = Swipeable; |
43930
780
148