diff --git a/packages/perseus/src/widgets/interactive-graphs/graphs/point.tsx b/packages/perseus/src/widgets/interactive-graphs/graphs/point.tsx index dcb5fa197c..b1f263656f 100644 --- a/packages/perseus/src/widgets/interactive-graphs/graphs/point.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/graphs/point.tsx @@ -6,13 +6,10 @@ import useGraphConfig from "../reducer/use-graph-config"; import {MovablePoint} from "./components/movable-point"; import {srFormatNumber} from "./screenreader-text"; -import { - useTransformDimensionsToPixels, - useTransformVectorsToPixels, - pixelsToVectors, -} from "./use-transform"; +import {useTransformVectorsToPixels, pixelsToVectors} from "./use-transform"; import type {PerseusStrings} from "../../../strings"; +import type {GraphConfig} from "../reducer/use-graph-config"; import type { PointGraphState, MafsGraphProps, @@ -30,23 +27,54 @@ export function renderPointGraph( }; } -type PointGraphProps = MafsGraphProps; +type Props = MafsGraphProps; +type StatefulProps = Props & { + graphConfig: GraphConfig; + pointsRef: React.MutableRefObject<(SVGElement | null)[]>; + top: number; + left: number; +}; + +function PointGraph(props: Props) { + const {numPoints} = props.graphState; + const graphConfig = useGraphConfig(); + const pointsRef = React.useRef>([]); + + // Dimensions to build the graph overlay for Unlimited Point. + const { + range: [x, y], + } = graphConfig; + const [[left, top]] = useTransformVectorsToPixels([x[0], y[1]]); + + // This useEffect is to handle the focus snapping for Unlimited Point. + React.useEffect(() => { + const focusedIndex = props.graphState.focusedPointIndex; + if (focusedIndex != null) { + pointsRef.current[focusedIndex]?.focus(); + } + }, [props.graphState.focusedPointIndex, pointsRef]); + + const statefulProps = { + ...props, + graphConfig, + pointsRef, + top, + left, + }; -function PointGraph(props: PointGraphProps) { - const numPoints = props.graphState.numPoints; if (numPoints === "unlimited") { - return UnlimitedPointGraph(props); + return UnlimitedPointGraph(statefulProps); } - return LimitedPointGraph(props); + return LimitedPointGraph(statefulProps); } -function LimitedPointGraph(props: PointGraphProps) { - const {dispatch} = props; +function LimitedPointGraph(statefulProps: StatefulProps) { + const {dispatch} = statefulProps; return ( <> - {props.graphState.coords.map((point, i) => ( + {statefulProps.graphState.coords.map((point, i) => ( >([]); +function UnlimitedPointGraph(statefulProps: StatefulProps) { + const {dispatch, graphConfig, pointsRef, top, left} = statefulProps; + const {coords} = statefulProps.graphState; - React.useEffect(() => { - const focusedIndex = props.graphState.focusedPointIndex; - if (focusedIndex != null) { - itemsRef.current[focusedIndex]?.focus(); - } - }, [props.graphState.focusedPointIndex, itemsRef]); + const {graphDimensionsInPixels} = graphConfig; + + const widthPx = graphDimensionsInPixels[0]; + const heightPx = graphDimensionsInPixels[1]; return ( <> @@ -110,7 +125,7 @@ function UnlimitedPointGraph(props: PointGraphProps) { dispatch(actions.pointGraph.addPoint(graphCoordinates[0])); }} /> - {props.graphState.coords.map((point, i) => ( + {coords.map((point, i) => ( { - itemsRef.current[i] = ref; + pointsRef.current[i] = ref; }} onFocus={() => { dispatch(actions.pointGraph.focusPoint(i));