import { type ChangeEvent, type KeyboardEvent, useState } from "react";
/**
* Buffer text input locally so keystrokes don't cause a settings-wide
* re-render (and optionally a server RPC round-trip) on every character.
* `onCommit` fires on blur and on Enter.
*
* The draft resynchronizes from the upstream `value` only when the input
* is not focused, so an external push (e.g. an optimistic settings
* update from the user's own commit, or a reset to defaults) doesn't
* clobber an in-progress edit.
*
* Returns a bag of props that should be spread onto an ``:
*
* const bag = useCommitOnBlur(instance.displayName ?? "", (next) => {...});
*
*/
export function useCommitOnBlur(value: string, onCommit: (next: string) => void) {
const [draft, setDraft] = useState(null);
return {
value: draft ?? value,
onChange: (event: ChangeEvent) => {
setDraft(event.target.value);
},
onFocus: () => {
setDraft(value);
},
onBlur: () => {
const next = draft ?? value;
setDraft(null);
if (next !== value) {
onCommit(next);
}
},
onKeyDown: (event: KeyboardEvent) => {
if (event.nativeEvent.isComposing || event.keyCode === 229) return;
if (event.key === "Enter") {
event.preventDefault();
(event.target as HTMLInputElement).blur();
}
},
};
}