@trackunit/filters-filter-bar 2.6.42 → 2.6.45

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
@@ -706,6 +706,24 @@ const useFiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters =
706
706
  ]);
707
707
  };
708
708
 
709
+ /**
710
+ * The filters menu's search box, registered as the menu's first keyboard stop so ArrowDown enters
711
+ * the filter rows and ArrowUp from the first row comes back here.
712
+ *
713
+ * It is a component rather than a few lines in `FiltersMenuContent` because `useMenuSearchField`
714
+ * registers through Floating UI's `FloatingList`, whose context `MenuContent` opens around its
715
+ * children -- a caller that also renders the `MenuContent` sits outside that context and registers
716
+ * nothing.
717
+ *
718
+ * @param {FiltersMenuSearchFieldProps} props The current query, its setter, and the id of the list this field filters
719
+ * @returns {ReactElement} The registered search input
720
+ */
721
+ const FiltersMenuSearchField = ({ searchText, setSearchText, filtersListId, }) => {
722
+ const [t] = useTranslation();
723
+ const { getSearchFieldProps } = reactComponents.useMenuSearchField();
724
+ return (jsxRuntime.jsx(reactFormComponents.Search, { "aria-controls": filtersListId, "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, ...getSearchFieldProps() }));
725
+ };
726
+
709
727
  const FilterGroupSection = ({ filterBarConfig, group, showSeparator, showTitle, }) => {
710
728
  const titleId = react.useId();
711
729
  return (jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [jsxRuntime.jsxs("div", { children: [showTitle ? (jsxRuntime.jsx(reactComponents.Text, { className: "h-7 p-2 text-neutral-400", "data-testid": `${group.key}-group-title`, id: titleId, size: "small", uppercase: true, weight: "bold", children: group.title })) : null, jsxRuntime.jsx("div", { "aria-labelledby": showTitle ? titleId : undefined, className: "grid", "data-testid": `${group.key}-group-list`, role: "group", children: jsxRuntime.jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: group.filters, visualStyle: "list-item" }) })] }), showSeparator ? jsxRuntime.jsx(reactComponents.MenuDivider, {}) : null] }));
@@ -732,75 +750,6 @@ const ResetFiltersButton = ({ resetFiltersToInitialState, "data-testid": dataTes
732
750
  }, ref: ref, size: "small", style: style, variant: "ghost", children: [t("filtersBar.resetFilters"), jsxRuntime.jsx("span", { className: "sr-only", children: t("filtersBar.resetFiltersSR") })] }));
733
751
  };
734
752
 
735
- const firstEnabledMenuItem = (root) => root?.querySelector('[role="menuitem"]:not([aria-disabled="true"])') ?? null;
736
- /**
737
- * Bridges Search and the registered FilterBar rows: Down from Search enters the first matching
738
- * item; Up from that item returns to Search. Initial focus lands on Search when it is shown,
739
- * otherwise on the first enabled row.
740
- *
741
- * @returns {UseFiltersMenuSearchNavigationResult} Search ref, panel-node callback, and Search ArrowDown handler
742
- */
743
- const useFiltersMenuSearchNavigation = ({ showSearch, }) => {
744
- const searchInputRef = react.useRef(null);
745
- const panelRef = react.useRef(null);
746
- const onPanelArrowUp = react.useCallback((event) => {
747
- if (event.key !== "ArrowUp") {
748
- return;
749
- }
750
- const firstItem = firstEnabledMenuItem(panelRef.current);
751
- const active = document.activeElement;
752
- if (firstItem && active && (active === firstItem || firstItem.contains(active))) {
753
- // Capture on the menu root so this wins over useListNavigation's
754
- // loop:true wrap (React onKeyDown on the floating element).
755
- event.preventDefault();
756
- event.stopImmediatePropagation();
757
- searchInputRef.current?.focus();
758
- }
759
- }, []);
760
- const setPanelNode = react.useCallback((node) => {
761
- if (panelRef.current) {
762
- panelRef.current.removeEventListener("keydown", onPanelArrowUp, true);
763
- }
764
- panelRef.current = node;
765
- if (node && showSearch) {
766
- // Attach here, not in an effect: MenuContent's ref is set after the
767
- // first paint, and a [showSearch]-only effect can snapshot a null panel.
768
- node.addEventListener("keydown", onPanelArrowUp, true);
769
- }
770
- }, [onPanelArrowUp, showSearch]);
771
- react.useEffect(() => {
772
- const focusInitialTarget = () => {
773
- if (showSearch) {
774
- searchInputRef.current?.focus();
775
- return;
776
- }
777
- firstEnabledMenuItem(panelRef.current)?.focus();
778
- };
779
- // Floating UI's default initialFocus is 0 (the trigger). FilterBar cannot
780
- // use initialFocus={1}: that would land on Reset when Search is hidden.
781
- const frame = requestAnimationFrame(focusInitialTarget);
782
- return () => cancelAnimationFrame(frame);
783
- }, [showSearch]);
784
- const handleSearchKeyDown = react.useCallback((event) => {
785
- if (event.key !== "ArrowDown") {
786
- return;
787
- }
788
- const firstItem = firstEnabledMenuItem(panelRef.current);
789
- if (firstItem) {
790
- // Stop list-navigation from owning this ArrowDown so activeIndex stays
791
- // unset and ArrowUp from the first row can return to Search.
792
- event.preventDefault();
793
- event.stopPropagation();
794
- firstItem.focus();
795
- }
796
- }, []);
797
- return react.useMemo(() => ({
798
- searchInputRef,
799
- setPanelNode,
800
- handleSearchKeyDown,
801
- }), [setPanelNode, handleSearchKeyDown]);
802
- };
803
-
804
753
  /**
805
754
  *
806
755
  */
