UNPKG

reactbits-mcp-server

Version:

MCP Server for React Bits - Access 99+ React components with animations, backgrounds, and UI elements

142 lines (127 loc) 3.26 kB
import { motion, useSpring, useTransform } from "framer-motion"; import { useEffect } from "react"; function Number({ mv, number, height }) { let y = useTransform(mv, (latest) => { let placeValue = latest % 10; let offset = (10 + number - placeValue) % 10; let memo = offset * height; if (offset > 5) { memo -= 10 * height; } return memo; }); const style = { position: "absolute", top: 0, right: 0, bottom: 0, left: 0, display: "flex", alignItems: "center", justifyContent: "center", }; return <motion.span style={{ ...style, y }}>{number}</motion.span>; } function Digit({ place, value, height, digitStyle }) { let valueRoundedToPlace = Math.floor(value / place); let animatedValue = useSpring(valueRoundedToPlace); useEffect(() => { animatedValue.set(valueRoundedToPlace); }, [animatedValue, valueRoundedToPlace]); const defaultStyle = { height, position: "relative", width: "1ch", fontVariantNumeric: "tabular-nums", }; return ( <div style={{ ...defaultStyle, ...digitStyle }}> {Array.from({ length: 10 }, (_, i) => ( <Number key={i} mv={animatedValue} number={i} height={height} /> ))} </div> ); } export default function Counter({ value, fontSize = 100, padding = 0, places = [100, 10, 1], gap = 8, borderRadius = 4, horizontalPadding = 8, textColor = "white", fontWeight = "bold", containerStyle, counterStyle, digitStyle, gradientHeight = 16, gradientFrom = "black", gradientTo = "transparent", topGradientStyle, bottomGradientStyle, }) { const height = fontSize + padding; const defaultContainerStyle = { position: "relative", display: "inline-block", }; const defaultCounterStyle = { fontSize, display: "flex", gap: gap, overflow: "hidden", borderRadius: borderRadius, paddingLeft: horizontalPadding, paddingRight: horizontalPadding, lineHeight: 1, color: textColor, fontWeight: fontWeight, }; const gradientContainerStyle = { pointerEvents: "none", position: "absolute", top: 0, bottom: 0, left: 0, right: 0, }; const defaultTopGradientStyle = { height: gradientHeight, background: `linear-gradient(to bottom, ${gradientFrom}, ${gradientTo})`, }; const defaultBottomGradientStyle = { position: "absolute", bottom: 0, width: "100%", height: gradientHeight, background: `linear-gradient(to top, ${gradientFrom}, ${gradientTo})`, }; return ( <div style={{ ...defaultContainerStyle, ...containerStyle }}> <div style={{ ...defaultCounterStyle, ...counterStyle }}> {places.map((place) => ( <Digit key={place} place={place} value={value} height={height} digitStyle={digitStyle} /> ))} </div> <div style={gradientContainerStyle}> <div style={topGradientStyle ? topGradientStyle : defaultTopGradientStyle} /> <div style={ bottomGradientStyle ? bottomGradientStyle : defaultBottomGradientStyle } /> </div> </div> ); }