{"version":3,"file":"useLatestRef.mjs","sources":["../../../../src/lib/hooks/shared/useLatestRef.ts"],"sourcesContent":["/**\n * @file useLatestRef Hook\n * @description Utility hook to maintain a ref that always points to the latest value\n *\n * This hook is useful for accessing the latest props or state in callbacks without\n * recreating the callback on every render. It's particularly helpful in event handlers,\n * async operations, and effect cleanup functions.\n *\n * @example\n * ```tsx\n * function SearchInput({ onSearch }: { onSearch: (query: string) => void }) {\n *   const onSearchRef = useLatestRef(onSearch);\n *   const [query, setQuery] = useState('');\n *\n *   useEffect(() => {\n *     const timer = setTimeout(() => {\n *       // Always calls the latest onSearch callback\n *       onSearchRef.current(query);\n *     }, 300);\n *     return () => clearTimeout(timer);\n *   }, [query]); // onSearch not in deps - no callback recreation\n *\n *   return <input value={query} onChange={e => setQuery(e.target.value)} />;\n * }\n * ```\n */\n\nimport { useRef } from 'react';\nimport type { MutableRefObject } from 'react';\n\n/**\n * Hook that maintains a ref with the latest value\n *\n * The ref is updated during render (not in an effect), ensuring it's\n * always current even if accessed synchronously after a state update.\n *\n * @param value - The value to keep updated in the ref\n * @returns Ref object containing the latest value\n */\nexport function useLatestRef<T>(value: T): MutableRefObject<T> {\n  const ref = useRef(value);\n\n  // Update ref during render to ensure it's always current\n  // This is safe because we're not causing side effects\n  // eslint-disable-next-line react-hooks/refs\n  ref.current = value;\n\n  return ref;\n}\n\n/**\n * Hook that creates a callback wrapper that always uses latest values\n *\n * Useful for creating stable callback references that access latest props/state\n * without recreating the callback on every render.\n *\n * @example\n * ```tsx\n * function Counter({ onIncrement }: { onIncrement: (n: number) => void }) {\n *   const [count, setCount] = useState(0);\n *\n *   // Callback never recreated, but always uses latest count and onIncrement\n *   const handleClick = useLatestCallback(() => {\n *     const newCount = count + 1;\n *     setCount(newCount);\n *     onIncrement(newCount);\n *   });\n *\n *   return <button onClick={handleClick}>Count: {count}</button>;\n * }\n * ```\n */\nexport function useLatestCallback<TArgs extends unknown[], TReturn>(\n  callback: (...args: TArgs) => TReturn\n): (...args: TArgs) => TReturn {\n  const callbackRef = useLatestRef(callback);\n\n  const stableCallback = useRef<((...args: TArgs) => TReturn) | undefined>(undefined);\n\n  stableCallback.current ??= (...args: TArgs): TReturn => {\n    return callbackRef.current(...args);\n  };\n\n  return stableCallback.current;\n}\n\n/**\n * Hook that provides both a value ref and a callback ref\n *\n * @example\n * ```tsx\n * const { valueRef, callbackRef } = useLatestRefs({\n *   count,\n *   onSave: handleSave\n * });\n *\n * // Access in async operations\n * setTimeout(() => {\n *   console.log(valueRef.current.count);\n *   callbackRef.current.onSave();\n * }, 1000);\n * ```\n */\nexport function useLatestRefs<T extends Record<string, unknown>>(values: T): MutableRefObject<T> {\n  return useLatestRef(values);\n}\n"],"names":["useLatestRef","value","ref","useRef","useLatestCallback","callback","callbackRef","stableCallback","args","useLatestRefs","values"],"mappings":";AAuCO,SAASA,EAAgBC,GAA+B;AAC7D,QAAMC,IAAMC,EAAOF,CAAK;AAKxB,SAAAC,EAAI,UAAUD,GAEPC;AACT;AAwBO,SAASE,EACdC,GAC6B;AAC7B,QAAMC,IAAcN,EAAaK,CAAQ,GAEnCE,IAAiBJ,EAAkD,MAAS;AAElF,SAAAI,EAAe,YAAY,IAAIC,MACtBF,EAAY,QAAQ,GAAGE,CAAI,GAG7BD,EAAe;AACxB;AAmBO,SAASE,EAAiDC,GAAgC;AAC/F,SAAOV,EAAaU,CAAM;AAC5B;"}