@trackunit/filters-filter-bar 1.18.4 → 1.18.6

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 CHANGED
@@ -495,7 +495,7 @@ const ITEM_HEIGHT = 28; //measured in DevTools on 03/10/2025
495
495
  *
496
496
  * @returns {ReactElement} - Returns the DynamicFilterList component.
497
497
  */
498
- const DynamicFilterList = ({ rowCount, keyMapper, labelMapper, onChange, checked, count, showRequestMoreUseSearch = false, type, className, }) => {
498
+ const DynamicFilterList = ({ rowCount, keyMapper, labelMapper, onChange, checked, count, showRequestMoreUseSearch = false, type = undefined, className, }) => {
499
499
  const [t] = useTranslation();
500
500
  const parentRef = react.useRef(null);
501
501
  const updatedRowCount = react.useMemo(() => (showRequestMoreUseSearch ? rowCount + 1 : rowCount), [rowCount, showRequestMoreUseSearch]);
@@ -532,13 +532,14 @@ const DynamicFilterList = ({ rowCount, keyMapper, labelMapper, onChange, checked
532
532
  *
533
533
  * @returns {ReactElement} - Returns the FilterHeader component.
534
534
  */
535
- const FilterHeader = ({ filterKey, title, searchEnabled, searchProps, filterHasChanges, resetIndividualFilterToInitialState, onResetFilter, loading = false, className, "data-testid": dataTestId, hideHeader = false, children, }) => {
535
+ const FilterHeader = ({ filterKey, title, searchEnabled = false, searchProps, filterHasChanges, resetIndividualFilterToInitialState, onResetFilter, loading = false, className, "data-testid": dataTestId, hideHeader = false, children, }) => {
536
536
  const [t] = useTranslation();
537
537
  const handleResetFilter = () => {
538
538
  resetIndividualFilterToInitialState(filterKey);
539
539
  onResetFilter?.();
540
540
  };
541
- return (jsxRuntime.jsx(reactFilterComponents.FilterHeader, { className: className, "data-testid": dataTestId ?? `${filterKey}-filter-header`, loading: loading, onReset: handleResetFilter, resetLabel: t("filtersBar.resetFilter"), searchComponent: searchEnabled ? jsxRuntime.jsx(FilterHeaderSearchComponent, { filterKey: filterKey, searchProps: searchProps }) : undefined, showReset: filterHasChanges, title: hideHeader ? undefined : title, children: children }));
541
+ const searchComponent = searchEnabled && searchProps !== undefined ? (jsxRuntime.jsx(FilterHeaderSearchComponent, { filterKey: filterKey, searchProps: searchProps })) : undefined;
542
+ return (jsxRuntime.jsx(reactFilterComponents.FilterHeader, { className: className, "data-testid": dataTestId ?? `${filterKey}-filter-header`, loading: loading, onReset: handleResetFilter, resetLabel: t("filtersBar.resetFilter"), searchComponent: searchComponent, showReset: filterHasChanges, title: hideHeader ? undefined : title, children: children }));
542
543
  };
543
544
  /**
544
545
  * FilterHeaderSearchComponent renders a search input for the FilterHeader component.
@@ -560,7 +561,7 @@ const FilterHeaderSearchComponent = ({ searchProps, filterKey, }) => {
560
561
  * shows no results if length or array is 0
561
562
  * otherwise it calls children as a render prop
562
563
  */
563
- const FilterResults = ({ results, ignoreUndefined, loading, children, }) => {
564
+ const FilterResults = ({ results, ignoreUndefined = false, loading, children, }) => {
564
565
  if (!results) {
565
566
  return null;
566
567
  }
@@ -569,7 +570,7 @@ const FilterResults = ({ results, ignoreUndefined, loading, children, }) => {
569
570
  }
570
571
  return jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(results) });
571
572
  };
572
- const EmptyResults = ({ loading }) => {
573
+ const EmptyResults = ({ loading = false }) => {
573
574
  const [t] = useTranslation();
574
575
  return (jsxRuntime.jsx("div", { className: "grid h-20 w-[280px] place-content-center pl-2 pr-2", "data-testid": "empty-filter-results", children: jsxRuntime.jsx(reactComponents.Text, { align: "center", className: "w-full break-words", italicize: true, subtle: true, children: loading ? t("filtersBar.loading") : t("filtersBar.emptyResults") }) }));
575
576
  };
@@ -2516,6 +2517,41 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, loadData
2516
2517
  }, [filterBarConfigMemoed, internalFilterBarDefinitions, dataLoaded, name, stableOnValuesChange]);
2517
2518
  };
2518
2519
 
2520
+ /**
2521
+ * Converts a filter bar configuration to a link.
2522
+ *
2523
+ * @example
2524
+ * ```ts
2525
+ * const filterBarLinkConfig: FilterBarToLinkConfig = {
2526
+ * searchPropertyName: "assetFilters",
2527
+ * filterBar: "ASSETS",
2528
+ * };
2529
+ *
2530
+ * const { getFilterBarLink } = useFilterBarsAsLink(filterBarLinkConfig);
2531
+ *
2532
+ * const link = getFilterBarLink({ ASSETS: { search: "excavator" } });
2533
+ * ```
2534
+ * @param filterBarLinkConfig - The filter bar configuration to convert to a link.
2535
+ * @returns { UseFilterBarsAsLinkResult } An object with a `getFilterBarLink` function that takes a merged filter bar definitions and returns a link.
2536
+ */
2537
+ const useFilterBarsAsLink = (filterBarLinkConfig) => {
2538
+ const filterBarLinkConfigArray = react.useMemo(() => {
2539
+ return Array.isArray(filterBarLinkConfig) ? filterBarLinkConfig : filterBarLinkConfig ? [filterBarLinkConfig] : [];
2540
+ }, [filterBarLinkConfig]);
2541
+ const { encode } = reactComponents.useCustomEncoding();
2542
+ const getFilterBarLink = react.useCallback((mergedFilterBarDefinitions) => {
2543
+ return filterBarLinkConfigArray
2544
+ .map(config => {
2545
+ const value = mergedFilterBarDefinitions[config.filterBar];
2546
+ return `${config.searchPropertyName || "filter"}=${value ? encode(value) : ""}`;
2547
+ })
2548
+ .join("&");
2549
+ }, [filterBarLinkConfigArray, encode]);
2550
+ return react.useMemo(() => {
2551
+ return { getFilterBarLink };
2552
+ }, [getFilterBarLink]);
2553
+ };
2554
+
2519
2555
  /**
2520
2556
  * Handles the application of a URL search parameter as a filter in the system.
2521
2557
  * The parameter is validated using the provided Zod schema.
@@ -2633,6 +2669,7 @@ exports.stringSchema = stringSchema;
2633
2669
  exports.toggleFilterValue = toggleFilterValue;
2634
2670
  exports.useFilterBar = useFilterBar;
2635
2671
  exports.useFilterBarAsync = useFilterBarAsync;
2672
+ exports.useFilterBarsAsLink = useFilterBarsAsLink;
2636
2673
  exports.useFiltersMenu = useFiltersMenu;
2637
2674
  exports.useSearchParamAsFilter = useSearchParamAsFilter;
2638
2675
  exports.validateFilter = validateFilter;
package/index.esm.js CHANGED
@@ -493,7 +493,7 @@ const ITEM_HEIGHT = 28; //measured in DevTools on 03/10/2025
493
493
  *
494
494
  * @returns {ReactElement} - Returns the DynamicFilterList component.
495
495
  */
496
- const DynamicFilterList = ({ rowCount, keyMapper, labelMapper, onChange, checked, count, showRequestMoreUseSearch = false, type, className, }) => {
496
+ const DynamicFilterList = ({ rowCount, keyMapper, labelMapper, onChange, checked, count, showRequestMoreUseSearch = false, type = undefined, className, }) => {
497
497
  const [t] = useTranslation();
498
498
  const parentRef = useRef(null);
499
499
  const updatedRowCount = useMemo(() => (showRequestMoreUseSearch ? rowCount + 1 : rowCount), [rowCount, showRequestMoreUseSearch]);
@@ -530,13 +530,14 @@ const DynamicFilterList = ({ rowCount, keyMapper, labelMapper, onChange, checked
530
530
  *
531
531
  * @returns {ReactElement} - Returns the FilterHeader component.
532
532
  */
533
- const FilterHeader = ({ filterKey, title, searchEnabled, searchProps, filterHasChanges, resetIndividualFilterToInitialState, onResetFilter, loading = false, className, "data-testid": dataTestId, hideHeader = false, children, }) => {
533
+ const FilterHeader = ({ filterKey, title, searchEnabled = false, searchProps, filterHasChanges, resetIndividualFilterToInitialState, onResetFilter, loading = false, className, "data-testid": dataTestId, hideHeader = false, children, }) => {
534
534
  const [t] = useTranslation();
535
535
  const handleResetFilter = () => {
536
536
  resetIndividualFilterToInitialState(filterKey);
537
537
  onResetFilter?.();
538
538
  };
539
- return (jsx(FilterHeader$1, { className: className, "data-testid": dataTestId ?? `${filterKey}-filter-header`, loading: loading, onReset: handleResetFilter, resetLabel: t("filtersBar.resetFilter"), searchComponent: searchEnabled ? jsx(FilterHeaderSearchComponent, { filterKey: filterKey, searchProps: searchProps }) : undefined, showReset: filterHasChanges, title: hideHeader ? undefined : title, children: children }));
539
+ const searchComponent = searchEnabled && searchProps !== undefined ? (jsx(FilterHeaderSearchComponent, { filterKey: filterKey, searchProps: searchProps })) : undefined;
540
+ return (jsx(FilterHeader$1, { className: className, "data-testid": dataTestId ?? `${filterKey}-filter-header`, loading: loading, onReset: handleResetFilter, resetLabel: t("filtersBar.resetFilter"), searchComponent: searchComponent, showReset: filterHasChanges, title: hideHeader ? undefined : title, children: children }));
540
541
  };
541
542
  /**
542
543
  * FilterHeaderSearchComponent renders a search input for the FilterHeader component.
@@ -558,7 +559,7 @@ const FilterHeaderSearchComponent = ({ searchProps, filterKey, }) => {
558
559
  * shows no results if length or array is 0
559
560
  * otherwise it calls children as a render prop
560
561
  */
561
- const FilterResults = ({ results, ignoreUndefined, loading, children, }) => {
562
+ const FilterResults = ({ results, ignoreUndefined = false, loading, children, }) => {
562
563
  if (!results) {
563
564
  return null;
564
565
  }
@@ -567,7 +568,7 @@ const FilterResults = ({ results, ignoreUndefined, loading, children, }) => {
567
568
  }
568
569
  return jsx(Fragment, { children: children(results) });
569
570
  };
570
- const EmptyResults = ({ loading }) => {
571
+ const EmptyResults = ({ loading = false }) => {
571
572
  const [t] = useTranslation();
572
573
  return (jsx("div", { className: "grid h-20 w-[280px] place-content-center pl-2 pr-2", "data-testid": "empty-filter-results", children: jsx(Text, { align: "center", className: "w-full break-words", italicize: true, subtle: true, children: loading ? t("filtersBar.loading") : t("filtersBar.emptyResults") }) }));
573
574
  };
@@ -2514,6 +2515,41 @@ const useFilterBarAsync = ({ name, onValuesChange, filterBarDefinition, loadData
2514
2515
  }, [filterBarConfigMemoed, internalFilterBarDefinitions, dataLoaded, name, stableOnValuesChange]);
2515
2516
  };
2516
2517
 
2518
+ /**
2519
+ * Converts a filter bar configuration to a link.
2520
+ *
2521
+ * @example
2522
+ * ```ts
2523
+ * const filterBarLinkConfig: FilterBarToLinkConfig = {
2524
+ * searchPropertyName: "assetFilters",
2525
+ * filterBar: "ASSETS",
2526
+ * };
2527
+ *
2528
+ * const { getFilterBarLink } = useFilterBarsAsLink(filterBarLinkConfig);
2529
+ *
2530
+ * const link = getFilterBarLink({ ASSETS: { search: "excavator" } });
2531
+ * ```
2532
+ * @param filterBarLinkConfig - The filter bar configuration to convert to a link.
2533
+ * @returns { UseFilterBarsAsLinkResult } An object with a `getFilterBarLink` function that takes a merged filter bar definitions and returns a link.
2534
+ */
2535
+ const useFilterBarsAsLink = (filterBarLinkConfig) => {
2536
+ const filterBarLinkConfigArray = useMemo(() => {
2537
+ return Array.isArray(filterBarLinkConfig) ? filterBarLinkConfig : filterBarLinkConfig ? [filterBarLinkConfig] : [];
2538
+ }, [filterBarLinkConfig]);
2539
+ const { encode } = useCustomEncoding();
2540
+ const getFilterBarLink = useCallback((mergedFilterBarDefinitions) => {
2541
+ return filterBarLinkConfigArray
2542
+ .map(config => {
2543
+ const value = mergedFilterBarDefinitions[config.filterBar];
2544
+ return `${config.searchPropertyName || "filter"}=${value ? encode(value) : ""}`;
2545
+ })
2546
+ .join("&");
2547
+ }, [filterBarLinkConfigArray, encode]);
2548
+ return useMemo(() => {
2549
+ return { getFilterBarLink };
2550
+ }, [getFilterBarLink]);
2551
+ };
2552
+
2517
2553
  /**
2518
2554
  * Handles the application of a URL search parameter as a filter in the system.
2519
2555
  * The parameter is validated using the provided Zod schema.
@@ -2590,4 +2626,4 @@ const mergeFilters = (filterBarDefinition, extraFilters) => {
2590
2626
  */
2591
2627
  setupLibraryTranslations();
2592
2628
 
2593
- export { AppliedFiltersRenderer, DefaultCheckboxFilter, DefaultDateRangeFilter, DefaultMinMaxFilter, DefaultRadioFilter, DynamicFilterList, FilterBar, FilterButtonTooltipLabel, FilterComponent, FilterEvents, FilterHeader, FilterResults, FilterTableComponent, FiltersMenu, FiltersMenuContent, FiltersRenderer, GroupedFiltersList, HierarchicalCheckboxFilter, MultipleFilterTooltipLabel, ResetFiltersButton, TooltipLabel, areaFilterGeoJsonGeometrySchema, booleanSchema, dateRangeSchema, isAreaFilterValue, isArrayFilterValue, isBooleanValue, isDateRangeValue, isMinMaxFilterValue, isStringArrayFilterValue, isValueName, isValueNameArray, mergeFilters, minMaxFilterSchema, mockFilterBar, numberSchema, stringArraySchema, stringSchema, toggleFilterValue, useFilterBar, useFilterBarAsync, useFiltersMenu, useSearchParamAsFilter, validateFilter, valueNameArraySchema, valueNameSchema };
2629
+ export { AppliedFiltersRenderer, DefaultCheckboxFilter, DefaultDateRangeFilter, DefaultMinMaxFilter, DefaultRadioFilter, DynamicFilterList, FilterBar, FilterButtonTooltipLabel, FilterComponent, FilterEvents, FilterHeader, FilterResults, FilterTableComponent, FiltersMenu, FiltersMenuContent, FiltersRenderer, GroupedFiltersList, HierarchicalCheckboxFilter, MultipleFilterTooltipLabel, ResetFiltersButton, TooltipLabel, areaFilterGeoJsonGeometrySchema, booleanSchema, dateRangeSchema, isAreaFilterValue, isArrayFilterValue, isBooleanValue, isDateRangeValue, isMinMaxFilterValue, isStringArrayFilterValue, isValueName, isValueNameArray, mergeFilters, minMaxFilterSchema, mockFilterBar, numberSchema, stringArraySchema, stringSchema, toggleFilterValue, useFilterBar, useFilterBarAsync, useFilterBarsAsLink, useFiltersMenu, useSearchParamAsFilter, validateFilter, valueNameArraySchema, valueNameSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/filters-filter-bar",
3
- "version": "1.18.4",
3
+ "version": "1.18.6",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -11,17 +11,17 @@
11
11
  "tailwind-merge": "^2.0.0",
12
12
  "string-ts": "^2.0.0",
13
13
  "zod": "^3.23.8",
14
- "@trackunit/iris-app-api": "1.15.8",
15
- "@trackunit/react-core-hooks": "1.14.2",
16
- "@trackunit/react-filter-components": "1.17.3",
17
- "@trackunit/react-date-and-time-components": "1.20.3",
14
+ "@trackunit/iris-app-api": "1.15.9",
15
+ "@trackunit/react-core-hooks": "1.14.3",
16
+ "@trackunit/react-filter-components": "1.17.5",
17
+ "@trackunit/react-date-and-time-components": "1.20.5",
18
18
  "@trackunit/shared-utils": "1.13.77",
19
- "@trackunit/react-form-components": "1.18.2",
19
+ "@trackunit/react-form-components": "1.18.4",
20
20
  "@trackunit/iris-app-runtime-core-api": "1.13.2",
21
21
  "@trackunit/geo-json-utils": "1.11.78",
22
- "@trackunit/i18n-library-translation": "1.15.2",
22
+ "@trackunit/i18n-library-translation": "1.15.4",
23
23
  "@trackunit/css-class-variance-utilities": "1.11.77",
24
- "@trackunit/react-components": "1.20.2"
24
+ "@trackunit/react-components": "1.20.4"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "react": "^19.0.0",
package/src/index.d.ts CHANGED
@@ -23,6 +23,7 @@ export * from "./lib/hooks/mockFilterBar";
23
23
  export * from "./lib/hooks/types";
24
24
  export * from "./lib/hooks/useFilterBar";
25
25
  export * from "./lib/hooks/useFilterBarAsync";
26
+ export * from "./lib/hooks/useFilterBarsAsLink";
26
27
  export * from "./lib/hooks/useFiltersMenu";
27
28
  export * from "./lib/hooks/useSearchParamAsFilter";
28
29
  export * from "./lib/types/FilterTypes";
@@ -0,0 +1,37 @@
1
+ import { AssetFilterKeysWithCustomFields, CustomerFilterKeysWithCustomFields, FilterBarToLinkConfig, SiteFilterKeysWithCustomFields } from "@trackunit/iris-app-api";
2
+ export type FiltersConfigValues = {
3
+ ASSETS?: Partial<Record<AssetFilterKeysWithCustomFields[number], unknown>>;
4
+ SITES?: Partial<Record<SiteFilterKeysWithCustomFields[number], unknown>>;
5
+ CUSTOMERS?: Partial<Record<CustomerFilterKeysWithCustomFields[number], unknown>>;
6
+ TIME_RANGE?: Record<string, unknown> | null;
7
+ };
8
+ /**
9
+ * The result of the useFilterBarsAsLink hook.
10
+ */
11
+ export interface UseFilterBarsAsLinkResult {
12
+ /**
13
+ * Gets the filter bar link.
14
+ *
15
+ * @param mergedFilterBarDefinitions - The merged filter bar definitions.
16
+ * @returns The filter bar link.
17
+ */
18
+ getFilterBarLink: (mergedFilterBarDefinitions: FiltersConfigValues) => string;
19
+ }
20
+ /**
21
+ * Converts a filter bar configuration to a link.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const filterBarLinkConfig: FilterBarToLinkConfig = {
26
+ * searchPropertyName: "assetFilters",
27
+ * filterBar: "ASSETS",
28
+ * };
29
+ *
30
+ * const { getFilterBarLink } = useFilterBarsAsLink(filterBarLinkConfig);
31
+ *
32
+ * const link = getFilterBarLink({ ASSETS: { search: "excavator" } });
33
+ * ```
34
+ * @param filterBarLinkConfig - The filter bar configuration to convert to a link.
35
+ * @returns { UseFilterBarsAsLinkResult } An object with a `getFilterBarLink` function that takes a merged filter bar definitions and returns a link.
36
+ */
37
+ export declare const useFilterBarsAsLink: (filterBarLinkConfig: FilterBarToLinkConfig | Array<FilterBarToLinkConfig> | null) => UseFilterBarsAsLinkResult;