@trackunit/filters-filter-bar 2.4.4 → 2.4.7-alpha-770d9994af7.0

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
@@ -3,11 +3,11 @@
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var i18nLibraryTranslation = require('@trackunit/i18n-library-translation');
5
5
  var react = require('react');
6
+ var tailwindMerge = require('tailwind-merge');
6
7
  var reactFilterComponents = require('@trackunit/react-filter-components');
7
8
  var reactComponents = require('@trackunit/react-components');
8
9
  var reactCoreHooks = require('@trackunit/react-core-hooks');
9
10
  var stringTs = require('string-ts');
10
- var tailwindMerge = require('tailwind-merge');
11
11
  var irisAppRuntimeCoreApi = require('@trackunit/iris-app-runtime-core-api');
12
12
  var reactFormComponents = require('@trackunit/react-form-components');
13
13
  var reactDateAndTimeComponents = require('@trackunit/react-date-and-time-components');
@@ -451,9 +451,9 @@ const ResetFiltersButtonWithIcon = ({ resetFiltersToInitialState, "data-testid":
451
451
  /**
452
452
  *
453
453
  */
454
- const AppliedFiltersRenderer = ({ appliedFilters, filterBarConfig, showResetButton = true, style, }) => {
454
+ const AppliedFiltersRenderer = ({ appliedFilters, filterBarConfig, showResetButton = true, className, "data-testid": dataTestId, ref, style, }) => {
455
455
  const filtersToRender = react.useMemo(() => appliedFilters.filter(filter => !filter.showDirectly), [appliedFilters]);
456
- return (jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", style: style, children: [filtersToRender.length > 0 ? (jsxRuntime.jsx("div", { className: "h-4 w-[1px] bg-neutral-300", "data-testid": "applied-filters-buttons" })) : null, jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: filtersToRender }), appliedFilters.length > 0 && showResetButton ? (jsxRuntime.jsx(ResetFiltersButtonWithIcon, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] }));
456
+ return (jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("flex flex-wrap items-center gap-2", className), "data-testid": dataTestId, ref: ref, style: style, children: [filtersToRender.length > 0 ? (jsxRuntime.jsx("div", { className: "h-4 w-[1px] bg-neutral-300", "data-testid": "applied-filters-buttons" })) : null, jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: filtersToRender }), appliedFilters.length > 0 && showResetButton ? (jsxRuntime.jsx(ResetFiltersButtonWithIcon, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] }));
457
457
  };
458
458
 
459
459
  /**
@@ -687,11 +687,11 @@ const DefaultCheckboxFilter = ({ filterDefinition, filterBarActions, options, lo
687
687
  onChange: customSearch?.onChange ?? setSearchText,
688
688
  onClear: customSearch?.onClear ?? (() => setSearchText("")),
689
689
  count: undefinedCount ? filteredOptions.length - 1 : filteredOptions.length,
690
- }, children: options.length >= 2 ? (jsxRuntime.jsx(reactComponents.Button, { className: "place-self-start", "data-testid": "selectAllButton", disabled: hasSelectedAll, onClick: handleSelectAll, size: "small", variant: "ghost", children: t("filtersBar.selectAll") })) : null }), jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("grid max-h-[50dvh] min-h-0 overflow-hidden", undefinedCount ? "grid-rows-[minmax(0,1fr)_auto]" : "grid-rows-[minmax(0,1fr)]"), children: [jsxRuntime.jsx(FilterResults, { ignoreUndefined: undefinedCount !== null, loading: loading, results: results, children: res => (jsxRuntime.jsx(DynamicFilterList, { checked: index => {
690
+ }, children: options.length >= 2 ? (jsxRuntime.jsx(reactComponents.Button, { className: "place-self-start", "data-testid": "selectAllButton", disabled: hasSelectedAll, onClick: handleSelectAll, size: "small", variant: "ghost", children: t("filtersBar.selectAll") })) : null }), jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("grid min-h-0 overflow-hidden", undefinedCount ? "grid-rows-[minmax(0,1fr)_auto]" : "grid-rows-[minmax(0,1fr)]"), children: [jsxRuntime.jsx(FilterResults, { ignoreUndefined: undefinedCount !== null, loading: loading, results: results, children: res => (jsxRuntime.jsx(DynamicFilterList, { checked: index => {
691
691
  return filterDefinition.type === "valueNameArray"
692
692
  ? filterBarActions.objectArrayIncludesValue(filterDefinition.filterKey, res[index]?.key || "")
693
693
  : filterBarActions.arrayIncludesValue(filterDefinition.filterKey, res[index]?.key || "");
694
- }, className: "mb-1 h-full", count: index => res[index]?.count, keyMapper: index => res[index]?.key || "", labelMapper: index => res[index]?.label || "", onChange: index => {
694
+ }, className: "h-full", count: index => res[index]?.count, keyMapper: index => res[index]?.key || "", labelMapper: index => res[index]?.label || "", onChange: index => {
695
695
  const result = res[index];
696
696
  if (result) {
697
697
  handleSetValue(result);
@@ -933,10 +933,10 @@ const useFiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters =
933
933
  *
934
934
  * @returns {ReactElement} - Returns the FiltersList component.
935
935
  */
936
- const GroupedFiltersList = ({ filterBarConfig, filtersGrouped, className, style, "data-testid": dataTestId = "grouped-filters-list", }) => {
937
- return (jsxRuntime.jsx("div", { className: className, "data-testid": dataTestId, role: "menu", style: style, children: filtersGrouped.map((group, idx) => {
936
+ const GroupedFiltersList = ({ filterBarConfig, filtersGrouped, className, ref, style, "data-testid": dataTestId = "grouped-filters-list", }) => {
937
+ return (jsxRuntime.jsx("div", { className: className, "data-testid": dataTestId, ref: ref, style: style, children: filtersGrouped.map((group, idx) => {
938
938
  const isLastGroup = idx === filtersGrouped.length - 1;
939
- return (jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [jsxRuntime.jsxs("div", { children: [filtersGrouped.length > 1 && (jsxRuntime.jsx(reactComponents.Text, { className: "h-7 px-3 py-2 text-neutral-400", "data-testid": `${group.key}-group-title`, size: "small", uppercase: true, weight: "bold", children: group.title })), jsxRuntime.jsx("ul", { "aria-labelledby": `${group.key}-group-title`, className: "grid", "data-testid": `${group.key}-group-list`, children: jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: group.filters, visualStyle: "list-item" }) })] }), isLastGroup ? null : jsxRuntime.jsx("div", { className: "h-[1px] w-full bg-neutral-200", role: "separator" })] }, group.key));
939
+ return (jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [jsxRuntime.jsxs("div", { children: [filtersGrouped.length > 1 && (jsxRuntime.jsx(reactComponents.Text, { className: "h-7 p-2 text-neutral-400", "data-testid": `${group.key}-group-title`, size: "small", uppercase: true, weight: "bold", children: group.title })), jsxRuntime.jsx("ul", { "aria-labelledby": `${group.key}-group-title`, className: "grid", "data-testid": `${group.key}-group-list`, children: jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: group.filters, visualStyle: "list-item" }) })] }), isLastGroup ? null : jsxRuntime.jsx("div", { className: "h-[1px] w-full bg-neutral-200", role: "separator" })] }, group.key));
940
940
  }) }));
941
941
  };
942
942
 
@@ -945,25 +945,38 @@ const GroupedFiltersList = ({ filterBarConfig, filtersGrouped, className, style,
945
945
  *
946
946
  * @returns {ReactElement | null} The rendered ResetFiltersButton component, or null if no filters have been applied.
947
947
  */
948
- const ResetFiltersButton = ({ resetFiltersToInitialState, "data-testid": dataTestId, className, }) => {
948
+ const ResetFiltersButton = ({ resetFiltersToInitialState, "data-testid": dataTestId, className, ref, style, }) => {
949
949
  const [t] = useTranslation();
950
950
  return (jsxRuntime.jsxs(reactComponents.Button, { className: className, "data-testid": dataTestId ?? "reset-filters-button", onClick: () => {
951
951
  resetFiltersToInitialState();
952
- }, size: "small", variant: "ghost", children: [t("filtersBar.resetFilters"), jsxRuntime.jsx("span", { className: "sr-only", children: t("filtersBar.resetFiltersSR") })] }));
952
+ }, ref: ref, size: "small", style: style, variant: "ghost", children: [t("filtersBar.resetFilters"), jsxRuntime.jsx("span", { className: "sr-only", children: t("filtersBar.resetFiltersSR") })] }));
953
953
  };
