UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

102 lines (101 loc) 3.13 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 useFilterReactRouter(id, { useSearchParams, excludeSearch = false }) { const searchParam = `${id}-search`; const filtersParam = `${id}-filters`; const { extend } = useSharedState(id, emptyState); const { filters, search } = useFilter(id); const [searchParams, setSearchParams] = useSearchParams(); const isRestoringRef = useRef(false); const searchParamsRef = useRef(searchParams); searchParamsRef.current = searchParams; const writeToUrl = useCallback((currentSearch, currentFilters) => { if (isRestoringRef.current) { return; } const params = new URLSearchParams(searchParamsRef.current); if (!excludeSearch) { if (currentSearch) { params.set(searchParam, currentSearch); } else { params.delete(searchParam); } } const filterKeys = Object.keys(currentFilters); if (filterKeys.length > 0) { params.set(filtersParam, JSON.stringify(currentFilters)); } else { params.delete(filtersParam); } setSearchParams(params, { replace: true }); }, [searchParam, filtersParam, setSearchParams, excludeSearch]); const readFromUrl = useCallback(() => { var _searchParams$get; const urlSearch = excludeSearch ? '' : (_searchParams$get = searchParams.get(searchParam)) !== null && _searchParams$get !== void 0 ? _searchParams$get : ''; let urlFilters = {}; const filtersRaw = searchParams.get(filtersParam); if (filtersRaw) { try { urlFilters = sanitizeUrlFilters(_JSON$parse(filtersRaw)); } catch {} } return { search: urlSearch, filters: urlFilters }; }, [searchParams, searchParam, filtersParam, excludeSearch]); useLayoutEffect(() => { 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]); 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=useReactRouter.js.map