@@ -808,25 +757,13 @@ const FiltersMenuContent = ({ filterBarConfig, setShowCustomFilters, setSearchTe
808
757
  const [t] = useTranslation();
809
758
  const filtersListId = react.useId();
810
759
  const showSearch = filterBarDefinitionCount > 5;
811
- const { searchInputRef, setPanelNode, handleSearchKeyDown } = useFiltersMenuSearchNavigation({
812
- showSearch,
813
- });
814
- const setPanelRef = react.useCallback((node) => {
815
- setPanelNode(node);
816
- if (typeof ref === "function") {
817
- ref(node);
818
- }
819
- else if (ref) {
820
- ref.current = node;
821
- }
822
- }, [setPanelNode, ref]);
823
760
  const visibleGroups = searchText
824
761
  ? searchResultsGrouped
825
762
  : showCustomFilters
826
763
  ? filtersToShowGrouped
827
764
  : removeCustomFieldsGroup(filtersToShowGrouped);
828
765
  const hasVisibleFilters = visibleGroups.some(group => group.filters.length > 0);
829
- return (jsxRuntime.jsxs(reactComponents.MenuContent, { "aria-label": t("filtersBar.filtersHeading"), className: tailwindMerge.twMerge("max-h-[min(600px,calc(100dvh-32px))] grid-rows-[minmax(0,1fr)] overflow-y-hidden p-0", className), "data-testid": dataTestId, listClassName: "grid-rows-min-fr !max-h-none min-h-0 gap-y-0 !overflow-y-hidden p-0", ref: setPanelRef, style: style, children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 p-1", children: [showSearch ? (jsxRuntime.jsx(reactFormComponents.Search, { "data-testid": "starred-filters-menu-search", fieldSize: "small", id: "search-filters-list", onChange: e => setSearchText(e.currentTarget.value), onClear: () => setSearchText(""), onKeyDown: handleSearchKeyDown, placeholder: t("filtersBar.searchFiltersPlaceholder"), ref: searchInputRef, value: searchText })) : null, 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(reactComponents.MenuDivider, {})] }), jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-col gap-1 overflow-auto p-1", id: filtersListId, children: [searchText && !hasVisibleFilters ? (jsxRuntime.jsx("div", { "aria-live": "polite", role: "status", children: jsxRuntime.jsx(reactComponents.Text, { className: "p-2 text-neutral-400", size: "small", children: t("filtersBar.emptyResults") }) })) : (jsxRuntime.jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: visibleGroups })), hasCustomFields && !showCustomFilters && !searchText ? (jsxRuntime.jsx(CustomFieldsHiddenGroup, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, filtersListId: filtersListId, onClickShow: () => {
766
+ return (jsxRuntime.jsxs(reactComponents.MenuContent, { "aria-label": t("filtersBar.filtersHeading"), autoFocus: true, className: tailwindMerge.twMerge("max-h-[min(600px,calc(100dvh-32px))] grid-rows-[minmax(0,1fr)] overflow-y-hidden p-0", className), "data-testid": dataTestId, listClassName: "grid-rows-min-fr !max-h-none min-h-0 gap-y-0 !overflow-y-hidden p-0", ref: ref, style: style, children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 p-1", children: [showSearch ? (jsxRuntime.jsx(FiltersMenuSearchField, { filtersListId: filtersListId, searchText: searchText, setSearchText: setSearchText })) : null, 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(reactComponents.MenuDivider, {})] }), jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-col gap-1 overflow-auto p-1", "data-testid": "starred-filters-menu-list", id: filtersListId, children: [searchText && !hasVisibleFilters ? (jsxRuntime.jsx("div", { "aria-live": "polite", role: "status", children: jsxRuntime.jsx(reactComponents.Text, { className: "p-2 text-neutral-400", size: "small", children: t("filtersBar.emptyResults") }) })) : (jsxRuntime.jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: visibleGroups })), hasCustomFields && !showCustomFilters && !searchText ? (jsxRuntime.jsx(CustomFieldsHiddenGroup, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, filtersListId: filtersListId, onClickShow: () => {
830
767
  setShowCustomFilters(true);
831
768
  } })) : null] })] }));
832
769
  };