954
954
 
955
955
  /**
956
956
  *
957
957
  */
958
- const FiltersMenuContent = ({ filterBarConfig, setShowCustomFilters, setSearchText, searchText, searchResultsGrouped, filtersToShowGrouped, removeCustomFieldsGroup, hasCustomFields, appliedCustomFields, showCustomFilters, filterBarDefinitionCount, }) => {
958
+ const FiltersMenuContent = ({ filterBarConfig, setShowCustomFilters, setSearchText, searchText, searchResultsGrouped, filtersToShowGrouped, removeCustomFieldsGroup, hasCustomFields, appliedCustomFields, showCustomFilters, filterBarDefinitionCount, className, "data-testid": dataTestId = "starred-filters-menu-popover", ref, style, }) => {
959
959
  const [t] = useTranslation();
960
- return (jsxRuntime.jsxs(reactComponents.Card, { className: "max-h-[min(600px,calc(100dvh-32px))] w-[300px] overflow-y-hidden", "data-testid": "starred-filters-menu-popover", id: "starred-filters-menu-popover", tabIndex: 0, children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 p-1", children: [filterBarDefinitionCount > 5 && (jsxRuntime.jsx(reactFormComponents.Search, { autoFocus: true, "data-testid": "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 pl-3", children: [jsxRuntime.jsx(reactComponents.Text, { className: "text-neutral-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", gap: "none", padding: "none", children: [jsxRuntime.jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: searchText
961
- ? searchResultsGrouped
962
- : showCustomFilters
963
- ? filtersToShowGrouped
964
- : removeCustomFieldsGroup(filtersToShowGrouped) }), hasCustomFields && !showCustomFilters && !searchText ? (jsxRuntime.jsx(CustomFieldsHiddenGroup, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, onClickShow: () => {
965
- setShowCustomFilters(true);
966
- } })) : null] })] }));
960
+ // Chrome-only shell (not `MenuContent`): filter rows are wrapped (`GroupedFiltersList`
961
+ // `FilterComponent` → `Filter` → `MenuItem`), so `MenuContent`'s direct-child registration would
962
+ // never attach keyboard nav — leaving a `role="menu"` with no owned menuitems. Shadow/layout come
963
+ // from `cvaMenu`/`cvaMenuList`; keyboard ownership returns when MenuItem self-registers (GLU-1644).
964
+ return (jsxRuntime.jsx("div", { className: reactComponents.cvaMenu({
965
+ className: tailwindMerge.twMerge("max-h-[min(600px,calc(100dvh-32px))] grid-rows-[minmax(0,1fr)] overflow-y-hidden p-0", className),
966
+ limitWidth: true,
967
+ }), "data-testid": dataTestId, ref: ref, style: style, children: jsxRuntime.jsxs("div", {
968
+ // `gap-y-0` cancels `cvaMenuList`'s default inter-item gap, which here would otherwise land
969
+ // between the header block (search/count + separator) and the scrollable list below it,
970
+ // showing as a sliver of whitespace above the list's own scrollbar.
971
+ className: reactComponents.cvaMenuList({
972
+ className: "grid-rows-min-fr !max-h-none min-h-0 gap-y-0 !overflow-y-hidden p-0",
973
+ }), children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 p-1", children: [filterBarDefinitionCount > 5 && (jsxRuntime.jsx(reactFormComponents.Search, { autoFocus: true, "data-testid": "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 pl-3", children: [jsxRuntime.jsx(reactComponents.Text, { className: "text-neutral-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("div", { className: "flex min-h-0 flex-col gap-1 overflow-auto p-1", children: [jsxRuntime.jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: searchText
974
+ ? searchResultsGrouped
975
+ : showCustomFilters
976
+ ? filtersToShowGrouped
977
+ : removeCustomFieldsGroup(filtersToShowGrouped) }), hasCustomFields && !showCustomFilters && !searchText ? (jsxRuntime.jsx(CustomFieldsHiddenGroup, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, onClickShow: () => {
978
+ setShowCustomFilters(true);
979
+ } })) : null] })] }) }));
967
980
  };
968
981
  const Separator = () => jsxRuntime.jsx("hr", { className: "border-neutral-200", role: "separator" });
969
982
  const FiltersAppliedCountLabel = ({ filterBarConfig, }) => {
@@ -992,6 +1005,26 @@ const CustomFieldsHiddenGroup = ({ appliedCustomFields, filterBarConfig, onClick
992
1005
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Separator, {}), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(reactComponents.Button, { "aria-controls": "filters-list", className: "text-primary-600 w-full justify-between px-3", onClick: onClickShow, prefix: jsxRuntime.jsx(reactComponents.Text, { className: "text-neutral-400", size: "small", uppercase: true, weight: "bold", children: t("filtersBar.groups.CUSTOM_FIELDS") }), size: "small", variant: "ghost-neutral", children: t("filtersBar.showAll") }), appliedCustomFields.length > 0 ? (jsxRuntime.jsx("ul", { "aria-label": "Visible custom fields", "data-testid": "applied-custom-fields-list", children: jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: appliedCustomFields, visualStyle: "list-item" }) })) : null] })] }));
993
1006
  };
994
1007
 
1008
+ const sharedButtonProps = {
1009
+ size: "small",
1010
+ variant: "secondary",
1011
+ };
1012
+ /**
1013
+ * FiltersMenuTriggerButton is the button that opens the filters popover menu.
1014
+ *
1015
+ * On small viewports (`isCompact`) it renders as a square icon-only button with the applied filters count
1016
+ * overlaid as a badge. Otherwise it renders as a regular button with a text label and an inline count badge.
1017
+ */
1018
+ const FiltersMenuTriggerButton = ({ isCompact, hasAppliedFilters, appliedValuesCount, title, buttonProps, }) => {
1019
+ const [t] = useTranslation();
1020
+ const label = title ?? t("filtersBar.filtersHeading");
1021
+ const icon = jsxRuntime.jsx(reactComponents.Icon, { ariaHidden: true, color: hasAppliedFilters ? "primary" : undefined, name: "Funnel", size: "small" });
1022
+ if (isCompact) {
1023
+ return (jsxRuntime.jsxs(reactComponents.ZStack, { className: "shrink-0", children: [jsxRuntime.jsx(reactComponents.IconButton, { ariaLabel: label, icon: icon, ...sharedButtonProps, ...buttonProps }), appliedValuesCount > 0 ? (jsxRuntime.jsx(reactComponents.Badge, { className: "-translate-y-1/3 translate-x-1/3 self-start justify-self-end", color: "primary", count: appliedValuesCount, hideZero: true, size: "condensed" })) : null] }));
1024
+ }
1025
+ return (jsxRuntime.jsx(reactComponents.Button, { prefix: icon, suffix: appliedValuesCount > 0 ? (jsxRuntime.jsx(reactComponents.Badge, { color: "primary", count: appliedValuesCount, hideZero: true, size: "condensed" })) : null, ...sharedButtonProps, ...buttonProps, children: title !== "" ? label : null }));
1026
+ };
1027
+
995
1028
  /**
996
1029
  * TooltipValues component that displays formatted tooltip values based on the provided input.
997
1030
  *
@@ -1032,8 +1065,8 @@ const TooltipValues = ({ values }) => {
1032
1065
  * @param {any} props.displayValues - The filter values to display.
1033
1066
  * @returns {ReactElement} The rendered component showing the title and values.
1034
1067
  */
1035
- const TooltipLabel = ({ title, displayValues }) => {
1036
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "text-xs font-medium", children: title }), jsxRuntime.jsx(TooltipValues, { values: displayValues })] }));
1068
+ const TooltipLabel = ({ title, displayValues, className, "data-testid": dataTestId, ref, style, }) => {
1069
+ return (jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("contents", className), "data-testid": dataTestId, ref: ref, style: style, children: [jsxRuntime.jsx("div", { className: "text-xs font-medium", children: title }), jsxRuntime.jsx(TooltipValues, { values: displayValues })] }));
1037
1070
  };
