Skip to content

Commit b7a74eb

Browse files
authored
Touchmove Propagation (#37)
Check target's "scrollability" before allowing scroll to pass through
1 parent 46d7b35 commit b7a74eb

File tree

2 files changed

+18
-20
lines changed

2 files changed

+18
-20
lines changed

src/utils.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,20 @@ export const listenerOptions = {
1111

1212
export function preventTouchMove(e) {
1313
e.preventDefault();
14+
15+
return false;
1416
}
1517

1618
export function allowTouchMove(e) {
17-
e.stopPropagation();
19+
const target = e.currentTarget;
20+
21+
if (target.scrollHeight > target.clientHeight) {
22+
e.stopPropagation();
23+
return true;
24+
}
25+
26+
e.preventDefault();
27+
return false;
1828
}
1929

2030
export function preventInertiaScroll() {

src/withTouchListeners.js

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,23 @@
22
import React, { PureComponent, type ComponentType } from 'react';
33
import { canUseDOM } from 'exenv';
44

5-
import { isTouchDevice, preventTouchMove } from './utils';
5+
import { isTouchDevice, listenerOptions, preventTouchMove } from './utils';
66

77
type Props = {};
88

9+
// Mobile Safari ignores { overflow: hidden } declaration on the body,
10+
// so we have to prevent touchmove events via JS
911
export default function withTouchListeners(WrappedComponent: ComponentType<*>) {
1012
return class TouchProvider extends PureComponent<Props> {
11-
listenerOptions = {
12-
capture: false,
13-
passive: false,
14-
};
1513
componentDidMount() {
16-
if (!canUseDOM) return;
17-
const target = document.body;
14+
if (!canUseDOM || !isTouchDevice()) return;
1815

19-
// account for touch devices
20-
if (target && isTouchDevice()) {
21-
// Mobile Safari ignores { overflow: hidden } declaration on the body.
22-
target.addEventListener('touchmove', preventTouchMove, this.listenerOptions);
23-
}
16+
document.addEventListener('touchmove', preventTouchMove, listenerOptions);
2417
}
2518
componentWillUnmount() {
26-
if (!canUseDOM) return;
19+
if (!canUseDOM || !isTouchDevice()) return;
2720

28-
const target = document.body;
29-
30-
// remove touch listeners
31-
if (target && isTouchDevice()) {
32-
target.removeEventListener('touchmove', preventTouchMove, this.listenerOptions);
33-
}
21+
document.removeEventListener('touchmove', preventTouchMove, listenerOptions);
3422
}
3523
render() {
3624
return <WrappedComponent {...this.props} />;

0 commit comments

Comments
 (0)