package/index.esm.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
2
  import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
3
- import { useMemo, useState, useEffect, useCallback, useId, useRef, Fragment as Fragment$1 } from 'react';
3
+ import { useMemo, useState, useEffect, useCallback, useId, Fragment as Fragment$1, useRef } from 'react';
4
4
  import { twMerge } from 'tailwind-merge';
5
5
  import { Filter, FilterBody, RadioFilterItem, CheckBoxFilterItem, FilterHeader as FilterHeader$1, FilterFooter } from '@trackunit/react-filter-components';
6
- import { Button, Icon, useList, List, Text, useTextSearch, MenuDivider, MenuContent, ZStack, IconButton, Badge, useViewportBreakpoints, MenuTree, Popover, PopoverTrigger, Tooltip, PopoverContent, useCustomEncoding, useSearchParamSync, useStorageKey, useWatch } from '@trackunit/react-components';
6
+ import { Button, Icon, useList, List, Text, useTextSearch, useMenuSearchField, MenuDivider, MenuContent, ZStack, IconButton, Badge, useViewportBreakpoints, MenuTree, Popover, PopoverTrigger, Tooltip, PopoverContent, useCustomEncoding, useSearchParamSync, useStorageKey, useWatch } from '@trackunit/react-components';
7
7
  import { useAnalytics, useCurrentUser } from '@trackunit/react-core-hooks';
8
8
  import { capitalize } from 'string-ts';
9
9
  import { createEvent } from '@trackunit/iris-app-runtime-core-api';
@@ -704,6 +704,24 @@ const useFiltersMenu = ({ filterBarDefinition, filterBarConfig, hiddenFilters =
704
704
  ]);
705
705
  };
706
706
 
