/**
 * ✔ hoverStyle: Convert hoverClass to hoverStyle.
 * ✔ hoverStartTime
 * ✔ hoverStayTime
 * ✘ hoverStopPropagation: Fixed value TRUE
 * ✔ onClick(tap)
 * ✔ onLongPress(longpress)
 * ✔ onTouchStart
 * ✘ onTouchMove
 * ✘ onTouchCancel
 * ✔ onTouchEnd
 */ import * as React from 'react' ; import { PanResponder , GestureResponderEvent , } from 'react-native' ; import { omit } from '../../utils' ; import { ClickableProps } from './PropsType' ; export default function < P extends Record < string , any > > ( WrappedComponent ) { return class _Clickable extends React . Component < P & ClickableProps > { static defaultProps = { hoverStartTime : 20 , hoverStayTime : 70 } ; state : any = { isHover : false } ; startTimestamp = 0 ; startTimer : any ; stayTimer : any ; panResponder : any = PanResponder . create ( { onStartShouldSetPanResponder : ( ) => { const { hoverStyle , onClick , onLongPress , onTouchStart , onTouchEnd } = this . props ; return ! ! ( hoverStyle || onClick || onLongPress || onTouchStart || onTouchEnd ) ; } , onShouldBlockNativeResponder : ( ) => false , onPanResponderGrant : ( evt ) => { const { onTouchStart } = this . props ; onTouchStart && onTouchStart ( this . getWxAppEvent ( evt ) ) ; this . startTimestamp = evt . nativeEvent . timestamp ; this . setStartTimer ( ) ; } , onPanResponderTerminationRequest : ( ) => true , onPanResponderRelease : ( evt , gestureState ) => { const { onClick , onLongPress , onTouchEnd } = this . props ; onTouchEnd && onTouchEnd ( this . getWxAppEvent ( evt ) ) ; const endTimestamp = evt . nativeEvent . timestamp ; const gapTime = endTimestamp - this . startTimestamp ; const hasMove = Math . abs ( gestureState . dx ) >= 1 || Math . abs ( gestureState . dy ) >= 1 ; if ( ! hasMove ) { if ( gapTime <= 350 ) { onClick && onClick ( this . getWxAppEvent ( evt ) ) ; } else { onLongPress && onLongPress ( this . getWxAppEvent ( evt ) ) ; } } this . setStayTimer ( ) ; } , onPanResponderTerminate : ( ) => { this . setStayTimer ( ) ; } , } ) ; setStartTimer = ( ) => { const { hoverStyle , hoverStartTime } = this . props ; if ( hoverStyle ) { this . startTimer && clearTimeout ( this . startTimer ) ; this . startTimer = setTimeout ( ( ) => { this . setState ( { isHover : true } ) ; } , hoverStartTime ) ; } } ; setStayTimer = ( ) => { const { hoverStyle , hoverStayTime } = this . props ; if ( hoverStyle ) { this . stayTimer && clearTimeout ( this . stayTimer ) ; this . stayTimer = setTimeout ( ( ) => { this . state . isHover && this . setState ( { isHover : false } ) ; } , hoverStayTime ) ; } } ; getWxAppEvent = ( event ) => { const nativeEvent = event . nativeEvent ; const { timestamp , target , pageX , pageY , touches = [ ] , changedTouches = [ ] } = nativeEvent ; return { type : 'tap' , timeStamp : timestamp , target : { id : target , dataset : { } } , currentTarget : { id : target , dataset : { } } , detail : { x : pageX , y : pageY } , touches : touches . map ( ( item ) => { return { identifier : item . identifier , pageX : item . pageX , pageY : item . pageY , clientX : item . locationX , clientY : item . locationY } ; } ) , changedTouches : changedTouches . map ( ( item ) => { return { identifier : item . identifier , pageX : item . pageX , pageY : item . pageY , clientX : item . locationX , clientY : item . locationY } ; } ) } ; } ; componentWillUnmount ( ) { this . startTimer && clearTimeout ( this . startTimer ) ; this . stayTimer && clearTimeout ( this . stayTimer ) ; } render ( ) { const { style , hoverStyle , onClick , onLongPress , onTouchStart , onTouchEnd , } = this . props ; const { isHover } = this . state ; if ( ! hoverStyle && ! onClick && ! onLongPress && ! onTouchStart && ! onTouchEnd ) { return ( < WrappedComponent { ... this . props } / > ) ; } return ( < WrappedComponent { ... omit ( this . props , [ 'style' , 'hoverStyle' , 'hoverStartTime' , 'hoverStayTime' , 'onClick' , 'onLongPress' , 'onTouchStart' , 'onTouchEnd' ] ) } { ... this . panResponder . panHandlers } style = { [ { backgroundColor : 'transparent' } , style , isHover && hoverStyle ] } / > ) ; } } ; }