import { LucideProps, Star } from "lucide-react"; import React, { DetailedHTMLProps, ForwardRefExoticComponent, HTMLAttributes, RefAttributes, } from "react"; import { twMerge } from "tailwind-merge"; type StarProps = { total?: number; value?: number; size?: number; starProps?: LucideProps; allowRating?: boolean; setValueExternal?: React.Dispatch>; }; export type TWUI_STAR_RATING_PROPS = DetailedHTMLProps< HTMLAttributes, HTMLDivElement > & StarProps; let timeout: any; /** * # Star Rating Component * @className_wrapper twui-star-rating */ export default function StarRating({ total = 5, value = 0, size, starProps, allowRating, setValueExternal, ...props }: TWUI_STAR_RATING_PROPS) { const totalArray = Array(total).fill(null); const [finalValue, setFinalValue] = React.useState(value); const [selectedStarValue, setSelectedStarValue] = React.useState(value); const starClicked = React.useRef(false); const sectionHovered = React.useRef(false); React.useEffect(() => { window.clearTimeout(timeout); timeout = setTimeout(() => { setValueExternal?.(finalValue); }, 500); }, [selectedStarValue]); return (
{ sectionHovered.current = true; }} onMouseLeave={() => { sectionHovered.current = false; }} > {totalArray.map((_, index) => { return ( ); })}
); } function StarComponent({ value = 0, size = 20, starProps, index, allowRating, finalValue, setFinalValue, starClicked, sectionHovered, setSelectedStarValue, selectedStarValue, }: StarProps & { index: number; finalValue: number; setFinalValue: React.Dispatch>; setSelectedStarValue: React.Dispatch>; starClicked: React.MutableRefObject; sectionHovered: React.MutableRefObject; selectedStarValue: number; }) { const isActive = index < finalValue; return (
{ if (!allowRating) return; setFinalValue(index + 1); }} onMouseLeave={() => { if (!allowRating) return; setTimeout(() => { if (sectionHovered.current) { return; } if (!starClicked.current) { setFinalValue(0); } if (selectedStarValue) { setFinalValue(selectedStarValue); } }, 200); }} onClick={() => { if (!allowRating) return; starClicked.current = true; setSelectedStarValue(index + 1); }} >
); }