UNPKG

recharts

Version:
53 lines (51 loc) 2.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useAnimatedLineLength = useAnimatedLineLength; var _react = require("react"); var _round = require("../util/round"); /** * Tracks the animated visible length of a Line's SVG path across data changes. * * Invariants: * 1. The visible length only grows (monotonically non-decreasing with animationElapsedTime). * 2. The visible length changes continuously — no jumps when data changes mid-animation. * This is achieved by tracking the maximum animated length in pixels and using it * as the starting point for the next animation. * 3. Once the line reaches 100% visibility, it never becomes partially visible again. * In that case the hook returns `null`, meaning no animation stroke-dasharray is needed. * * @param points The current set of points for the line. When this reference changes, * the hook detects a data change and starts a new animation from the current visible length. * @returns A stable callback `(animationElapsedTime, totalLength) => number | null` where: * - `animationElapsedTime` is the animation progress (0 to 1) * - `totalLength` is the current total length of the SVG path in pixels * - returns the visible length in pixels, or `null` if the line is fully visible */ function useAnimatedLineLength(points) { var startingLengthRef = (0, _react.useRef)(0); var maxAnimatedLengthRef = (0, _react.useRef)(0); var reachedFullRef = (0, _react.useRef)(false); var prevPointsRef = (0, _react.useRef)(points); if (prevPointsRef.current !== points) { startingLengthRef.current = maxAnimatedLengthRef.current; prevPointsRef.current = points; } // The callback is stable (never changes identity) because it only reads from refs. // This avoids triggering unnecessary re-renders in consumers. return (0, _react.useCallback)((animationElapsedTime, totalLength) => { if (reachedFullRef.current) { return null; } var visibleLength = Math.min((0, _round.round)(startingLengthRef.current + animationElapsedTime * totalLength), totalLength); if (animationElapsedTime > 0 && totalLength > 0) { maxAnimatedLengthRef.current = Math.max(maxAnimatedLengthRef.current, visibleLength); if (visibleLength >= totalLength) { reachedFullRef.current = true; return null; } } return visibleLength; }, []); }