UNPKG

jotai-location

Version:
76 lines (75 loc) • 3.07 kB
import { atom } from 'jotai/vanilla'; import { RESET } from 'jotai/vanilla/utils'; const safeJSONParse = (initialValue) => (str) => { try { return JSON.parse(str); } catch (_a) { return initialValue; } }; export const setHashWithPush = (searchParams) => { const newUrl = `${window.location.pathname}${window.location.search}${searchParams ? `#${searchParams}` : ''}`; window.history.pushState(window.history.state, '', newUrl); }; export const setHashWithReplace = (searchParams) => { const newUrl = `${window.location.pathname}${window.location.search}${searchParams ? `#${searchParams}` : ''}`; window.history.replaceState(window.history.state, '', newUrl); }; function getSetHashFn(setHashOption) { if (setHashOption === 'replaceState') { return setHashWithReplace; } if (typeof setHashOption === 'function') { return setHashOption; } return setHashWithPush; } export function atomWithHash(key, initialValue, options) { const serialize = (options === null || options === void 0 ? void 0 : options.serialize) || JSON.stringify; const deserialize = (options === null || options === void 0 ? void 0 : options.deserialize) || safeJSONParse(initialValue); const subscribe = (options === null || options === void 0 ? void 0 : options.subscribe) || ((callback) => { window.addEventListener('hashchange', callback); return () => { window.removeEventListener('hashchange', callback); }; }); const isLocationAvailable = typeof window !== 'undefined' && !!window.location; const strAtom = atom(isLocationAvailable ? new URLSearchParams(window.location.hash.slice(1)).get(key) : null); strAtom.onMount = (setAtom) => { if (!isLocationAvailable) { return undefined; } const callback = () => { setAtom(new URLSearchParams(window.location.hash.slice(1)).get(key)); }; const unsubscribe = subscribe(callback); callback(); return unsubscribe; }; const valueAtom = atom((get) => { const str = get(strAtom); return str === null ? initialValue : deserialize(str); }); return atom((get) => get(valueAtom), (get, set, update, setOptions) => { var _a; const nextValue = typeof update === 'function' ? update(get(valueAtom)) : update; const searchParams = new URLSearchParams(window.location.hash.slice(1)); if (nextValue === RESET) { set(strAtom, null); searchParams.delete(key); } else { const str = serialize(nextValue); set(strAtom, str); searchParams.set(key, str); } const setHash = getSetHashFn((_a = setOptions === null || setOptions === void 0 ? void 0 : setOptions.setHash) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.setHash); setHash(searchParams.toString()); }); }