@@ -4,79 +4,79 @@ import { Star } from "lucide-react";
44import { cn } from "@/lib/utils" ;
55
66export interface StarRatingProps {
7- value : number ; // 0-5, can be fractional for average
8- onValueChange ?: ( value : number ) => void ;
9- readonly ?: boolean ;
10- size ?: "sm" | "md" | "lg" ;
11- showValue ?: boolean ;
12- className ?: string ;
7+ value : number ; // 0-5, can be fractional for average
8+ onValueChange ?: ( value : number ) => void ;
9+ readonly ?: boolean ;
10+ size ?: "sm" | "md" | "lg" ;
11+ showValue ?: boolean ;
12+ className ?: string ;
1313}
1414
1515export function StarRating ( {
16- value,
17- onValueChange,
18- readonly = false ,
19- size = "md" ,
20- showValue = false ,
21- className,
16+ value,
17+ onValueChange,
18+ readonly = false ,
19+ size = "md" ,
20+ showValue = false ,
21+ className,
2222} : StarRatingProps ) {
23- const sizeClasses = {
24- sm : "h-3 w-3" ,
25- md : "h-4 w-4" ,
26- lg : "h-5 w-5" ,
27- } ;
23+ const sizeClasses = {
24+ sm : "h-3 w-3" ,
25+ md : "h-4 w-4" ,
26+ lg : "h-5 w-5" ,
27+ } ;
2828
29- const handleClick = ( newValue : number ) => {
30- if ( ! readonly && onValueChange ) {
31- onValueChange ( newValue ) ;
32- }
33- } ;
29+ const handleClick = ( newValue : number ) => {
30+ if ( ! readonly && onValueChange ) {
31+ onValueChange ( newValue ) ;
32+ }
33+ } ;
3434
35- const handleMouseEnter = ( hoverValue : number ) => {
36- if ( ! readonly ) {
37- // Optional: Add hover state if needed
38- }
39- } ;
35+ const handleMouseEnter = ( hoverValue : number ) => {
36+ if ( ! readonly ) {
37+ // Optional: Add hover state if needed
38+ }
39+ } ;
4040
41- return (
42- < div className = { cn ( "flex items-center gap-1" , className ) } >
43- < div className = "flex items-center gap-0.5" >
44- { [ 1 , 2 , 3 , 4 , 5 ] . map ( ( starValue ) => {
45- const isFilled = value >= starValue ;
46- const isHalfFilled = value >= starValue - 0.5 && value < starValue ;
41+ return (
42+ < div className = { cn ( "flex items-center gap-1" , className ) } >
43+ < div className = "flex items-center gap-0.5" >
44+ { [ 1 , 2 , 3 , 4 , 5 ] . map ( ( starValue ) => {
45+ const isFilled = value >= starValue ;
46+ const isHalfFilled = value >= starValue - 0.5 && value < starValue ;
4747
48- return (
49- < button
50- className = { cn (
51- "transition-colors" ,
52- ! readonly && "cursor-pointer hover:opacity-80" ,
53- readonly && "cursor-default"
54- ) }
55- disabled = { readonly }
56- key = { starValue }
57- onClick = { ( ) => handleClick ( starValue ) }
58- onMouseEnter = { ( ) => handleMouseEnter ( starValue ) }
59- type = "button"
60- >
61- < Star
62- className = { cn (
63- sizeClasses [ size ] ,
64- isFilled
65- ? "fill-yellow-400 text-yellow-400"
66- : isHalfFilled
67- ? "fill-yellow-400/50 text-yellow-400/50"
68- : "fill-none text-muted-foreground/30"
69- ) }
70- />
71- </ button >
72- ) ;
73- } ) }
74- </ div >
75- { showValue && value > 0 && (
76- < span className = "ml-1 text-muted-foreground text-xs" >
77- { value . toFixed ( 1 ) }
78- </ span >
79- ) }
80- </ div >
81- ) ;
48+ return (
49+ < button
50+ className = { cn (
51+ "transition-colors" ,
52+ ! readonly && "cursor-pointer hover:opacity-80" ,
53+ readonly && "cursor-default"
54+ ) }
55+ disabled = { readonly }
56+ key = { starValue }
57+ onClick = { ( ) => handleClick ( starValue ) }
58+ onMouseEnter = { ( ) => handleMouseEnter ( starValue ) }
59+ type = "button"
60+ >
61+ < Star
62+ className = { cn (
63+ sizeClasses [ size ] ,
64+ isFilled
65+ ? "fill-yellow-400 text-yellow-400"
66+ : isHalfFilled
67+ ? "fill-yellow-400/50 text-yellow-400/50"
68+ : "fill-none text-muted-foreground/30"
69+ ) }
70+ />
71+ </ button >
72+ ) ;
73+ } ) }
74+ </ div >
75+ { showValue && value > 0 && (
76+ < span className = "ml-1 text-muted-foreground text-xs" >
77+ { value . toFixed ( 1 ) }
78+ </ span >
79+ ) }
80+ </ div >
81+ ) ;
8282}
0 commit comments