import React , { useCallback , useRef , useState , useEffect , CSSProperties , } from "react" ; import { is } from "../utils/is" ; /**
 * 可触摸元素的属性，兼容PC
 */ export interface ClickableProps extends React . HTMLProps < HTMLDivElement > { children : React . ReactNode ; bubble : boolean ; activeClassName : string ; activeStyle : React . CSSProperties ; disable : boolean ; } export function Clickable ( props ) { let { children , bubble = true , className , activeClassName , style , activeStyle , disable = false , ... attrs } = props ; if ( ! activeClassName && ! activeStyle ) { activeStyle = { opacity : 0.6 , } ; } const touchable = is ( "touchable" ) ; const [ boxClass , setBoxClass ] = useState < undefined | string > ( className ) ; const [ boxStyle , setBoxStyle ] = useState < CSSProperties | undefined > ( style ) ; const touchRef = useRef < boolean > ( false ) ; const onStart = ( event ) => { if ( ! touchRef . current ) { touchRef . current = true ; if ( ! bubble ) { event . stopPropagation ( ) ; } if ( typeof activeClassName === "string" ) { setBoxClass ( typeof boxClass === "string" ? `${ boxClass } ${ activeClassName }` : activeClassName ) ; } if ( typeof activeStyle === "object" ) { setBoxStyle ( typeof boxStyle === "object" ? { ... boxStyle , ... activeStyle } : activeStyle ) ; } } } ; const onEnd = useCallback < ( ) => void > ( ( ) => { if ( touchRef . current ) { touchRef . current = false ; setBoxClass ( className ) ; setBoxStyle ( style ) ; } } , [ className , style ] ) ; useEffect ( ( ) => { if ( ! disable && ! touchable ) { const doc = document . documentElement ; doc . addEventListener ( "mouseup" , onEnd ) ; return ( ) => { doc . removeEventListener ( "mouseup" , onEnd ) ; } ; } } , [ disable , touchable , onEnd ] ) ; const fullAttrs = { ... attrs , className : boxClass , style : boxStyle , } ; if ( ! disable ) { if ( touchable ) { fullAttrs . onTouchStart = onStart ; fullAttrs . onTouchEnd = onEnd ; fullAttrs . onTouchCancel = onEnd ; } else { fullAttrs . onMouseDown = onStart ; } } return < div { ... fullAttrs } > { children } < /div>; }