{"version":3,"file":"index.modern.mjs","sources":["../src/atomWithLocation.ts","../src/atomWithHash.ts"],"sourcesContent":["import { atom } from 'jotai/vanilla';\nimport type { SetStateAction, WritableAtom } from 'jotai/vanilla';\n\ntype Location = {\n  pathname?: string;\n  searchParams?: URLSearchParams;\n  hash?: string;\n};\n\nconst getLocation = (): Location => {\n  if (typeof window === 'undefined' || !window.location) {\n    return {};\n  }\n  return {\n    pathname: window.location.pathname,\n    searchParams: new URLSearchParams(window.location.search),\n    hash: window.location.hash,\n  };\n};\n\nconst applyLocation = (\n  location: Location,\n  options?: { replace?: boolean },\n): void => {\n  const url = new URL(window.location.href);\n  if ('pathname' in location) {\n    url.pathname = location.pathname;\n  }\n  if ('searchParams' in location) {\n    url.search = location.searchParams.toString();\n  }\n  if ('hash' in location) {\n    url.hash = location.hash;\n  }\n  if (options?.replace) {\n    window.history.replaceState(window.history.state, '', url);\n  } else {\n    window.history.pushState(null, '', url);\n  }\n};\n\nconst subscribe = (callback: () => void) => {\n  window.addEventListener('popstate', callback);\n  return () => window.removeEventListener('popstate', callback);\n};\n\ntype Options<T> = {\n  preloaded?: T;\n  replace?: boolean;\n  getLocation?: () => T;\n  applyLocation?: (location: T, options?: { replace?: boolean }) => void;\n  subscribe?: (callback: () => void) => () => void;\n};\n\ntype RequiredOptions<T> = Omit<Options<T>, 'getLocation' | 'applyLocation'> &\n  Required<Pick<Options<T>, 'getLocation' | 'applyLocation'>>;\n\ntype AtomOptions<T> = Pick<Options<T>, 'replace'>;\n\nexport function atomWithLocation(\n  options?: Options<Location>,\n): WritableAtom<\n  Location,\n  [SetStateAction<Location>, AtomOptions<Location>?],\n  void\n>;\n\nexport function atomWithLocation<T>(\n  options: RequiredOptions<T>,\n): WritableAtom<T, [SetStateAction<T>, AtomOptions<T>?], void>;\n\nexport function atomWithLocation<T>(options?: Options<T>) {\n  const getL =\n    options?.getLocation ||\n    (getLocation as unknown as NonNullable<Options<T>['getLocation']>);\n  const appL =\n    options?.applyLocation ||\n    (applyLocation as unknown as NonNullable<Options<T>['applyLocation']>);\n  const sub = options?.subscribe || subscribe;\n  const baseAtom = atom(options?.preloaded ?? getL());\n\n  if (process.env.NODE_ENV !== 'production') {\n    baseAtom.debugPrivate = true;\n  }\n\n  baseAtom.onMount = (set) => {\n    const callback = () => set(getL());\n    const unsub = sub(callback);\n    callback();\n    return unsub;\n  };\n  const derivedAtom = atom(\n    (get) => get(baseAtom),\n    (get, set, arg: SetStateAction<T>, atomOptions: AtomOptions<T> = {}) => {\n      set(baseAtom, arg);\n      appL(get(baseAtom), { ...options, ...atomOptions });\n    },\n  );\n  return derivedAtom;\n}\n","import { atom } from 'jotai/vanilla';\nimport type { WritableAtom } from 'jotai/vanilla';\nimport { RESET } from 'jotai/vanilla/utils';\n\ntype SetStateActionWithReset<Value> =\n  | Value\n  | typeof RESET\n  | ((prev: Value) => Value | typeof RESET);\n\nconst safeJSONParse = (initialValue: unknown) => (str: string) => {\n  try {\n    return JSON.parse(str);\n  } catch (e) {\n    return initialValue;\n  }\n};\n\nexport type SetHashOption =\n  | 'default'\n  | 'replaceState'\n  | ((searchParams: string) => void);\n\nexport type AtomWithHashSetOptions = {\n  setHash?: SetHashOption;\n};\n\nexport const setHashWithPush = (searchParams: string) => {\n  window.location.hash = searchParams;\n};\n\nexport const setHashWithReplace = (searchParams: string): void => {\n  window.history.replaceState(\n    window.history.state,\n    '',\n    `${window.location.pathname}${window.location.search}#${searchParams}`,\n  );\n};\n\nfunction getSetHashFn(setHashOption?: SetHashOption) {\n  if (setHashOption === 'replaceState') {\n    return setHashWithReplace;\n  }\n  if (typeof setHashOption === 'function') {\n    return setHashOption;\n  }\n  return setHashWithPush;\n}\n\nexport function atomWithHash<Value>(\n  key: string,\n  initialValue: Value,\n  options?: {\n    serialize?: (val: Value) => string;\n    deserialize?: (str: string) => Value;\n    subscribe?: (callback: () => void) => () => void;\n    setHash?: SetHashOption;\n  },\n): WritableAtom<\n  Value,\n  [SetStateActionWithReset<Value>, AtomWithHashSetOptions?],\n  void\n> {\n  const serialize = options?.serialize || JSON.stringify;\n\n  const deserialize = options?.deserialize || safeJSONParse(initialValue);\n  const subscribe =\n    options?.subscribe ||\n    ((callback) => {\n      window.addEventListener('hashchange', callback);\n      return () => {\n        window.removeEventListener('hashchange', callback);\n      };\n    });\n\n  const isLocationAvailable =\n    typeof window !== 'undefined' && !!window.location;\n\n  const strAtom = atom(\n    isLocationAvailable\n      ? new URLSearchParams(window.location.hash.slice(1)).get(key)\n      : null,\n  );\n  strAtom.onMount = (setAtom) => {\n    if (!isLocationAvailable) {\n      return undefined;\n    }\n    const callback = () => {\n      setAtom(new URLSearchParams(window.location.hash.slice(1)).get(key));\n    };\n    const unsubscribe = subscribe(callback);\n    callback();\n    return unsubscribe;\n  };\n  const valueAtom = atom((get) => {\n    const str = get(strAtom);\n    return str === null ? initialValue : deserialize(str);\n  });\n  return atom(\n    (get) => get(valueAtom),\n    (\n      get,\n      set,\n      update: SetStateActionWithReset<Value>,\n      setOptions?: AtomWithHashSetOptions,\n    ) => {\n      const nextValue =\n        typeof update === 'function'\n          ? (update as (prev: Value) => Value | typeof RESET)(get(valueAtom))\n          : update;\n      const searchParams = new URLSearchParams(window.location.hash.slice(1));\n      if (nextValue === RESET) {\n        set(strAtom, null);\n        searchParams.delete(key);\n      } else {\n        const str = serialize(nextValue);\n        set(strAtom, str);\n        searchParams.set(key, str);\n      }\n      const setHash = getSetHashFn(setOptions?.setHash ?? options?.setHash);\n      setHash(searchParams.toString());\n    },\n  );\n}\n"],"names":["getLocation","window","location","pathname","searchParams","URLSearchParams","search","hash","applyLocation","options","url","URL","href","toString","replace","history","replaceState","state","pushState","subscribe","callback","addEventListener","removeEventListener","atomWithLocation","_options$preloaded","getL","appL","sub","baseAtom","atom","preloaded","process","env","NODE_ENV","debugPrivate","onMount","set","unsub","get","arg","atomOptions","_extends","setHashWithPush","setHashWithReplace","atomWithHash","key","initialValue","serialize","JSON","stringify","deserialize","str","parse","e","safeJSONParse","isLocationAvailable","strAtom","slice","setAtom","unsubscribe","valueAtom","update","setOptions","_setOptions$setHash","nextValue","RESET","delete","setHashOption","setHash"],"mappings":"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"}