UNPKG

jotai-location

Version:
1 lines • 9.52 kB
{"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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"}