import clsx from "clsx"; import { ChangeEvent, ComponentPropsWithRef, RefObject, useRef, useState } from "react"; import { Button } from "../../button"; import { useMergeRefs } from "../../../hooks"; export interface StarsProps extends Omit< ComponentPropsWithRef<"input">, "onChange" | "defaultValue" | "value" | "max" | "step" > { onChange?: (value: number | null) => void; defaultValue?: number | null; value?: number | null; max?: number; step?: number; zeroAsResetValue?: boolean; ref?: RefObject; } export function Stars({ onChange, defaultValue, value: controlledValue, max = 5, step = 1, required = false, ref, ...rest }: StarsProps) { const isControlled = typeof controlledValue !== "undefined"; const [unControlledValue, setUnControlledValue] = useState(defaultValue); const [hoveredValue, setHoveredValue] = useState(-1); const rangeValue = isControlled ? controlledValue : unControlledValue; if (typeof rangeValue === "undefined") { throw Error("you have to define either value or defaultValue"); } const inputRef = useRef(null!); const combinedRef = useMergeRefs([inputRef, ref]); function handleClickStar(nextValue: number) { if (!isControlled) { inputRef.current.value = nextValue.toString(); setUnControlledValue(nextValue); } onChange?.(nextValue); } /** * for a11y */ function handleInputChange(event: ChangeEvent) { const nextValue = event.target.valueAsNumber; if (!isControlled) { setUnControlledValue(nextValue); } onChange?.(nextValue); } function handleReset() { if (!isControlled) { setUnControlledValue(null); } onChange?.(null); } const currentValue = hoveredValue !== -1 ? hoveredValue : rangeValue; return (
{Array.from({ length: max }).map((_, i) => { const hasChanged = hoveredValue !== rangeValue; return ( setHoveredValue(i + 1)} onMouseOut={() => setHoveredValue(-1)} onClick={() => handleClickStar(i + 1)} className={clsx( "cursor-pointer", currentValue !== null && i < currentValue ? hasChanged && hoveredValue !== -1 ? "fe-star text-yellow-3" : "fe-star text-yellow-4" : "fe-star-empty text-gray-2", )} /> ); })} {!required && rangeValue !== null && ( )} {/* {rangeValue === null ? "null" : (rangeValue ?? "undefined")} */}
); }