// Copyright: © 2026 TWWIM UG. All rights reserved. (www.twwim.com) /** * NumberInput — labelled integer input with bounded validation styling. * * @layer Presentation */ interface NumberInputProps { label: string; help?: string; min: number; max: number; value: number; onChange: (v: number) => void; } export function NumberInput({ label, help, min, max, value, onChange, }: NumberInputProps) { const invalid = !Number.isInteger(value) || value < min || value > max; return (
{ const next = Number.parseInt(e.target.value, 10); onChange(Number.isFinite(next) ? next : 0); }} className={`w-full px-3 py-2 text-sm border rounded-lg focus:ring-2 focus:ring-cyan-500 focus:outline-none ${ invalid ? 'border-red-400 bg-red-50' : 'border-gray-300 bg-white' }`} /> {help &&

{help}

}
); }