46 lines
992 B
TypeScript
46 lines
992 B
TypeScript
import React from 'react';
|
|
import { Star } from 'lucide-react';
|
|
|
|
interface RatingProps {
|
|
value: number;
|
|
onChange?: (value: number) => void;
|
|
max?: number;
|
|
readonly?: boolean;
|
|
size?: 'sm' | 'md' | 'lg';
|
|
}
|
|
|
|
const sizeMap = {
|
|
sm: 16,
|
|
md: 24,
|
|
lg: 32,
|
|
};
|
|
|
|
export default function Rating({
|
|
value,
|
|
onChange,
|
|
max = 5,
|
|
readonly = false,
|
|
size = 'md',
|
|
}: RatingProps) {
|
|
const iconSize = sizeMap[size];
|
|
|
|
return (
|
|
<div className="flex items-center gap-1">
|
|
{Array.from({ length: max }).map((_, i) => {
|
|
const isFilled = i < value;
|
|
return (
|
|
<Star
|
|
key={i}
|
|
size={iconSize}
|
|
className={`
|
|
cursor-pointer transition-colors
|
|
${isFilled ? 'fill-yellow-400 text-yellow-400' : 'text-gray-300'}
|
|
${readonly ? 'cursor-default' : 'hover:text-yellow-500'}
|
|
`}
|
|
onClick={() => !readonly && onChange?.(i + 1)}
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
} |