"use client"; import { useState, type KeyboardEvent } from "react"; import "./star-rate.css"; /** * Star Rate * A five-star rating where choosing fills the stars one after another, each popping as it * lights; five stars throws a little sparkle. Hovering previews the fill, and the line below * says what the rating means. */ type Props = { value?: number; defaultValue?: number; onChange?: (v: number) => void; label?: string; words?: string[]; className?: string }; const WORDS = ["Not rated", "Not for me", "It was fine", "Good", "Really good", "Loved it"]; export function StarRate({ value, defaultValue = 0, onChange, label = "Rating", words = WORDS, className = "" }: Props) { const [inner, setInner] = useState(defaultValue); const v = value ?? inner; const [hover, setHover] = useState(0); const [beat, setBeat] = useState(0); const set = (n: number) => { if (value === undefined) setInner(n); setBeat((b) => b + 1); onChange?.(n); }; const shown = hover || v; const onKey = (e: KeyboardEvent) => { const m: Record = { ArrowRight: v + 1, ArrowUp: v + 1, ArrowLeft: v - 1, ArrowDown: v - 1, Home: 1, End: 5 }; if (!(e.key in m)) return; e.preventDefault(); const n = Math.max(1, Math.min(5, m[e.key])); set(n); (e.currentTarget.querySelector(`[data-n="${n}"]`) as HTMLElement | null)?.focus(); }; return (
setHover(0)} data-beat={beat}> {[1, 2, 3, 4, 5].map((n) => ( ))}

{words[shown] ?? ""}

); }