+ "content": "import { useCallback, useMemo, useRef, useState } from \"react\"\n\nimport type { ChangeEvent, FocusEvent } from \"react\"\n\ninterface UseInputValueReturn {\n different: boolean\n dirty: boolean\n touched: boolean\n value: string\n handleBlur: (event: FocusEvent<HTMLInputElement>) => void\n handleChange: (event: ChangeEvent<HTMLInputElement>) => void\n reset: () => void\n}\n\nconst DEFAULT_DIRTY_STATE = false\nconst DEFAULT_TOUCHED_STATE = false\n\n/**\n * Manage a controlled input value and track additional form input states like\n *\n * @param initialValue - Initial value of the input\n * @returns An object with the following properties:\n * - `different`: Whether the value is different from the initial value\n * - `dirty`: Whether the input has been modified at least once\n * - `touched`: Whether the input was focused and blurred\n * - `value`: Current value of the input\n * - `handleBlur`: Function to be called when the input is blurred\n * - `handleChange`: Function that updates the value of the input\n * - `reset` Function to reset the initial value as well as the value of all states\n *\n * @example\n * ```tsx\n * function FormComponent() {\n * const {\n * different,\n * dirty,\n * touched,\n * value,\n * handleBlur,\n * handleChange,\n * reset\n * } = useInputControl(\"John\")\n *\n * return (\n * <form>\n * <fieldset>\n * <input\n * value={value}\n * onChange={handleChange}\n * onBlur={handleBlur}\n * />\n * </fieldset>\n * <p>Dirty: {dirty.toString()}</p>\n * <p>Touched: {touched.toString()}</p>\n * <p>Different: {different.toString()}</p>\n * <button onClick={reset}>Reset</button>\n * </form>\n * )\n * }\n */\nexport function useInputControl(\n initialValue: string,\n): UseInputValueReturn {\n const ref = useRef(initialValue)\n const [value, setValue] = useState(initialValue)\n const [dirty, setDirty] = useState(DEFAULT_DIRTY_STATE)\n const [touched, setTouched] = useState(DEFAULT_TOUCHED_STATE)\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const handleBlur = useCallback((event: FocusEvent<HTMLInputElement>) => {\n setTouched(true)\n }, [])\n const handleChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {\n setDirty(true)\n setValue(event.currentTarget.value)\n }, [])\n const reset = useCallback(() => {\n setDirty(DEFAULT_DIRTY_STATE)\n setTouched(DEFAULT_TOUCHED_STATE)\n setValue(ref.current)\n }, [])\n\n const different = ref.current !== value\n\n return useMemo(\n () => ({\n different,\n dirty,\n touched,\n value,\n handleBlur,\n handleChange,\n reset,\n }),\n [different, dirty, touched, value, handleBlur, handleChange, reset],\n )\n}\n",
0 commit comments