1- import  {  useAutoAnimate  }  from  '@formkit/auto-animate/react' ; 
21import  {  WindIcon  }  from  '@phosphor-icons/react' ; 
2+ import  {  useRef ,  useEffect ,  useState  }  from  'react' ; 
33
44export  interface  WindDirectionProps  { 
55  speedMs ?: number ; 
66  direction ?: number ; 
7+   metric ?: boolean ; 
78} 
89
9- export  const  WindDirection  =  ( {  speedMs,  direction } : WindDirectionProps )  =>  { 
10-   const  speed  =  speedMs  !==  undefined  ? speedMs  *  ( 18  /  5 )  : undefined ; 
11-   const  [ parent ]  =  useAutoAnimate ( ) ; 
10+ export  const  WindDirection  =  ( { 
11+   speedMs, 
12+   direction, 
13+   metric =  true , 
14+ } : WindDirectionProps )  =>  { 
15+   // Convert m/s to user's preferred unit 
16+   const  speed  = 
17+     speedMs  !==  undefined 
18+       ? speedMs  *  ( metric  ? 3.6  : 2.23694 )  // km/h or mph 
19+       : undefined ; 
20+ 
21+   const  [ normalizedAngle ,  setNormalizedAngle ]  =  useState < number > ( 0 ) ; 
22+   const  prevAngleRef  =  useRef < number > ( 0 ) ; 
23+ 
24+   useEffect ( ( )  =>  { 
25+     if  ( direction  ===  undefined )  return ; 
26+ 
27+     const  currentAngle  =  direction ; 
28+     const  prevAngle  =  prevAngleRef . current ; 
29+ 
30+     // Calculate the shortest path difference 
31+     let  diff  =  currentAngle  -  prevAngle ; 
32+ 
33+     // Normalize to [-π, π] range 
34+     while  ( diff  >  Math . PI )  diff  -=  2  *  Math . PI ; 
35+     while  ( diff  <  - Math . PI )  diff  +=  2  *  Math . PI ; 
36+ 
37+     // Update the normalized angle 
38+     setNormalizedAngle ( ( prev )  =>  prev  +  diff ) ; 
39+     prevAngleRef . current  =  currentAngle ; 
40+   } ,  [ direction ] ) ; 
41+ 
1242  return  ( 
1343    < div  className = "bg-slate-800/70 p-2 rounded-sm" > 
1444      < div  className = "flex flex-row gap-x-2 items-center text-sm mb-3" > 
@@ -17,21 +47,20 @@ export const WindDirection = ({ speedMs, direction }: WindDirectionProps) => {
1747      </ div > 
1848      < div 
1949        id = "wind" 
20-         ref = { parent } 
2150        className = "flex aspect-square relative w-full max-w-[120px] mx-auto" 
2251      > 
2352        < svg 
2453          xmlns = "http://www.w3.org/2000/svg" 
2554          viewBox = "0 0 60 60" 
2655          className = "absolute stroke-current stroke-[3] w-full h-full box-border fill-none origin-center transform-gpu transition-transform duration-1000 ease-out" 
2756          style = { { 
28-             rotate : `calc(${ direction   ??   0 }  , 
57+             rotate : `calc(${ normalizedAngle }  , 
2958          } } 
3059        > 
3160          < path  d = "M48 8A28 28 90 0158 30c0 15.464-12.536 28-28 28S2 45.464 2 30A28 28 90 0112 8M22 9 30 1l8 8"  /> 
3261        </ svg > 
3362        < div  className = "absolute w-full h-full flex justify-center items-center text-[32px]" > 
34-           { speed  !==  undefined  ? speed . toFixed ( 1 )  : '-' } 
63+           { speed  !==  undefined  ? Math . round ( speed )  : '-' } 
3564        </ div > 
3665      </ div > 
3766    </ div > 
0 commit comments