1038
1071
 
1039
1072
  /**
@@ -1095,8 +1128,7 @@ const MultipleFilterTooltipLabel = ({ filterBarConfig, filterKeys, filters, }) =
1095
1128
  * @template TFilterBarDefinition - The type representing the filter bar definition.
1096
1129
  * @returns {ReactElement} - Returns the FilterMenu component.
1097
1130
  */
1098
- const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [], compact = false, title, "data-testid": dataTestId = "filters-menu", className, style, buttonProps, allowShowFiltersDirectly = true, includeFilterKeys, }) => {
1099
- const [t] = useTranslation();
1131
+ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [], compact = false, title, "data-testid": dataTestId = "filters-menu", className, ref, style, buttonProps, allowShowFiltersDirectly = true, includeFilterKeys, }) => {
1100
1132
  const [showCustomFilters, setShowCustomFilters] = react.useState(false);
1101
1133
  const { isSm } = reactComponents.useViewportBreakpoints();
1102
1134
  const filterBarDefinitionCount = react.useMemo(() => sharedUtils.objectValues(filterBarDefinition).length, [filterBarDefinition]);
@@ -1117,14 +1149,14 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
1117
1149
  includeFilterKeys,
1118
1150
  allowShowFiltersDirectly,
1119
1151
  });
1120
- return (jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("flex items-start gap-2", className), "data-testid": dataTestId, style: style, children: [jsxRuntime.jsx(reactComponents.Popover, { onOpenStateChange: open => {
1121
- if (!open) {
1122
- setShowCustomFilters(false);
1123
- setSearchText("");
1124
- }
1125
- }, placement: "bottom-start", children: modalState => {
1126
- 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: modalState.isOpen, label: jsxRuntime.jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filters: appliedFilters }), placement: "bottom", children: !isSm ? (jsxRuntime.jsx(reactComponents.Button, { "aria-label": title ?? t("filtersBar.filtersHeading"), prefix: jsxRuntime.jsx(reactComponents.Icon, { ariaHidden: true, color: filterBarConfig.appliedFilterKeys().length > 0 ? "primary" : undefined, name: "Funnel", size: "small" }), size: "small", suffix: totalAppliedValuesCount > 0 ? (jsxRuntime.jsx(reactComponents.Badge, { color: "primary", count: totalAppliedValuesCount, hideZero: true, size: "condensed" })) : null, variant: "secondary", ...buttonProps })) : (jsxRuntime.jsx(reactComponents.Button, { prefix: jsxRuntime.jsx(reactComponents.Icon, { ariaHidden: true, color: filterBarConfig.appliedFilterKeys().length > 0 ? "primary" : undefined, name: "Funnel", size: "small" }), size: "small", suffix: totalAppliedValuesCount > 0 ? (jsxRuntime.jsx(reactComponents.Badge, { color: "primary", count: totalAppliedValuesCount, hideZero: true, size: "condensed" })) : null, 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 }) })] }));
1127
- } }), showDirectlyFilters.length > 0 ? (jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: showDirectlyFilters })) : null, compact === false ? (jsxRuntime.jsx(AppliedFiltersRenderer, { appliedFilters: appliedFilters, filterBarConfig: filterBarConfig })) : null] }));
1152
+ return (jsxRuntime.jsxs("div", { className: tailwindMerge.twMerge("flex items-start gap-2", className), "data-testid": dataTestId, ref: ref, style: style, children: [jsxRuntime.jsx(reactComponents.MenuTree, { children: jsxRuntime.jsx(reactComponents.Popover, { onOpenStateChange: open => {
1153
+ if (!open) {
1154
+ setShowCustomFilters(false);
1155
+ setSearchText("");
1156
+ }
1157
+ }, placement: "bottom-start", children: modalState => {
1158
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx("div", { className: "shrink-0", "data-testid": "starred-filters-menu-trigger", id: "starred-filters-menu-trigger", children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: modalState.isOpen, label: jsxRuntime.jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filters: appliedFilters }), placement: "bottom", children: jsxRuntime.jsx(FiltersMenuTriggerButton, { appliedValuesCount: totalAppliedValuesCount, buttonProps: buttonProps, hasAppliedFilters: filterBarConfig.appliedFilterKeys().length > 0, isCompact: !isSm, title: title }) }) }) }), 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 }) })] }));
1159
+ } }) }), showDirectlyFilters.length > 0 ? (jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: showDirectlyFilters })) : null, compact === false ? (jsxRuntime.jsx(AppliedFiltersRenderer, { appliedFilters: appliedFilters, filterBarConfig: filterBarConfig })) : null] }));
1128
1160
  };
1129
1161
 
1130
1162
  /**
@@ -1132,7 +1164,7 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
1132
1164
  *
1133
1165
  * @returns {ReactElement} - Returns the Filter component.
1134
1166
  */
1135
- const FilterTableComponent = ({ filterKey, filterBarDefinition, filterBarConfig, }) => {
1167
+ const FilterTableComponent = ({ filterKey, filterBarDefinition, filterBarConfig, className, "data-testid": dataTestId, ref, style, }) => {
1136
1168
  const [t] = useTranslation();
1137
1169
  const ensureFilterKey = react.useCallback((key) => {
1138
1170
  return key;
@@ -1162,16 +1194,16 @@ const FilterTableComponent = ({ filterKey, filterBarDefinition, filterBarConfig,
1162
1194
  const activeFilterKeys = filterKey.filter(key => appliedFilterKeys.includes(key));
1163
1195
  const multipleFiltersAppliedCount = getManuallyAppliedFilterCount(activeFilterKeys);
1164
1196
  const multipleFiltersIsActive = multipleFiltersAppliedCount > 0;
1165
- return (jsxRuntime.jsx(reactComponents.Popover, { placement: "bottom-start", children: modalState => {
1166
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx("div", { className: "relative", children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: modalState.isOpen || !multipleFiltersIsActive, label: jsxRuntime.jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKeys: filterKey, filters: filters }), placement: "bottom", children: jsxRuntime.jsx(reactComponents.IconButton, { ariaLabel: t("filtersBar.filtersHeading"), className: "h-8 w-5 p-0", icon: jsxRuntime.jsx(reactComponents.Icon, { name: "Funnel", size: "small" }), variant: multipleFiltersIsActive ? "ghost" : "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))) }) })] }));
1167
- } }));
1197
+ return (jsxRuntime.jsx("div", { className: className, "data-testid": dataTestId, ref: ref, style: style, children: jsxRuntime.jsx(reactComponents.MenuTree, { children: jsxRuntime.jsx(reactComponents.Popover, { placement: "bottom-start", children: modalState => {
1198
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx("div", { className: "relative", children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: modalState.isOpen || !multipleFiltersIsActive, label: jsxRuntime.jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKeys: filterKey, filters: filters }), placement: "bottom", children: jsxRuntime.jsx(reactComponents.IconButton, { ariaLabel: t("filtersBar.filtersHeading"), className: "h-8 w-5 p-0", icon: jsxRuntime.jsx(reactComponents.Icon, { name: "Funnel", size: "small" }), variant: multipleFiltersIsActive ? "ghost" : "ghost-neutral" }) }) }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { children: jsxRuntime.jsx("div", { className: reactComponents.cvaMenu({ limitWidth: true }), children: jsxRuntime.jsx("div", { className: reactComponents.cvaMenuList(), children: filters.map((value, index) => value && (jsxRuntime.jsx(FilterComponent, { filter: value, filterBarActions: filterBarConfig, filterState: filterBarConfig, visualStyle: "list-item" }, index))) }) }) })] }));
1199
+ } }) }) }));
1168
1200
  }
1169
1201
  const filter = filterBarDefinition[ensureFilterKey(filterKey)];
1170
1202
  if (!filter) {
1171
1203
  return null;
1172
1204
  }
1173
1205
  const isActive = filterBarConfig.appliedFilterKeys().includes(filterKey);
