{"version":3,"file":"use-on-change.cjs","names":[],"sources":["../../src/hooks/use-on-change.ts"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***Performs a shallow-to-recursive difference check between two values.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n *    - Detects whether two values are **different**.\n *    - Designed as a **lightweight comparator** for state-change detection.\n *\n * - ***Comparison behavior:***\n *    - Uses **strict inequality (`!==`)** for non-array values.\n *    - Recursively compares **arrays by index and length**.\n *\n * - ⚠️ ***Important limitations:***\n *    - ❌ Does **NOT** perform deep object comparison.\n *    - ❌ Plain objects are compared by **reference**, not by structure.\n *    - ❌ Functions, Maps, Sets, Dates, etc. are compared by reference.\n *\n * - ✅ **Safe for:**\n *    - Primitive values (`string`, `number`, `boolean`, `null`, `undefined`)\n *    - Arrays of primitives\n *    - Nested arrays (recursive)\n *\n * ---\n *\n * ℹ️ This function is intentionally simple and predictable.\n * If you need structural deep equality, use a dedicated deep-compare utility.\n *\n * ---\n *\n * - ***Common use cases:***\n *    - Detecting state changes in custom React hooks.\n *    - Lightweight comparison for dependency tracking.\n *    - Guarding side-effects against unnecessary executions.\n *\n * @param a - Previous value to compare.\n * @param b - Current value to compare.\n *\n * @returns\n * - `true`  ➔ values are different\n * - `false` ➔ values are considered equal\n *\n * @example\n * **Primitive comparison.**\n * ```ts\n * isDifferent(1, 1);        // false\n * isDifferent(1, 2);        // true\n * isDifferent(\"a\", \"a\");    // false\n * isDifferent(\"a\", \"b\");    // true\n * ```\n *\n * @example\n * **Array comparison.**\n * ```ts\n * isDifferent([1, 2], [1, 2]);       // false\n * isDifferent([1, 2], [2, 1]);       // true\n * isDifferent([1, 2], [1, 2, 3]);    // true\n * ```\n *\n * @example\n * **Nested arrays.**\n * ```ts\n * isDifferent([[1], [2]], [[1], [2]]); // false\n * isDifferent([[1], [2]], [[1], [3]]); // true\n * ```\n *\n * @example\n * **Object references.**\n * ```ts\n * isDifferent({ a: 1 }, { a: 1 }); // true (different references)\n *\n * const obj = { a: 1 };\n * isDifferent(obj, obj);           // false\n * ```\n *\n * @internal\n */\nfunction isDifferent(a: unknown, b: unknown): boolean {\n  if (Array.isArray(a) && Array.isArray(b)) {\n    return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]));\n  }\n\n  return a !== b;\n}\n\n/** --------------------------------------------------------------------------\n * * ***Run a side-effect when a value changes (manual change detection).***\n * --------------------------------------------------------------------------\n *\n * A lightweight hook to detect changes between renders and execute\n * a callback **only when the value is considered \"updated\"**.\n *\n * ---\n *\n * - ***Core behavior:***\n *    - Stores the previous value internally.\n *    - Compares `previous` and `current` values on every render.\n *    - Executes `onChange(current, previous)` **synchronously**\n *      when `isUpdated(previous, current)` returns `true`.\n *\n * ---\n *\n * - ⚠️ ***Important notes:***\n *    - This hook **does NOT use `useEffect`**.\n *    - The comparison and callback run during render.\n *    - Make sure `onChange` does **not cause infinite re-renders**.\n *\n * ---\n *\n * - ***Default comparison strategy:***\n *    - Uses a shallow `!==` comparison.\n *    - Supports basic deep comparison for arrays.\n *\n * ---\n *\n * - ***Designed for:***\n *    - Lightweight change tracking.\n *    - Controlled state synchronization.\n *    - Custom state diffing logic without `useEffect`.\n *\n * ---\n *\n * @template T - The watched value type.\n *\n * @param value\n * The current value to observe.\n *\n * @param onChange\n * Callback invoked when the value is considered changed.\n *\n * Receives:\n * - `current` — the new value.\n * - `previous` — the previous value.\n *\n * @param isUpdated\n * Optional custom comparison function.\n *\n * Determines whether the value has changed.\n * Defaults to a shallow comparison with array support.\n *\n * ---\n *\n * @example\n * **1. Detect primitive value changes.**\n * ```tsx\n * const [count, setCount] = useState(0);\n *\n * useOnChange(count, (current, prev) => {\n *   console.log(\"Count changed:\", prev, \"➔\", current);\n * });\n * ```\n *\n * @example\n * **2. Detect object changes with custom comparator.**\n * ```tsx\n * type User = { id: number; name: string };\n *\n * useOnChange(\n *   user,\n *   (current, prev) => {\n *     console.log(\"User updated\", prev, current);\n *   },\n *   (prev, current) => prev.id !== current.id\n * );\n * ```\n *\n * @example\n * **3. Sync external state without `useEffect`.**\n * ```tsx\n * useOnChange(value, (current) => {\n *   localStorage.setItem(\"value\", JSON.stringify(current));\n * });\n * ```\n */\nexport function useOnChange<T>(\n  value: T,\n  onChange: (current: T, previous: T) => void,\n  isUpdated: (prev: T, current: T) => boolean = isDifferent\n): void {\n  const [prev, setPrev] = useState<T>(value);\n\n  if (isUpdated(prev, value)) {\n    onChange(value, prev);\n    setPrev(value);\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,SAAS,YAAY,GAAY,GAAqB;CACpD,IAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GACrC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,YAAY,GAAG,EAAE,EAAE,CAAC;CAGvE,OAAO,MAAM;AACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,SAAgB,YACd,OACA,UACA,YAA8C,aACxC;CACN,MAAM,CAAC,MAAM,+BAAuB,KAAK;CAEzC,IAAI,UAAU,MAAM,KAAK,GAAG;EAC1B,SAAS,OAAO,IAAI;EACpB,QAAQ,KAAK;CACf;AACF"}
