GoScrobble/web/node_modules/@restart/hooks/esm/useThrottledEventHandler.js

86 lines
2.5 KiB
JavaScript

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import { useRef } from 'react';
import useMounted from './useMounted';
import useEventCallback from './useEventCallback';
var isSyntheticEvent = function isSyntheticEvent(event) {
return typeof event.persist === 'function';
};
/**
* Creates a event handler function throttled by `requestAnimationFrame` that
* returns the **most recent** event. Useful for noisy events that update react state.
*
* ```tsx
* function Component() {
* const [position, setPosition] = useState();
* const handleMove = useThrottledEventHandler<React.PointerEvent>(
* (event) => {
* setPosition({
* top: event.clientX,
* left: event.clientY,
* })
* }
* )
*
* return (
* <div onPointerMove={handleMove}>
* <div style={position} />
* </div>
* );
* }
* ```
*
* @param handler An event handler function
* @typeParam TEvent The event object passed to the handler function
* @returns The event handler with a `clear` method attached for clearing any in-flight handler calls
*
*/
export default function useThrottledEventHandler(handler) {
var isMounted = useMounted();
var eventHandler = useEventCallback(handler);
var nextEventInfoRef = useRef({
event: null,
handle: null
});
var clear = function clear() {
cancelAnimationFrame(nextEventInfoRef.current.handle);
nextEventInfoRef.current.handle = null;
};
var handlePointerMoveAnimation = function handlePointerMoveAnimation() {
var next = nextEventInfoRef.current;
if (next.handle && next.event) {
if (isMounted()) {
next.handle = null;
eventHandler(next.event);
}
}
next.event = null;
};
var throttledHandler = function throttledHandler(event) {
if (!isMounted()) return;
if (isSyntheticEvent(event)) {
event.persist();
} // Special handling for a React.Konva event which reuses the
// event object as it bubbles, setting target
else if ('evt' in event) {
event = _extends({}, event);
}
nextEventInfoRef.current.event = event;
if (!nextEventInfoRef.current.handle) {
nextEventInfoRef.current.handle = requestAnimationFrame(handlePointerMoveAnimation);
}
};
throttledHandler.clear = clear;
return throttledHandler;
}