1174
- return (jsxRuntime.jsx("div", { onClick: event => event.stopPropagation(), children: jsxRuntime.jsx("div", { className: "relative", children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: !isActive, label: jsxRuntime.jsx(SingleFilterTooltipLabel, { filter: filter, filterBarConfig: filterBarConfig, filterKey: filterKey }), placement: "bottom", children: jsxRuntime.jsx(FilterComponent, { asIcon: "Funnel", className: "h-8 w-5 p-0", filter: filter, filterBarActions: filterBarConfig, filterState: filterBarConfig }) }) }) }));
1206
+ return (jsxRuntime.jsx("div", { className: className, "data-testid": dataTestId, onClick: event => event.stopPropagation(), ref: ref, style: style, children: jsxRuntime.jsx("div", { className: "relative", children: jsxRuntime.jsx(reactComponents.Tooltip, { disabled: !isActive, label: jsxRuntime.jsx(SingleFilterTooltipLabel, { filter: filter, filterBarConfig: filterBarConfig, filterKey: filterKey }), placement: "bottom", children: jsxRuntime.jsx(FilterComponent, { asIcon: "Funnel", className: "h-8 w-5 p-0", filter: filter, filterBarActions: filterBarConfig, filterState: filterBarConfig }) }) }) }));
1175
1207
  };
1176
1208
 
1177
1209
  /**
package/index.esm.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
2
  import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
3
3
  import { useMemo, useState, useEffect, useCallback, Fragment as Fragment$1, useRef } from 'react';
4
+ import { twMerge } from 'tailwind-merge';
4
5
  import { Filter, FilterBody, RadioFilterItem, CheckBoxFilterItem, FilterHeader as FilterHeader$1, FilterFooter } from '@trackunit/react-filter-components';
5
- import { Button, Icon, useList, List, Text, useTextSearch, Card, CardBody, useViewportBreakpoints, Popover, PopoverTrigger, Tooltip, Badge, PopoverContent, IconButton, MenuList, useCustomEncoding, useSearchParamSync, useStorageKey, storageSerializer, useWatch } from '@trackunit/react-components';
6
+ import { Button, Icon, useList, List, Text, useTextSearch, cvaMenuList, cvaMenu, ZStack, IconButton, Badge, useViewportBreakpoints, MenuTree, Popover, PopoverTrigger, Tooltip, PopoverContent, useCustomEncoding, useSearchParamSync, useStorageKey, storageSerializer, useWatch } from '@trackunit/react-components';
6
7
  import { useAnalytics, useCurrentUser } from '@trackunit/react-core-hooks';
7
8
  import { capitalize } from 'string-ts';
8
- import { twMerge } from 'tailwind-merge';
9
9
  import { createEvent } from '@trackunit/iris-app-runtime-core-api';
10
10
  import { Search, NumberField, RadioGroup } from '@trackunit/react-form-components';
11
11
  import { DayRangePicker } from '@trackunit/react-date-and-time-components';
@@ -449,9 +449,9 @@ const ResetFiltersButtonWithIcon = ({ resetFiltersToInitialState, "data-testid":
449
449
  /**
450
450
  *
451
451
  */
