UNPKG

react-longpressable

Version:

Long-press component for React that uses pointer events.

116 lines (95 loc) 2.4 kB
import React from 'react' import PropType from 'prop-types' function eventToPosition(event) { return { x: event.clientX, y: event.clientY } } function distance(pointA, pointB) { return Math.sqrt( Math.pow(pointB.x - pointA.x, 2) + Math.pow(pointB.y - pointA.y, 2) ) } export default class LongPressable extends React.PureComponent { static propTypes = { onLongPress: PropType.func.isRequired, onShortPress: PropType.func, longPressTime: PropType.number, primaryMouseButtonOnly: PropType.bool, // Maximum distance (pixels) user is allowed to drag before // click is canceled dragThreshold: PropType.number, children: PropType.node } static defaultProps = { longPressTime: 500, primaryMouseButtonOnly: true, dragThreshold: 100 } isLongPressing = false startingPosition = { x: 0, y: 0 } componentWillUnmount() { this.clearTimeout() } clearTimeout = () => { if (this.timerID) { clearTimeout(this.timerID) this.timerID = null } } onPointerUp = (e) => { if (this.timerID) { this.cancelLongPress() } const mousePosition = eventToPosition(e) if (!this.isLongPressing && !this.exceedDragThreshold(mousePosition)) { this.props.onShortPress(e) } else { this.isLongPressing = false } } onPointerDown = (e) => { if (this.props.primaryMouseButtonOnly) { if (e.pointerType === 'mouse' && e.button !== 0) { return } } this.startingPosition = eventToPosition(e) this.timerID = setTimeout(() => { this.isLongPressing = true this.props.onLongPress(e) }, this.props.longPressTime) } onPointerMove = (e) => { const mousePosition = eventToPosition(e) if (this.timerID && this.exceedDragThreshold(mousePosition)) { this.cancelLongPress() } } onPointerLeave = () => { if (this.timerID) { this.cancelLongPress() } } cancelLongPress() { this.clearTimeout() } exceedDragThreshold(point) { return distance(this.startingPosition, point) > this.props.dragThreshold } render() { return ( <div onPointerUp={this.onPointerUp} onPointerDown={this.onPointerDown} onPointerMove={this.onPointerMove} onPointerLeave={this.onPointerLeave} > {this.props.children} </div> ) } }