UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

106 lines (105 loc) 3.34 kB
"use client"; import _JSON$parse from "core-js-pure/stable/json/parse.js"; import { useCallback, useRef } from 'react'; import { useFilter } from "./useFilter.js"; import { useSharedState } from "../../../shared/helpers/useSharedState.js"; import { useIsomorphicLayoutEffect as useLayoutEffect } from "../../../shared/helpers/useIsomorphicLayoutEffect.js"; import { sanitizeUrlFilters } from "../utils/sanitizeUrlFilters.js"; const emptyState = { search: '', filters: {} }; export default function useFilterQueryLocator(id, options) { const { excludeSearch = false } = options !== null && options !== void 0 ? options : {}; const searchParam = `${id}-search`; const filtersParam = `${id}-filters`; const { extend } = useSharedState(id, emptyState); const { filters, search } = useFilter(id); const isRestoringRef = useRef(false); const writeToUrl = useCallback((currentSearch, currentFilters) => { if (isRestoringRef.current) { return; } const url = new URL(window.location.href); if (!excludeSearch) { if (currentSearch) { url.searchParams.set(searchParam, currentSearch); } else { url.searchParams.delete(searchParam); } } const filterKeys = Object.keys(currentFilters); if (filterKeys.length > 0) { url.searchParams.set(filtersParam, JSON.stringify(currentFilters)); } else { url.searchParams.delete(filtersParam); } window.history.replaceState({}, '', url.toString()); }, [searchParam, filtersParam, excludeSearch]); const readFromUrl = useCallback(() => { var _params$get; const params = new URLSearchParams(window.location.search); const urlSearch = excludeSearch ? '' : (_params$get = params.get(searchParam)) !== null && _params$get !== void 0 ? _params$get : ''; let urlFilters = {}; const filtersRaw = params.get(filtersParam); if (filtersRaw) { try { urlFilters = sanitizeUrlFilters(_JSON$parse(filtersRaw)); } catch {} } return { search: urlSearch, filters: urlFilters }; }, [searchParam, filtersParam, excludeSearch]); const restoreFromUrl = useCallback(() => { const { search: urlSearch, filters: urlFilters } = readFromUrl(); const hasState = urlSearch || Object.keys(urlFilters).length > 0; if (hasState) { isRestoringRef.current = true; extend({ search: urlSearch, filters: urlFilters }); isRestoringRef.current = false; } }, [readFromUrl, extend]); useLayoutEffect(() => { restoreFromUrl(); const handlePopstate = () => { restoreFromUrl(); }; window.addEventListener('popstate', handlePopstate); return () => window.removeEventListener('popstate', handlePopstate); }, [restoreFromUrl]); const prevRef = useRef({ search: '', filters: {} }); useLayoutEffect(() => { const prev = prevRef.current; const filtersChanged = JSON.stringify(prev.filters) !== JSON.stringify(filters); const searchChanged = prev.search !== search; if (filtersChanged || searchChanged) { prevRef.current = { search, filters }; writeToUrl(search, filters); } }, [search, filters, writeToUrl]); return { readFromUrl }; } //# sourceMappingURL=useQueryLocator.js.map