452
- const AppliedFiltersRenderer = ({ appliedFilters, filterBarConfig, showResetButton = true, style, }) => {
452
+ const AppliedFiltersRenderer = ({ appliedFilters, filterBarConfig, showResetButton = true, className, "data-testid": dataTestId, ref, style, }) => {
453
453
  const filtersToRender = useMemo(() => appliedFilters.filter(filter => !filter.showDirectly), [appliedFilters]);
454
- return (jsxs("div", { className: "flex flex-wrap items-center gap-2", style: style, children: [filtersToRender.length > 0 ? (jsx("div", { className: "h-4 w-[1px] bg-neutral-300", "data-testid": "applied-filters-buttons" })) : null, jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: filtersToRender }), appliedFilters.length > 0 && showResetButton ? (jsx(ResetFiltersButtonWithIcon, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] }));
454
+ return (jsxs("div", { className: twMerge("flex flex-wrap items-center gap-2", className), "data-testid": dataTestId, ref: ref, style: style, children: [filtersToRender.length > 0 ? (jsx("div", { className: "h-4 w-[1px] bg-neutral-300", "data-testid": "applied-filters-buttons" })) : null, jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: filtersToRender }), appliedFilters.length > 0 && showResetButton ? (jsx(ResetFiltersButtonWithIcon, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] }));
455
455
  };
456
456
 
457
457
  /**
@@ -685,11 +685,11 @@ const DefaultCheckboxFilter = ({ filterDefinition, filterBarActions, options, lo
685
685
  onChange: customSearch?.onChange ?? setSearchText,
686
686
  onClear: customSearch?.onClear ?? (() => setSearchText("")),
687
687
  count: undefinedCount ? filteredOptions.length - 1 : filteredOptions.length,
688
- }, children: options.length >= 2 ? (jsx(Button, { className: "place-self-start", "data-testid": "selectAllButton", disabled: hasSelectedAll, onClick: handleSelectAll, size: "small", variant: "ghost", children: t("filtersBar.selectAll") })) : null }), jsxs("div", { className: twMerge("grid max-h-[50dvh] min-h-0 overflow-hidden", undefinedCount ? "grid-rows-[minmax(0,1fr)_auto]" : "grid-rows-[minmax(0,1fr)]"), children: [jsx(FilterResults, { ignoreUndefined: undefinedCount !== null, loading: loading, results: results, children: res => (jsx(DynamicFilterList, { checked: index => {
688
+ }, children: options.length >= 2 ? (jsx(Button, { className: "place-self-start", "data-testid": "selectAllButton", disabled: hasSelectedAll, onClick: handleSelectAll, size: "small", variant: "ghost", children: t("filtersBar.selectAll") })) : null }), jsxs("div", { className: twMerge("grid min-h-0 overflow-hidden", undefinedCount ? "grid-rows-[minmax(0,1fr)_auto]" : "grid-rows-[minmax(0,1fr)]"), children: [jsx(FilterResults, { ignoreUndefined: undefinedCount !== null, loading: loading, results: results, children: res => (jsx(DynamicFilterList, { checked: index => {
689
689
  return filterDefinition.type === "valueNameArray"
690
690
  ? filterBarActions.objectArrayIncludesValue(filterDefinition.filterKey, res[index]?.key || "")
691
691
  : filterBarActions.arrayIncludesValue(filterDefinition.filterKey, res[index]?.key || "");
692
- }, className: "mb-1 h-full", count: index => res[index]?.count, keyMapper: index => res[index]?.key || "", labelMapper: index => res[index]?.label || "", onChange: index => {
692
+ }, className: "h-full", count: index => res[index]?.count, keyMapper: index => res[index]?.key || "", labelMapper: index => res[index]?.label || "", onChange: index => {
693
693
  const result = res[index];
694
694
  if (result) {
695
695
  handleSetValue(result);
@@ -931,10 +931,10 @@ const useFiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters =
931
931
  *
932
932
  * @returns {ReactElement} - Returns the FiltersList component.
933
933
  */
934
- const GroupedFiltersList = ({ filterBarConfig, filtersGrouped, className, style, "data-testid": dataTestId = "grouped-filters-list", }) => {
935
- return (jsx("div", { className: className, "data-testid": dataTestId, role: "menu", style: style, children: filtersGrouped.map((group, idx) => {
934
+ const GroupedFiltersList = ({ filterBarConfig, filtersGrouped, className, ref, style, "data-testid": dataTestId = "grouped-filters-list", }) => {
935
+ return (jsx("div", { className: className, "data-testid": dataTestId, ref: ref, style: style, children: filtersGrouped.map((group, idx) => {
936
936
  const isLastGroup = idx === filtersGrouped.length - 1;
937
- return (jsxs("div", { className: "flex flex-col gap-1", children: [jsxs("div", { children: [filtersGrouped.length > 1 && (jsx(Text, { className: "h-7 px-3 py-2 text-neutral-400", "data-testid": `${group.key}-group-title`, size: "small", uppercase: true, weight: "bold", children: group.title })), jsx("ul", { "aria-labelledby": `${group.key}-group-title`, className: "grid", "data-testid": `${group.key}-group-list`, children: jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: group.filters, visualStyle: "list-item" }) })] }), isLastGroup ? null : jsx("div", { className: "h-[1px] w-full bg-neutral-200", role: "separator" })] }, group.key));
937
+ return (jsxs("div", { className: "flex flex-col gap-1", children: [jsxs("div", { children: [filtersGrouped.length > 1 && (jsx(Text, { className: "h-7 p-2 text-neutral-400", "data-testid": `${group.key}-group-title`, size: "small", uppercase: true, weight: "bold", children: group.title })), jsx("ul", { "aria-labelledby": `${group.key}-group-title`, className: "grid", "data-testid": `${group.key}-group-list`, children: jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: group.filters, visualStyle: "list-item" }) })] }), isLastGroup ? null : jsx("div", { className: "h-[1px] w-full bg-neutral-200", role: "separator" })] }, group.key));
938
938
  }) }));
939
939
  };
940
940
 
@@ -943,25 +943,38 @@ const GroupedFiltersList = ({ filterBarConfig, filtersGrouped, className, style,
943
943
  *
944
944
  * @returns {ReactElement | null} The rendered ResetFiltersButton component, or null if no filters have been applied.
945
945
  */
946
- const ResetFiltersButton = ({ resetFiltersToInitialState, "data-testid": dataTestId, className, }) => {
946
+ const ResetFiltersButton = ({ resetFiltersToInitialState, "data-testid": dataTestId, className, ref, style, }) => {
947
947
  const [t] = useTranslation();
948
948
  return (jsxs(Button, { className: className, "data-testid": dataTestId ?? "reset-filters-button", onClick: () => {
949
949
  resetFiltersToInitialState();
950
- }, size: "small", variant: "ghost", children: [t("filtersBar.resetFilters"), jsx("span", { className: "sr-only", children: t("filtersBar.resetFiltersSR") })] }));
950
+ }, ref: ref, size: "small", style: style, variant: "ghost", children: [t("filtersBar.resetFilters"), jsx("span", { className: "sr-only", children: t("filtersBar.resetFiltersSR") })] }));
951
951
  };
952
952
 
953
953
  /**
954
954
  *
955
955
  */
956
- const FiltersMenuContent = ({ filterBarConfig, setShowCustomFilters, setSearchText, searchText, searchResultsGrouped, filtersToShowGrouped, removeCustomFieldsGroup, hasCustomFields, appliedCustomFields, showCustomFilters, filterBarDefinitionCount, }) => {
956
+ const FiltersMenuContent = ({ filterBarConfig, setShowCustomFilters, setSearchText, searchText, searchResultsGrouped, filtersToShowGrouped, removeCustomFieldsGroup, hasCustomFields, appliedCustomFields, showCustomFilters, filterBarDefinitionCount, className, "data-testid": dataTestId = "starred-filters-menu-popover", ref, style, }) => {
957
957
  const [t] = useTranslation();
958
- return (jsxs(Card, { className: "max-h-[min(600px,calc(100dvh-32px))] w-[300px] overflow-y-hidden", "data-testid": "starred-filters-menu-popover", id: "starred-filters-menu-popover", tabIndex: 0, children: [jsxs("div", { className: "flex flex-col gap-1 p-1", children: [filterBarDefinitionCount > 5 && (jsx(Search, { autoFocus: true, "data-testid": "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 pl-3", children: [jsx(Text, { className: "text-neutral-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", gap: "none", padding: "none", children: [jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: searchText
959
- ? searchResultsGrouped
960
- : showCustomFilters
961
- ? filtersToShowGrouped
962
- : removeCustomFieldsGroup(filtersToShowGrouped) }), hasCustomFields && !showCustomFilters && !searchText ? (jsx(CustomFieldsHiddenGroup, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, onClickShow: () => {
963
- setShowCustomFilters(true);
964
- } })) : null] })] }));
958
+ // Chrome-only shell (not `MenuContent`): filter rows are wrapped (`GroupedFiltersList`
959
+ // `FilterComponent` → `Filter` → `MenuItem`), so `MenuContent`'s direct-child registration would
960
+ // never attach keyboard nav — leaving a `role="menu"` with no owned menuitems. Shadow/layout come
961
+ // from `cvaMenu`/`cvaMenuList`; keyboard ownership returns when MenuItem self-registers (GLU-1644).
962
+ return (jsx("div", { className: cvaMenu({
963
+ className: twMerge("max-h-[min(600px,calc(100dvh-32px))] grid-rows-[minmax(0,1fr)] overflow-y-hidden p-0", className),
964
+ limitWidth: true,
965
+ }), "data-testid": dataTestId, ref: ref, style: style, children: jsxs("div", {
966
+ // `gap-y-0` cancels `cvaMenuList`'s default inter-item gap, which here would otherwise land
967
+ // between the header block (search/count + separator) and the scrollable list below it,
968
+ // showing as a sliver of whitespace above the list's own scrollbar.
969
+ className: cvaMenuList({
970
+ className: "grid-rows-min-fr !max-h-none min-h-0 gap-y-0 !overflow-y-hidden p-0",
971
+ }), children: [jsxs("div", { children: [jsxs("div", { className: "flex flex-col gap-1 p-1", children: [filterBarDefinitionCount > 5 && (jsx(Search, { autoFocus: true, "data-testid": "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 pl-3", children: [jsx(Text, { className: "text-neutral-400", size: "small", children: jsx(FiltersAppliedCountLabel, { filterBarConfig: filterBarConfig }) }), filterBarConfig.appliedFilterKeys().length > 0 ? (jsx(ResetFiltersButton, { resetFiltersToInitialState: filterBarConfig.resetFiltersToInitialState })) : null] })] }), jsx(Separator, {})] }), jsxs("div", { className: "flex min-h-0 flex-col gap-1 overflow-auto p-1", children: [jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: searchText
972
+ ? searchResultsGrouped
973
+ : showCustomFilters
974
+ ? filtersToShowGrouped
975
+ : removeCustomFieldsGroup(filtersToShowGrouped) }), hasCustomFields && !showCustomFilters && !searchText ? (jsx(CustomFieldsHiddenGroup, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, onClickShow: () => {
976
+ setShowCustomFilters(true);
977
+ } })) : null] })] }) }));
965
978
  };
966
979
  const Separator = () => jsx("hr", { className: "border-neutral-200", role: "separator" });
967
980
  const FiltersAppliedCountLabel = ({ filterBarConfig, }) => {
@@ -990,6 +1003,26 @@ const CustomFieldsHiddenGroup = ({ appliedCustomFields, filterBarConfig, onClick
990
1003
  return (jsxs(Fragment, { children: [jsx(Separator, {}), jsxs("div", { children: [jsx(Button, { "aria-controls": "filters-list", className: "text-primary-600 w-full justify-between px-3", onClick: onClickShow, prefix: jsx(Text, { className: "text-neutral-400", size: "small", uppercase: true, weight: "bold", children: t("filtersBar.groups.CUSTOM_FIELDS") }), size: "small", variant: "ghost-neutral", children: t("filtersBar.showAll") }), appliedCustomFields.length > 0 ? (jsx("ul", { "aria-label": "Visible custom fields", "data-testid": "applied-custom-fields-list", children: jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: appliedCustomFields, visualStyle: "list-item" }) })) : null] })] }));
991
1004
  };
992
1005
 
1006
+ const sharedButtonProps = {
1007
+ size: "small",
1008
+ variant: "secondary",
1009
+ };
1010
+ /**
1011
+ * FiltersMenuTriggerButton is the button that opens the filters popover menu.
1012
+ *
1013
+ * On small viewports (`isCompact`) it renders as a square icon-only button with the applied filters count
1014
+ * overlaid as a badge. Otherwise it renders as a regular button with a text label and an inline count badge.
1015
+ */
1016
+ const FiltersMenuTriggerButton = ({ isCompact, hasAppliedFilters, appliedValuesCount, title, buttonProps, }) => {
1017
+ const [t] = useTranslation();
1018
+ const label = title ?? t("filtersBar.filtersHeading");
1019
+ const icon = jsx(Icon, { ariaHidden: true, color: hasAppliedFilters ? "primary" : undefined, name: "Funnel", size: "small" });
1020
+ if (isCompact) {
1021
+ return (jsxs(ZStack, { className: "shrink-0", children: [jsx(IconButton, { ariaLabel: label, icon: icon, ...sharedButtonProps, ...buttonProps }), appliedValuesCount > 0 ? (jsx(Badge, { className: "-translate-y-1/3 translate-x-1/3 self-start justify-self-end", color: "primary", count: appliedValuesCount, hideZero: true, size: "condensed" })) : null] }));
1022
+ }
1023
+ return (jsx(Button, { prefix: icon, suffix: appliedValuesCount > 0 ? (jsx(Badge, { color: "primary", count: appliedValuesCount, hideZero: true, size: "condensed" })) : null, ...sharedButtonProps, ...buttonProps, children: title !== "" ? label : null }));
1024
+ };
1025
+
993
1026
  /**
994
1027
  * TooltipValues component that displays formatted tooltip values based on the provided input.
995
1028
  *
@@ -1030,8 +1063,8 @@ const TooltipValues = ({ values }) => {
1030
1063
  * @param {any} props.displayValues - The filter values to display.
1031
1064
  * @returns {ReactElement} The rendered component showing the title and values.
1032
1065
  */
1033
- const TooltipLabel = ({ title, displayValues }) => {
1034
- return (jsxs(Fragment, { children: [jsx("div", { className: "text-xs font-medium", children: title }), jsx(TooltipValues, { values: displayValues })] }));
1066
+ const TooltipLabel = ({ title, displayValues, className, "data-testid": dataTestId, ref, style, }) => {
1067
+ return (jsxs("div", { className: twMerge("contents", className), "data-testid": dataTestId, ref: ref, style: style, children: [jsx("div", { className: "text-xs font-medium", children: title }), jsx(TooltipValues, { values: displayValues })] }));
1035
1068
  };
1036
1069
 
1037
1070
  /**
@@ -1093,8 +1126,7 @@ const MultipleFilterTooltipLabel = ({ filterBarConfig, filterKeys, filters, }) =
1093
1126
  * @template TFilterBarDefinition - The type representing the filter bar definition.
1094
1127
  * @returns {ReactElement} - Returns the FilterMenu component.
1095
1128
  */
1096
- const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [], compact = false, title, "data-testid": dataTestId = "filters-menu", className, style, buttonProps, allowShowFiltersDirectly = true, includeFilterKeys, }) => {
1097
- const [t] = useTranslation();
1129
+ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [], compact = false, title, "data-testid": dataTestId = "filters-menu", className, ref, style, buttonProps, allowShowFiltersDirectly = true, includeFilterKeys, }) => {
1098
1130
  const [showCustomFilters, setShowCustomFilters] = useState(false);
1099
1131
  const { isSm } = useViewportBreakpoints();
1100
1132
  const filterBarDefinitionCount = useMemo(() => objectValues(filterBarDefinition).length, [filterBarDefinition]);
@@ -1115,14 +1147,14 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
1115
1147
  includeFilterKeys,
1116
1148
  allowShowFiltersDirectly,
1117
1149
  });
1118
- return (jsxs("div", { className: twMerge("flex items-start gap-2", className), "data-testid": dataTestId, style: style, children: [jsx(Popover, { onOpenStateChange: open => {
1119
- if (!open) {
1120
- setShowCustomFilters(false);
1121
- setSearchText("");
1122
- }
1123
- }, placement: "bottom-start", children: modalState => {
1124
- return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { "data-testid": "starred-filters-menu-trigger", id: "starred-filters-menu-trigger", children: jsx(Tooltip, { disabled: modalState.isOpen, label: jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filters: appliedFilters }), placement: "bottom", children: !isSm ? (jsx(Button, { "aria-label": title ?? t("filtersBar.filtersHeading"), prefix: jsx(Icon, { ariaHidden: true, color: filterBarConfig.appliedFilterKeys().length > 0 ? "primary" : undefined, name: "Funnel", size: "small" }), size: "small", suffix: totalAppliedValuesCount > 0 ? (jsx(Badge, { color: "primary", count: totalAppliedValuesCount, hideZero: true, size: "condensed" })) : null, variant: "secondary", ...buttonProps })) : (jsx(Button, { prefix: jsx(Icon, { ariaHidden: true, color: filterBarConfig.appliedFilterKeys().length > 0 ? "primary" : undefined, name: "Funnel", size: "small" }), size: "small", suffix: totalAppliedValuesCount > 0 ? (jsx(Badge, { color: "primary", count: totalAppliedValuesCount, hideZero: true, size: "condensed" })) : null, variant: "secondary", ...buttonProps, children: title !== "" ? (title ?? t("filtersBar.filtersHeading")) : null })) }) }) }), jsx(PopoverContent, { cellPadding: 100, children: jsx(FiltersMenuContent, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, filterBarDefinitionCount: filterBarDefinitionCount, filtersToShowGrouped: filtersToShowGrouped, hasCustomFields: hasCustomFields, removeCustomFieldsGroup: removeCustomFieldsGroup, searchResultsGrouped: searchResultsGrouped, searchText: searchText, setSearchText: setSearchText, setShowCustomFilters: setShowCustomFilters, showCustomFilters: showCustomFilters }) })] }));
1125
- } }), showDirectlyFilters.length > 0 ? (jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: showDirectlyFilters })) : null, compact === false ? (jsx(AppliedFiltersRenderer, { appliedFilters: appliedFilters, filterBarConfig: filterBarConfig })) : null] }));
1150
+ return (jsxs("div", { className: twMerge("flex items-start gap-2", className), "data-testid": dataTestId, ref: ref, style: style, children: [jsx(MenuTree, { children: jsx(Popover, { onOpenStateChange: open => {
1151
+ if (!open) {
1152
+ setShowCustomFilters(false);
1153
+ setSearchText("");
1154
+ }
1155
+ }, placement: "bottom-start", children: modalState => {
1156
+ return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { className: "shrink-0", "data-testid": "starred-filters-menu-trigger", id: "starred-filters-menu-trigger", children: jsx(Tooltip, { disabled: modalState.isOpen, label: jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filters: appliedFilters }), placement: "bottom", children: jsx(FiltersMenuTriggerButton, { appliedValuesCount: totalAppliedValuesCount, buttonProps: buttonProps, hasAppliedFilters: filterBarConfig.appliedFilterKeys().length > 0, isCompact: !isSm, title: title }) }) }) }), jsx(PopoverContent, { cellPadding: 100, children: jsx(FiltersMenuContent, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, filterBarDefinitionCount: filterBarDefinitionCount, filtersToShowGrouped: filtersToShowGrouped, hasCustomFields: hasCustomFields, removeCustomFieldsGroup: removeCustomFieldsGroup, searchResultsGrouped: searchResultsGrouped, searchText: searchText, setSearchText: setSearchText, setShowCustomFilters: setShowCustomFilters, showCustomFilters: showCustomFilters }) })] }));
1157
+ } }) }), showDirectlyFilters.length > 0 ? (jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: showDirectlyFilters })) : null, compact === false ? (jsx(AppliedFiltersRenderer, { appliedFilters: appliedFilters, filterBarConfig: filterBarConfig })) : null] }));
1126
1158
  };
