@trackunit/filters-filter-bar 1.3.190 → 1.3.192
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 +100 -19
- package/index.esm.js +101 -20
- package/package.json +13 -13
- package/src/lib/components/FilterTooltips/MultipleFilterTooltipLabel.d.ts +19 -0
- package/src/lib/components/FilterTooltips/SingleFilterTooltipLabel.d.ts +18 -0
- package/src/lib/components/FilterTooltips/TooltipValues.d.ts +14 -0
package/index.cjs.js
CHANGED
|
@@ -110,7 +110,7 @@ var defaultTranslations = {
|
|
|
110
110
|
"filter.more.options.if.you.search.title": "Over {{count}} items found.",
|
|
111
111
|
"filtersBar.appliedFiltersTooltip.none": "No filters applied",
|
|
112
112
|
"filtersBar.appliedFiltersTooltip.plural": "{{count}} filters applied:",
|
|
113
|
-
"filtersBar.appliedFiltersTooltip.singular": "{{filterName}} filter applied",
|
|
113
|
+
"filtersBar.appliedFiltersTooltip.singular": "{{filterName}} filter applied:",
|
|
114
114
|
"filtersBar.defaultAssetFilters.followedFilter.ALL": "All Assets",
|
|
115
115
|
"filtersBar.defaultAssetFilters.followedFilter.allLabel": "All Assets",
|
|
116
116
|
"filtersBar.defaultAssetFilters.followedFilter.FOLLOWED": "Followed Only",
|
|
@@ -779,6 +779,99 @@ const FiltersRenderer = ({ filters, filterBarConfig, visualStyle, }) => {
|
|
|
779
779
|
.map(filter => (jsxRuntime.jsx(FilterComponent, { filter: filter, filterBarActions: filterBarConfig, filterState: { values: filterBarConfig.values, setters: filterBarConfig.setters }, visualStyle: visualStyle }, `filter-${filter.filterKey}`)));
|
|
780
780
|
};
|
|
781
781
|
|
|
782
|
+
/**
|
|
783
|
+
* TooltipValues component that displays formatted tooltip values based on the provided input.
|
|
784
|
+
*
|
|
785
|
+
* @param {TooltipValuesProps} props - The props for the TooltipValues component.
|
|
786
|
+
* @param {FilterValueType} props.values - The input values to render in the tooltip.
|
|
787
|
+
* @returns {ReactElement} The rendered TooltipValues component.
|
|
788
|
+
*/
|
|
789
|
+
const TooltipValues = ({ values }) => {
|
|
790
|
+
return jsxRuntime.jsx("div", { children: renderTooltipValues(values) });
|
|
791
|
+
};
|
|
792
|
+
const renderTooltipValues = (values) => {
|
|
793
|
+
if (values === undefined) {
|
|
794
|
+
return null;
|
|
795
|
+
}
|
|
796
|
+
// Array of objects ValueName[]
|
|
797
|
+
if (Array.isArray(values) && typeof values[0] === "object") {
|
|
798
|
+
return (jsxRuntime.jsx("ul", { className: "list-inside", children: values.map((value, index) => (jsxRuntime.jsx("li", { className: "list-disc", children: value.name }, index))) }));
|
|
799
|
+
}
|
|
800
|
+
// Array of strings
|
|
801
|
+
if (Array.isArray(values)) {
|
|
802
|
+
return (jsxRuntime.jsx("ul", { className: "list-inside", children: values.map((value, index) => {
|
|
803
|
+
return (jsxRuntime.jsx("li", { className: "list-disc", children: typeof value === "string" ? value : value.name }, index));
|
|
804
|
+
}) }));
|
|
805
|
+
}
|
|
806
|
+
// single object ValueName
|
|
807
|
+
if (typeof values === "object" && values.name) {
|
|
808
|
+
return (jsxRuntime.jsx("ul", { className: "list-inside", children: jsxRuntime.jsx("li", { className: "list-disc", children: values.name }) }));
|
|
809
|
+
}
|
|
810
|
+
// String or number
|
|
811
|
+
if (typeof values === "string" || typeof values === "number") {
|
|
812
|
+
return (jsxRuntime.jsx("ul", { className: "list-inside", children: jsxRuntime.jsx("li", { className: "list-disc", children: values.toString() }) }));
|
|
813
|
+
}
|
|
814
|
+
// BooleanValue
|
|
815
|
+
if (typeof values === "object" && values.booleanValue !== undefined) {
|
|
816
|
+
return values.booleanValue ? "Yes" : "No";
|
|
817
|
+
}
|
|
818
|
+
// MinMaxFilterValue
|
|
819
|
+
if (typeof values === "object" && "min" in values && "max" in values) {
|
|
820
|
+
const minMax = values;
|
|
821
|
+
return `Min: ${minMax.min}, Max: ${minMax.max}`;
|
|
822
|
+
}
|
|
823
|
+
return null;
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* Component that displays a tooltip label with filter details.
|
|
828
|
+
*
|
|
829
|
+
* @template TFilterBarDefinition - The type of the filter bar definition.
|
|
830
|
+
* @param {SingleFilterTooltipLabelProps} props - Component properties.
|
|
831
|
+
* @param {FilterState<TFilterBarDefinition> & FilterMapActions & FilterMapGetter} props.filterBarConfig -
|
|
832
|
+
* Configuration object for the filter bar, containing state, actions, and accessors.
|
|
833
|
+
* @param {string} props.filterKey - The key identifying the filter.
|
|
834
|
+
* @returns {ReactElement} The rendered tooltip label and applied filter values.
|
|
835
|
+
*/
|
|
836
|
+
const SingleFilterTooltipLabel = ({ filterBarConfig, filterKey, }) => {
|
|
837
|
+
const title = filterBarConfig.getFilterTitle(filterKey);
|
|
838
|
+
const values = filterBarConfig.getValuesByKey(filterKey);
|
|
839
|
+
const [t] = useTranslation();
|
|
840
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [t("filtersBar.appliedFiltersTooltip.singular", {
|
|
841
|
+
filterName: title,
|
|
842
|
+
}), jsxRuntime.jsx(TooltipValues, { values: values })] }));
|
|
843
|
+
};
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* Component that displays a tooltip for filters.
|
|
847
|
+
* Differentiates cases with no applied filters, a single filter, or multiple filters.
|
|
848
|
+
*
|
|
849
|
+
* @template TFilterBarDefinition The type definition for the FilterBar.
|
|
850
|
+
* @param {MultipleFilterTooltipLabelProps} props The component's props.
|
|
851
|
+
* @param {FilterState<TFilterBarDefinition> & FilterMapActions & FilterMapGetter} props.filterBarConfig
|
|
852
|
+
* The FilterBar configuration, including filter state, actions, and getter methods.
|
|
853
|
+
* @param {string[]} [props.filterKeys] An optional list of filter keys to filter the currently applied filters.
|
|
854
|
+
* @returns {ReactElement | string} Returns a element or string for the tooltip displaying applied filters.
|
|
855
|
+
*/
|
|
856
|
+
const MultipleFilterTooltipLabel = ({ filterBarConfig, filterKeys, }) => {
|
|
857
|
+
const [t] = useTranslation();
|
|
858
|
+
const appliedFilterKeys = filterKeys
|
|
859
|
+
? filterKeys.filter(key => filterBarConfig.appliedFilterKeys().includes(key))
|
|
860
|
+
: filterBarConfig.appliedFilterKeys();
|
|
861
|
+
switch (appliedFilterKeys.length) {
|
|
862
|
+
case 0:
|
|
863
|
+
return t("filtersBar.appliedFiltersTooltip.none");
|
|
864
|
+
case 1:
|
|
865
|
+
return jsxRuntime.jsx(SingleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKey: appliedFilterKeys[0] });
|
|
866
|
+
default:
|
|
867
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [t("filtersBar.appliedFiltersTooltip.plural", { count: appliedFilterKeys.length }), appliedFilterKeys.map(filterKey => {
|
|
868
|
+
const title = filterBarConfig.getFilterTitle(filterKey);
|
|
869
|
+
const values = filterBarConfig.getValuesByKey(filterKey);
|
|
870
|
+
return filterBarConfig.appliedFilterKeys().includes(filterKey) ? (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { children: [title, ":"] }), jsxRuntime.jsx(TooltipValues, { values: values })] }, filterKey)) : null;
|
|
871
|
+
})] }));
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
|
|
782
875
|
/**
|
|
783
876
|
* FiltersList is a React component that displays a list of filters within a filter bar.
|
|
784
877
|
*
|
|
@@ -847,7 +940,7 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
|
|
|
847
940
|
setSearchText("");
|
|
848
941
|
}
|
|
849
942
|
}, placement: "bottom-start", children: modalState => {
|
|
850
|
-
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(
|
|
943
|
+
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 }), 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 && filterBarConfig.appliedFilterKeys().length > 0 && isSm ? (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", children: jsxRuntime.jsx("span", { className: "hidden sm:block", children: title ?? t("filtersBar.filtersHeading") }) }) }) }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { cellPadding: 100, children: jsxRuntime.jsxs(reactComponents.Card, { className: "max-h-[min(600px,_calc(100dvh-32px))] w-[300px] overflow-y-hidden", dataTestId: "starred-filters-menu-popover", children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 p-1", children: [jsxRuntime.jsx(reactFormComponents.Search, { autoFocus: true, dataTestId: "starred-filters-menu-search", fieldSize: "small", id: "search-filters-list", onChange: e => setSearchText(e.currentTarget.value), onClear: () => setSearchText(""), placeholder: t("filtersBar.searchFiltersPlaceholder"), value: searchText }), jsxRuntime.jsxs("div", { className: "flex h-7 items-center justify-between gap-1 px-3", children: [jsxRuntime.jsx(reactComponents.Text, { className: "text-secondary-400", size: "small", children: jsxRuntime.jsx(FiltersAppliedCountLabel, { filterBarConfig: filterBarConfig }) }), filterBarConfig.appliedFilterKeys().length > 0 ? (jsxRuntime.jsx(ResetFiltersButton, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] })] }), jsxRuntime.jsx(Separator, {}), jsxRuntime.jsxs(reactComponents.CardBody, { className: "gap-1 p-1", density: "none", disableGap: true, children: [jsxRuntime.jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: searchText
|
|
851
944
|
? searchResultsGrouped
|
|
852
945
|
: showCustomFilters
|
|
853
946
|
? filtersToShowGrouped
|
|
@@ -857,21 +950,6 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
|
|
|
857
950
|
} }), showDirectlyFilters.length > 0 ? (jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: showDirectlyFilters })) : null, !compact ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [appliedFilters.filter(filter => !filter.showDirectly).length > 0 ? (jsxRuntime.jsx("div", { className: "h-4 w-[1px] bg-slate-300", "data-testid": "applied-filters-buttons" })) : null, jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: appliedFilters }), filterBarConfig.appliedFilterKeys().length > 0 ? (jsxRuntime.jsx(ResetFiltersButton, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] })) : null] }));
|
|
858
951
|
};
|
|
859
952
|
const Separator = () => jsxRuntime.jsx("hr", { className: "border-secondary-200", role: "separator" });
|
|
860
|
-
const FilterButtonTooltipLabel = ({ filterBarConfig, }) => {
|
|
861
|
-
const [t] = useTranslation();
|
|
862
|
-
switch (filterBarConfig.appliedFilterKeys().length) {
|
|
863
|
-
case 0:
|
|
864
|
-
return t("filtersBar.appliedFiltersTooltip.none");
|
|
865
|
-
case 1:
|
|
866
|
-
return filterBarConfig.appliedFilterKeys()[0]
|
|
867
|
-
? t("filtersBar.appliedFiltersTooltip.singular", {
|
|
868
|
-
filterName: filterBarConfig.getFilterTitle(filterBarConfig.appliedFilterKeys()[0]),
|
|
869
|
-
})
|
|
870
|
-
: null; // should never happen though
|
|
871
|
-
default:
|
|
872
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [t("filtersBar.appliedFiltersTooltip.plural", { count: filterBarConfig.appliedFilterKeys().length }), jsxRuntime.jsx("ul", { className: "list-inside", children: filterBarConfig.appliedFilterKeys().map((appliedFilterKey, index) => (jsxRuntime.jsx("li", { className: "list-disc", children: filterBarConfig.getFilterTitle(appliedFilterKey) }, index))) })] }));
|
|
873
|
-
}
|
|
874
|
-
};
|
|
875
953
|
const FiltersAppliedCountLabel = ({ filterBarConfig, }) => {
|
|
876
954
|
const [t] = useTranslation();
|
|
877
955
|
switch (filterBarConfig.appliedFilterKeys().length) {
|
|
@@ -906,13 +984,16 @@ const FilterTableComponent = ({ filterKey, filterBarDefinition, filterBarConfig,
|
|
|
906
984
|
return [];
|
|
907
985
|
}, [filterKey, filterBarDefinition, ensureFilterKey]);
|
|
908
986
|
if (Array.isArray(filterKey)) {
|
|
909
|
-
|
|
987
|
+
const isActive = filterKey.some(key => filterBarConfig.appliedFilterKeys().includes(key));
|
|
988
|
+
return (jsxRuntime.jsx(reactComponents.Popover, { placement: "bottom-start", children: modalState => {
|
|
989
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx("div", { children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: modalState.isOpen || !isActive, label: jsxRuntime.jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKeys: filterKey }), children: jsxRuntime.jsx(reactComponents.IconButton, { icon: jsxRuntime.jsx(reactComponents.Icon, { name: "Filter", size: "small" }), size: "extraSmall", variant: isActive ? "filled" : "ghost-neutral" }) }) }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { children: jsxRuntime.jsx(reactComponents.MenuList, { children: filters.map((value, index) => value && (jsxRuntime.jsx(FilterComponent, { filter: value, filterBarActions: filterBarConfig, filterState: filterBarConfig, visualStyle: "list-item" }, index))) }) })] }));
|
|
990
|
+
} }));
|
|
910
991
|
}
|
|
911
992
|
const filter = filterBarDefinition[ensureFilterKey(filterKey)];
|
|
912
993
|
if (!filter) {
|
|
913
994
|
return null;
|
|
914
995
|
}
|
|
915
|
-
return (jsxRuntime.jsx("div", { onClick: event => event.stopPropagation(), children: jsxRuntime.jsx(FilterComponent, { asIcon: "Filter", filter: filter, filterBarActions: filterBarConfig, filterState: filterBarConfig, size: "extraSmall" }) }));
|
|
996
|
+
return (jsxRuntime.jsx("div", { onClick: event => event.stopPropagation(), children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: !filterBarConfig.appliedFilterKeys().includes(filterKey), label: jsxRuntime.jsx(SingleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKey: filterKey }), children: jsxRuntime.jsx(FilterComponent, { asIcon: "Filter", filter: filter, filterBarActions: filterBarConfig, filterState: filterBarConfig, size: "extraSmall" }) }) }));
|
|
916
997
|
};
|
|
917
998
|
|
|
918
999
|
/**
|
package/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
|
|
3
|
-
import { VirtualizedList, Text, Button, useViewportBreakpoints, Popover, PopoverTrigger, Tooltip, Icon, PopoverContent, Card, CardBody,
|
|
3
|
+
import { VirtualizedList, Text, Button, useViewportBreakpoints, Popover, PopoverTrigger, Tooltip, Icon, PopoverContent, Card, CardBody, IconButton, MenuList } from '@trackunit/react-components';
|
|
4
4
|
import { useAnalytics, useTextSearch, useCurrentUser } from '@trackunit/react-core-hooks';
|
|
5
5
|
import { FilterBody, RadioFilterItem, CheckBoxFilterItem, FilterHeader as FilterHeader$1, FilterFooter, Filter } from '@trackunit/react-filter-components';
|
|
6
6
|
import { useRef, useMemo, useState, useEffect, useCallback, Fragment as Fragment$1 } from 'react';
|
|
@@ -108,7 +108,7 @@ var defaultTranslations = {
|
|
|
108
108
|
"filter.more.options.if.you.search.title": "Over {{count}} items found.",
|
|
109
109
|
"filtersBar.appliedFiltersTooltip.none": "No filters applied",
|
|
110
110
|
"filtersBar.appliedFiltersTooltip.plural": "{{count}} filters applied:",
|
|
111
|
-
"filtersBar.appliedFiltersTooltip.singular": "{{filterName}} filter applied",
|
|
111
|
+
"filtersBar.appliedFiltersTooltip.singular": "{{filterName}} filter applied:",
|
|
112
112
|
"filtersBar.defaultAssetFilters.followedFilter.ALL": "All Assets",
|
|
113
113
|
"filtersBar.defaultAssetFilters.followedFilter.allLabel": "All Assets",
|
|
114
114
|
"filtersBar.defaultAssetFilters.followedFilter.FOLLOWED": "Followed Only",
|
|
@@ -777,6 +777,99 @@ const FiltersRenderer = ({ filters, filterBarConfig, visualStyle, }) => {
|
|
|
777
777
|
.map(filter => (jsx(FilterComponent, { filter: filter, filterBarActions: filterBarConfig, filterState: { values: filterBarConfig.values, setters: filterBarConfig.setters }, visualStyle: visualStyle }, `filter-${filter.filterKey}`)));
|
|
778
778
|
};
|
|
779
779
|
|
|
780
|
+
/**
|
|
781
|
+
* TooltipValues component that displays formatted tooltip values based on the provided input.
|
|
782
|
+
*
|
|
783
|
+
* @param {TooltipValuesProps} props - The props for the TooltipValues component.
|
|
784
|
+
* @param {FilterValueType} props.values - The input values to render in the tooltip.
|
|
785
|
+
* @returns {ReactElement} The rendered TooltipValues component.
|
|
786
|
+
*/
|
|
787
|
+
const TooltipValues = ({ values }) => {
|
|
788
|
+
return jsx("div", { children: renderTooltipValues(values) });
|
|
789
|
+
};
|
|
790
|
+
const renderTooltipValues = (values) => {
|
|
791
|
+
if (values === undefined) {
|
|
792
|
+
return null;
|
|
793
|
+
}
|
|
794
|
+
// Array of objects ValueName[]
|
|
795
|
+
if (Array.isArray(values) && typeof values[0] === "object") {
|
|
796
|
+
return (jsx("ul", { className: "list-inside", children: values.map((value, index) => (jsx("li", { className: "list-disc", children: value.name }, index))) }));
|
|
797
|
+
}
|
|
798
|
+
// Array of strings
|
|
799
|
+
if (Array.isArray(values)) {
|
|
800
|
+
return (jsx("ul", { className: "list-inside", children: values.map((value, index) => {
|
|
801
|
+
return (jsx("li", { className: "list-disc", children: typeof value === "string" ? value : value.name }, index));
|
|
802
|
+
}) }));
|
|
803
|
+
}
|
|
804
|
+
// single object ValueName
|
|
805
|
+
if (typeof values === "object" && values.name) {
|
|
806
|
+
return (jsx("ul", { className: "list-inside", children: jsx("li", { className: "list-disc", children: values.name }) }));
|
|
807
|
+
}
|
|
808
|
+
// String or number
|
|
809
|
+
if (typeof values === "string" || typeof values === "number") {
|
|
810
|
+
return (jsx("ul", { className: "list-inside", children: jsx("li", { className: "list-disc", children: values.toString() }) }));
|
|
811
|
+
}
|
|
812
|
+
// BooleanValue
|
|
813
|
+
if (typeof values === "object" && values.booleanValue !== undefined) {
|
|
814
|
+
return values.booleanValue ? "Yes" : "No";
|
|
815
|
+
}
|
|
816
|
+
// MinMaxFilterValue
|
|
817
|
+
if (typeof values === "object" && "min" in values && "max" in values) {
|
|
818
|
+
const minMax = values;
|
|
819
|
+
return `Min: ${minMax.min}, Max: ${minMax.max}`;
|
|
820
|
+
}
|
|
821
|
+
return null;
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Component that displays a tooltip label with filter details.
|
|
826
|
+
*
|
|
827
|
+
* @template TFilterBarDefinition - The type of the filter bar definition.
|
|
828
|
+
* @param {SingleFilterTooltipLabelProps} props - Component properties.
|
|
829
|
+
* @param {FilterState<TFilterBarDefinition> & FilterMapActions & FilterMapGetter} props.filterBarConfig -
|
|
830
|
+
* Configuration object for the filter bar, containing state, actions, and accessors.
|
|
831
|
+
* @param {string} props.filterKey - The key identifying the filter.
|
|
832
|
+
* @returns {ReactElement} The rendered tooltip label and applied filter values.
|
|
833
|
+
*/
|
|
834
|
+
const SingleFilterTooltipLabel = ({ filterBarConfig, filterKey, }) => {
|
|
835
|
+
const title = filterBarConfig.getFilterTitle(filterKey);
|
|
836
|
+
const values = filterBarConfig.getValuesByKey(filterKey);
|
|
837
|
+
const [t] = useTranslation();
|
|
838
|
+
return (jsxs(Fragment, { children: [t("filtersBar.appliedFiltersTooltip.singular", {
|
|
839
|
+
filterName: title,
|
|
840
|
+
}), jsx(TooltipValues, { values: values })] }));
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Component that displays a tooltip for filters.
|
|
845
|
+
* Differentiates cases with no applied filters, a single filter, or multiple filters.
|
|
846
|
+
*
|
|
847
|
+
* @template TFilterBarDefinition The type definition for the FilterBar.
|
|
848
|
+
* @param {MultipleFilterTooltipLabelProps} props The component's props.
|
|
849
|
+
* @param {FilterState<TFilterBarDefinition> & FilterMapActions & FilterMapGetter} props.filterBarConfig
|
|
850
|
+
* The FilterBar configuration, including filter state, actions, and getter methods.
|
|
851
|
+
* @param {string[]} [props.filterKeys] An optional list of filter keys to filter the currently applied filters.
|
|
852
|
+
* @returns {ReactElement | string} Returns a element or string for the tooltip displaying applied filters.
|
|
853
|
+
*/
|
|
854
|
+
const MultipleFilterTooltipLabel = ({ filterBarConfig, filterKeys, }) => {
|
|
855
|
+
const [t] = useTranslation();
|
|
856
|
+
const appliedFilterKeys = filterKeys
|
|
857
|
+
? filterKeys.filter(key => filterBarConfig.appliedFilterKeys().includes(key))
|
|
858
|
+
: filterBarConfig.appliedFilterKeys();
|
|
859
|
+
switch (appliedFilterKeys.length) {
|
|
860
|
+
case 0:
|
|
861
|
+
return t("filtersBar.appliedFiltersTooltip.none");
|
|
862
|
+
case 1:
|
|
863
|
+
return jsx(SingleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKey: appliedFilterKeys[0] });
|
|
864
|
+
default:
|
|
865
|
+
return (jsxs(Fragment, { children: [t("filtersBar.appliedFiltersTooltip.plural", { count: appliedFilterKeys.length }), appliedFilterKeys.map(filterKey => {
|
|
866
|
+
const title = filterBarConfig.getFilterTitle(filterKey);
|
|
867
|
+
const values = filterBarConfig.getValuesByKey(filterKey);
|
|
868
|
+
return filterBarConfig.appliedFilterKeys().includes(filterKey) ? (jsxs("div", { children: [jsxs("div", { children: [title, ":"] }), jsx(TooltipValues, { values: values })] }, filterKey)) : null;
|
|
869
|
+
})] }));
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
|
|
780
873
|
/**
|
|
781
874
|
* FiltersList is a React component that displays a list of filters within a filter bar.
|
|
782
875
|
*
|
|
@@ -845,7 +938,7 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
|
|
|
845
938
|
setSearchText("");
|
|
846
939
|
}
|
|
847
940
|
}, placement: "bottom-start", children: modalState => {
|
|
848
|
-
return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { "data-testid": "starred-filters-menu-trigger", id: "starred-filters-menu-trigger", children: jsx(Tooltip, { disabled: !compact || modalState.isOpen, label: jsx(
|
|
941
|
+
return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { "data-testid": "starred-filters-menu-trigger", id: "starred-filters-menu-trigger", children: jsx(Tooltip, { disabled: !compact || modalState.isOpen, label: jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig }), children: jsx(Button, { prefix: jsx(Icon, { ariaHidden: true, color: filterBarConfig.appliedFilterKeys().length > 0 ? "primary" : undefined, name: "Filter", size: "small" }), size: "small", suffix: compact && filterBarConfig.appliedFilterKeys().length > 0 && isSm ? (jsxs("div", { children: [jsxs("span", { "aria-hidden": true, children: ["(", filterBarConfig.appliedFilterKeys().length, ")"] }), jsxs("span", { className: "sr-only", children: [filterBarConfig.appliedFilterKeys().length, " filters applied"] })] })) : undefined, variant: "secondary", children: jsx("span", { className: "hidden sm:block", children: title ?? t("filtersBar.filtersHeading") }) }) }) }) }), jsx(PopoverContent, { cellPadding: 100, children: jsxs(Card, { className: "max-h-[min(600px,_calc(100dvh-32px))] w-[300px] overflow-y-hidden", dataTestId: "starred-filters-menu-popover", children: [jsxs("div", { className: "flex flex-col gap-1 p-1", children: [jsx(Search, { autoFocus: true, dataTestId: "starred-filters-menu-search", fieldSize: "small", id: "search-filters-list", onChange: e => setSearchText(e.currentTarget.value), onClear: () => setSearchText(""), placeholder: t("filtersBar.searchFiltersPlaceholder"), value: searchText }), jsxs("div", { className: "flex h-7 items-center justify-between gap-1 px-3", children: [jsx(Text, { className: "text-secondary-400", size: "small", children: jsx(FiltersAppliedCountLabel, { filterBarConfig: filterBarConfig }) }), filterBarConfig.appliedFilterKeys().length > 0 ? (jsx(ResetFiltersButton, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] })] }), jsx(Separator, {}), jsxs(CardBody, { className: "gap-1 p-1", density: "none", disableGap: true, children: [jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: searchText
|
|
849
942
|
? searchResultsGrouped
|
|
850
943
|
: showCustomFilters
|
|
851
944
|
? filtersToShowGrouped
|
|
@@ -855,21 +948,6 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
|
|
|
855
948
|
} }), showDirectlyFilters.length > 0 ? (jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: showDirectlyFilters })) : null, !compact ? (jsxs(Fragment, { children: [appliedFilters.filter(filter => !filter.showDirectly).length > 0 ? (jsx("div", { className: "h-4 w-[1px] bg-slate-300", "data-testid": "applied-filters-buttons" })) : null, jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: appliedFilters }), filterBarConfig.appliedFilterKeys().length > 0 ? (jsx(ResetFiltersButton, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] })) : null] }));
|
|
856
949
|
};
|
|
857
950
|
const Separator = () => jsx("hr", { className: "border-secondary-200", role: "separator" });
|
|
858
|
-
const FilterButtonTooltipLabel = ({ filterBarConfig, }) => {
|
|
859
|
-
const [t] = useTranslation();
|
|
860
|
-
switch (filterBarConfig.appliedFilterKeys().length) {
|
|
861
|
-
case 0:
|
|
862
|
-
return t("filtersBar.appliedFiltersTooltip.none");
|
|
863
|
-
case 1:
|
|
864
|
-
return filterBarConfig.appliedFilterKeys()[0]
|
|
865
|
-
? t("filtersBar.appliedFiltersTooltip.singular", {
|
|
866
|
-
filterName: filterBarConfig.getFilterTitle(filterBarConfig.appliedFilterKeys()[0]),
|
|
867
|
-
})
|
|
868
|
-
: null; // should never happen though
|
|
869
|
-
default:
|
|
870
|
-
return (jsxs(Fragment, { children: [t("filtersBar.appliedFiltersTooltip.plural", { count: filterBarConfig.appliedFilterKeys().length }), jsx("ul", { className: "list-inside", children: filterBarConfig.appliedFilterKeys().map((appliedFilterKey, index) => (jsx("li", { className: "list-disc", children: filterBarConfig.getFilterTitle(appliedFilterKey) }, index))) })] }));
|
|
871
|
-
}
|
|
872
|
-
};
|
|
873
951
|
const FiltersAppliedCountLabel = ({ filterBarConfig, }) => {
|
|
874
952
|
const [t] = useTranslation();
|
|
875
953
|
switch (filterBarConfig.appliedFilterKeys().length) {
|
|
@@ -904,13 +982,16 @@ const FilterTableComponent = ({ filterKey, filterBarDefinition, filterBarConfig,
|
|
|
904
982
|
return [];
|
|
905
983
|
}, [filterKey, filterBarDefinition, ensureFilterKey]);
|
|
906
984
|
if (Array.isArray(filterKey)) {
|
|
907
|
-
|
|
985
|
+
const isActive = filterKey.some(key => filterBarConfig.appliedFilterKeys().includes(key));
|
|
986
|
+
return (jsx(Popover, { placement: "bottom-start", children: modalState => {
|
|
987
|
+
return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { children: jsx(Tooltip, { disabled: modalState.isOpen || !isActive, label: jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKeys: filterKey }), children: jsx(IconButton, { icon: jsx(Icon, { name: "Filter", size: "small" }), size: "extraSmall", variant: isActive ? "filled" : "ghost-neutral" }) }) }) }), jsx(PopoverContent, { children: jsx(MenuList, { children: filters.map((value, index) => value && (jsx(FilterComponent, { filter: value, filterBarActions: filterBarConfig, filterState: filterBarConfig, visualStyle: "list-item" }, index))) }) })] }));
|
|
988
|
+
} }));
|
|
908
989
|
}
|
|
909
990
|
const filter = filterBarDefinition[ensureFilterKey(filterKey)];
|
|
910
991
|
if (!filter) {
|
|
911
992
|
return null;
|
|
912
993
|
}
|
|
913
|
-
return (jsx("div", { onClick: event => event.stopPropagation(), children: jsx(FilterComponent, { asIcon: "Filter", filter: filter, filterBarActions: filterBarConfig, filterState: filterBarConfig, size: "extraSmall" }) }));
|
|
994
|
+
return (jsx("div", { onClick: event => event.stopPropagation(), children: jsx(Tooltip, { disabled: !filterBarConfig.appliedFilterKeys().includes(filterKey), label: jsx(SingleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKey: filterKey }), children: jsx(FilterComponent, { asIcon: "Filter", filter: filter, filterBarActions: filterBarConfig, filterState: filterBarConfig, size: "extraSmall" }) }) }));
|
|
914
995
|
};
|
|
915
996
|
|
|
916
997
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/filters-filter-bar",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.192",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -13,19 +13,19 @@
|
|
|
13
13
|
"jest-fetch-mock": "^3.0.3",
|
|
14
14
|
"tailwind-merge": "^2.0.0",
|
|
15
15
|
"string-ts": "^2.0.0",
|
|
16
|
-
"@trackunit/iris-app-api": "1.3.123",
|
|
17
|
-
"@trackunit/react-core-hooks": "1.3.128",
|
|
18
|
-
"@trackunit/react-filter-components": "1.3.159",
|
|
19
|
-
"@trackunit/react-date-and-time-components": "1.3.162",
|
|
20
16
|
"zod": "3.23.4",
|
|
21
|
-
"@trackunit/
|
|
22
|
-
"@trackunit/react-
|
|
23
|
-
"@trackunit/react-
|
|
24
|
-
"@trackunit/
|
|
25
|
-
"@trackunit/
|
|
26
|
-
"@trackunit/
|
|
27
|
-
"@trackunit/react-
|
|
28
|
-
"@trackunit/
|
|
17
|
+
"@trackunit/iris-app-api": "1.3.124",
|
|
18
|
+
"@trackunit/react-core-hooks": "1.3.129",
|
|
19
|
+
"@trackunit/react-filter-components": "1.3.161",
|
|
20
|
+
"@trackunit/react-date-and-time-components": "1.3.164",
|
|
21
|
+
"@trackunit/shared-utils": "1.5.119",
|
|
22
|
+
"@trackunit/react-form-components": "1.3.161",
|
|
23
|
+
"@trackunit/react-core-contexts-api": "1.4.125",
|
|
24
|
+
"@trackunit/geo-json-utils": "1.3.119",
|
|
25
|
+
"@trackunit/i18n-library-translation": "1.3.133",
|
|
26
|
+
"@trackunit/css-class-variance-utilities": "1.3.119",
|
|
27
|
+
"@trackunit/react-components": "1.4.143",
|
|
28
|
+
"@trackunit/react-test-setup": "1.0.9"
|
|
29
29
|
},
|
|
30
30
|
"module": "./index.esm.js",
|
|
31
31
|
"main": "./index.cjs.js",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { FilterBarDefinition, FilterMapActions, FilterMapGetter, FilterState } from "../../types/FilterTypes";
|
|
3
|
+
interface MultipleFilterTooltipLabelProps<TFilterBarDefinition extends FilterBarDefinition> {
|
|
4
|
+
filterBarConfig: FilterState<TFilterBarDefinition> & FilterMapActions & FilterMapGetter;
|
|
5
|
+
filterKeys?: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Component that displays a tooltip for filters.
|
|
9
|
+
* Differentiates cases with no applied filters, a single filter, or multiple filters.
|
|
10
|
+
*
|
|
11
|
+
* @template TFilterBarDefinition The type definition for the FilterBar.
|
|
12
|
+
* @param {MultipleFilterTooltipLabelProps} props The component's props.
|
|
13
|
+
* @param {FilterState<TFilterBarDefinition> & FilterMapActions & FilterMapGetter} props.filterBarConfig
|
|
14
|
+
* The FilterBar configuration, including filter state, actions, and getter methods.
|
|
15
|
+
* @param {string[]} [props.filterKeys] An optional list of filter keys to filter the currently applied filters.
|
|
16
|
+
* @returns {ReactElement | string} Returns a element or string for the tooltip displaying applied filters.
|
|
17
|
+
*/
|
|
18
|
+
declare const MultipleFilterTooltipLabel: <TFilterBarDefinition extends FilterBarDefinition>({ filterBarConfig, filterKeys, }: MultipleFilterTooltipLabelProps<TFilterBarDefinition>) => ReactElement | string;
|
|
19
|
+
export default MultipleFilterTooltipLabel;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { FilterBarDefinition, FilterMapActions, FilterMapGetter, FilterState } from "../../types/FilterTypes";
|
|
3
|
+
interface SingleFilterTooltipLabelProps<TFilterBarDefinition extends FilterBarDefinition> {
|
|
4
|
+
filterBarConfig: FilterState<TFilterBarDefinition> & FilterMapActions & FilterMapGetter;
|
|
5
|
+
filterKey: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Component that displays a tooltip label with filter details.
|
|
9
|
+
*
|
|
10
|
+
* @template TFilterBarDefinition - The type of the filter bar definition.
|
|
11
|
+
* @param {SingleFilterTooltipLabelProps} props - Component properties.
|
|
12
|
+
* @param {FilterState<TFilterBarDefinition> & FilterMapActions & FilterMapGetter} props.filterBarConfig -
|
|
13
|
+
* Configuration object for the filter bar, containing state, actions, and accessors.
|
|
14
|
+
* @param {string} props.filterKey - The key identifying the filter.
|
|
15
|
+
* @returns {ReactElement} The rendered tooltip label and applied filter values.
|
|
16
|
+
*/
|
|
17
|
+
declare const SingleFilterTooltipLabel: <TFilterBarDefinition extends FilterBarDefinition>({ filterBarConfig, filterKey, }: SingleFilterTooltipLabelProps<TFilterBarDefinition>) => ReactElement;
|
|
18
|
+
export default SingleFilterTooltipLabel;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { FilterValueType } from "../../types/FilterTypes";
|
|
3
|
+
type TooltipValuesProps = {
|
|
4
|
+
values: FilterValueType;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* TooltipValues component that displays formatted tooltip values based on the provided input.
|
|
8
|
+
*
|
|
9
|
+
* @param {TooltipValuesProps} props - The props for the TooltipValues component.
|
|
10
|
+
* @param {FilterValueType} props.values - The input values to render in the tooltip.
|
|
11
|
+
* @returns {ReactElement} The rendered TooltipValues component.
|
|
12
|
+
*/
|
|
13
|
+
declare const TooltipValues: ({ values }: TooltipValuesProps) => ReactElement;
|
|
14
|
+
export default TooltipValues;
|