Last active
July 3, 2023 13:26
-
-
Save Zeko369/66cf4ea5915fd17f48ee9c7b2d3e60b1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use client"; | |
import { useCallback, useRef } from "react"; | |
import { css } from "../../../styled-system/css"; | |
function useLongPress( | |
callback: (e: React.MouseEvent | React.TouchEvent) => void, | |
shortClick: () => void, | |
duration: number = 500 | |
) { | |
// This will be a reference to our `setTimeout` counter, so we can clear it | |
// if the user moves or releases their pointer. | |
const timeout = useRef(null); | |
// Create an event handler for mouse down and touch start events. We wrap the | |
// handler in the `useCallback` hook and pass `callback` and `duration` as | |
// dependencies so it only creates a new callback if either of these changes. | |
const onPressStart = useCallback( | |
(event: React.MouseEvent | React.TouchEvent) => { | |
// Prevent the browser's default response to this event. On mobile browsers | |
// long presses are used . This will also block touch scrolling - a more | |
// robust implementation will take this into account, but this is fine | |
// for prototyping. | |
event.preventDefault(); | |
// Start a timeout that, after the provided `duration`, will fire the | |
// supplied callbacl. | |
// @ts-ignore | |
timeout.current = setTimeout(() => { | |
callback(event); | |
timeout.current = null; | |
}, duration); | |
}, | |
[callback, duration] | |
); | |
// This function, when called, will cancel the timeout and thus end the | |
// gesture. We provide an empty dependency array as we never want this | |
// function to change for the lifecycle of the component. | |
const cancelTimeout = useCallback((runcallback: boolean) => { | |
// @ts-ignore | |
clearTimeout(timeout.current); | |
runcallback && timeout.current && shortClick(); | |
}, []); | |
return { | |
// Initiate the gesture on mouse down or touch start | |
onMouseDown: onPressStart, | |
onTouchStart: onPressStart, | |
// Cancel the gesture if the pointer is moved. This is quite an aggressive | |
// approach so you might want to make an alternative function here that | |
// detects how far the pointer has moved from its origin using `e.pageX` | |
// for `MouseEvent`s or `e.touches[0].pageX` for `TouchEvent`s. | |
onMouseMove: () => cancelTimeout(false), | |
onTouchMove: () => cancelTimeout(false), | |
// Cancel the timeout when the pointer session is ended. | |
onMouseUp: () => cancelTimeout(true), | |
onTouchEnd: () => cancelTimeout(true), | |
}; | |
} | |
export default function Page() { | |
const handler = useLongPress( | |
(e) => { | |
console.log("Long press detected", e); | |
}, | |
() => { | |
console.log("Short click"); | |
} | |
); | |
return ( | |
<button | |
{...handler} | |
className={css({ | |
padding: 3, | |
backgroundColor: "#a3a3a3", | |
borderRadius: 4, | |
})} | |
> | |
Long press meeeee daddy | |
</button> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment