Use useCallback.
This commit is contained in:
+78
-104
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState, useRef } from "react";
|
import { useEffect, useState, useRef, useCallback } from "react";
|
||||||
import type { Dispatch, SetStateAction } from "react";
|
import type { Dispatch, SetStateAction } from "react";
|
||||||
import type { CartesianSpace } from "../types";
|
import type { CartesianSpace } from "../types";
|
||||||
import { minmax } from "../util";
|
import { minmax } from "../util";
|
||||||
@@ -12,6 +12,22 @@ function isTouchEvent(event: Event): event is TouchEvent {
|
|||||||
return "touches" in event;
|
return "touches" in event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractEventCoordinates(event: MouseEvent | TouchEvent): {
|
||||||
|
clientX: number;
|
||||||
|
clientY: number;
|
||||||
|
} {
|
||||||
|
if (isTouchEvent(event)) {
|
||||||
|
return {
|
||||||
|
clientX: event.touches[0].clientX,
|
||||||
|
clientY: event.touches[0].clientY,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
clientX: event.clientX,
|
||||||
|
clientY: event.clientY,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function useCrosshair({
|
export function useCrosshair({
|
||||||
origin,
|
origin,
|
||||||
dimensions,
|
dimensions,
|
||||||
@@ -26,19 +42,6 @@ export function useCrosshair({
|
|||||||
const [isDragging, setIsDragging] = useState(false);
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
const crosshairRef = useRef<HTMLDivElement>(null);
|
const crosshairRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// Construct event handler refs
|
|
||||||
// Prevents unnecessary function recreation
|
|
||||||
const calculatePositionsRef = useRef((_: MouseEvent | TouchEvent) => {});
|
|
||||||
const startCrosshairInteractionRef = useRef(
|
|
||||||
(_: MouseEvent | TouchEvent) => {},
|
|
||||||
);
|
|
||||||
const processCrosshairInteractionRef = useRef(
|
|
||||||
(_: MouseEvent | TouchEvent) => {},
|
|
||||||
);
|
|
||||||
const endCrosshairInteractionRef = useRef((_: MouseEvent | TouchEvent) => {});
|
|
||||||
|
|
||||||
// Store dependencies as refs
|
|
||||||
// Always use latest values
|
|
||||||
const originRef = useRef(origin);
|
const originRef = useRef(origin);
|
||||||
const dimensionsRef = useRef(dimensions);
|
const dimensionsRef = useRef(dimensions);
|
||||||
|
|
||||||
@@ -47,121 +50,92 @@ export function useCrosshair({
|
|||||||
dimensionsRef.current = dimensions;
|
dimensionsRef.current = dimensions;
|
||||||
}, [origin, dimensions]);
|
}, [origin, dimensions]);
|
||||||
|
|
||||||
// Update handler functions when dependencies change via reference
|
const calculatePositions = useCallback(
|
||||||
|
(event: MouseEvent | TouchEvent) => {
|
||||||
useEffect(() => {
|
|
||||||
calculatePositionsRef.current = (event: MouseEvent | TouchEvent) => {
|
|
||||||
const orig = originRef.current;
|
const orig = originRef.current;
|
||||||
const dims = dimensionsRef.current;
|
const dims = dimensionsRef.current;
|
||||||
|
|
||||||
const clientX = isTouchEvent(event)
|
const { clientX, clientY } = extractEventCoordinates(event);
|
||||||
? event.touches[0].clientX
|
|
||||||
: event.clientX;
|
|
||||||
const clientY = isTouchEvent(event)
|
|
||||||
? event.touches[0].clientY
|
|
||||||
: event.clientY;
|
|
||||||
|
|
||||||
const xPos = minmax(clientX - orig.x, 0, dims.x - 1);
|
const xPos = minmax(clientX - orig.x, 0, dims.x - 1);
|
||||||
const yPos = minmax(clientY - orig.y, 0, dims.y - 1);
|
const yPos = minmax(clientY - orig.y, 0, dims.y - 1);
|
||||||
setXPosition(xPos);
|
setXPosition(xPos);
|
||||||
setYPosition(yPos);
|
setYPosition(yPos);
|
||||||
};
|
},
|
||||||
|
[setXPosition, setYPosition],
|
||||||
|
);
|
||||||
|
|
||||||
startCrosshairInteractionRef.current = (event: MouseEvent | TouchEvent) => {
|
const processCrosshairInteraction = useCallback(
|
||||||
|
(event: MouseEvent | TouchEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
calculatePositionsRef.current(event);
|
calculatePositions(event);
|
||||||
|
},
|
||||||
|
[calculatePositions],
|
||||||
|
);
|
||||||
|
|
||||||
|
const endCrosshairInteraction = useCallback(
|
||||||
|
(event: MouseEvent | TouchEvent) => {
|
||||||
|
setIsDragging(false);
|
||||||
|
if (!isTouchEvent(event)) {
|
||||||
|
document.removeEventListener("mousemove", processCrosshairInteraction);
|
||||||
|
document.removeEventListener("mouseup", endCrosshairInteraction);
|
||||||
|
} else {
|
||||||
|
document.removeEventListener("touchmove", processCrosshairInteraction);
|
||||||
|
document.removeEventListener("touchend", endCrosshairInteraction);
|
||||||
|
document.removeEventListener("touchcancel", endCrosshairInteraction);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[processCrosshairInteraction],
|
||||||
|
);
|
||||||
|
|
||||||
|
const startCrosshairInteraction = useCallback(
|
||||||
|
(event: MouseEvent | TouchEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
calculatePositions(event);
|
||||||
setIsDragging(true);
|
setIsDragging(true);
|
||||||
|
|
||||||
if (!isTouchEvent(event)) {
|
if (!isTouchEvent(event)) {
|
||||||
document.addEventListener(
|
document.addEventListener("mousemove", processCrosshairInteraction);
|
||||||
"mousemove",
|
document.addEventListener("mouseup", endCrosshairInteraction, {
|
||||||
processCrosshairInteractionRef.current,
|
passive: true,
|
||||||
);
|
});
|
||||||
document.addEventListener(
|
|
||||||
"mouseup",
|
|
||||||
endCrosshairInteractionRef.current,
|
|
||||||
{ passive: true },
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener(
|
document.addEventListener("touchmove", processCrosshairInteraction);
|
||||||
"touchmove",
|
document.addEventListener("touchend", endCrosshairInteraction, {
|
||||||
processCrosshairInteractionRef.current,
|
passive: true,
|
||||||
);
|
});
|
||||||
document.addEventListener(
|
document.addEventListener("touchcancel", endCrosshairInteraction, {
|
||||||
"touchend",
|
passive: true,
|
||||||
endCrosshairInteractionRef.current,
|
});
|
||||||
{ passive: true },
|
|
||||||
);
|
|
||||||
document.addEventListener(
|
|
||||||
"touchcancel",
|
|
||||||
endCrosshairInteractionRef.current,
|
|
||||||
{ passive: true },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[calculatePositions, processCrosshairInteraction, endCrosshairInteraction],
|
||||||
|
);
|
||||||
|
|
||||||
processCrosshairInteractionRef.current = (
|
|
||||||
event: MouseEvent | TouchEvent,
|
|
||||||
) => {
|
|
||||||
event.preventDefault();
|
|
||||||
calculatePositionsRef.current(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
endCrosshairInteractionRef.current = (event: MouseEvent | TouchEvent) => {
|
|
||||||
setIsDragging(false);
|
|
||||||
if (!isTouchEvent(event)) {
|
|
||||||
document.removeEventListener(
|
|
||||||
"mousemove",
|
|
||||||
processCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
document.removeEventListener(
|
|
||||||
"mouseup",
|
|
||||||
endCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
document.removeEventListener(
|
|
||||||
"touchmove",
|
|
||||||
processCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
document.removeEventListener(
|
|
||||||
"touchend",
|
|
||||||
endCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
document.removeEventListener(
|
|
||||||
"touchcancel",
|
|
||||||
endCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Set up entry listeners
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentRef = crosshairRef.current;
|
const currentRef = crosshairRef.current;
|
||||||
if (currentRef) {
|
if (currentRef) {
|
||||||
currentRef.addEventListener(
|
currentRef.addEventListener("mousedown", startCrosshairInteraction);
|
||||||
"mousedown",
|
currentRef.addEventListener("touchstart", startCrosshairInteraction);
|
||||||
startCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
currentRef.addEventListener(
|
|
||||||
"touchstart",
|
|
||||||
startCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (currentRef) {
|
if (currentRef) {
|
||||||
currentRef.removeEventListener(
|
currentRef.removeEventListener("mousedown", startCrosshairInteraction);
|
||||||
"mousedown",
|
currentRef.removeEventListener("touchstart", startCrosshairInteraction);
|
||||||
startCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
currentRef.removeEventListener(
|
|
||||||
"touchstart",
|
|
||||||
startCrosshairInteractionRef.current,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.removeEventListener("mousemove", processCrosshairInteraction);
|
||||||
|
document.removeEventListener("mouseup", endCrosshairInteraction);
|
||||||
|
document.removeEventListener("touchmove", processCrosshairInteraction);
|
||||||
|
document.removeEventListener("touchend", endCrosshairInteraction);
|
||||||
|
document.removeEventListener("touchcancel", endCrosshairInteraction);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [
|
||||||
|
startCrosshairInteraction,
|
||||||
|
processCrosshairInteraction,
|
||||||
|
endCrosshairInteraction,
|
||||||
|
]);
|
||||||
|
|
||||||
return { crosshairRef, isDragging };
|
return { crosshairRef, isDragging };
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-14
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useRef, useEffect } from "react";
|
import { useState, useRef, useEffect, useCallback } from "react";
|
||||||
import type { RefObject } from "react";
|
import type { RefObject } from "react";
|
||||||
|
|
||||||
export function handleScroll(
|
export function handleScroll(
|
||||||
@@ -6,7 +6,7 @@ export function handleScroll(
|
|||||||
scrollDelta: number,
|
scrollDelta: number,
|
||||||
handleIncrement: () => void,
|
handleIncrement: () => void,
|
||||||
handleDecrement: () => void,
|
handleDecrement: () => void,
|
||||||
) {
|
): number {
|
||||||
const newLength = prevLength + scrollDelta;
|
const newLength = prevLength + scrollDelta;
|
||||||
|
|
||||||
if (Math.abs(newLength) > 50) {
|
if (Math.abs(newLength) > 50) {
|
||||||
@@ -47,10 +47,7 @@ export function useScroll<T extends HTMLElement>({
|
|||||||
deltaYMultiplierRef.current = deltaYMultiplier;
|
deltaYMultiplierRef.current = deltaYMultiplier;
|
||||||
}, [onScrollUp, onScrollDown, deltaYMultiplier]);
|
}, [onScrollUp, onScrollDown, deltaYMultiplier]);
|
||||||
|
|
||||||
const handleWheelEventRef = useRef((_: WheelEvent) => {});
|
const handleWheelEvent = useCallback((event: WheelEvent) => {
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
handleWheelEventRef.current = (event: WheelEvent) => {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
setScrollLength((prev) =>
|
setScrollLength((prev) =>
|
||||||
@@ -61,28 +58,27 @@ export function useScroll<T extends HTMLElement>({
|
|||||||
onScrollUpRef.current,
|
onScrollUpRef.current,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
function addScrollListener() {
|
const addScrollListener = useCallback(() => {
|
||||||
const currentRef = targetRef.current;
|
const currentRef = targetRef.current;
|
||||||
if (currentRef) {
|
if (currentRef) {
|
||||||
currentRef.addEventListener("wheel", handleWheelEventRef.current);
|
currentRef.addEventListener("wheel", handleWheelEvent);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}, [handleWheelEvent, targetRef]);
|
||||||
|
|
||||||
function removeScrollListener() {
|
const removeScrollListener = useCallback(() => {
|
||||||
const currentRef = targetRef.current;
|
const currentRef = targetRef.current;
|
||||||
if (currentRef) {
|
if (currentRef) {
|
||||||
currentRef.removeEventListener("wheel", handleWheelEventRef.current);
|
currentRef.removeEventListener("wheel", handleWheelEvent);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}, [handleWheelEvent, targetRef]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
removeScrollListener();
|
removeScrollListener();
|
||||||
};
|
};
|
||||||
}, []);
|
}, [removeScrollListener]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addScrollListener,
|
addScrollListener,
|
||||||
|
|||||||
+96
-115
@@ -1,5 +1,5 @@
|
|||||||
import { useState, useRef, useEffect } from "react";
|
import { useState, useRef, useEffect, useCallback } from "react";
|
||||||
import type { Dispatch, SetStateAction, RefObject } from "react";
|
import type { Dispatch, SetStateAction } from "react";
|
||||||
import { minmax } from "../util";
|
import { minmax } from "../util";
|
||||||
import type { CartesianSpace } from "../types";
|
import type { CartesianSpace } from "../types";
|
||||||
import { useScroll } from "./scroll";
|
import { useScroll } from "./scroll";
|
||||||
@@ -26,6 +26,20 @@ function chooseValueByDirection(
|
|||||||
return direction === Direction.HORIZONTAL ? xValue : yValue;
|
return direction === Direction.HORIZONTAL ? xValue : yValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractEventCoordinate(
|
||||||
|
event: MouseEvent | TouchEvent,
|
||||||
|
direction: Direction,
|
||||||
|
): number {
|
||||||
|
if (isTouchEvent(event)) {
|
||||||
|
return chooseValueByDirection(
|
||||||
|
direction,
|
||||||
|
event.touches[0].clientX,
|
||||||
|
event.touches[0].clientY,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return chooseValueByDirection(direction, event.clientX, event.clientY);
|
||||||
|
}
|
||||||
|
|
||||||
export function useSlider({
|
export function useSlider({
|
||||||
direction,
|
direction,
|
||||||
origin,
|
origin,
|
||||||
@@ -36,21 +50,10 @@ export function useSlider({
|
|||||||
origin: CartesianSpace;
|
origin: CartesianSpace;
|
||||||
dimensions: CartesianSpace;
|
dimensions: CartesianSpace;
|
||||||
setPosition: Dispatch<SetStateAction<number>>;
|
setPosition: Dispatch<SetStateAction<number>>;
|
||||||
}): { sliderRef: RefObject<HTMLDivElement | null>; isDragging: boolean } {
|
}) {
|
||||||
const [isDragging, setIsDragging] = useState(false);
|
const [isDragging, setIsDragging] = useState(false);
|
||||||
const sliderRef = useRef<HTMLDivElement>(null);
|
const sliderRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// Construct event handler refs
|
|
||||||
// Prevents unnecessary function recreation
|
|
||||||
const calculatePositionRef = useRef((_: MouseEvent | TouchEvent) => {});
|
|
||||||
const startSliderInteractionRef = useRef((_: MouseEvent | TouchEvent) => {});
|
|
||||||
const processSliderInteractionRef = useRef(
|
|
||||||
(_: MouseEvent | TouchEvent) => {},
|
|
||||||
);
|
|
||||||
const endSliderInteractionRef = useRef((_: MouseEvent | TouchEvent) => {});
|
|
||||||
|
|
||||||
// Store dependencies as refs
|
|
||||||
// Always use latest values
|
|
||||||
const directionRef = useRef(direction);
|
const directionRef = useRef(direction);
|
||||||
const originRef = useRef(origin);
|
const originRef = useRef(origin);
|
||||||
const dimensionsRef = useRef(dimensions);
|
const dimensionsRef = useRef(dimensions);
|
||||||
@@ -61,147 +64,125 @@ export function useSlider({
|
|||||||
dimensionsRef.current = dimensions;
|
dimensionsRef.current = dimensions;
|
||||||
}, [direction, origin, dimensions]);
|
}, [direction, origin, dimensions]);
|
||||||
|
|
||||||
// Setup scroll handlers
|
// Setup drag handlers
|
||||||
const handleScrollUp = () => {
|
const calculatePosition = useCallback(
|
||||||
const dir = directionRef.current;
|
(event: MouseEvent | TouchEvent) => {
|
||||||
const dims = dimensionsRef.current;
|
|
||||||
|
|
||||||
setPosition((prev: number) =>
|
|
||||||
minmax(prev - 1, 0, chooseValueByDirection(dir, dims.x, dims.y)),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleScrollDown = () => {
|
|
||||||
const dir = directionRef.current;
|
|
||||||
const dims = dimensionsRef.current;
|
|
||||||
|
|
||||||
setPosition((prev: number) =>
|
|
||||||
minmax(prev + 1, 0, chooseValueByDirection(dir, dims.x, dims.y)),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize scroll handling
|
|
||||||
const { addScrollListener, removeScrollListener } = useScroll({
|
|
||||||
targetRef: sliderRef,
|
|
||||||
onScrollUp: handleScrollUp,
|
|
||||||
onScrollDown: handleScrollDown,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update handler functions when dependencies change via reference
|
|
||||||
useEffect(() => {
|
|
||||||
calculatePositionRef.current = (event: MouseEvent | TouchEvent) => {
|
|
||||||
const dir = directionRef.current;
|
const dir = directionRef.current;
|
||||||
const orig = originRef.current;
|
const orig = originRef.current;
|
||||||
const dims = dimensionsRef.current;
|
const dims = dimensionsRef.current;
|
||||||
|
|
||||||
const clientCoord = isTouchEvent(event)
|
const clientCoord = extractEventCoordinate(event, dir);
|
||||||
? chooseValueByDirection(
|
|
||||||
dir,
|
|
||||||
event.touches[0].clientX,
|
|
||||||
event.touches[0].clientY,
|
|
||||||
)
|
|
||||||
: chooseValueByDirection(dir, event.clientX, event.clientY);
|
|
||||||
const positionValue = minmax(
|
const positionValue = minmax(
|
||||||
clientCoord - chooseValueByDirection(dir, orig.x, orig.y),
|
clientCoord - chooseValueByDirection(dir, orig.x, orig.y),
|
||||||
0,
|
0,
|
||||||
chooseValueByDirection(dir, dims.x, dims.y),
|
chooseValueByDirection(dir, dims.x, dims.y),
|
||||||
);
|
);
|
||||||
setPosition(positionValue);
|
setPosition(positionValue);
|
||||||
};
|
},
|
||||||
|
[setPosition],
|
||||||
|
);
|
||||||
|
|
||||||
startSliderInteractionRef.current = (event: MouseEvent | TouchEvent) => {
|
const processSliderInteraction = useCallback(
|
||||||
|
(event: MouseEvent | TouchEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
calculatePositionRef.current(event);
|
calculatePosition(event);
|
||||||
|
},
|
||||||
|
[calculatePosition],
|
||||||
|
);
|
||||||
|
|
||||||
|
const endSliderInteraction = useCallback(
|
||||||
|
(event: MouseEvent | TouchEvent) => {
|
||||||
|
setIsDragging(false);
|
||||||
|
if (!isTouchEvent(event)) {
|
||||||
|
document.removeEventListener("mousemove", processSliderInteraction);
|
||||||
|
document.removeEventListener("mouseup", endSliderInteraction);
|
||||||
|
} else {
|
||||||
|
document.removeEventListener("touchmove", processSliderInteraction);
|
||||||
|
document.removeEventListener("touchend", endSliderInteraction);
|
||||||
|
document.removeEventListener("touchcancel", endSliderInteraction);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[processSliderInteraction],
|
||||||
|
);
|
||||||
|
|
||||||
|
const startSliderInteraction = useCallback(
|
||||||
|
(event: MouseEvent | TouchEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
calculatePosition(event);
|
||||||
setIsDragging(true);
|
setIsDragging(true);
|
||||||
|
|
||||||
if (!isTouchEvent(event)) {
|
if (!isTouchEvent(event)) {
|
||||||
document.addEventListener(
|
document.addEventListener("mousemove", processSliderInteraction);
|
||||||
"mousemove",
|
document.addEventListener("mouseup", endSliderInteraction, {
|
||||||
processSliderInteractionRef.current,
|
|
||||||
);
|
|
||||||
document.addEventListener("mouseup", endSliderInteractionRef.current, {
|
|
||||||
passive: true,
|
passive: true,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener(
|
document.addEventListener("touchmove", processSliderInteraction);
|
||||||
"touchmove",
|
document.addEventListener("touchend", endSliderInteraction, {
|
||||||
processSliderInteractionRef.current,
|
|
||||||
);
|
|
||||||
document.addEventListener("touchend", endSliderInteractionRef.current, {
|
|
||||||
passive: true,
|
passive: true,
|
||||||
});
|
});
|
||||||
document.addEventListener(
|
document.addEventListener("touchcancel", endSliderInteraction, {
|
||||||
"touchcancel",
|
|
||||||
endSliderInteractionRef.current,
|
|
||||||
{
|
|
||||||
passive: true,
|
passive: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
[calculatePosition, processSliderInteraction, endSliderInteraction],
|
||||||
);
|
);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
processSliderInteractionRef.current = (event: MouseEvent | TouchEvent) => {
|
// Setup scroll handlers
|
||||||
event.preventDefault();
|
const handleScrollUp = useCallback(() => {
|
||||||
calculatePositionRef.current(event);
|
const dir = directionRef.current;
|
||||||
};
|
const dims = dimensionsRef.current;
|
||||||
|
|
||||||
endSliderInteractionRef.current = (event: MouseEvent | TouchEvent) => {
|
setPosition((prev: number) =>
|
||||||
setIsDragging(false);
|
minmax(prev - 1, 0, chooseValueByDirection(dir, dims.x, dims.y)),
|
||||||
if (!isTouchEvent(event)) {
|
|
||||||
document.removeEventListener(
|
|
||||||
"mousemove",
|
|
||||||
processSliderInteractionRef.current,
|
|
||||||
);
|
);
|
||||||
document.removeEventListener(
|
}, [setPosition]);
|
||||||
"mouseup",
|
|
||||||
endSliderInteractionRef.current,
|
const handleScrollDown = useCallback(() => {
|
||||||
|
const dir = directionRef.current;
|
||||||
|
const dims = dimensionsRef.current;
|
||||||
|
|
||||||
|
setPosition((prev: number) =>
|
||||||
|
minmax(prev + 1, 0, chooseValueByDirection(dir, dims.x, dims.y)),
|
||||||
);
|
);
|
||||||
} else {
|
}, [setPosition]);
|
||||||
document.removeEventListener(
|
|
||||||
"touchmove",
|
const { addScrollListener, removeScrollListener } = useScroll({
|
||||||
processSliderInteractionRef.current,
|
targetRef: sliderRef,
|
||||||
);
|
onScrollUp: handleScrollUp,
|
||||||
document.removeEventListener(
|
onScrollDown: handleScrollDown,
|
||||||
"touchend",
|
});
|
||||||
endSliderInteractionRef.current,
|
|
||||||
);
|
|
||||||
document.removeEventListener(
|
|
||||||
"touchcancel",
|
|
||||||
endSliderInteractionRef.current,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Set up entry listeners
|
// Set up entry listeners
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentRef = sliderRef.current;
|
const currentRef = sliderRef.current;
|
||||||
if (currentRef) {
|
if (currentRef) {
|
||||||
addScrollListener();
|
addScrollListener();
|
||||||
currentRef.addEventListener(
|
currentRef.addEventListener("mousedown", startSliderInteraction);
|
||||||
"mousedown",
|
currentRef.addEventListener("touchstart", startSliderInteraction);
|
||||||
startSliderInteractionRef.current,
|
|
||||||
);
|
|
||||||
currentRef.addEventListener(
|
|
||||||
"touchstart",
|
|
||||||
startSliderInteractionRef.current,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (currentRef) {
|
if (currentRef) {
|
||||||
removeScrollListener();
|
removeScrollListener();
|
||||||
currentRef.removeEventListener(
|
currentRef.removeEventListener("mousedown", startSliderInteraction);
|
||||||
"mousedown",
|
currentRef.removeEventListener("touchstart", startSliderInteraction);
|
||||||
startSliderInteractionRef.current,
|
|
||||||
);
|
|
||||||
currentRef.removeEventListener(
|
|
||||||
"touchstart",
|
|
||||||
startSliderInteractionRef.current,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.removeEventListener("mousemove", processSliderInteraction);
|
||||||
|
document.removeEventListener("mouseup", endSliderInteraction);
|
||||||
|
document.removeEventListener("touchmove", processSliderInteraction);
|
||||||
|
document.removeEventListener("touchend", endSliderInteraction);
|
||||||
|
document.removeEventListener("touchcancel", endSliderInteraction);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [
|
||||||
|
addScrollListener,
|
||||||
|
removeScrollListener,
|
||||||
|
startSliderInteraction,
|
||||||
|
processSliderInteraction,
|
||||||
|
endSliderInteraction,
|
||||||
|
]);
|
||||||
|
|
||||||
return { sliderRef, isDragging };
|
return { sliderRef, isDragging };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user