UNPKG

@carbon/react

Version:

React components for the Carbon Design System

126 lines (115 loc) 3.99 kB
/** * Copyright IBM Corp. 2016, 2023 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); const usePressable = (ref, { onPress, onPressIn, onPressOut, onLongPress, delayLongPressMs = 500 } = {}) => { const savedOnPress = React.useRef(onPress); const savedOnPressIn = React.useRef(onPressIn); const savedOnPressOut = React.useRef(onPressOut); const savedOnLongPress = React.useRef(onLongPress); const [pendingLongPress, setPendingLongPress] = React.useState(false); const [longPress, setLongPress] = React.useState(false); const state = React.useRef({ longPress: false }); React.useEffect(() => { savedOnPress.current = onPress; }, [onPress]); React.useEffect(() => { savedOnPressIn.current = onPressIn; }, [onPressIn]); React.useEffect(() => { savedOnPressOut.current = onPressOut; }, [onPressOut]); React.useEffect(() => { savedOnLongPress.current = onLongPress; }, [onLongPress]); React.useEffect(() => { const element = ref.current; if (!element) return; // Fired when a pointer becomes active buttons state. const onPointerDown = event => { setPendingLongPress(true); savedOnPressIn.current?.(); event.preventDefault(); }; // Fired when a pointer is no longer active buttons state. const onPointerUp = () => { setPendingLongPress(false); setLongPress(false); savedOnPressOut.current?.(state.current); }; // A browser fires this event if it concludes the pointer // will no longer be able to generate events (for example // the related device is deactivated). const onPointerCancel = () => { setPendingLongPress(false); setLongPress(false); savedOnPressOut.current?.(state.current); state.current.longPress = false; }; // Fired when a pointer is moved out of the hit test // boundaries of an element. For pen devices, this event // is fired when the stylus leaves the hover range // detectable by the digitizer. const onPointerLeave = () => { setPendingLongPress(false); setLongPress(false); savedOnPressOut.current?.(state.current); state.current.longPress = false; }; const onClick = () => { setLongPress(false); setPendingLongPress(false); savedOnPress.current?.(state.current); state.current.longPress = false; }; // Certain devices treat long press events as context menu triggers const onContextMenu = event => { event.preventDefault(); }; element.addEventListener('pointerdown', onPointerDown); element.addEventListener('pointerup', onPointerUp); element.addEventListener('pointercancel', onPointerCancel); element.addEventListener('pointerleave', onPointerLeave); element.addEventListener('click', onClick); element.addEventListener('contextmenu', onContextMenu); return () => { element.removeEventListener('pointerdown', onPointerDown); element.removeEventListener('pointerup', onPointerUp); element.removeEventListener('pointercancel', onPointerCancel); element.removeEventListener('pointerleave', onPointerLeave); element.removeEventListener('click', onClick); element.removeEventListener('contextmenu', onContextMenu); }; }, [ref]); React.useEffect(() => { if (pendingLongPress) { const timeoutId = setTimeout(() => { setPendingLongPress(false); setLongPress(true); }, delayLongPressMs); return () => { clearTimeout(timeoutId); }; } }, [pendingLongPress, delayLongPressMs]); React.useEffect(() => { if (longPress) { state.current.longPress = true; return savedOnLongPress.current?.(); } }, [longPress]); }; exports.usePressable = usePressable;