{"version":3,"sources":["../../src/use-cloned-state/index.ts"],"sourcesContent":["import { useLatest } from '../use-latest'\nimport { useSafeState } from '../use-safe-state'\nimport { useStableFn } from '../use-stable-fn'\nimport { useUpdateDeepCompareEffect } from '../use-update-deep-compare-effect'\nimport { useUpdateEffect } from '../use-update-effect'\n\nimport type { ReactSetState } from '../use-safe-state'\n\nexport type UseClonedStateOptions = {\n  /**\n   * Clone function\n   *\n   * @defaultValue defaultCloneFn (Implemented simply using JSON.parse(JSON.stringify(source)))\n   */\n  clone?: <T>(source: T) => T\n  /**\n   * Whether to manually trigger the synchronize (syncSource) function when the input state changes, defaulting to manual.\n   *\n   * @defaultValue true\n   */\n  manual?: boolean\n  /**\n   * Whether to perform a deep comparison of the input state and trigger the synchronize (syncSource) function only if the deep comparison result is false.\n   *\n   * deep comparison is enabled by default\n   *\n   * @defaultValue true\n   */\n  deep?: boolean\n}\n\nexport type UseClonedStateReturns<T> = readonly [\n  /**\n   * Cloned state\n   */\n  cloned: T,\n  /**\n   * Set cloned state\n   */\n  setCloned: ReactSetState<T>,\n  /**\n   * Synchronize cloned state with source state\n   */\n  syncSource: () => void,\n]\n\nexport type CloneFn<F, T = F> = (x: F) => T\n\nexport function defaultCloneFn<T>(source: T): T {\n  return JSON.parse(JSON.stringify(source))\n}\n\n/**\n * A React Hook for creating a cloned state that supports modification, synchronous operation, and isolation from each other.\n *\n * With support for custom `clone` functions, `JSON.parse(JSON.stringify(source))` by default.\n */\nexport function useClonedState<T>(source: T, options: UseClonedStateOptions = {}): UseClonedStateReturns<T> {\n  const { deep = true, manual = false, clone = defaultCloneFn } = options\n\n  const [cloned, setCloned] = useSafeState(() => clone(source))\n  const latest = useLatest({ manual, deep, source, clone })\n\n  const syncSource = useStableFn(() => {\n    const { clone, source } = latest.current\n    setCloned(clone(source))\n  })\n\n  // for shallow compare\n  useUpdateEffect(\n    () => {\n      !latest.current.manual && syncSource()\n    },\n    deep ? [] : [source],\n  )\n\n  // for deep compare\n  useUpdateDeepCompareEffect(\n    () => {\n      !latest.current.manual && syncSource()\n    },\n    deep ? [source] : [],\n  )\n\n  return [cloned, setCloned, syncSource] as const\n}\n"],"names":["defaultCloneFn","useClonedState","source","JSON","parse","stringify","options","deep","manual","clone","useSafeState","cloned","setCloned","latest","useLatest","syncSource","useStableFn","current","useUpdateEffect","useUpdateDeepCompareEffect"],"mappings":";;;;;;;;;;;QAgDgBA;eAAAA;;QASAC;eAAAA;;;yBAzDU;4BACG;2BACD;0CACe;+BACX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CzB,SAASD,eAAkBE,MAAS;IACzC,OAAOC,KAAKC,KAAK,CAACD,KAAKE,SAAS,CAACH;AACnC;AAOO,SAASD,eAAkBC,MAAS;QAAEI,UAAAA,iEAAiC,CAAC;IAC7E,oBAAgEA,QAAxDC,MAAAA,kCAAO,wCAAiDD,QAA3CE,QAAAA,sCAAS,0CAAkCF,QAA3BG,OAAAA,oCAAQT;IAE7C,IAA4BU,iCAAAA,IAAAA,0BAAY,EAAC;eAAMD,MAAMP;YAA9CS,SAAqBD,kBAAbE,YAAaF;IAC5B,IAAMG,SAASC,IAAAA,oBAAS,EAAC;QAAEN,QAAAA;QAAQD,MAAAA;QAAML,QAAAA;QAAQO,OAAAA;IAAM;IAEvD,IAAMM,aAAaC,IAAAA,wBAAW,EAAC;QAC7B,IAA0BH,kBAAAA,OAAOI,OAAO,EAAhCR,QAAkBI,gBAAlBJ,OAAOP,WAAWW,gBAAXX;QACfU,UAAUH,MAAMP;IAClB;IAEA,sBAAsB;IACtBgB,IAAAA,gCAAe,EACb;QACE,CAACL,OAAOI,OAAO,CAACT,MAAM,IAAIO;IAC5B,GACAR,OAAO,EAAE,GAAG;QAACL;KAAO;IAGtB,mBAAmB;IACnBiB,IAAAA,sDAA0B,EACxB;QACE,CAACN,OAAOI,OAAO,CAACT,MAAM,IAAIO;IAC5B,GACAR,OAAO;QAACL;KAAO,GAAG,EAAE;IAGtB,OAAO;QAACS;QAAQC;QAAWG;KAAW;AACxC"}