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.key === "Enter") { event.preventDefault(); (event.target as HTMLInputElement).blur(); } }, }; }