@trackunit/filters-filter-bar 1.7.88 → 1.7.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.js +420 -71
- package/index.esm.js +415 -74
- package/package.json +14 -14
- package/src/lib/hooks/types.d.ts +4 -0
- package/src/lib/hooks/useSearchParamAsFilter.d.ts +1 -3
- package/src/lib/hooks/utils/useFilterBarActions.d.ts +1 -1
- package/src/lib/hooks/utils/useFilterBarPersistence.d.ts +46 -2
- package/src/lib/hooks/utils/useFilterUrlSync.d.ts +10 -0
- package/src/lib/hooks/utils/useIsDefaultValue.d.ts +10 -0
- package/src/lib/hooks/utils/useSearchUtils.d.ts +8 -0
- package/src/lib/types/FilterTypes.d.ts +21 -3
- package/src/lib/types/FilterZodTypes.d.ts +44 -0
package/index.cjs.js
CHANGED
|
@@ -15,9 +15,9 @@ var tailwindMerge = require('tailwind-merge');
|
|
|
15
15
|
var irisAppApi = require('@trackunit/iris-app-api');
|
|
16
16
|
var cssClassVarianceUtilities = require('@trackunit/css-class-variance-utilities');
|
|
17
17
|
var dequal = require('dequal');
|
|
18
|
-
var isEqual = require('lodash/isEqual');
|
|
19
18
|
var geoJsonUtils = require('@trackunit/geo-json-utils');
|
|
20
19
|
var zod = require('zod');
|
|
20
|
+
var reactRouter = require('@tanstack/react-router');
|
|
21
21
|
|
|
22
22
|
var defaultTranslations = {
|
|
23
23
|
"access.management.filter.operator.role.keyAdmin": "Key Admin",
|
|
@@ -1061,7 +1061,7 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
|
|
|
1061
1061
|
setSearchText("");
|
|
1062
1062
|
}
|
|
1063
1063
|
}, placement: "bottom-start", children: modalState => {
|
|
1064
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx("div", { "data-testid": "starred-filters-menu-trigger", id: "starred-filters-menu-trigger", children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: !compact || modalState.isOpen, label: jsxRuntime.jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filters: appliedFilters }), children: jsxRuntime.jsx(reactComponents.Button, { prefix: jsxRuntime.jsx(reactComponents.Icon, { ariaHidden: true, color: filterBarConfig.appliedFilterKeys().length > 0 ? "primary" : undefined, name: "Filter", size: "small" }), size: "small", suffix: compact && showAppliedFiltersCount && filterBarConfig.appliedFilterKeys().length > 0
|
|
1064
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx("div", { "data-testid": "starred-filters-menu-trigger", id: "starred-filters-menu-trigger", children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: !compact || modalState.isOpen, label: jsxRuntime.jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filters: appliedFilters }), children: !isSm ? (jsxRuntime.jsx(reactComponents.IconButton, { "aria-label": title ?? t("filtersBar.filtersHeading"), icon: jsxRuntime.jsx(reactComponents.Icon, { ariaHidden: true, color: filterBarConfig.appliedFilterKeys().length > 0 ? "primary" : undefined, name: "Filter", size: "small" }), size: "small", variant: "secondary", ...buttonProps })) : (jsxRuntime.jsx(reactComponents.Button, { prefix: jsxRuntime.jsx(reactComponents.Icon, { ariaHidden: true, color: filterBarConfig.appliedFilterKeys().length > 0 ? "primary" : undefined, name: "Filter", size: "small" }), size: "small", suffix: compact && showAppliedFiltersCount && filterBarConfig.appliedFilterKeys().length > 0 ? (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("span", { "aria-hidden": true, children: ["(", filterBarConfig.appliedFilterKeys().length, ")"] }), jsxRuntime.jsxs("span", { className: "sr-only", children: [filterBarConfig.appliedFilterKeys().length, " filters applied"] })] })) : undefined, variant: "secondary", ...buttonProps, children: title !== "" ? (title ?? t("filtersBar.filtersHeading")) : null })) }) }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { cellPadding: 100, children: jsxRuntime.jsx(FiltersMenuContent, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, filterBarDefinitionCount: filterBarDefinitionCount, filtersToShowGrouped: filtersToShowGrouped, hasCustomFields: hasCustomFields, removeCustomFieldsGroup: removeCustomFieldsGroup, searchResultsGrouped: searchResultsGrouped, searchText: searchText, setSearchText: setSearchText, setShowCustomFilters: setShowCustomFilters, showCustomFilters: showCustomFilters }) })] }));
|
|
1065
1065
|
} }), showDirectlyFilters.length > 0 ? (jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: showDirectlyFilters })) : null, !compact ? jsxRuntime.jsx(AppliedFiltersRenderer, { appliedFilters: appliedFilters, filterBarConfig: filterBarConfig }) : null] }));
|
|
1066
1066
|
};
|
|
1067
1067
|
|
|
@@ -1437,6 +1437,23 @@ const createInitialState = ({ name, mainFilters, setValue, }) => {
|
|
|
1437
1437
|
* Dont move these to FilterTypes.ts since rollup will mess up the type.d.ts file by moving jsdocs in random places.
|
|
1438
1438
|
*/
|
|
1439
1439
|
const areaFilterGeoJsonGeometrySchema = zod.z.union([geoJsonUtils.geoJsonPolygonSchema, geoJsonUtils.geoJsonMultiPolygonSchema]);
|
|
1440
|
+
const stringSchema = zod.z.string();
|
|
1441
|
+
const stringArraySchema = zod.z.array(zod.z.string());
|
|
1442
|
+
const numberSchema = zod.z.number();
|
|
1443
|
+
const booleanSchema = zod.z.boolean();
|
|
1444
|
+
const valueNameSchema = zod.z.object({
|
|
1445
|
+
value: stringSchema,
|
|
1446
|
+
name: stringSchema,
|
|
1447
|
+
});
|
|
1448
|
+
const minMaxFilterSchema = zod.z.object({
|
|
1449
|
+
min: numberSchema.optional(),
|
|
1450
|
+
max: numberSchema.optional(),
|
|
1451
|
+
});
|
|
1452
|
+
const dateRangeSchema = zod.z.object({
|
|
1453
|
+
from: stringSchema.optional(),
|
|
1454
|
+
to: stringSchema.optional(),
|
|
1455
|
+
});
|
|
1456
|
+
const valueNameArraySchema = zod.z.array(valueNameSchema);
|
|
1440
1457
|
|
|
1441
1458
|
const hasValue = (value) => {
|
|
1442
1459
|
if (value === undefined || value === null) {
|
|
@@ -1542,9 +1559,49 @@ const validateFilter = ({ values, filterDefinitions, }) => {
|
|
|
1542
1559
|
inBadState = true;
|
|
1543
1560
|
}
|
|
1544
1561
|
});
|
|
1545
|
-
stateKeys
|
|
1546
|
-
|
|
1547
|
-
|
|
1562
|
+
// check that all keys in stateKeys are in filterDefinitions
|
|
1563
|
+
stateKeys.forEach(stateKey => {
|
|
1564
|
+
if (!filterDefinitions.find(filterDefinition => filterDefinition.filterKey === stateKey)) {
|
|
1565
|
+
inBadState = true;
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
return !inBadState;
|
|
1569
|
+
};
|
|
1570
|
+
|
|
1571
|
+
/**
|
|
1572
|
+
* Generic hook for setting the value of a filter bar.
|
|
1573
|
+
*
|
|
1574
|
+
* @template TFilterBarDefinition - The type of the filter bar definition.
|
|
1575
|
+
* @returns {object} An object containing the setValue function.
|
|
1576
|
+
*/
|
|
1577
|
+
const useIsDefaultValue = () => {
|
|
1578
|
+
const isDefaultValue = react.useCallback((key, filterValue, filterBarDefinition, initialState) => {
|
|
1579
|
+
const filterDefinition = filterBarDefinition[key];
|
|
1580
|
+
if ((initialState && dequal.dequal(filterValue, initialState[key])) ||
|
|
1581
|
+
dequal.dequal(filterValue, filterDefinition?.defaultValue)) {
|
|
1582
|
+
return true;
|
|
1583
|
+
}
|
|
1584
|
+
if (!filterValue) {
|
|
1585
|
+
return true;
|
|
1586
|
+
}
|
|
1587
|
+
if (Array.isArray(filterValue)) {
|
|
1588
|
+
return filterValue.length === 0;
|
|
1589
|
+
}
|
|
1590
|
+
if (isMinMaxFilterValue(filterValue)) {
|
|
1591
|
+
return filterValue.min === undefined && filterValue.max === undefined;
|
|
1592
|
+
}
|
|
1593
|
+
if (isValueName(filterValue)) {
|
|
1594
|
+
return filterValue.value === "";
|
|
1595
|
+
}
|
|
1596
|
+
if (isDateRangeValue(filterValue)) {
|
|
1597
|
+
return filterValue.from === undefined && filterValue.to === undefined;
|
|
1598
|
+
}
|
|
1599
|
+
if (typeof filterValue === "object") {
|
|
1600
|
+
return sharedUtils.objectKeys(filterValue).length === 0;
|
|
1601
|
+
}
|
|
1602
|
+
return false;
|
|
1603
|
+
}, []);
|
|
1604
|
+
return react.useMemo(() => ({ isDefaultValue }), [isDefaultValue]);
|
|
1548
1605
|
};
|
|
1549
1606
|
|
|
1550
1607
|
/**
|
|
@@ -1554,6 +1611,7 @@ const validateFilter = ({ values, filterDefinitions, }) => {
|
|
|
1554
1611
|
* @returns {object} An object containing filter bar configuration and actions.
|
|
1555
1612
|
*/
|
|
1556
1613
|
const useFilterBarActions = ({ name, filterBarConfig, filterBarDefinition, setFilterBarConfig, setValue, initialState, }) => {
|
|
1614
|
+
const { isDefaultValue } = useIsDefaultValue();
|
|
1557
1615
|
const filterMapGetter = react.useMemo(() => {
|
|
1558
1616
|
return {
|
|
1559
1617
|
getFilterBarName: () => {
|
|
@@ -1566,28 +1624,7 @@ const useFilterBarActions = ({ name, filterBarConfig, filterBarDefinition, setFi
|
|
|
1566
1624
|
const filter = filterBarConfig.values[key];
|
|
1567
1625
|
return filter?.includes(value) || false;
|
|
1568
1626
|
},
|
|
1569
|
-
isDefaultValue(key,
|
|
1570
|
-
const filterDefinition = filterBarDefinition[key];
|
|
1571
|
-
if (dequal.dequal(filterValue, initialState?.[key]) || dequal.dequal(filterValue, filterDefinition?.defaultValue)) {
|
|
1572
|
-
return true;
|
|
1573
|
-
}
|
|
1574
|
-
if (!filterValue) {
|
|
1575
|
-
return true;
|
|
1576
|
-
}
|
|
1577
|
-
if (Array.isArray(filterValue)) {
|
|
1578
|
-
return filterValue.length === 0;
|
|
1579
|
-
}
|
|
1580
|
-
if (isMinMaxFilterValue(filterValue)) {
|
|
1581
|
-
return filterValue.min === undefined && filterValue.max === undefined;
|
|
1582
|
-
}
|
|
1583
|
-
if (isValueName(filterValue)) {
|
|
1584
|
-
return filterValue.value === "";
|
|
1585
|
-
}
|
|
1586
|
-
if (typeof filterValue === "object") {
|
|
1587
|
-
return sharedUtils.objectKeys(filterValue).length === 0;
|
|
1588
|
-
}
|
|
1589
|
-
return false;
|
|
1590
|
-
},
|
|
1627
|
+
isDefaultValue: (key, value) => isDefaultValue(key, value, filterBarDefinition, initialState),
|
|
1591
1628
|
getValuesByKey(key) {
|
|
1592
1629
|
return filterBarConfig.values[key];
|
|
1593
1630
|
},
|
|
@@ -1614,7 +1651,7 @@ const useFilterBarActions = ({ name, filterBarConfig, filterBarDefinition, setFi
|
|
|
1614
1651
|
return filter?.value === value || false;
|
|
1615
1652
|
},
|
|
1616
1653
|
};
|
|
1617
|
-
}, [filterBarDefinition, filterBarConfig.name, filterBarConfig.values, initialState]);
|
|
1654
|
+
}, [filterBarDefinition, filterBarConfig.name, filterBarConfig.values, initialState, isDefaultValue]);
|
|
1618
1655
|
const filterMapActions = react.useMemo(() => {
|
|
1619
1656
|
// Reset an individual filter to its initial state
|
|
1620
1657
|
const resetIndividualFilterToInitialState = (key) => {
|
|
@@ -1831,6 +1868,127 @@ const useFilterBarActions = ({ name, filterBarConfig, filterBarDefinition, setFi
|
|
|
1831
1868
|
return react.useMemo(() => ({ filterMapGetter, filterMapActions }), [filterMapGetter, filterMapActions]);
|
|
1832
1869
|
};
|
|
1833
1870
|
|
|
1871
|
+
/**
|
|
1872
|
+
* Hook to sync filter values with URL
|
|
1873
|
+
*
|
|
1874
|
+
* @returns {object} Object containing loadFromUrl and saveToUrl functions
|
|
1875
|
+
*/
|
|
1876
|
+
const useFilterUrlSync = () => {
|
|
1877
|
+
const getZodSchema = react.useCallback((filterType) => {
|
|
1878
|
+
if (filterType === "string") {
|
|
1879
|
+
return stringSchema;
|
|
1880
|
+
}
|
|
1881
|
+
else if (filterType === "stringArray") {
|
|
1882
|
+
return stringArraySchema;
|
|
1883
|
+
}
|
|
1884
|
+
else if (filterType === "dateRange") {
|
|
1885
|
+
return dateRangeSchema;
|
|
1886
|
+
}
|
|
1887
|
+
else if (filterType === "area") {
|
|
1888
|
+
return areaFilterGeoJsonGeometrySchema;
|
|
1889
|
+
}
|
|
1890
|
+
else if (filterType === "valueNameArray") {
|
|
1891
|
+
return valueNameArraySchema;
|
|
1892
|
+
}
|
|
1893
|
+
else if (filterType === "valueName") {
|
|
1894
|
+
return valueNameSchema;
|
|
1895
|
+
}
|
|
1896
|
+
else if (filterType === "minMax") {
|
|
1897
|
+
return minMaxFilterSchema;
|
|
1898
|
+
}
|
|
1899
|
+
else if (filterType === "boolean") {
|
|
1900
|
+
return booleanSchema;
|
|
1901
|
+
}
|
|
1902
|
+
return numberSchema;
|
|
1903
|
+
}, []);
|
|
1904
|
+
const getJsonParsedVal = react.useCallback((filterValue, zodSchema) => {
|
|
1905
|
+
if (!zodSchema) {
|
|
1906
|
+
return filterValue;
|
|
1907
|
+
}
|
|
1908
|
+
if (zodSchema._def.typeName === "ZodString") {
|
|
1909
|
+
return filterValue ? filterValue + "" : filterValue;
|
|
1910
|
+
}
|
|
1911
|
+
if (typeof filterValue === "string") {
|
|
1912
|
+
try {
|
|
1913
|
+
return JSON.parse(filterValue);
|
|
1914
|
+
}
|
|
1915
|
+
catch (e) {
|
|
1916
|
+
return filterValue;
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
return filterValue;
|
|
1920
|
+
}, []);
|
|
1921
|
+
const getFilterValuesFromUrl = react.useCallback((definitions, search) => {
|
|
1922
|
+
const loadedValues = {};
|
|
1923
|
+
definitions.forEach(filter => {
|
|
1924
|
+
const filterValue = search[filter.filterKey];
|
|
1925
|
+
if (filterValue) {
|
|
1926
|
+
const zodSchema = filter.zodSchema || getZodSchema(filter.type);
|
|
1927
|
+
const jsonParsed = getJsonParsedVal(filterValue, zodSchema);
|
|
1928
|
+
const zodParsed = zodSchema.safeParse(jsonParsed);
|
|
1929
|
+
if (zodParsed.success) {
|
|
1930
|
+
loadedValues[filter.filterKey] = zodParsed.data;
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
});
|
|
1934
|
+
return loadedValues;
|
|
1935
|
+
}, [getJsonParsedVal, getZodSchema]);
|
|
1936
|
+
const getFilterValuesToUrl = react.useCallback((values, definitions, setEmptyAndDefaultValues, isDefaultValue) => {
|
|
1937
|
+
const urlObject = {};
|
|
1938
|
+
definitions.forEach(filter => {
|
|
1939
|
+
const value = values?.[filter.filterKey];
|
|
1940
|
+
if (value) {
|
|
1941
|
+
if (setEmptyAndDefaultValues) {
|
|
1942
|
+
urlObject[filter.filterKey] = value;
|
|
1943
|
+
}
|
|
1944
|
+
else if (!isDefaultValue(filter.filterKey, value)) {
|
|
1945
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
1946
|
+
delete urlObject[filter.filterKey];
|
|
1947
|
+
}
|
|
1948
|
+
else {
|
|
1949
|
+
urlObject[filter.filterKey] = value;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
else {
|
|
1953
|
+
delete urlObject[filter.filterKey];
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
});
|
|
1957
|
+
return urlObject;
|
|
1958
|
+
}, []);
|
|
1959
|
+
return react.useMemo(() => ({
|
|
1960
|
+
getFilterValuesFromUrl,
|
|
1961
|
+
getFilterValuesToUrl,
|
|
1962
|
+
}), [getFilterValuesFromUrl, getFilterValuesToUrl]);
|
|
1963
|
+
};
|
|
1964
|
+
|
|
1965
|
+
/**
|
|
1966
|
+
* This hook provides functionality to:
|
|
1967
|
+
* - Get the length of the search parameters excluding a specific key
|
|
1968
|
+
*/
|
|
1969
|
+
const useSearchUtils = () => {
|
|
1970
|
+
const location = reactRouter.useLocation();
|
|
1971
|
+
const getSearchParamsLengthExcluding = react.useCallback((excludeKey, searchParams) => {
|
|
1972
|
+
return sharedUtils.objectKeys(searchParams)
|
|
1973
|
+
.filter(key => key !== excludeKey)
|
|
1974
|
+
.reduce((totalLength, key) => {
|
|
1975
|
+
const keyLength = encodeURIComponent(String(key)).length;
|
|
1976
|
+
const value = searchParams[key] !== null ? encodeURIComponent(searchParams[key]?.toString() ?? "") : "";
|
|
1977
|
+
const valueLength = value.length;
|
|
1978
|
+
// Add 1 for '=' and 1 for '&' (except for the first param)
|
|
1979
|
+
return totalLength + keyLength + valueLength + (totalLength > 0 ? 2 : 1);
|
|
1980
|
+
}, 0);
|
|
1981
|
+
}, []);
|
|
1982
|
+
const getUrlLengthWithSearchParam = react.useCallback((key, value, prev) => {
|
|
1983
|
+
const searchParamsLength = getSearchParamsLengthExcluding(key, prev);
|
|
1984
|
+
const urlLength = location.href.length - (location.searchStr.length || 0) + (location.hash.length || 0) + searchParamsLength;
|
|
1985
|
+
// 1 === '&' and 1 === '='
|
|
1986
|
+
return urlLength + 1 + key.length + 1 + value.length;
|
|
1987
|
+
}, [getSearchParamsLengthExcluding, location]);
|
|
1988
|
+
return react.useMemo(() => ({ getSearchParamsLengthExcluding, getUrlLengthWithSearchParam }), [getSearchParamsLengthExcluding, getUrlLengthWithSearchParam]);
|
|
1989
|
+
};
|
|
1990
|
+
|
|
1991
|
+
const MAX_URL_LENGTH = 5000;
|
|
1834
1992
|
/**
|
|
1835
1993
|
* Get the persistence key for the filter bar.
|
|
1836
1994
|
*
|
|
@@ -1842,20 +2000,131 @@ const getPersistenceKey = (name, clientSideUserId) => `filter-${name}-${clientSi
|
|
|
1842
2000
|
/**
|
|
1843
2001
|
* Custom hook for managing the persistence of filter bar configurations.
|
|
1844
2002
|
*
|
|
2003
|
+
* This hook provides a complete state management solution for filter bars with automatic
|
|
2004
|
+
* URL synchronization and localStorage persistence. It maintains the following state:
|
|
2005
|
+
*
|
|
2006
|
+
* ## State Management Flow:
|
|
2007
|
+
*
|
|
2008
|
+
* 1. **Initial Load**:
|
|
2009
|
+
* - Loads from localStorage (if no custom loadData or saveData function is provided)
|
|
2010
|
+
* - Updates with state from URL search parameters
|
|
2011
|
+
* - Ensures URL is updated with the final state after load
|
|
2012
|
+
*
|
|
2013
|
+
* 2. **Save Operations**:
|
|
2014
|
+
* - Updates localStorage with new filter values
|
|
2015
|
+
* - Updates URL search parameters to reflect current state
|
|
2016
|
+
* - Maintains synchronization between localStorage and URL
|
|
2017
|
+
*
|
|
2018
|
+
* 3. **URL Change Detection**:
|
|
2019
|
+
* - Listens for changes in URL search parameters
|
|
2020
|
+
* - Compares URL state with last known state to detect external changes
|
|
2021
|
+
* - Triggers refreshData callback when external URL changes are detected
|
|
2022
|
+
* - Only updates URL when no custom loadData or saveData function provided
|
|
2023
|
+
*
|
|
2024
|
+
* ## Behavior Modes:
|
|
2025
|
+
*
|
|
2026
|
+
* **Default Mode** (no custom functions):
|
|
2027
|
+
* - Uses localStorage for persistence
|
|
2028
|
+
* - Automatically syncs with URL search parameters
|
|
2029
|
+
* - Handles URL updates and change detection
|
|
2030
|
+
*
|
|
2031
|
+
* **Custom Mode** (with loadData/saveData functions):
|
|
2032
|
+
* - Does NOT sync with URL or use localStorage
|
|
2033
|
+
* - Relies entirely on provided functions for persistence
|
|
2034
|
+
* - Does not provide URL change detection via refreshData callback
|
|
2035
|
+
*
|
|
2036
|
+
* The hook prevents infinite loops by:
|
|
2037
|
+
* - Tracking what state was last sent to the URL
|
|
2038
|
+
* - Only updating URL when state actually changes
|
|
2039
|
+
* - Distinguishing between internal state changes and external URL changes
|
|
2040
|
+
*
|
|
1845
2041
|
* @template TFilterBarDefinition - The type of the filter bar definition.
|
|
1846
2042
|
* @param {FilterBarPersistenceProps<TFilterBarDefinition>} props - The props for the filter bar persistence.
|
|
1847
2043
|
* @returns { object } An object containing the loadData and saveData functions.
|
|
1848
2044
|
*/
|
|
1849
|
-
const useFilterBarPersistence = ({ name, setValue, loadData: inputLoadData, saveData: inputSaveData, }) => {
|
|
2045
|
+
const useFilterBarPersistence = ({ name, setValue, refreshData, isDefaultValue, loadData: inputLoadData, saveData: inputSaveData, }) => {
|
|
1850
2046
|
const { clientSideUserId } = reactCoreHooks.useCurrentUser();
|
|
2047
|
+
const search = reactRouter.useSearch({ strict: false });
|
|
2048
|
+
const location = reactRouter.useLocation();
|
|
2049
|
+
const navigate = reactRouter.useNavigate();
|
|
2050
|
+
const { encode, decode } = reactCoreHooks.useCustomEncoding();
|
|
2051
|
+
const { getUrlLengthWithSearchParam } = useSearchUtils();
|
|
2052
|
+
const updateSearch = react.useCallback(async (searchParams) => {
|
|
2053
|
+
if (!inputLoadData && !inputSaveData) {
|
|
2054
|
+
// should check if the state has actually changed from what we last sent to the URL
|
|
2055
|
+
if (!searchParams[name] ||
|
|
2056
|
+
(typeof searchParams[name] === "string" &&
|
|
2057
|
+
!dequal.dequal(decode(searchParams[name]), typeof search[name] === "string" ? decode(search[name]) : search[name]))) {
|
|
2058
|
+
return requestAnimationFrame(async () => {
|
|
2059
|
+
const replace = !search[name];
|
|
2060
|
+
await navigate({
|
|
2061
|
+
to: ".",
|
|
2062
|
+
search: (prev) => {
|
|
2063
|
+
if (getUrlLengthWithSearchParam(name, searchParams[name] || "", prev) <= MAX_URL_LENGTH) {
|
|
2064
|
+
return { ...prev, ...searchParams };
|
|
2065
|
+
}
|
|
2066
|
+
else {
|
|
2067
|
+
// eslint-disable-next-line no-console
|
|
2068
|
+
console.log(`URL too long, skipping sync of filters to the browsers URL, to avoid crashing the browser, limit is ${MAX_URL_LENGTH}, was: ${getUrlLengthWithSearchParam(name, searchParams[name] || "", prev)}`);
|
|
2069
|
+
const newSearchParams = { ...prev, [name]: undefined };
|
|
2070
|
+
return newSearchParams;
|
|
2071
|
+
}
|
|
2072
|
+
},
|
|
2073
|
+
hash: location.hash,
|
|
2074
|
+
replace,
|
|
2075
|
+
});
|
|
2076
|
+
});
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
return Promise.resolve();
|
|
2080
|
+
}, [navigate, name, search, inputLoadData, inputSaveData, decode, getUrlLengthWithSearchParam, location.hash]);
|
|
1851
2081
|
const getFromLocalStorage = react.useCallback((persistenceKey) => {
|
|
1852
2082
|
return localStorage.getItem(getPersistenceKey(persistenceKey, clientSideUserId));
|
|
1853
2083
|
}, [clientSideUserId]);
|
|
1854
2084
|
const lastName = react.useRef(name);
|
|
1855
2085
|
const [initialStoredFilters] = react.useState(() => (!inputLoadData && getFromLocalStorage(name)) || "{}");
|
|
1856
|
-
const
|
|
2086
|
+
const { getFilterValuesFromUrl, getFilterValuesToUrl } = useFilterUrlSync();
|
|
2087
|
+
const lastSavedStateRef = react.useRef(undefined);
|
|
2088
|
+
const lastSearchUpdateRef = react.useRef(undefined);
|
|
2089
|
+
const refreshDataRef = react.useRef(refreshData);
|
|
2090
|
+
react.useEffect(() => {
|
|
2091
|
+
refreshDataRef.current = refreshData;
|
|
2092
|
+
}, [refreshData]);
|
|
2093
|
+
// Add this useEffect to detect external URL changes
|
|
2094
|
+
react.useEffect(() => {
|
|
2095
|
+
if (!inputLoadData && !inputSaveData) {
|
|
2096
|
+
requestAnimationFrame(() => {
|
|
2097
|
+
const currentSearchValue = search[name];
|
|
2098
|
+
let currentSearchValueParsed;
|
|
2099
|
+
let lastSearchUpdateRefParsed;
|
|
2100
|
+
try {
|
|
2101
|
+
currentSearchValueParsed = currentSearchValue ? decode(currentSearchValue) : undefined;
|
|
2102
|
+
}
|
|
2103
|
+
catch (error) {
|
|
2104
|
+
// Invalid compressed data, treat as undefined
|
|
2105
|
+
currentSearchValueParsed = undefined;
|
|
2106
|
+
}
|
|
2107
|
+
try {
|
|
2108
|
+
lastSearchUpdateRefParsed = lastSearchUpdateRef.current ? decode(lastSearchUpdateRef.current) : undefined;
|
|
2109
|
+
}
|
|
2110
|
+
catch (error) {
|
|
2111
|
+
// Invalid compressed data, treat as undefined
|
|
2112
|
+
lastSearchUpdateRefParsed = undefined;
|
|
2113
|
+
}
|
|
2114
|
+
// H4sIADGRuGgAA3WTy07eQAxGXwVlXUtje27uruqWd0C2x1NaAa2AdoN49xq6-LOgUpQo0onny7H9ctzHsy591q8_73_dxXM8xNPT8fnl-KN3v-P4fHy5vj4-HQ96__5yd3e8fjqeQh_9Nt9v48fVfayr9f3b1YrHBH3f3GDBaj4Zui-HuvsADeO8KeFGrmYrj8hCbzTZrF0coRMRVEYHGcKAsW1Iw8qiF3ox06zbASth1t4GVsqCUvIxqO9R-EJ7w2aDJnjHCbV6JtmlgOSHQzB4DLvQtiwiRGB3aUk3h0lLgdyjFiyD8USPhd55BYzakkbaSbeA2jfmFaV7v9BMErKLguWpUNdQEKwTsqqXNETL_eRkbqojy1K0pCtVkK4LJM2VPtk6lQtdcIpSs2RGno9aQG0LSJrmvgrKHCeDFWWQN0iNNZMYgczFQNtH0VbqKifaq7uVBFdvBIgRIBoClcLXQFlC7VR7E7l2PdHKnH36kN5rJFY96Z0m3mhTKv-hG8cscytgU0vLnAOlTNAWdd_TR11y8m3dsxsGyJp_2XOg5hyZOxaP2Qu6nX137DbnW5L0_S-3p9CPk2hC09sG15SXgrKrHgQlpYe6ZKl9oScNb74IOmMmmbkSYmmHdYWZ7z3baWKpiWq0nA6u2fkEYFoOS-_OtibuIqfdaa0oDytgnB2saSC3YTSI0UKIc9nofWJf_wIRCrRd6AMAAA
|
|
2115
|
+
// Check if this is an external URL change (not from our own updates)
|
|
2116
|
+
// Only trigger refreshData if there's a meaningful change in the URL value
|
|
2117
|
+
if (search[name] !== undefined && !dequal.dequal(currentSearchValueParsed, lastSearchUpdateRefParsed)) {
|
|
2118
|
+
// This is an external URL change with actual data, trigger refreshData
|
|
2119
|
+
if (refreshDataRef.current) {
|
|
2120
|
+
refreshDataRef.current();
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
}, [search, name, inputLoadData, inputSaveData, decode]);
|
|
1857
2126
|
const saveData = react.useCallback((filterBarConfig, filterBarDefinitions) => {
|
|
1858
|
-
const newValues = Object.assign({},
|
|
2127
|
+
const newValues = Object.assign({}, lastSavedStateRef.current || {});
|
|
1859
2128
|
if (filterBarConfig.values) {
|
|
1860
2129
|
Object.entries(filterBarConfig.values).forEach(([key, value]) => {
|
|
1861
2130
|
const typedKey = key;
|
|
@@ -1868,41 +2137,83 @@ const useFilterBarPersistence = ({ name, setValue, loadData: inputLoadData, save
|
|
|
1868
2137
|
const toPersist = {
|
|
1869
2138
|
values: newValues,
|
|
1870
2139
|
};
|
|
1871
|
-
if (!dequal.dequal(newValues,
|
|
1872
|
-
|
|
2140
|
+
if (!dequal.dequal(newValues, lastSavedStateRef.current)) {
|
|
2141
|
+
lastSavedStateRef.current = newValues;
|
|
1873
2142
|
if (inputSaveData) {
|
|
1874
2143
|
inputSaveData(newValues);
|
|
1875
2144
|
}
|
|
1876
2145
|
else {
|
|
1877
2146
|
localStorage.setItem(getPersistenceKey(name, clientSideUserId), JSON.stringify(toPersist));
|
|
2147
|
+
const urlObject = getFilterValuesToUrl(newValues, sharedUtils.objectValues(filterBarDefinitions), false, isDefaultValue);
|
|
2148
|
+
const result = {};
|
|
2149
|
+
if (filterBarConfig.name) {
|
|
2150
|
+
result[filterBarConfig.name] = encode(urlObject);
|
|
2151
|
+
// Update the ref BEFORE updating the URL to prevent false external change detection
|
|
2152
|
+
lastSearchUpdateRef.current = result[filterBarConfig.name];
|
|
2153
|
+
}
|
|
2154
|
+
updateSearch(result);
|
|
1878
2155
|
}
|
|
1879
2156
|
}
|
|
1880
|
-
}, [name, clientSideUserId, inputSaveData,
|
|
1881
|
-
const
|
|
1882
|
-
|
|
1883
|
-
|
|
2157
|
+
}, [name, clientSideUserId, inputSaveData, getFilterValuesToUrl, updateSearch, encode, isDefaultValue]);
|
|
2158
|
+
const loadFromLocalStorage = react.useCallback(() => {
|
|
2159
|
+
let storedFilters = null;
|
|
2160
|
+
if (lastName.current !== name) {
|
|
2161
|
+
storedFilters = localStorage.getItem(getPersistenceKey(name, clientSideUserId)) || "{}";
|
|
2162
|
+
lastName.current = name;
|
|
1884
2163
|
}
|
|
1885
2164
|
else {
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
2165
|
+
storedFilters = initialStoredFilters;
|
|
2166
|
+
}
|
|
2167
|
+
if (storedFilters && storedFilters !== "undefined") {
|
|
2168
|
+
try {
|
|
2169
|
+
const loadedFilterBarConfigValues = JSON.parse(storedFilters);
|
|
2170
|
+
return loadedFilterBarConfigValues?.values || {};
|
|
1890
2171
|
}
|
|
1891
|
-
|
|
1892
|
-
|
|
2172
|
+
catch (error) {
|
|
2173
|
+
return {};
|
|
1893
2174
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
2175
|
+
}
|
|
2176
|
+
return {};
|
|
2177
|
+
}, [clientSideUserId, name, initialStoredFilters, lastName]);
|
|
2178
|
+
const loadFromSearchURL = react.useCallback(() => {
|
|
2179
|
+
let searchParams = search || {};
|
|
2180
|
+
const searchParamValue = searchParams[name];
|
|
2181
|
+
if (searchParamValue) {
|
|
2182
|
+
try {
|
|
2183
|
+
searchParams = decode(searchParamValue);
|
|
2184
|
+
}
|
|
2185
|
+
catch (error) {
|
|
2186
|
+
searchParams = {};
|
|
2187
|
+
}
|
|
2188
|
+
return searchParams;
|
|
2189
|
+
}
|
|
2190
|
+
return null;
|
|
2191
|
+
}, [search, name, decode]);
|
|
2192
|
+
const loadValues = react.useCallback((filterDefinitions) => {
|
|
2193
|
+
if (inputLoadData) {
|
|
2194
|
+
return inputLoadData();
|
|
2195
|
+
}
|
|
2196
|
+
else {
|
|
2197
|
+
const values = loadFromLocalStorage() || {};
|
|
2198
|
+
const searchParams = loadFromSearchURL();
|
|
2199
|
+
if (searchParams && sharedUtils.objectKeys(searchParams).length > 0) {
|
|
2200
|
+
const valuesFromUrl = getFilterValuesFromUrl(filterDefinitions, searchParams);
|
|
2201
|
+
if (sharedUtils.objectKeys(valuesFromUrl).length > 0) {
|
|
2202
|
+
// if there are values from the URL, update ALL filters values based on the searchParams or their defaults
|
|
2203
|
+
filterDefinitions.forEach(filter => {
|
|
2204
|
+
const key = filter.filterKey;
|
|
2205
|
+
if (key in valuesFromUrl) {
|
|
2206
|
+
values[key] = valuesFromUrl[key];
|
|
2207
|
+
}
|
|
2208
|
+
else {
|
|
2209
|
+
values[key] = filter.defaultValue;
|
|
2210
|
+
}
|
|
2211
|
+
});
|
|
1901
2212
|
}
|
|
1902
2213
|
}
|
|
1903
|
-
return
|
|
2214
|
+
return values;
|
|
1904
2215
|
}
|
|
1905
|
-
}, [inputLoadData,
|
|
2216
|
+
}, [inputLoadData, loadFromLocalStorage, getFilterValuesFromUrl, loadFromSearchURL]);
|
|
1906
2217
|
const loadData = react.useCallback((updatedFilterDefinitionsValues) => {
|
|
1907
2218
|
const initialStateValues = createInitialState({
|
|
1908
2219
|
name,
|
|
@@ -1910,16 +2221,22 @@ const useFilterBarPersistence = ({ name, setValue, loadData: inputLoadData, save
|
|
|
1910
2221
|
setValue,
|
|
1911
2222
|
});
|
|
1912
2223
|
const loadedFilterBarConfigValues = {
|
|
1913
|
-
values: loadValues(),
|
|
2224
|
+
values: loadValues(updatedFilterDefinitionsValues),
|
|
1914
2225
|
};
|
|
1915
2226
|
let initialFilterBarConfig;
|
|
1916
2227
|
if (loadedFilterBarConfigValues.values) {
|
|
1917
|
-
// make sure the last saved state is the same as the loaded values no manipulation of values!
|
|
1918
|
-
setLastSavedState(Object.assign({}, loadedFilterBarConfigValues.values));
|
|
1919
2228
|
if (validateFilter({
|
|
1920
2229
|
values: loadedFilterBarConfigValues.values,
|
|
1921
2230
|
filterDefinitions: updatedFilterDefinitionsValues,
|
|
1922
2231
|
})) {
|
|
2232
|
+
sharedUtils.objectKeys(initialStateValues.values).forEach(key => {
|
|
2233
|
+
if (loadedFilterBarConfigValues.values) {
|
|
2234
|
+
loadedFilterBarConfigValues.values[key] =
|
|
2235
|
+
loadedFilterBarConfigValues.values[key] !== undefined
|
|
2236
|
+
? loadedFilterBarConfigValues.values[key]
|
|
2237
|
+
: initialStateValues.values[key];
|
|
2238
|
+
}
|
|
2239
|
+
});
|
|
1923
2240
|
initialFilterBarConfig = {
|
|
1924
2241
|
values: loadedFilterBarConfigValues.values,
|
|
1925
2242
|
name: name,
|
|
@@ -1941,9 +2258,17 @@ const useFilterBarPersistence = ({ name, setValue, loadData: inputLoadData, save
|
|
|
1941
2258
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1942
2259
|
initialFilterBarConfig.setters[`set${stringTs.capitalize(key)}`] = (callback) => setValue(key, callback);
|
|
1943
2260
|
});
|
|
2261
|
+
const urlObject = getFilterValuesToUrl(initialFilterBarConfig.values, updatedFilterDefinitionsValues, false, isDefaultValue);
|
|
2262
|
+
const result = {};
|
|
2263
|
+
if (initialFilterBarConfig.name) {
|
|
2264
|
+
result[initialFilterBarConfig.name] = encode(JSON.stringify(urlObject));
|
|
2265
|
+
// Update the ref BEFORE updating the URL to prevent false external change detection
|
|
2266
|
+
lastSearchUpdateRef.current = result[initialFilterBarConfig.name];
|
|
2267
|
+
}
|
|
2268
|
+
updateSearch(result);
|
|
1944
2269
|
return initialFilterBarConfig;
|
|
1945
|
-
}, [name, setValue, loadValues]);
|
|
1946
|
-
return react.useMemo(() => ({ loadData, saveData }), [loadData, saveData]);
|
|
2270
|
+
}, [name, setValue, loadValues, getFilterValuesToUrl, updateSearch, encode, isDefaultValue]);
|
|
2271
|
+
return react.useMemo(() => ({ loadData, saveData, getFilterValuesToUrl }), [loadData, saveData, getFilterValuesToUrl]);
|
|
1947
2272
|
};
|
|
1948
2273
|
|
|
1949
2274
|
/**
|
|
@@ -1976,21 +2301,18 @@ const useGenericSetValue = () => {
|
|
|
1976
2301
|
const useFilterBar = ({ name, onValuesChange, filterBarDefinition, loadData: inputLoadData, saveData: inputSaveData, }) => {
|
|
1977
2302
|
const lastName = react.useRef(name);
|
|
1978
2303
|
const { setValue } = useGenericSetValue();
|
|
2304
|
+
const { isDefaultValue } = useIsDefaultValue();
|
|
1979
2305
|
const { loadData, saveData } = useFilterBarPersistence({
|
|
1980
2306
|
name,
|
|
2307
|
+
isDefaultValue: (key, value) => isDefaultValue(key, value, filterBarDefinition),
|
|
1981
2308
|
setValue: (key, callback) => setValue(setFilterBarConfig, key, callback),
|
|
2309
|
+
refreshData: () => setFilterBarConfig(loadData(sharedUtils.objectValues(filterBarDefinition))),
|
|
1982
2310
|
loadData: inputLoadData,
|
|
1983
2311
|
saveData: inputSaveData,
|
|
1984
2312
|
});
|
|
1985
2313
|
const [filterBarConfig, setFilterBarConfig] = react.useState(() => {
|
|
1986
2314
|
return loadData(sharedUtils.objectValues(filterBarDefinition));
|
|
1987
2315
|
});
|
|
1988
|
-
react.useEffect(() => {
|
|
1989
|
-
if (lastName.current !== name) {
|
|
1990
|
-
setFilterBarConfig(loadData(sharedUtils.objectValues(filterBarDefinition)));
|
|
1991
|
-
lastName.current = name;
|
|
1992
|
-
}
|
|
1993
|
-
}, [filterBarDefinition, loadData, name]);
|
|
1994
2316
|
const { filterMapActions, filterMapGetter } = useFilterBarActions({
|
|
1995
2317
|
name,
|
|
1996
2318
|
filterBarConfig,
|
|
@@ -1999,10 +2321,20 @@ const useFilterBar = ({ name, onValuesChange, filterBarDefinition, loadData: inp
|
|
|
1999
2321
|
setFilterBarConfig,
|
|
2000
2322
|
setValue: (key, callback) => setValue(setFilterBarConfig, key, callback),
|
|
2001
2323
|
});
|
|
2324
|
+
const onValuesChangeRef = react.useRef(onValuesChange);
|
|
2325
|
+
react.useEffect(() => {
|
|
2326
|
+
onValuesChangeRef.current = onValuesChange;
|
|
2327
|
+
}, [onValuesChange]);
|
|
2002
2328
|
react.useEffect(() => {
|
|
2003
2329
|
saveData(filterBarConfig, filterBarDefinition);
|
|
2004
|
-
|
|
2005
|
-
}, [filterBarConfig, filterBarDefinition,
|
|
2330
|
+
onValuesChangeRef.current?.(filterBarConfig.values);
|
|
2331
|
+
}, [filterBarConfig, filterBarDefinition, saveData]);
|
|
2332
|
+
react.useEffect(() => {
|
|
2333
|
+
if (lastName.current !== name) {
|
|
2334
|
+
setFilterBarConfig(loadData(sharedUtils.objectValues(filterBarDefinition)));
|
|
2335
|
+
lastName.current = name;
|
|
2336
|
+
}
|
|
2337
|
+
}, [filterBarDefinition, loadData, name]);
|
|
2006
2338
|
return react.useMemo(() => {
|
|
2007
2339
|
return {
|
|
2008
2340
|
filterBarConfig: { ...filterBarConfig, ...filterMapActions, ...filterMapGetter },
|
|
@@ -2022,13 +2354,20 @@ const useFilterBar = ({ name, onValuesChange, filterBarDefinition, loadData: inp
|
|
|
2022
2354
|
const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, loadData: inputLoadData, saveData: inputSaveData, }) => {
|
|
2023
2355
|
const [isDataLoaded, setIsDataLoaded] = react.useState(false);
|
|
2024
2356
|
const [asyncLoadedFilterBarDefinitions, setAsyncLoadedFilterBarDefinitions] = react.useState();
|
|
2357
|
+
const { isDefaultValue } = useIsDefaultValue();
|
|
2025
2358
|
const internalFilterBarDefinitions = react.useMemo(() => asyncLoadedFilterBarDefinitions ?? filterBarDefinition, [filterBarDefinition, asyncLoadedFilterBarDefinitions]);
|
|
2026
2359
|
const { setValue } = useGenericSetValue();
|
|
2027
2360
|
const { loadData, saveData } = useFilterBarPersistence({
|
|
2028
2361
|
name,
|
|
2362
|
+
isDefaultValue: (key, value) => isDefaultValue(key, value, filterBarDefinition, filterBarConfig.initialState),
|
|
2029
2363
|
setValue: (key, callback) => setValue(setFilterBarConfig, key, callback),
|
|
2030
2364
|
loadData: inputLoadData,
|
|
2031
2365
|
saveData: inputSaveData,
|
|
2366
|
+
refreshData: () => {
|
|
2367
|
+
if (asyncLoadedFilterBarDefinitions) {
|
|
2368
|
+
setFilterBarConfig(loadData(sharedUtils.objectValues(asyncLoadedFilterBarDefinitions)));
|
|
2369
|
+
}
|
|
2370
|
+
},
|
|
2032
2371
|
});
|
|
2033
2372
|
const [filterBarConfig, setFilterBarConfig] = react.useState(() => {
|
|
2034
2373
|
const initialConfig = {
|
|
@@ -2039,13 +2378,16 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, loadData
|
|
|
2039
2378
|
};
|
|
2040
2379
|
return initialConfig;
|
|
2041
2380
|
});
|
|
2381
|
+
const setValueMemoized = react.useCallback((key, callback) => {
|
|
2382
|
+
setValue(setFilterBarConfig, key, callback);
|
|
2383
|
+
}, [setFilterBarConfig, setValue]);
|
|
2042
2384
|
const { filterMapActions, filterMapGetter } = useFilterBarActions({
|
|
2043
2385
|
name,
|
|
2044
2386
|
filterBarConfig,
|
|
2045
2387
|
filterBarDefinition: internalFilterBarDefinitions,
|
|
2046
2388
|
initialState: filterBarConfig.initialState,
|
|
2047
2389
|
setFilterBarConfig,
|
|
2048
|
-
setValue:
|
|
2390
|
+
setValue: setValueMemoized,
|
|
2049
2391
|
});
|
|
2050
2392
|
const dataLoaded = react.useCallback((loadedFilterDefinitionsValues) => {
|
|
2051
2393
|
setIsDataLoaded(false);
|
|
@@ -2084,19 +2426,18 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, loadData
|
|
|
2084
2426
|
* The parameter is validated using the provided Zod schema.
|
|
2085
2427
|
*
|
|
2086
2428
|
* @template T - A Zod schema used for validation.
|
|
2087
|
-
* @param {string} searchParamName - The name of the search parameter in the URL.
|
|
2088
2429
|
* @param {string} filterName - The name of the filter.
|
|
2089
2430
|
* @param {object} search - The current search state, provided by `useSearch` from @tanstack/react-router.
|
|
2090
2431
|
* @param {T} zodSchema - The Zod schema for validating the filter data.
|
|
2091
2432
|
* @param {ErrorHandlingContextValue} errorHandler - Error handling context for capturing and reporting exceptions.
|
|
2092
2433
|
* @returns {any} The parsed filter data if validation succeeds, otherwise `null`.
|
|
2093
2434
|
*/
|
|
2094
|
-
const useSearchParamAsFilter = ({
|
|
2435
|
+
const useSearchParamAsFilter = ({ filterName, search, zodSchema, errorHandler, }) => {
|
|
2095
2436
|
return react.useMemo(() => {
|
|
2096
|
-
if (!sharedUtils.objectKeys(search).includes(
|
|
2437
|
+
if (!sharedUtils.objectKeys(search).includes(filterName)) {
|
|
2097
2438
|
return null;
|
|
2098
2439
|
}
|
|
2099
|
-
const foundParam = search[
|
|
2440
|
+
const foundParam = search[filterName];
|
|
2100
2441
|
try {
|
|
2101
2442
|
const getJsonParsedVal = () => {
|
|
2102
2443
|
if (zodSchema._def.typeName === "ZodString") {
|
|
@@ -2127,7 +2468,7 @@ const useSearchParamAsFilter = ({ searchParamName, filterName, search, zodSchema
|
|
|
2127
2468
|
zodParseError: null,
|
|
2128
2469
|
});
|
|
2129
2470
|
}
|
|
2130
|
-
}, [search,
|
|
2471
|
+
}, [search, zodSchema, errorHandler, filterName]);
|
|
2131
2472
|
};
|
|
2132
2473
|
const captureUrlParseException = (errorHandler, { filterName, param, jsonParsed: parsed }) => errorHandler.captureException(new Error(JSON.stringify({
|
|
2133
2474
|
info: `Received invalid values for ${filterName} from URL query params. Can't set ${filterName} filter with this. Please fix the URL query params (or schema).`,
|
|
@@ -2178,6 +2519,8 @@ exports.MultipleFilterTooltipLabel = MultipleFilterTooltipLabel;
|
|
|
2178
2519
|
exports.ResetFiltersButton = ResetFiltersButton;
|
|
2179
2520
|
exports.TooltipLabel = TooltipLabel;
|
|
2180
2521
|
exports.areaFilterGeoJsonGeometrySchema = areaFilterGeoJsonGeometrySchema;
|
|
2522
|
+
exports.booleanSchema = booleanSchema;
|
|
2523
|
+
exports.dateRangeSchema = dateRangeSchema;
|
|
2181
2524
|
exports.isAreaFilterValue = isAreaFilterValue;
|
|
2182
2525
|
exports.isArrayFilterValue = isArrayFilterValue;
|
|
2183
2526
|
exports.isBooleanValue = isBooleanValue;
|
|
@@ -2187,10 +2530,16 @@ exports.isStringArrayFilterValue = isStringArrayFilterValue;
|
|
|
2187
2530
|
exports.isValueName = isValueName;
|
|
2188
2531
|
exports.isValueNameArray = isValueNameArray;
|
|
2189
2532
|
exports.mergeFilters = mergeFilters;
|
|
2533
|
+
exports.minMaxFilterSchema = minMaxFilterSchema;
|
|
2190
2534
|
exports.mockFilterBar = mockFilterBar;
|
|
2535
|
+
exports.numberSchema = numberSchema;
|
|
2536
|
+
exports.stringArraySchema = stringArraySchema;
|
|
2537
|
+
exports.stringSchema = stringSchema;
|
|
2191
2538
|
exports.toggleFilterValue = toggleFilterValue;
|
|
2192
2539
|
exports.useFilterBar = useFilterBar;
|
|
2193
2540
|
exports.useFilterBarAsync = useFilterBarAsync;
|
|
2194
2541
|
exports.useFiltersMenu = useFiltersMenu;
|
|
2195
2542
|
exports.useSearchParamAsFilter = useSearchParamAsFilter;
|
|
2196
2543
|
exports.validateFilter = validateFilter;
|
|
2544
|
+
exports.valueNameArraySchema = valueNameArraySchema;
|
|
2545
|
+
exports.valueNameSchema = valueNameSchema;
|