"use client"; import { useRef, type KeyboardEvent } from "react"; import { cn } from "@/lib/utils"; /** Keep only digits and a single leading minus sign, so junk like "1-2" can't be typed. */ function sanitizeSigned(value: string): string { const cleaned = value.replace(/[^0-9-]/g, ""); return cleaned.replace(/(?!^)-/g, ""); // drop any minus that isn't at the start } interface FractionInputProps { numerator: string; denominator: string; onNumeratorChange: (value: string) => void; onDenominatorChange: (value: string) => void; onSubmit?: () => void; disabled?: boolean; className?: string; } export function FractionInput({ numerator, denominator, onNumeratorChange, onDenominatorChange, onSubmit, disabled = false, className, }: FractionInputProps) { const denominatorRef = useRef(null); const inputClass = "w-16 rounded-lg border border-border bg-surface px-2 py-1.5 text-center text-lg font-bold focus:border-unit-1 focus:outline-none"; return (
onNumeratorChange(sanitizeSigned(e.target.value))} onKeyDown={(e) => { // "/" is how pupils think of a fraction — jump to the denominator. if (e.key === "/" || e.key === "Enter") { if (e.key === "/") { e.preventDefault(); denominatorRef.current?.focus(); } else { onSubmit?.(); } } }} disabled={disabled} className={inputClass} placeholder="?" aria-label="Numerator" />
onDenominatorChange(sanitizeSigned(e.target.value))} onKeyDown={(e: KeyboardEvent) => { if (e.key === "Enter") onSubmit?.(); }} disabled={disabled} className={inputClass} placeholder="?" aria-label="Denominator" />
); } interface DecimalInputProps { value: string; onChange: (value: string) => void; onSubmit?: () => void; disabled?: boolean; className?: string; } export function DecimalInput({ value, onChange, onSubmit, disabled, className }: DecimalInputProps) { return ( onChange(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") onSubmit?.(); }} disabled={disabled} className={cn( "w-28 rounded-lg border border-border bg-surface px-3 py-2 text-center text-lg font-bold focus:border-unit-2 focus:outline-none", className, )} placeholder="?" aria-label="Answer" /> ); } interface RatioInputProps { parts: string[]; onChange: (index: number, value: string) => void; disabled?: boolean; className?: string; } export function RatioInput({ parts, onChange, disabled, className }: RatioInputProps) { return (
{parts.map((p, i) => ( {i > 0 && :} onChange(i, e.target.value)} disabled={disabled} className="w-14 rounded-lg border border-border bg-surface px-2 py-2 text-center text-lg font-bold focus:border-unit-4 focus:outline-none" placeholder="?" aria-label={`Part ${i + 1}`} /> ))}
); }