react-animated-numbers
Version:
Library showing animation of number changes in react.js
68 lines (67 loc) • 3.67 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importDefault(require("react"));
const react_2 = require("motion/react");
const NUMBERS = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9,
];
const AnimatedNumber = ({ className, animateToNumber, fontStyle, transitions, includeComma, locale, }) => {
const ref = react_1.default.useRef(null);
const isInView = (0, react_2.useInView)(ref, { once: true });
const controls = (0, react_2.useAnimation)();
const animateTonumberString = includeComma
? Math.abs(animateToNumber).toLocaleString(locale || "en-US")
: String(Math.abs(animateToNumber));
const animateToNumbersArr = Array.from(animateTonumberString, Number).map((x, idx) => (isNaN(x) ? animateTonumberString[idx] : x));
const [numberHeight, setNumberHeight] = react_1.default.useState(0);
const [numberWidth, setNumberWidth] = react_1.default.useState(0);
const numberDivRef = react_1.default.useRef(null);
react_1.default.useEffect(() => {
var _a, _b;
const rect = (_b = (_a = numberDivRef.current) === null || _a === void 0 ? void 0 : _a.getClientRects()) === null || _b === void 0 ? void 0 : _b[0];
if (rect) {
setNumberHeight(rect.height);
setNumberWidth(rect.width);
}
}, []);
react_1.default.useEffect(() => {
if (isInView) {
controls.start("visible");
}
}, [isInView, animateToNumber, controls]);
return (react_1.default.createElement("span", { ref: ref },
numberHeight !== 0 && (react_1.default.createElement("div", { style: {
display: "flex",
flexDirection: "row",
overflow: "hidden",
}, className: className }, animateToNumbersArr.map((n, index) => {
if (typeof n === "string") {
return (react_1.default.createElement("div", { key: index, style: Object.assign(Object.assign({}, fontStyle), { fontVariantNumeric: "tabular-nums" }) }, n));
}
return (react_1.default.createElement(react_2.motion.div, { key: `${n}_${index}`, style: {
height: numberHeight,
width: numberWidth,
}, initial: "hidden", variants: {
hidden: { y: 0 },
visible: {
y: -1 *
(numberHeight *
(typeof animateToNumbersArr[index] === "number"
? animateToNumbersArr[index]
: 0)) -
numberHeight * 20,
},
}, animate: controls, transition: transitions === null || transitions === void 0 ? void 0 : transitions(index) }, NUMBERS.map((number, index) => (react_1.default.createElement("div", { key: index, style: Object.assign(Object.assign({}, fontStyle), { fontVariantNumeric: "tabular-nums" }) }, number)))));
}))),
react_1.default.createElement("div", { ref: numberDivRef, style: Object.assign({ position: "absolute", top: -9999 }, fontStyle) }, 0)));
};
const Enhanced = react_1.default.memo(AnimatedNumber, (prevProps, nextProps) => {
return (prevProps.animateToNumber === nextProps.animateToNumber &&
prevProps.fontStyle === nextProps.fontStyle &&
prevProps.includeComma === nextProps.includeComma);
});
exports.default = Enhanced;
;