@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
106 lines (105 loc) • 3.34 kB
JavaScript
"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