1- ' use client' ;
1+ " use client" ;
22
3- import React , { useCallback , useEffect , useState } from 'react' ;
4- import { cva , type VariantProps } from 'class-variance-authority' ;
5- import { Star } from 'lucide-react' ;
6- import { motion , useInView , type SpringOptions , type UseInViewOptions } from 'motion/react' ;
7- import { cn } from '@/lib/utils' ;
3+ import React , { useCallback , useEffect , useState } from "react" ;
4+
5+ import { cn } from "@/lib/utils" ;
6+ import { type VariantProps , cva } from "class-variance-authority" ;
7+ import { Star } from "lucide-react" ;
8+ import {
9+ type SpringOptions ,
10+ type UseInViewOptions ,
11+ motion ,
12+ useInView ,
13+ } from "motion/react" ;
814
915const githubButtonVariants = cva (
10- ' cursor-pointer relative overflow-hidden will-change-transform backface-visibility-hidden transform-gpu transition-transform duration-200 ease-out hover:scale-105 group whitespace-nowrap focus-visible:outline-hidden inline-flex items-center justify-center whitespace-nowrap font-medium ring-offset-background disabled:pointer-events-none disabled:opacity-60 [&_svg]:shrink-0' ,
16+ " cursor-pointer relative overflow-hidden will-change-transform backface-visibility-hidden transform-gpu transition-transform duration-200 ease-out hover:scale-105 group whitespace-nowrap focus-visible:outline-hidden inline-flex items-center justify-center whitespace-nowrap font-medium ring-offset-background disabled:pointer-events-none disabled:opacity-60 [&_svg]:shrink-0" ,
1117 {
1218 variants : {
1319 variant : {
1420 default :
15- 'bg-zinc-950 hover:bg-zinc-900 text-white border-gray-700 dark:bg-zinc-50 dark:border-gray-300 dark:text-zinc-950 dark:hover:bg-zinc-50' ,
16- outline : 'bg-background text-accent-foreground border border-input hover:bg-accent' ,
21+ "bg-zinc-950 hover:bg-zinc-900 text-white border-gray-700 dark:bg-zinc-50 dark:border-gray-300 dark:text-zinc-950 dark:hover:bg-zinc-50" ,
22+ outline :
23+ "bg-background text-accent-foreground border border-input hover:bg-accent" ,
1724 } ,
1825 size : {
19- default : 'h-8.5 rounded-md px-3 gap-2 text-[0.8125rem] leading-none [&_svg]:size-4 gap-2' ,
20- sm : 'h-7 rounded-md px-2.5 gap-1.5 text-xs leading-none [&_svg]:size-3.5 gap-1.5' ,
21- lg : 'h-10 rounded-md px-4 gap-2.5 text-sm leading-none [&_svg]:size-5 gap-2.5' ,
26+ default :
27+ "h-8.5 rounded-md px-3 gap-2 text-[0.8125rem] leading-none [&_svg]:size-4 gap-2" ,
28+ sm : "h-7 rounded-md px-2.5 gap-1.5 text-xs leading-none [&_svg]:size-3.5 gap-1.5" ,
29+ lg : "h-10 rounded-md px-4 gap-2.5 text-sm leading-none [&_svg]:size-5 gap-2.5" ,
2230 } ,
2331 } ,
2432 defaultVariants : {
25- variant : ' default' ,
26- size : ' default' ,
33+ variant : " default" ,
34+ size : " default" ,
2735 } ,
2836 } ,
2937) ;
3038
31- interface GithubButtonProps extends React . ComponentProps < 'button' > , VariantProps < typeof githubButtonVariants > {
39+ interface GithubButtonProps
40+ extends React . ComponentProps < "button" > ,
41+ VariantProps < typeof githubButtonVariants > {
3242 /** Whether to round stars */
3343 roundStars ?: boolean ;
3444 /** Whether to show Github icon */
@@ -70,22 +80,22 @@ interface GithubButtonProps extends React.ComponentProps<'button'>, VariantProps
7080function GithubButton ( {
7181 initialStars = 0 ,
7282 targetStars = 0 ,
73- starsClass = '' ,
83+ starsClass = "" ,
7484 fixedWidth = true ,
7585 animationDuration = 2 ,
7686 animationDelay = 0 ,
7787 autoAnimate = true ,
7888 className,
79- variant = ' default' ,
80- size = ' default' ,
89+ variant = " default" ,
90+ size = " default" ,
8191 showGithubIcon = true ,
8292 showStarIcon = true ,
8393 roundStars = false ,
8494 separator = false ,
8595 filled = false ,
8696 repoUrl,
8797 onClick,
88- label = '' ,
98+ label = "" ,
8999 useInViewTrigger = false ,
90100 inViewOptions = { once : true } ,
91101 transition,
@@ -98,7 +108,7 @@ function GithubButton({
98108
99109 // Format number with units
100110 const formatNumber = ( num : number ) => {
101- const units = [ 'k' , 'M' , 'B' , 'T' ] ;
111+ const units = [ "k" , "M" , "B" , "T" ] ;
102112
103113 if ( roundStars && num >= 1000 ) {
104114 let unitIndex = - 1 ;
@@ -114,7 +124,7 @@ function GithubButton({
114124 return `${ formatted } ${ units [ unitIndex ] } ` ;
115125 }
116126
117- return num . toString ( ) . replace ( / \B (? = ( \d { 3 } ) + (? ! \d ) ) / g, ',' ) ;
127+ return num . toString ( ) . replace ( / \B (? = ( \d { 3 } ) + (? ! \d ) ) / g, "," ) ;
118128 } ;
119129
120130 // Start animation
@@ -135,7 +145,9 @@ function GithubButton({
135145 const easeOutQuart = 1 - Math . pow ( 1 - progress , 4 ) ;
136146
137147 // Update star count from 0 to target with more frequent updates
138- const newStars = Math . round ( startValue + ( endValue - startValue ) * easeOutQuart ) ;
148+ const newStars = Math . round (
149+ startValue + ( endValue - startValue ) * easeOutQuart ,
150+ ) ;
139151 setCurrentStars ( newStars ) ;
140152
141153 // Update star fill progress (0 to 100)
@@ -154,7 +166,13 @@ function GithubButton({
154166 setTimeout ( ( ) => {
155167 requestAnimationFrame ( animate ) ;
156168 } , animationDelay * 1000 ) ;
157- } , [ isAnimating , hasAnimated , targetStars , animationDuration , animationDelay ] ) ;
169+ } , [
170+ isAnimating ,
171+ hasAnimated ,
172+ targetStars ,
173+ animationDuration ,
174+ animationDelay ,
175+ ] ) ;
158176
159177 // Use in-view detection if enabled
160178 const ref = React . useRef ( null ) ;
@@ -185,10 +203,10 @@ function GithubButton({
185203 // Next.js compatible navigation approach
186204 try {
187205 // Create a temporary anchor element for reliable navigation
188- const link = document . createElement ( 'a' ) ;
206+ const link = document . createElement ( "a" ) ;
189207 link . href = repoUrl ;
190- link . target = ' _blank' ;
191- link . rel = ' noopener noreferrer' ;
208+ link . target = " _blank" ;
209+ link . rel = " noopener noreferrer" ;
192210
193211 // Temporarily add to DOM and click
194212 document . body . appendChild ( link ) ;
@@ -197,7 +215,7 @@ function GithubButton({
197215 } catch {
198216 // Fallback to window.open
199217 try {
200- window . open ( repoUrl , ' _blank' , ' noopener,noreferrer' ) ;
218+ window . open ( repoUrl , " _blank" , " noopener,noreferrer" ) ;
201219 } catch {
202220 // Final fallback
203221 window . location . href = repoUrl ;
@@ -220,7 +238,7 @@ function GithubButton({
220238
221239 const handleKeyDown = ( event : React . KeyboardEvent < HTMLButtonElement > ) => {
222240 // Handle Enter and Space key presses for accessibility
223- if ( event . key === ' Enter' || event . key === ' ' ) {
241+ if ( event . key === " Enter" || event . key === " " ) {
224242 event . preventDefault ( ) ;
225243
226244 if ( repoUrl ) {
@@ -234,7 +252,10 @@ function GithubButton({
234252 return (
235253 < button
236254 ref = { ref }
237- className = { cn ( githubButtonVariants ( { variant, size, className } ) , separator && 'ps-0' ) }
255+ className = { cn (
256+ githubButtonVariants ( { variant, size, className } ) ,
257+ separator && "ps-0" ,
258+ ) }
238259 onClick = { handleClick }
239260 onKeyDown = { handleKeyDown }
240261 role = "button"
@@ -245,8 +266,8 @@ function GithubButton({
245266 { showGithubIcon && (
246267 < div
247268 className = { cn (
248- 'h-full relative flex items-center justify-center' ,
249- separator && ' w-9 bg-muted/60 border-e border-input' ,
269+ " relative flex h-full items-center justify-center" ,
270+ separator && " w-9 border-e border-input bg-muted/60" ,
250271 ) }
251272 >
252273 < svg role = "img" viewBox = "0 0 24 24" fill = "currentColor" >
@@ -260,9 +281,12 @@ function GithubButton({
260281 { /* Animated Star Icon */ }
261282 { showStarIcon && (
262283 < div className = "relative inline-flex shrink-0" >
263- < Star className = "fill-muted-foreground text-muted-foreground" aria-hidden = "true" />
264284 < Star
265- className = "absolute top-0 start-0 text-yellow-400 fill-yellow-400"
285+ className = "fill-muted-foreground text-muted-foreground"
286+ aria-hidden = "true"
287+ />
288+ < Star
289+ className = "absolute start-0 top-0 fill-yellow-400 text-yellow-400"
266290 size = { 18 }
267291 aria-hidden = "true"
268292 style = { {
@@ -273,11 +297,16 @@ function GithubButton({
273297 ) }
274298
275299 { /* Animated Number Counter with Ticker Effect */ }
276- < div className = { cn ( 'flex flex-col font-semibold relative overflow-hidden' , starsClass ) } >
300+ < div
301+ className = { cn (
302+ "relative flex flex-col overflow-hidden font-semibold" ,
303+ starsClass ,
304+ ) }
305+ >
277306 < motion . div
278307 animate = { { opacity : 1 } }
279308 transition = { {
280- type : ' spring' ,
309+ type : " spring" ,
281310 stiffness : 300 ,
282311 damping : 30 ,
283312 ...transition ,
@@ -286,7 +315,11 @@ function GithubButton({
286315 >
287316 < span > { currentStars > 0 && formatNumber ( currentStars ) } </ span >
288317 </ motion . div >
289- { fixedWidth && < span className = "opacity-0 h-0 overflow-hidden tabular-nums" > { formatNumber ( targetStars ) } </ span > }
318+ { fixedWidth && (
319+ < span className = "h-0 overflow-hidden tabular-nums opacity-0" >
320+ { formatNumber ( targetStars ) }
321+ </ span >
322+ ) }
290323 </ div >
291324 </ button >
292325 ) ;
0 commit comments