{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"rating","type":"registry:ui","title":"Rating","description":"","dependencies":["class-variance-authority"],"registryDependencies":[],"files":[{"path":"rating.tsx","type":"registry:ui","content":"\"use client\"\n\nimport { useState } from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\nconst ratingVariants = cva(\"flex items-center\", {\n variants: {\n size: {\n sm: \"gap-2\",\n default: \"gap-2.5\",\n lg: \"gap-3\",\n },\n },\n defaultVariants: {\n size: \"default\",\n },\n})\n\nconst starVariants = cva(\"\", {\n variants: {\n size: {\n sm: \"w-4 h-4\",\n default: \"w-5 h-5\",\n lg: \"w-6 h-6\",\n },\n },\n defaultVariants: {\n size: \"default\",\n },\n})\n\nconst valueVariants = cva(\"text-muted-foreground w-5\", {\n variants: {\n size: {\n sm: \"text-xs\",\n default: \"text-sm\",\n lg: \"text-base\",\n },\n },\n defaultVariants: {\n size: \"default\",\n },\n})\n\nfunction Rating({\n rating,\n maxRating = 5,\n size,\n className,\n starClassName,\n showValue = false,\n editable = false,\n onRatingChange,\n ...props\n}: React.ComponentProps<\"div\"> &\n VariantProps & {\n /**\n * Current rating value (supports decimal values for partial stars)\n */\n rating: number\n /**\n * Maximum rating value (number of stars to show)\n */\n maxRating?: number\n /**\n * Whether to show the numeric rating value\n */\n showValue?: boolean\n /**\n * Class name for the value span\n */\n starClassName?: string\n /**\n * Whether the rating is editable (clickable)\n */\n editable?: boolean\n /**\n * Callback function called when rating changes\n */\n onRatingChange?: (rating: number) => void\n }) {\n const [hoveredRating, setHoveredRating] = useState(null)\n const displayRating =\n editable && hoveredRating !== null ? hoveredRating : rating\n\n const handleStarClick = (starRating: number) => {\n if (editable && onRatingChange) {\n onRatingChange(starRating)\n }\n }\n\n const handleStarMouseEnter = (starRating: number) => {\n if (editable) {\n setHoveredRating(starRating)\n }\n }\n\n const handleStarMouseLeave = () => {\n if (editable) {\n setHoveredRating(null)\n }\n }\n\n const renderStars = () => {\n const stars = []\n\n for (let i = 1; i <= maxRating; i++) {\n const filled = displayRating >= i\n const partiallyFilled = displayRating > i - 1 && displayRating < i\n const fillPercentage = partiallyFilled\n ? (displayRating - (i - 1)) * 100\n : 0\n\n stars.push(\n handleStarClick(i)}\n onMouseEnter={() => handleStarMouseEnter(i)}\n onMouseLeave={handleStarMouseLeave}\n >\n {/* Background star (empty) */}\n \n\n {/* Filled star */}\n \n \n \n \n )\n }\n\n return stars\n }\n\n return (\n \n
{renderStars()}
\n {showValue && (\n \n {displayRating.toFixed(1)}\n \n )}\n \n )\n}\n\nexport { Rating }","target":"components/neui/rating.tsx"}]}