UNPKG

@ifed/hook

Version:
107 lines (106 loc) 3.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = require("react"); var _easingFunctions = _interopRequireDefault(require("./easingFunctions")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const useAnimateNumber = ({ number = 0, durationInMs = 4000, easingFunctionName = 'easeOutExpo', setInitialValue = false }) => { const decimalPlaces = String(number).split('.')?.[1]?.length || 0; const [data, setData] = (0, _react.useState)({ currentNumber: 0, originalNumber: setInitialValue ? number : 0, step: 0, isGoingUp: false, isAnimating: false }); const requestRef = (0, _react.useRef)(); const mountedRef = (0, _react.useRef)(true); const previousTimeRef = (0, _react.useRef)(); const animate = (0, _react.useCallback)(time => { if (!mountedRef.current) return; if (previousTimeRef.current === undefined) { previousTimeRef.current = time; requestRef.current = requestAnimationFrame(animate); return; } const reset = () => { setData({ currentNumber: number, originalNumber: number, step: 0, isGoingUp: false, isAnimating: false }); previousTimeRef.current = undefined; if (requestRef.current) cancelAnimationFrame(requestRef.current); requestRef.current = undefined; }; if (typeof number !== 'number') { try { number = parseFloat(number); } catch (e) { console.error('useAnimateNumber: number is not a number'); reset(); return; } } if (number === data.currentNumber) { reset(); return; } const deltaTime = time - previousTimeRef.current; if (deltaTime >= durationInMs) { reset(); return; } let easingFunction = _easingFunctions.default.easeOutExpo; if (easingFunctionName && _easingFunctions.default[easingFunctionName]) { easingFunction = _easingFunctions.default[easingFunctionName]; } const progress = deltaTime / durationInMs; const percentageOfTargetValue = easingFunction(progress); let currentValue = percentageOfTargetValue * number; setData(previousData => { const isGoingUp = number > previousData.originalNumber; if (!isGoingUp) { currentValue = (1 - percentageOfTargetValue) * previousData.originalNumber + number; } if (currentValue !== 0) { currentValue = parseFloat(currentValue.toFixed(decimalPlaces)); } if (isGoingUp && currentValue > number) { currentValue = number; } if (!isGoingUp && currentValue < number) { currentValue = number; } return { ...previousData, currentNumber: currentValue, isGoingUp, isAnimating: true }; }); requestRef.current = window.requestAnimationFrame(animate); }, [number, durationInMs, decimalPlaces, easingFunctionName]); (0, _react.useEffect)(() => { requestRef.current = window.requestAnimationFrame(animate); return () => { if (requestRef.current) cancelAnimationFrame(requestRef.current); }; }, [number, animate]); return { number: data.currentNumber, isGoingUp: data.isGoingUp, isAnimating: data.isAnimating }; }; var _default = useAnimateNumber; exports.default = _default;