, 'onChange' | 'onBlur' | 'value'> {
value: string | number;
onCommit: (value: string) => void;
+ /** When provided, an inline × button appears and calls this on click. */
+ onClear?: () => void;
+ /** className for the outer wrapper div (e.g. "flex-1"). Only used when onClear is set. */
+ containerClassName?: string;
}
/**
* A controlled input that buffers keystrokes locally and only calls
* `onCommit` when the field loses focus, preventing a settings save
* on every keystroke.
+ *
+ * When `onClear` is provided the component wraps itself in a relative div
+ * and shows an inline × button. Move any flex-sizing classes (e.g. flex-1)
+ * to `containerClassName` so they apply to the wrapper instead of the input.
*/
-export function SettingsInput({ value, onCommit, ...props }: SettingsInputProps) {
+export function SettingsInput({ value, onCommit, onClear, containerClassName, className, ...props }: SettingsInputProps) {
const [local, setLocal] = useState(String(value ?? ''));
// Sync if the committed value changes externally (e.g. device switch).
useEffect(() => { setLocal(String(value ?? '')); }, [value]);
- return (
+ const input = (
setLocal(e.target.value)}
onBlur={() => onCommit(local)}
/>
);
+
+ if (!onClear) return input;
+
+ return (
+
+ {input}
+ {local !== '' && (
+
+ )}
+
+ );
}