{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"rating","type":"registry:ui","title":"Rating","description":"","dependencies":["class-variance-authority","cn"],"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 \"cn\"\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<typeof ratingVariants> & {\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<number | null>(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        <div\n          key={i}\n          className={cn(\"relative\", editable && \"cursor-pointer\")}\n          onClick={() => handleStarClick(i)}\n          onMouseEnter={() => handleStarMouseEnter(i)}\n          onMouseLeave={handleStarMouseLeave}\n        >\n          {/* Background star (empty) */}\n          <IconPlaceholder\n            lucide=\"StarIcon\"\n            tabler=\"IconStar\"\n            hugeicons=\"StarIcon\"\n            phosphor=\"StarIcon\"\n            remixicon=\"RiStarLine\"\n            data-slot=\"rating-star-empty\"\n            className={cn(starVariants({ size }), \"text-muted-foreground/30\")}\n          />\n\n          {/* Filled star */}\n          <div\n            className=\"absolute inset-0 overflow-hidden\"\n            style={{\n              width: filled ? \"100%\" : `${fillPercentage}%`,\n            }}\n          >\n            <IconPlaceholder\n              lucide=\"StarIcon\"\n              tabler=\"IconStar\"\n              hugeicons=\"StarIcon\"\n              phosphor=\"StarIcon\"\n              remixicon=\"RiStarLine\"\n              data-slot=\"rating-star-filled\"\n              className={cn(\n                starVariants({ size }),\n                \"fill-yellow-400 text-yellow-400\"\n              )}\n            />\n          </div>\n        </div>\n      )\n    }\n\n    return stars\n  }\n\n  return (\n    <div\n      data-slot=\"rating\"\n      className={cn(ratingVariants({ size }), className)}\n      {...props}\n    >\n      <div className=\"flex items-center\">{renderStars()}</div>\n      {showValue && (\n        <span\n          data-slot=\"rating-value\"\n          className={cn(valueVariants({ size }), starClassName)}\n        >\n          {displayRating.toFixed(1)}\n        </span>\n      )}\n    </div>\n  )\n}\n\nexport { Rating }","target":"components/reui/rating.tsx"}]}