1127
1159
 
1128
1160
  /**
@@ -1130,7 +1162,7 @@ const FiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters = [],
1130
1162
  *
1131
1163
  * @returns {ReactElement} - Returns the Filter component.
1132
1164
  */
1133
- const FilterTableComponent = ({ filterKey, filterBarDefinition, filterBarConfig, }) => {
1165
+ const FilterTableComponent = ({ filterKey, filterBarDefinition, filterBarConfig, className, "data-testid": dataTestId, ref, style, }) => {
1134
1166
  const [t] = useTranslation();
1135
1167
  const ensureFilterKey = useCallback((key) => {
1136
1168
  return key;
@@ -1160,16 +1192,16 @@ const FilterTableComponent = ({ filterKey, filterBarDefinition, filterBarConfig,
1160
1192
  const activeFilterKeys = filterKey.filter(key => appliedFilterKeys.includes(key));
1161
1193
  const multipleFiltersAppliedCount = getManuallyAppliedFilterCount(activeFilterKeys);
1162
1194
  const multipleFiltersIsActive = multipleFiltersAppliedCount > 0;
1163
- return (jsx(Popover, { placement: "bottom-start", children: modalState => {
1164
- return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { className: "relative", children: jsx(Tooltip, { disabled: modalState.isOpen || !multipleFiltersIsActive, label: jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKeys: filterKey, filters: filters }), placement: "bottom", children: jsx(IconButton, { ariaLabel: t("filtersBar.filtersHeading"), className: "h-8 w-5 p-0", icon: jsx(Icon, { name: "Funnel", size: "small" }), variant: multipleFiltersIsActive ? "ghost" : "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))) }) })] }));
1165
- } }));
1195
+ return (jsx("div", { className: className, "data-testid": dataTestId, ref: ref, style: style, children: jsx(MenuTree, { children: jsx(Popover, { placement: "bottom-start", children: modalState => {
1196
+ return (jsxs(Fragment, { children: [jsx(PopoverTrigger, { children: jsx("div", { className: "relative", children: jsx(Tooltip, { disabled: modalState.isOpen || !multipleFiltersIsActive, label: jsx(MultipleFilterTooltipLabel, { filterBarConfig: filterBarConfig, filterKeys: filterKey, filters: filters }), placement: "bottom", children: jsx(IconButton, { ariaLabel: t("filtersBar.filtersHeading"), className: "h-8 w-5 p-0", icon: jsx(Icon, { name: "Funnel", size: "small" }), variant: multipleFiltersIsActive ? "ghost" : "ghost-neutral" }) }) }) }), jsx(PopoverContent, { children: jsx("div", { className: cvaMenu({ limitWidth: true }), children: jsx("div", { className: cvaMenuList(), children: filters.map((value, index) => value && (jsx(FilterComponent, { filter: value, filterBarActions: filterBarConfig, filterState: filterBarConfig, visualStyle: "list-item" }, index))) }) }) })] }));
1197
+ } }) }) }));
1166
1198
  }
1167
1199
  const filter = filterBarDefinition[ensureFilterKey(filterKey)];
1168
1200
  if (!filter) {
1169
1201
  return null;
1170
1202
  }
1171
1203
  const isActive = filterBarConfig.appliedFilterKeys().includes(filterKey);
1172
- return (jsx("div", { onClick: event => event.stopPropagation(), children: jsx("div", { className: "relative", children: jsx(Tooltip, { disabled: !isActive, label: jsx(SingleFilterTooltipLabel, { filter: filter, filterBarConfig: filterBarConfig, filterKey: filterKey }), placement: "bottom", children: jsx(FilterComponent, { asIcon: "Funnel", className: "h-8 w-5 p-0", filter: filter, filterBarActions: filterBarConfig, filterState: filterBarConfig }) }) }) }));
1204
+ return (jsx("div", { className: className, "data-testid": dataTestId, onClick: event => event.stopPropagation(), ref: ref, style: style, children: jsx("div", { className: "relative", children: jsx(Tooltip, { disabled: !isActive, label: jsx(SingleFilterTooltipLabel, { filter: filter, filterBarConfig: filterBarConfig, filterKey: filterKey }), placement: "bottom", children: jsx(FilterComponent, { asIcon: "Funnel", className: "h-8 w-5 p-0", filter: filter, filterBarActions: filterBarConfig, filterState: filterBarConfig }) }) }) }));
1173
1205
  };
1174
1206
 
1175
1207
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/filters-filter-bar",
3
- "version": "2.4.4",
3
+ "version": "2.4.7-alpha-770d9994af7.0",
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.25.76",
14
- "@trackunit/iris-app-api": "2.3.1",
15
- "@trackunit/react-core-hooks": "1.20.1",
16
- "@trackunit/react-filter-components": "2.4.4",
17
- "@trackunit/react-date-and-time-components": "2.4.4",
18
- "@trackunit/shared-utils": "1.16.1",
19
- "@trackunit/react-form-components": "2.4.4",
20
- "@trackunit/iris-app-runtime-core-api": "1.17.1",
21
- "@trackunit/geo-json-utils": "1.15.1",
22
- "@trackunit/i18n-library-translation": "2.3.1",
23
- "@trackunit/css-class-variance-utilities": "1.14.1",
24
- "@trackunit/react-components": "2.5.4"
14
+ "@trackunit/iris-app-api": "2.3.4-alpha-770d9994af7.0",
15
+ "@trackunit/react-core-hooks": "1.20.4-alpha-770d9994af7.0",
16
+ "@trackunit/react-filter-components": "2.4.7-alpha-770d9994af7.0",
17
+ "@trackunit/react-date-and-time-components": "2.4.7-alpha-770d9994af7.0",
18
+ "@trackunit/shared-utils": "1.16.3-alpha-770d9994af7.0",
19
+ "@trackunit/react-form-components": "2.4.7-alpha-770d9994af7.0",
20
+ "@trackunit/iris-app-runtime-core-api": "1.17.3-alpha-770d9994af7.0",
21
+ "@trackunit/geo-json-utils": "1.15.3-alpha-770d9994af7.0",
22
+ "@trackunit/i18n-library-translation": "2.3.4-alpha-770d9994af7.0",
23
+ "@trackunit/css-class-variance-utilities": "1.14.3-alpha-770d9994af7.0",
24
+ "@trackunit/react-components": "2.6.2-alpha-770d9994af7.0"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "@apollo/client": "^3.13.8",
@@ -1,11 +1,13 @@
1
- import type { Styleable } from "@trackunit/react-components";
1
+ import { CommonProps, Refable, type Styleable } from "@trackunit/react-components";
2
2
  import { ReactElement } from "react";
3
3
  import { FilterBarConfig, FilterBarDefinition, FilterDefinition, FilterMapActions, FilterMapGetter } from "../types/FilterTypes";
4
- /**
5
- *
6
- */
7
- export declare const AppliedFiltersRenderer: <TFilterBarDefinition extends FilterBarDefinition>({ appliedFilters, filterBarConfig, showResetButton, style, }: {
4
+ interface AppliedFiltersRendererProps<TFilterBarDefinition extends FilterBarDefinition> extends CommonProps, Refable<HTMLDivElement>, Styleable {
8
5
  appliedFilters: Array<FilterDefinition>;
9
6
  filterBarConfig: FilterBarConfig<TFilterBarDefinition> & FilterMapActions & FilterMapGetter;
10
7
  showResetButton?: boolean;
11
- } & Styleable) => ReactElement;
8
+ }
9
+ /**
10
+ *
11
+ */
12
+ export declare const AppliedFiltersRenderer: <TFilterBarDefinition extends FilterBarDefinition>({ appliedFilters, filterBarConfig, showResetButton, className, "data-testid": dataTestId, ref, style, }: AppliedFiltersRendererProps<TFilterBarDefinition>) => ReactElement;
13
+ export {};
@@ -1,6 +1,7 @@
1
+ import { CommonProps, Refable, type Styleable } from "@trackunit/react-components";
1
2
  import { ReactElement } from "react";
2
3
  import { FilterBarDefinition, FilterMapActions, FilterMapGetter, FilterState } from "../types/FilterTypes";
3
- interface FilterComponentProps<TFilterBarDefinition extends FilterBarDefinition> {
4
+ interface FilterComponentProps<TFilterBarDefinition extends FilterBarDefinition> extends CommonProps, Refable<HTMLDivElement>, Styleable {
4
5
  /**
5
6
  * The definition of the filter.
6
7
  */
@@ -19,5 +20,5 @@ interface FilterComponentProps<TFilterBarDefinition extends FilterBarDefinition>
19
20
  *
20
21
  * @returns {ReactElement} - Returns the Filter component.
21
22
  */
22
- export declare const FilterTableComponent: <TFilterBarDefinition extends FilterBarDefinition>({ filterKey, filterBarDefinition, filterBarConfig, }: FilterComponentProps<TFilterBarDefinition>) => ReactElement | null;
23
+ export declare const FilterTableComponent: <TFilterBarDefinition extends FilterBarDefinition>({ filterKey, filterBarDefinition, filterBarConfig, className, "data-testid": dataTestId, ref, style, }: FilterComponentProps<TFilterBarDefinition>) => ReactElement | null;
23
24
  export {};
@@ -1,6 +1,7 @@
1
+ import { CommonProps, Refable, type Styleable } from "@trackunit/react-components";
1
2
  import { ReactElement } from "react";
2
3
  import { FilterValueType } from "../../types/FilterTypes";
3
- interface TooltipLabelProps {
4
+ interface TooltipLabelProps extends CommonProps, Refable<HTMLDivElement>, Styleable {
4
5
  title: string;
5
6
  displayValues: FilterValueType;
6
7
  }
@@ -12,5 +13,5 @@ interface TooltipLabelProps {
12
13
  * @param {any} props.displayValues - The filter values to display.
13
14
  * @returns {ReactElement} The rendered component showing the title and values.
14
15
  */
15
- export declare const TooltipLabel: ({ title, displayValues }: TooltipLabelProps) => ReactElement;
16
+ export declare const TooltipLabel: ({ title, displayValues, className, "data-testid": dataTestId, ref, style, }: TooltipLabelProps) => ReactElement;
16
17
  export {};
@@ -1,7 +1,7 @@
1
- import { ButtonProps, CommonProps, type Styleable } from "@trackunit/react-components";
1
+ import { ButtonProps, CommonProps, Refable, type Styleable } from "@trackunit/react-components";
2
2
  import { ReactElement } from "react";
3
3
  import { FilterBarConfig, FilterBarDefinition, FilterMapActions, FilterMapGetter } from "../types/FilterTypes";
4
- interface FiltersMenuProps<TFilterBarDefinition extends FilterBarDefinition> extends CommonProps, Styleable {
4
+ interface FiltersMenuProps<TFilterBarDefinition extends FilterBarDefinition> extends CommonProps, Refable<HTMLDivElement>, Styleable {
5
5
  /**
6
6
  * If true, the filters marked as showDirectly will not be shown directly in the filter bar
7
7
  */
@@ -41,5 +41,5 @@ interface FiltersMenuProps<TFilterBarDefinition extends FilterBarDefinition> ext
41
41
  * @template TFilterBarDefinition - The type representing the filter bar definition.
42
42
  * @returns {ReactElement} - Returns the FilterMenu component.
43
43
  */
44
- export declare const FiltersMenu: <TFilterBarDefinition extends FilterBarDefinition>({ filterBarDefinition, filterBarConfig, hiddenFilters, compact, title, "data-testid": dataTestId, className, style, buttonProps, allowShowFiltersDirectly, includeFilterKeys, }: FiltersMenuProps<TFilterBarDefinition>) => ReactElement;
44
+ export declare const FiltersMenu: <TFilterBarDefinition extends FilterBarDefinition>({ filterBarDefinition, filterBarConfig, hiddenFilters, compact, title, "data-testid": dataTestId, className, ref, style, buttonProps, allowShowFiltersDirectly, includeFilterKeys, }: FiltersMenuProps<TFilterBarDefinition>) => ReactElement;
45
45
  export {};
@@ -1,10 +1,8 @@
1
+ import { CommonProps, Refable, type Styleable } from "@trackunit/react-components";
1
2
  import { ReactElement } from "react";
2
3
  import { GroupOfFilters } from "../hooks/useGroupFilters";
3
4
  import { FilterBarConfig, FilterBarDefinition, FilterDefinition, FilterMapActions, FilterMapGetter } from "../types/FilterTypes";
4
- /**
5
- *
6
- */
7
- export declare const FiltersMenuContent: ({ filterBarConfig, setShowCustomFilters, setSearchText, searchText, searchResultsGrouped, filtersToShowGrouped, removeCustomFieldsGroup, hasCustomFields, appliedCustomFields, showCustomFilters, filterBarDefinitionCount, }: {
5
+ interface FiltersMenuContentProps extends CommonProps, Refable<HTMLDivElement>, Styleable {
8
6
  filterBarConfig: FilterBarConfig<FilterBarDefinition> & FilterMapActions & FilterMapGetter;
9
7
  setShowCustomFilters: (show: boolean) => void;
10
8
  setSearchText: (text: string) => void;
@@ -16,4 +14,9 @@ export declare const FiltersMenuContent: ({ filterBarConfig, setShowCustomFilter
16
14
  appliedCustomFields: Array<FilterDefinition>;
17
15
  showCustomFilters: boolean;
18
16
  filterBarDefinitionCount: number;
19
- }) => ReactElement;
17
+ }
18
+ /**
19
+ *
20
+ */
21
+ export declare const FiltersMenuContent: ({ filterBarConfig, setShowCustomFilters, setSearchText, searchText, searchResultsGrouped, filtersToShowGrouped, removeCustomFieldsGroup, hasCustomFields, appliedCustomFields, showCustomFilters, filterBarDefinitionCount, className, "data-testid": dataTestId, ref, style, }: FiltersMenuContentProps) => ReactElement;
22
+ export {};
@@ -0,0 +1,32 @@
1
+ import { ButtonProps } from "@trackunit/react-components";
2
+ import { ReactElement } from "react";
3
+ interface FiltersMenuTriggerButtonProps {
4
+ /**
5
+ * If true, renders a square icon-only button (used on small viewports) instead of the full button with a text label.
6
+ */
7
+ isCompact: boolean;
8
+ /**
9
+ * Whether any filters are currently applied. Highlights the funnel icon when true.
10
+ */
11
+ hasAppliedFilters: boolean;
12
+ /**
13
+ * The number of applied filter values, shown as a count badge on the button.
14
+ */
15
+ appliedValuesCount: number;
16
+ /**
17
+ * The title of the filter bar, default is "Filters" (translated). Pass an empty string to render no label.
18
+ */
19
+ title?: string;
20
+ /**
21
+ * Props to override the trigger button's look and feel.
22
+ */
23
+ buttonProps?: ButtonProps;
24
+ }
25
+ /**
26
+ * FiltersMenuTriggerButton is the button that opens the filters popover menu.
27
+ *
28
+ * On small viewports (`isCompact`) it renders as a square icon-only button with the applied filters count
29
+ * overlaid as a badge. Otherwise it renders as a regular button with a text label and an inline count badge.
30
+ */
31
+ export declare const FiltersMenuTriggerButton: ({ isCompact, hasAppliedFilters, appliedValuesCount, title, buttonProps, }: FiltersMenuTriggerButtonProps) => ReactElement;
32
+ export {};
@@ -1,8 +1,8 @@
1
- import { CommonProps, type Styleable } from "@trackunit/react-components";
1
+ import { CommonProps, Refable, type Styleable } from "@trackunit/react-components";
2
2
  import { ReactElement } from "react";
3
3
  import { GroupOfFilters } from "../hooks/useGroupFilters";
4
4
  import { FilterBarConfig, FilterBarDefinition, FilterMapActions, FilterMapGetter } from "../types/FilterTypes";
5
- interface FiltersListProps extends CommonProps, Styleable {
5
+ interface FiltersListProps extends CommonProps, Refable<HTMLDivElement>, Styleable {
6
6
  /**
7
7
  * The configuration of the filter bar, including its actions and state.
8
8
  */
@@ -14,5 +14,5 @@ interface FiltersListProps extends CommonProps, Styleable {
14
14
  *
15
15
  * @returns {ReactElement} - Returns the FiltersList component.
16
16
  */
17
- export declare const GroupedFiltersList: ({ filterBarConfig, filtersGrouped, className, style, "data-testid": dataTestId, }: FiltersListProps) => ReactElement;
17
+ export declare const GroupedFiltersList: ({ filterBarConfig, filtersGrouped, className, ref, style, "data-testid": dataTestId, }: FiltersListProps) => ReactElement;
18
18
  export {};
@@ -1,6 +1,6 @@
1
- import { CommonProps } from "@trackunit/react-components";
1
+ import { CommonProps, Refable, type Styleable } from "@trackunit/react-components";
2
2
  import { ReactElement } from "react";
3
- interface ResetFiltersProps extends CommonProps {
3
+ interface ResetFiltersProps extends CommonProps, Refable<HTMLButtonElement>, Styleable {
4
4
  /**
5
5
  * A function that resets the filters to their initial state.
6
6
  */
@@ -11,5 +11,5 @@ interface ResetFiltersProps extends CommonProps {
11
11
  *
12
12
  * @returns {ReactElement | null} The rendered ResetFiltersButton component, or null if no filters have been applied.
13
13
  */
14
- export declare const ResetFiltersButton: ({ resetFiltersToInitialState, "data-testid": dataTestId, className, }: ResetFiltersProps) => ReactElement | null;
14
+ export declare const ResetFiltersButton: ({ resetFiltersToInitialState, "data-testid": dataTestId, className, ref, style, }: ResetFiltersProps) => ReactElement | null;
15
15
  export {};