707
+ /**
708
+ * The filters menu's search box, registered as the menu's first keyboard stop so ArrowDown enters
709
+ * the filter rows and ArrowUp from the first row comes back here.
710
+ *
711
+ * It is a component rather than a few lines in `FiltersMenuContent` because `useMenuSearchField`
712
+ * registers through Floating UI's `FloatingList`, whose context `MenuContent` opens around its
713
+ * children -- a caller that also renders the `MenuContent` sits outside that context and registers
714
+ * nothing.
715
+ *
716
+ * @param {FiltersMenuSearchFieldProps} props The current query, its setter, and the id of the list this field filters
717
+ * @returns {ReactElement} The registered search input
718
+ */
719
+ const FiltersMenuSearchField = ({ searchText, setSearchText, filtersListId, }) => {
720
+ const [t] = useTranslation();
721
+ const { getSearchFieldProps } = useMenuSearchField();
722
+ return (jsx(Search, { "aria-controls": filtersListId, "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, ...getSearchFieldProps() }));
723
+ };
724
+
707
725
  const FilterGroupSection = ({ filterBarConfig, group, showSeparator, showTitle, }) => {
708
726
  const titleId = useId();
709
727
  return (jsxs("div", { className: "flex flex-col gap-1", children: [jsxs("div", { children: [showTitle ? (jsx(Text, { className: "h-7 p-2 text-neutral-400", "data-testid": `${group.key}-group-title`, id: titleId, size: "small", uppercase: true, weight: "bold", children: group.title })) : null, jsx("div", { "aria-labelledby": showTitle ? titleId : undefined, className: "grid", "data-testid": `${group.key}-group-list`, role: "group", children: jsx(FiltersRenderer, { filterBarConfig: filterBarConfig, filters: group.filters, visualStyle: "list-item" }) })] }), showSeparator ? jsx(MenuDivider, {}) : null] }));
@@ -730,75 +748,6 @@ const ResetFiltersButton = ({ resetFiltersToInitialState, "data-testid": dataTes
730
748
  }, ref: ref, size: "small", style: style, variant: "ghost", children: [t("filtersBar.resetFilters"), jsx("span", { className: "sr-only", children: t("filtersBar.resetFiltersSR") })] }));
731
749
  };
732
750
 
733
- const firstEnabledMenuItem = (root) => root?.querySelector('[role="menuitem"]:not([aria-disabled="true"])') ?? null;
734
- /**
735
- * Bridges Search and the registered FilterBar rows: Down from Search enters the first matching
736
- * item; Up from that item returns to Search. Initial focus lands on Search when it is shown,
737
- * otherwise on the first enabled row.
738
- *
739
- * @returns {UseFiltersMenuSearchNavigationResult} Search ref, panel-node callback, and Search ArrowDown handler
740
- */
741
- const useFiltersMenuSearchNavigation = ({ showSearch, }) => {
742
- const searchInputRef = useRef(null);
743
- const panelRef = useRef(null);
744
- const onPanelArrowUp = useCallback((event) => {
745
- if (event.key !== "ArrowUp") {
746
- return;
747
- }
748
- const firstItem = firstEnabledMenuItem(panelRef.current);
749
- const active = document.activeElement;
750
- if (firstItem && active && (active === firstItem || firstItem.contains(active))) {
751
- // Capture on the menu root so this wins over useListNavigation's
752
- // loop:true wrap (React onKeyDown on the floating element).
753
- event.preventDefault();
754
- event.stopImmediatePropagation();
755
- searchInputRef.current?.focus();
756
- }
757
- }, []);
758
- const setPanelNode = useCallback((node) => {
759
- if (panelRef.current) {
760
- panelRef.current.removeEventListener("keydown", onPanelArrowUp, true);
761
- }
762
- panelRef.current = node;
763
- if (node && showSearch) {
764
- // Attach here, not in an effect: MenuContent's ref is set after the
765
- // first paint, and a [showSearch]-only effect can snapshot a null panel.
766
- node.addEventListener("keydown", onPanelArrowUp, true);
767
- }
768
- }, [onPanelArrowUp, showSearch]);
769
- useEffect(() => {
770
- const focusInitialTarget = () => {
771
- if (showSearch) {
772
- searchInputRef.current?.focus();
773
- return;
774
- }
775
- firstEnabledMenuItem(panelRef.current)?.focus();
776
- };
777
- // Floating UI's default initialFocus is 0 (the trigger). FilterBar cannot
778
- // use initialFocus={1}: that would land on Reset when Search is hidden.
779
- const frame = requestAnimationFrame(focusInitialTarget);
780
- return () => cancelAnimationFrame(frame);
781
- }, [showSearch]);
782
- const handleSearchKeyDown = useCallback((event) => {
783
- if (event.key !== "ArrowDown") {
784
- return;
785
- }
786
- const firstItem = firstEnabledMenuItem(panelRef.current);
787
- if (firstItem) {
788
- // Stop list-navigation from owning this ArrowDown so activeIndex stays
789
- // unset and ArrowUp from the first row can return to Search.
790
- event.preventDefault();
791
- event.stopPropagation();
792
- firstItem.focus();
793
- }
794
- }, []);
795
- return useMemo(() => ({
796
- searchInputRef,
797
- setPanelNode,
798
- handleSearchKeyDown,
799
- }), [setPanelNode, handleSearchKeyDown]);
800
- };
801
-
802
751
  /**
803
752
  *
804
753
  */
@@ -806,25 +755,13 @@ const FiltersMenuContent = ({ filterBarConfig, setShowCustomFilters, setSearchTe
806
755
  const [t] = useTranslation();
807
756
  const filtersListId = useId();
808
757
  const showSearch = filterBarDefinitionCount > 5;
809
- const { searchInputRef, setPanelNode, handleSearchKeyDown } = useFiltersMenuSearchNavigation({
810
- showSearch,
811
- });
812
- const setPanelRef = useCallback((node) => {
813
- setPanelNode(node);
814
- if (typeof ref === "function") {
815
- ref(node);
816
- }
817
- else if (ref) {
818
- ref.current = node;
819
- }
820
- }, [setPanelNode, ref]);
821
758
  const visibleGroups = searchText
822
759
  ? searchResultsGrouped
823
760
  : showCustomFilters
824
761
  ? filtersToShowGrouped
825
762
  : removeCustomFieldsGroup(filtersToShowGrouped);
826
763
  const hasVisibleFilters = visibleGroups.some(group => group.filters.length > 0);
827
- return (jsxs(MenuContent, { "aria-label": t("filtersBar.filtersHeading"), className: twMerge("max-h-[min(600px,calc(100dvh-32px))] grid-rows-[minmax(0,1fr)] overflow-y-hidden p-0", className), "data-testid": dataTestId, listClassName: "grid-rows-min-fr !max-h-none min-h-0 gap-y-0 !overflow-y-hidden p-0", ref: setPanelRef, style: style, children: [jsxs("div", { children: [jsxs("div", { className: "flex flex-col gap-1 p-1", children: [showSearch ? (jsx(Search, { "data-testid": "starred-filters-menu-search", fieldSize: "small", id: "search-filters-list", onChange: e => setSearchText(e.currentTarget.value), onClear: () => setSearchText(""), onKeyDown: handleSearchKeyDown, placeholder: t("filtersBar.searchFiltersPlaceholder"), ref: searchInputRef, value: searchText })) : null, 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(MenuDivider, {})] }), jsxs("div", { className: "flex min-h-0 flex-col gap-1 overflow-auto p-1", id: filtersListId, children: [searchText && !hasVisibleFilters ? (jsx("div", { "aria-live": "polite", role: "status", children: jsx(Text, { className: "p-2 text-neutral-400", size: "small", children: t("filtersBar.emptyResults") }) })) : (jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: visibleGroups })), hasCustomFields && !showCustomFilters && !searchText ? (jsx(CustomFieldsHiddenGroup, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, filtersListId: filtersListId, onClickShow: () => {
764
+ return (jsxs(MenuContent, { "aria-label": t("filtersBar.filtersHeading"), autoFocus: true, className: twMerge("max-h-[min(600px,calc(100dvh-32px))] grid-rows-[minmax(0,1fr)] overflow-y-hidden p-0", className), "data-testid": dataTestId, listClassName: "grid-rows-min-fr !max-h-none min-h-0 gap-y-0 !overflow-y-hidden p-0", ref: ref, style: style, children: [jsxs("div", { children: [jsxs("div", { className: "flex flex-col gap-1 p-1", children: [showSearch ? (jsx(FiltersMenuSearchField, { filtersListId: filtersListId, searchText: searchText, setSearchText: setSearchText })) : null, 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(MenuDivider, {})] }), jsxs("div", { className: "flex min-h-0 flex-col gap-1 overflow-auto p-1", "data-testid": "starred-filters-menu-list", id: filtersListId, children: [searchText && !hasVisibleFilters ? (jsx("div", { "aria-live": "polite", role: "status", children: jsx(Text, { className: "p-2 text-neutral-400", size: "small", children: t("filtersBar.emptyResults") }) })) : (jsx(GroupedFiltersList, { className: "flex flex-col gap-1", filterBarConfig: filterBarConfig, filtersGrouped: visibleGroups })), hasCustomFields && !showCustomFilters && !searchText ? (jsx(CustomFieldsHiddenGroup, { appliedCustomFields: appliedCustomFields, filterBarConfig: filterBarConfig, filtersListId: filtersListId, onClickShow: () => {
828
765
  setShowCustomFilters(true);
829
766
  } })) : null] })] }));
830
767
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/filters-filter-bar",
3
- "version": "2.6.42",
3
+ "version": "2.6.45",
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.4.27",
15
- "@trackunit/react-core-hooks": "1.21.36",
16
- "@trackunit/react-filter-components": "2.6.41",
17
- "@trackunit/react-date-and-time-components": "2.6.41",
18
- "@trackunit/shared-utils": "1.16.28",
19
- "@trackunit/react-form-components": "2.6.41",
20
- "@trackunit/iris-app-runtime-core-api": "1.17.36",
21
- "@trackunit/geo-json-utils": "1.15.27",
22
- "@trackunit/i18n-library-translation": "2.4.36",
23
- "@trackunit/css-class-variance-utilities": "1.14.25",
24
- "@trackunit/react-components": "2.11.3"
14
+ "@trackunit/iris-app-api": "2.4.29",
15
+ "@trackunit/react-core-hooks": "1.21.38",
16
+ "@trackunit/react-filter-components": "2.6.44",
17
+ "@trackunit/react-date-and-time-components": "2.6.44",
18
+ "@trackunit/shared-utils": "1.16.30",
19
+ "@trackunit/react-form-components": "2.6.44",
20
+ "@trackunit/iris-app-runtime-core-api": "1.17.38",
21
+ "@trackunit/geo-json-utils": "1.15.29",
22
+ "@trackunit/i18n-library-translation": "2.4.38",
23
+ "@trackunit/css-class-variance-utilities": "1.14.27",
24
+ "@trackunit/react-components": "2.11.6"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "@apollo/client": "^3.13.8",
@@ -0,0 +1,20 @@
1
+ import { ReactElement } from "react";
2
+ interface FiltersMenuSearchFieldProps {
3
+ searchText: string;
4
+ setSearchText: (text: string) => void;
5
+ filtersListId: string;
6
+ }
7
+ /**
8
+ * The filters menu's search box, registered as the menu's first keyboard stop so ArrowDown enters
9
+ * the filter rows and ArrowUp from the first row comes back here.
10
+ *
11
+ * It is a component rather than a few lines in `FiltersMenuContent` because `useMenuSearchField`
12
+ * registers through Floating UI's `FloatingList`, whose context `MenuContent` opens around its
13
+ * children -- a caller that also renders the `MenuContent` sits outside that context and registers
14
+ * nothing.
15
+ *
16
+ * @param {FiltersMenuSearchFieldProps} props The current query, its setter, and the id of the list this field filters
17
+ * @returns {ReactElement} The registered search input
18
+ */
19
+ export declare const FiltersMenuSearchField: ({ searchText, setSearchText, filtersListId, }: FiltersMenuSearchFieldProps) => ReactElement;
20
+ export {};
@@ -1 +0,0 @@
1
- {"version":3,"file":"entry.js","sourceRoot":"","sources":["../../../../../libs/filters/filter-bar/migrations/entry.ts"],"names":[],"mappings":"","sourcesContent":["export {};\n"]}
@@ -1,16 +0,0 @@
1
- import { KeyboardEvent, Ref, RefCallback } from "react";
2
- export interface UseFiltersMenuSearchNavigationResult {
3
- searchInputRef: Ref<HTMLInputElement>;
4
- setPanelNode: RefCallback<HTMLDivElement>;
5
- handleSearchKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void;
6
- }
7
- /**
8
- * Bridges Search and the registered FilterBar rows: Down from Search enters the first matching
9
- * item; Up from that item returns to Search. Initial focus lands on Search when it is shown,
10
- * otherwise on the first enabled row.
11
- *
12
- * @returns {UseFiltersMenuSearchNavigationResult} Search ref, panel-node callback, and Search ArrowDown handler
13
- */
14
- export declare const useFiltersMenuSearchNavigation: ({ showSearch, }: {
15
- showSearch: boolean;
16
- }) => UseFiltersMenuSearchNavigationResult;