@@ -19,6 +19,7 @@ export const LEFT = 'Left'
19
19
export const RIGHT = 'Right'
20
20
export const UP = 'Up'
21
21
export const DOWN = 'Down'
22
+ const touchStart = 'touchstart'
22
23
const touchMove = 'touchmove'
23
24
const touchEnd = 'touchend'
24
25
const mouseMove = 'mousemove'
@@ -46,22 +47,19 @@ function rotateXYByAngle(pos, angle) {
46
47
return [ x , y ]
47
48
}
48
49
49
- const getTouchHandlerOption = props => {
50
- if ( props . touchHandlerOption ) return props . touchHandlerOption
51
- return props . preventDefaultTouchmoveEvent
52
- ? { passive : false }
53
- : { passive : true }
54
- }
55
-
56
50
function getHandlers ( set , props ) {
57
51
const onStart = event => {
58
52
// if more than a single touch don't track, for now...
59
53
if ( event . touches && event . touches . length > 1 ) return
60
54
61
- set ( ( ) => {
55
+ set ( state => {
56
+ if ( state . props . trackMouse ) {
57
+ document . addEventListener ( mouseMove , onMove )
58
+ document . addEventListener ( mouseUp , onUp )
59
+ }
62
60
const { clientX, clientY } = event . touches ? event . touches [ 0 ] : event
63
- const xy = rotateXYByAngle ( [ clientX , clientY ] , props . rotationAngle )
64
- return { ...initialState , xy, start : event . timeStamp || 0 }
61
+ const xy = rotateXYByAngle ( [ clientX , clientY ] , state . props . rotationAngle )
62
+ return { ...state , ... initialState , xy, start : event . timeStamp || 0 }
65
63
} )
66
64
}
67
65
@@ -75,7 +73,10 @@ function getHandlers(set, props) {
75
73
return state
76
74
}
77
75
const { clientX, clientY } = event . touches ? event . touches [ 0 ] : event
78
- const [ x , y ] = rotateXYByAngle ( [ clientX , clientY ] , props . rotationAngle )
76
+ const [ x , y ] = rotateXYByAngle (
77
+ [ clientX , clientY ] ,
78
+ state . props . rotationAngle
79
+ )
79
80
const deltaX = state . xy [ 0 ] - x
80
81
const deltaY = state . xy [ 1 ] - y
81
82
const absX = Math . abs ( deltaX )
@@ -90,19 +91,23 @@ function getHandlers(set, props) {
90
91
const dir = getDirection ( absX , absY , deltaX , deltaY )
91
92
const eventData = { event, absX, absY, deltaX, deltaY, velocity, dir }
92
93
93
- props . onSwiping && props . onSwiping ( eventData )
94
+ state . props . onSwiping && state . props . onSwiping ( eventData )
94
95
95
96
// track if a swipe is cancelable(handler for swiping or swiped(dir) exists)
96
97
// so we can call preventDefault if needed
97
98
let cancelablePageSwipe = false
98
- if ( props . onSwiping || props . onSwiped || props [ `onSwiped${ dir } ` ] ) {
99
+ if (
100
+ state . props . onSwiping ||
101
+ state . props . onSwiped ||
102
+ state . props [ `onSwiped${ dir } ` ]
103
+ ) {
99
104
cancelablePageSwipe = true
100
105
}
101
106
102
107
if (
103
108
cancelablePageSwipe &&
104
- props . preventDefaultTouchmoveEvent &&
105
- props . trackTouch
109
+ state . props . preventDefaultTouchmoveEvent &&
110
+ state . props . trackTouch
106
111
)
107
112
event . preventDefault ( )
108
113
@@ -115,58 +120,69 @@ function getHandlers(set, props) {
115
120
if ( state . swiping ) {
116
121
const eventData = { ...state . lastEventData , event }
117
122
118
- props . onSwiped && props . onSwiped ( eventData )
123
+ state . props . onSwiped && state . props . onSwiped ( eventData )
119
124
120
- props [ `onSwiped${ eventData . dir } ` ] &&
121
- props [ `onSwiped${ eventData . dir } ` ] ( eventData )
125
+ state . props [ `onSwiped${ eventData . dir } ` ] &&
126
+ state . props [ `onSwiped${ eventData . dir } ` ] ( eventData )
122
127
}
123
- return { ...initialState }
128
+ return { ...state , ... initialState }
124
129
} )
125
130
}
126
131
127
- const onDown = e => {
128
- if ( props . trackMouse ) {
129
- document . addEventListener ( mouseMove , onMove )
130
- document . addEventListener ( mouseUp , onUp )
131
- }
132
- if ( props . trackTouch ) {
133
- const touchHandlerOption = getTouchHandlerOption ( props )
134
- document . addEventListener ( touchMove , onMove , touchHandlerOption )
135
- document . addEventListener ( touchEnd , onUp , touchHandlerOption )
136
- }
137
- onStart ( e )
138
- }
139
-
140
132
const stop = ( ) => {
141
- if ( props . trackMouse ) {
142
- document . removeEventListener ( mouseMove , onMove )
143
- document . removeEventListener ( mouseUp , onUp )
144
- }
145
- if ( props . trackTouch ) {
146
- const touchHandlerOption = getTouchHandlerOption ( props )
147
- document . removeEventListener ( touchMove , onMove , touchHandlerOption )
148
- document . removeEventListener ( touchEnd , onUp , touchHandlerOption )
149
- }
133
+ set ( state => {
134
+ if ( state . props . trackMouse ) {
135
+ document . removeEventListener ( mouseMove , onMove )
136
+ document . removeEventListener ( mouseUp , onUp )
137
+ }
138
+ return state
139
+ } )
150
140
}
151
141
152
142
const onUp = e => {
153
143
stop ( )
154
144
onEnd ( e )
155
145
}
156
146
157
- const output = { }
158
- if ( props . trackMouse ) {
159
- output . onMouseDown = onDown
147
+ const cleanUp = el => {
148
+ if ( el && el . removeEventListener ) {
149
+ el . removeEventListener ( touchStart , onStart )
150
+ el . removeEventListener ( touchMove , onMove )
151
+ el . removeEventListener ( touchEnd , onUp )
152
+ }
160
153
}
161
- if ( props . trackTouch ) {
162
- output . onTouchStart = onDown
154
+
155
+ const onRef = el => {
156
+ if ( el === null ) return
157
+ set ( state => {
158
+ if ( state . el === el ) return state
159
+ if ( state . el && state . el !== el ) cleanUp ( state . el )
160
+ if ( state . props . trackTouch ) {
161
+ if ( el && el . addEventListener ) {
162
+ el . addEventListener ( touchStart , onStart )
163
+ el . addEventListener ( touchMove , onMove )
164
+ el . addEventListener ( touchEnd , onUp )
165
+ return { ...state , el }
166
+ }
167
+ }
168
+ return state
169
+ } )
170
+ }
171
+
172
+ // set ref callback to attach touch event listeners
173
+ const output = { ref : onRef }
174
+ if ( props . trackMouse ) {
175
+ output . onMouseDown = onStart
163
176
}
164
177
178
+ // update props
179
+ set ( state => ( { ...state , props } ) )
180
+
165
181
return output
166
182
}
167
183
168
184
export function useSwipeable ( props ) {
169
- const transientState = React . useRef ( initialState )
185
+ const transientState = React . useRef ( { ... initialState , type : 'hook' } )
170
186
const [ spread ] = React . useState ( ( ) => currentProps =>
171
187
getHandlers ( cb => ( transientState . current = cb ( transientState . current ) ) , {
172
188
...defaultProps ,
@@ -200,7 +216,7 @@ export class Swipeable extends React.PureComponent {
200
216
201
217
constructor ( props ) {
202
218
super ( props )
203
- this . _state = initialState
219
+ this . _state = { ... initialState , type : 'class' }
204
220
this . _set = cb => ( this . _state = cb ( this . _state ) )
205
221
}
206
222
@@ -214,9 +230,10 @@ export class Swipeable extends React.PureComponent {
214
230
...rest
215
231
} = this . props
216
232
const handlers = getHandlers ( this . _set , rest )
233
+ const ref = innerRef ? el => ( innerRef ( el ) , handlers . ref ( el ) ) : handlers . ref
217
234
return React . createElement (
218
235
nodeName ,
219
- { ...handlers , className, style, ref : innerRef } ,
236
+ { ...handlers , className, style, ref } ,
220
237
children
221
238
)
222
239
}
0 commit comments