{"version":3,"sources":["../../src/use-url-search-params/index.ts"],"sourcesContent":["import { useEventListener } from '../use-event-listener'\nimport { useMount } from '../use-mount'\nimport { usePausableUpdateDeepCompareEffect } from '../use-pausable-update-deep-compare-effect'\nimport { useSetState } from '../use-set-state'\nimport { useStableFn } from '../use-stable-fn'\nimport { isDefined, noNullish } from '../utils/basic'\n\nimport type { UseSetStateSetMergedState } from '../use-set-state'\nimport type { Arrayable, Noop, PureObject } from '../utils/basic'\n\nexport type UrlParamType = string | number | boolean | null | undefined\nexport type UrlParams = Record<string, Arrayable<UrlParamType>>\nexport type UseUrlSearchParamsMode = 'history' | 'hash' | 'hash-params'\n\nexport interface UseUrlSearchParamsOptions<T> {\n  /**\n   * Remove nullish values from the URLSearchParams\n   *\n   * @defaultValue true\n   */\n  removeNullishValues?: boolean\n  /**\n   * Remove falsy values from the URLSearchParams\n   *\n   * @defaultValue false\n   */\n  removeFalsyValues?: boolean\n  /**\n   * Initial value for the URLSearchParams\n   *\n   * @defaultValue {}\n   */\n  initialValue?: T & Record<string, Arrayable<UrlParamType>>\n  /**\n   * Write back to `window.history` automatically\n   *\n   * @defaultValue true\n   */\n  write?: boolean\n}\n\nexport type UseUrlSearchParamsReturns<T extends Record<string, Arrayable<UrlParamType>>> = readonly [\n  T,\n  UseSetStateSetMergedState<T>,\n  Noop,\n]\n\n/**\n * A React Hook that helps to manage the URL search params.\n *\n * There three mode in `useUrlSearchParams`:\n *\n * - **history**: like `/path/to/page?a=1&b=2`\n * - **hash**: like `/path/to/page#heading?a=1&b=2` (with `?` in hash)\n * - **hash-params**: like `/path/to/page#a=1&b=2` (without `?` in hash)\n */\nexport function useUrlSearchParams<T extends Record<string, Arrayable<UrlParamType>> = UrlParams>(\n  mode: UseUrlSearchParamsMode = 'history',\n  options: UseUrlSearchParamsOptions<T> = {},\n): UseUrlSearchParamsReturns<T> {\n  const {\n    initialValue = {} as T,\n    removeNullishValues: rmNullish = true,\n    removeFalsyValues: rmFalsy = false,\n    write: enableWrite = true,\n  } = options\n\n  const [state, setState] = useSetState<T>(initialValue as T, { deep: true })\n\n  function read() {\n    return new URLSearchParams(getRawParams(mode))\n  }\n\n  function updateState(params: URLSearchParams) {\n    const unusedKeys = new Set(Object.keys(state))\n    const nextState: Record<string, undefined | string | string[]> = {}\n\n    for (const key of params.keys()) {\n      const allValue = params.getAll(key)\n      const isArray = (key in initialValue && Array.isArray(initialValue[key])) || allValue.length > 1\n      const value = params[isArray ? 'getAll' : 'get'](key)\n      if (noNullish(value)) nextState[key] = value\n      unusedKeys.delete(key)\n    }\n\n    const unusedProps = Object.fromEntries(\n      [...unusedKeys.entries()].map(([k, _v]) => {\n        const isArray = k in initialValue && Array.isArray(initialValue[k])\n        return [k, isArray ? [] : undefined]\n      }),\n    )\n\n    setState({ ...nextState, ...unusedProps } as Pick<T, keyof T>)\n  }\n\n  const pausable = usePausableUpdateDeepCompareEffect(() => {\n    enableWrite && write(obj2URLSearchParams(state, rmNullish, rmFalsy))\n  }, [state, enableWrite, rmNullish, rmFalsy])\n\n  function write(params: URLSearchParams) {\n    pausable.pause()\n    history.replaceState(history.state, document.title, location.pathname + constructQuery(params, mode))\n    pausable.resume()\n  }\n\n  function handleChange() {\n    updateState(read())\n  }\n\n  useEventListener(() => window, 'popstate', handleChange, false)\n\n  useEventListener(() => window, mode !== 'history' ? 'hashchange' : [], handleChange, false)\n\n  useMount(() => {\n    const initialSp = read()\n\n    if (initialSp.size) {\n      updateState(initialSp)\n    } else {\n      const sp = obj2URLSearchParams(initialValue, rmNullish, rmFalsy)\n      sp.size && enableWrite && write(sp)\n    }\n  })\n\n  const clearParams = useStableFn(() => {\n    updateState(new URLSearchParams())\n    enableWrite && write(new URLSearchParams())\n  })\n\n  return [state, setState, clearParams] as const\n}\n\nfunction getRawParams(mode: UseUrlSearchParamsMode) {\n  if (mode === 'history') {\n    return location.search || ''\n  }\n\n  const hash = (location.hash || '').replace(/^#/, '')\n  const index = hash.indexOf('?')\n\n  if (mode === 'hash') {\n    return index >= 0 ? hash.slice(index) : ''\n  }\n\n  if (mode === 'hash-params') {\n    return index >= 0 ? hash.slice(0, index) : hash\n  }\n}\n\nfunction constructQuery(params: URLSearchParams, mode: UseUrlSearchParamsMode) {\n  const stringified = params.toString()\n\n  /**\n   * /path/to/page?mode=history#hash\n   */\n  if (mode === 'history') {\n    return `${stringified ? `?${stringified}` : ''}${location.hash || ''}`\n  }\n\n  const search = location.search\n  const hash = (location.hash || '').replace(/^#/, '')\n  const questionMarkIdx = hash.indexOf('?')\n\n  /**\n   * /path/to/page#hash-pre?mode=hash\n   *\n   * hash = hash-pre?mode=hash\n   * hashPrefix = hash-pre\n   */\n  if (mode === 'hash') {\n    const prefix = questionMarkIdx >= 0 ? hash.slice(0, questionMarkIdx) : hash\n    return `${search}${prefix || stringified ? '#' : ''}${prefix}${stringified ? `?${stringified}` : ''}`\n  }\n\n  /**\n   * /path/to/page#mode=hash-params?hash-suffix\n   *\n   * hash = mode=hash-params?hash-suffix\n   */\n  if (mode === 'hash-params') {\n    const suffix = questionMarkIdx >= 0 ? hash.slice(questionMarkIdx) : ''\n    return `${search}${suffix || stringified ? '#' : ''}${stringified || ''}${suffix}`\n  }\n\n  return ''\n}\n\nfunction obj2URLSearchParams(obj: PureObject, rmNullish = false, rmFalsy = false) {\n  const sp: URLSearchParams = new URLSearchParams()\n\n  for (const [key, value] of Object.entries(obj)) {\n    if (Array.isArray(value)) {\n      for (const item of value) {\n        if (isDefined(item)) {\n          sp.append(key, item.toString())\n        }\n      }\n    } else if (rmNullish && !noNullish(value)) {\n      sp.delete(key)\n    } else if (rmFalsy && !value) {\n      sp.delete(key)\n    } else {\n      if (isDefined(value)) {\n        sp.set(key, value.toString())\n      } else {\n        sp.delete(key)\n      }\n    }\n  }\n\n  return sp\n}\n"],"names":["useUrlSearchParams","mode","options","initialValue","rmNullish","removeNullishValues","rmFalsy","removeFalsyValues","enableWrite","write","useSetState","deep","state","setState","read","URLSearchParams","getRawParams","updateState","params","unusedKeys","Set","Object","keys","nextState","key","allValue","getAll","isArray","Array","length","value","noNullish","delete","unusedProps","fromEntries","entries","map","k","_v","undefined","pausable","usePausableUpdateDeepCompareEffect","obj2URLSearchParams","pause","history","replaceState","document","title","location","pathname","constructQuery","resume","handleChange","useEventListener","window","useMount","initialSp","size","sp","clearParams","useStableFn","search","hash","replace","index","indexOf","slice","stringified","toString","questionMarkIdx","prefix","suffix","obj","item","isDefined","append","set"],"mappings":"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"}