Added color reducer. Performed state management refactor to prevent circular behavior.

This commit is contained in:
Jay
2025-08-06 14:26:55 -04:00
parent c27a5258d3
commit e011bd0763
21 changed files with 2592 additions and 799 deletions
+47 -17
View File
@@ -1,12 +1,13 @@
import { useCallback, useEffect, useRef, useState } from "react";
import type { Dispatch, SetStateAction } from "react";
import type { CartesianSpace } from "@/types";
import type { CartesianSpace, Range, Setter } from "@/types";
import {
extractEventCoordinates,
isLeftMouseButton,
isTouchEvent,
minmax,
positionToValue,
valueToPosition,
} from "@/util";
if (typeof TouchEvent === "undefined") {
@@ -19,37 +20,57 @@ export function useCrosshair({
dimensions,
setXPosition,
setYPosition,
xValue,
yValue,
setXValue,
setYValue,
xValueRange,
yValueRange,
}: {
origin: CartesianSpace;
dimensions: CartesianSpace;
setXPosition: Dispatch<SetStateAction<number>>;
setYPosition: Dispatch<SetStateAction<number>>;
setXPosition: Setter<number>;
setYPosition: Setter<number>;
xValue: number;
yValue: number;
setXValue: Setter<number>;
setYValue: Setter<number>;
xValueRange: Range;
yValueRange: Range;
}) {
const [isDragging, setIsDragging] = useState(false);
const crosshairRef = useRef<HTMLDivElement>(null);
const originRef = useRef(origin);
const dimensionsRef = useRef(dimensions);
const setXValueRef = useRef(setXValue);
const setYValueRef = useRef(setYValue);
const xValueRangeRef = useRef(xValueRange);
const yValueRangeRef = useRef(yValueRange);
useEffect(() => {
originRef.current = origin;
dimensionsRef.current = dimensions;
}, [origin, dimensions]);
setXValueRef.current = setXValue;
setYValueRef.current = setYValue;
xValueRangeRef.current = xValueRange;
yValueRangeRef.current = yValueRange;
}, [origin, dimensions, setXValue, setYValue, xValueRange, yValueRange]);
const calculatePositions = useCallback(
(event: MouseEvent | TouchEvent) => {
const orig = originRef.current;
const dims = dimensionsRef.current;
const calculatePositions = useCallback((event: MouseEvent | TouchEvent) => {
const orig = originRef.current;
const dims = dimensionsRef.current;
const { clientX, clientY } = extractEventCoordinates(event);
const { clientX, clientY } = extractEventCoordinates(event);
const xPos = minmax(clientX - orig.x, 0, dims.x - 1);
const yPos = minmax(clientY - orig.y, 0, dims.y - 1);
setXPosition(xPos);
setYPosition(yPos);
},
[setXPosition, setYPosition],
);
const xPos = minmax(clientX - orig.x, 0, dims.x - 1);
const yPos = minmax(clientY - orig.y, 0, dims.y - 1);
const newXValue = positionToValue(xPos, dims.x - 1, xValueRangeRef.current);
const newYValue = positionToValue(yPos, dims.y - 1, yValueRangeRef.current);
setXValueRef.current(newXValue);
setYValueRef.current(newYValue);
}, []);
const handleMove = useCallback(
(event: MouseEvent | TouchEvent) => {
@@ -101,6 +122,15 @@ export function useCrosshair({
[calculatePositions, handleMove, handleEnd],
);
useEffect(() => {
const dims = dimensionsRef.current;
const newXPos = valueToPosition(xValue, dims.x - 1, xValueRangeRef.current);
const newYPos = valueToPosition(yValue, dims.y - 1, yValueRangeRef.current);
if (newXPos === newXPos) setXPosition(newXPos);
if (newYPos === newYPos) setYPosition(newYPos);
}, [xValue, yValue, setXPosition, setYPosition]);
useEffect(() => {
const currentRef = crosshairRef.current;
if (currentRef) {