Completed crosshair, slider, and scroll hooks.

This commit is contained in:
Jay
2025-07-23 11:05:47 -04:00
parent d224f335e9
commit 051c6602b5
7 changed files with 794 additions and 129 deletions
+71
View File
@@ -1,3 +1,6 @@
import { useState, useRef, useEffect } from "react";
import type { RefObject } from "react";
export function handleScroll(
prevLength: number,
scrollDelta: number,
@@ -18,3 +21,71 @@ export function handleScroll(
return newLength;
}
type ScrollHandler = () => void;
export function useScroll<T extends HTMLElement>({
targetRef,
onScrollUp,
onScrollDown,
deltaYMultiplier: deltaYMultiplier = 1,
}: {
targetRef: RefObject<T | null>;
onScrollUp: ScrollHandler;
onScrollDown: ScrollHandler;
deltaYMultiplier?: number;
}) {
const [_, setScrollLength] = useState(0);
const onScrollUpRef = useRef(onScrollUp);
const onScrollDownRef = useRef(onScrollDown);
const deltaYMultiplierRef = useRef(deltaYMultiplier);
useEffect(() => {
onScrollUpRef.current = onScrollUp;
onScrollDownRef.current = onScrollDown;
deltaYMultiplierRef.current = deltaYMultiplier;
}, [onScrollUp, onScrollDown, deltaYMultiplier]);
const handleWheelEventRef = useRef((_: WheelEvent) => {});
useEffect(() => {
handleWheelEventRef.current = (event: WheelEvent) => {
event.preventDefault();
setScrollLength((prev) =>
handleScroll(
prev,
event.deltaY * deltaYMultiplierRef.current,
onScrollDownRef.current,
onScrollUpRef.current,
),
);
};
}, []);
function addScrollListener() {
const currentRef = targetRef.current;
if (currentRef) {
currentRef.addEventListener("wheel", handleWheelEventRef.current);
}
}
function removeScrollListener() {
const currentRef = targetRef.current;
if (currentRef) {
currentRef.removeEventListener("wheel", handleWheelEventRef.current);
}
}
useEffect(() => {
return () => {
removeScrollListener();
};
}, []);
return {
addScrollListener,
removeScrollListener,
};
}