@databiosphere/findable-ui 42.1.0 → 44.0.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.
Files changed (160) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +27 -0
  3. package/lib/common/categories/config/range/typeGuards.d.ts +8 -0
  4. package/lib/common/categories/config/range/typeGuards.js +9 -0
  5. package/lib/common/filters/sort/config/types.d.ts +13 -0
  6. package/lib/common/filters/sort/config/types.js +8 -0
  7. package/lib/common/filters/sort/config/utils.d.ts +8 -0
  8. package/lib/common/filters/sort/config/utils.js +9 -0
  9. package/lib/common/filters/sort/models/utils.d.ts +23 -0
  10. package/lib/common/filters/sort/models/utils.js +41 -0
  11. package/lib/components/Filter/components/SearchAllFilters/common/constants.d.ts +3 -13
  12. package/lib/components/Filter/components/SearchAllFilters/common/constants.js +12 -36
  13. package/lib/components/Filter/components/SearchAllFilters/components/OutlinedInput/constants.d.ts +2 -0
  14. package/lib/components/Filter/components/SearchAllFilters/components/OutlinedInput/constants.js +7 -0
  15. package/lib/components/Filter/components/SearchAllFilters/components/OutlinedInput/outlinedInput.d.ts +2 -0
  16. package/lib/components/Filter/components/SearchAllFilters/components/OutlinedInput/outlinedInput.js +13 -0
  17. package/lib/components/Filter/components/SearchAllFilters/components/OutlinedInput/utils.d.ts +11 -0
  18. package/lib/components/Filter/components/SearchAllFilters/components/OutlinedInput/utils.js +17 -0
  19. package/lib/components/Filter/components/SearchAllFilters/components/VariableSizeList/VariableSizeList.d.ts +2 -0
  20. package/lib/components/Filter/components/SearchAllFilters/components/VariableSizeList/VariableSizeList.js +9 -10
  21. package/lib/components/Filter/components/SearchAllFilters/context/context.d.ts +2 -0
  22. package/lib/components/Filter/components/SearchAllFilters/context/context.js +10 -0
  23. package/lib/components/Filter/components/SearchAllFilters/context/hook.d.ts +6 -0
  24. package/lib/components/Filter/components/SearchAllFilters/context/hook.js +9 -0
  25. package/lib/components/Filter/components/SearchAllFilters/context/types.d.ts +11 -0
  26. package/lib/components/Filter/components/SearchAllFilters/context/types.js +1 -0
  27. package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.d.ts +2 -19
  28. package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.js +37 -74
  29. package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.styles.d.ts +2 -2
  30. package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.styles.js +7 -8
  31. package/lib/components/Filter/components/SearchAllFilters/stories/args.d.ts +3 -0
  32. package/lib/components/Filter/components/SearchAllFilters/stories/args.js +8 -0
  33. package/lib/components/Filter/components/SearchAllFilters/stories/searchAllFilters.stories.d.ts +6 -0
  34. package/lib/components/Filter/components/SearchAllFilters/stories/searchAllFilters.stories.js +19 -0
  35. package/lib/components/Filter/components/SearchAllFilters/types.d.ts +10 -0
  36. package/lib/components/Filter/components/SearchAllFilters/types.js +1 -0
  37. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/columnFiltersAdapter.js +16 -2
  38. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/hook.d.ts +3 -0
  39. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/hook.js +8 -0
  40. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/types.d.ts +6 -0
  41. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/types.js +1 -0
  42. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/utils.d.ts +14 -0
  43. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/utils.js +23 -0
  44. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/types.d.ts +7 -1
  45. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/utils.d.ts +3 -1
  46. package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/utils.js +122 -19
  47. package/lib/components/Filter/components/controls/Controls/components/FilterSort/constants.d.ts +5 -0
  48. package/lib/components/Filter/components/controls/Controls/components/FilterSort/constants.js +17 -0
  49. package/lib/components/Filter/components/controls/Controls/components/FilterSort/filterSort.d.ts +2 -0
  50. package/lib/components/Filter/components/controls/Controls/components/FilterSort/filterSort.js +28 -0
  51. package/lib/components/Filter/components/controls/Controls/components/FilterSort/filterSort.styles.d.ts +9 -0
  52. package/lib/components/Filter/components/controls/Controls/components/FilterSort/filterSort.styles.js +25 -0
  53. package/lib/components/Filter/components/controls/Controls/components/FilterSort/stories/filterSort.stories.d.ts +6 -0
  54. package/lib/components/Filter/components/controls/Controls/components/FilterSort/stories/filterSort.stories.js +9 -0
  55. package/lib/components/Filter/components/controls/Controls/components/FilterSort/types.d.ts +6 -0
  56. package/lib/components/Filter/components/controls/Controls/components/FilterSort/types.js +1 -0
  57. package/lib/components/Filter/components/controls/Controls/controls.d.ts +2 -3
  58. package/lib/components/Filter/components/controls/Controls/controls.js +4 -2
  59. package/lib/components/Filter/components/controls/Controls/controls.styles.js +2 -1
  60. package/lib/components/Filter/components/controls/Controls/types.d.ts +6 -0
  61. package/lib/components/Filter/components/controls/Controls/types.js +1 -0
  62. package/lib/components/Filter/components/surfaces/popper/Popper/popper.styles.d.ts +6 -0
  63. package/lib/components/Filter/components/surfaces/popper/Popper/popper.styles.js +18 -0
  64. package/lib/components/Filter/components/surfaces/types.d.ts +6 -2
  65. package/lib/components/Filter/components/surfaces/types.js +2 -0
  66. package/lib/components/Index/components/EntityView/components/views/ChartView/components/Chart/hooks/UsePlotOptions/hook.js +2 -2
  67. package/lib/components/Index/components/EntityView/components/views/ChartView/components/Chart/utils.d.ts +0 -7
  68. package/lib/components/Index/components/EntityView/components/views/ChartView/components/Chart/utils.js +0 -11
  69. package/lib/config/entities.d.ts +2 -0
  70. package/lib/hooks/useCategoryFilter.d.ts +4 -9
  71. package/lib/hooks/useCategoryFilter.js +5 -15
  72. package/lib/providers/exploreState/actions/updateFilterSort/action.d.ts +10 -0
  73. package/lib/providers/exploreState/actions/updateFilterSort/action.js +21 -0
  74. package/lib/providers/exploreState/actions/updateFilterSort/dispatch.d.ts +7 -0
  75. package/lib/providers/exploreState/actions/updateFilterSort/dispatch.js +12 -0
  76. package/lib/providers/exploreState/actions/updateFilterSort/types.d.ts +7 -0
  77. package/lib/providers/exploreState/actions/updateFilterSort/types.js +1 -0
  78. package/lib/providers/exploreState/actions/updateFilterSort/utils.d.ts +10 -0
  79. package/lib/providers/exploreState/actions/updateFilterSort/utils.js +22 -0
  80. package/lib/providers/exploreState/initializer/constants.js +2 -0
  81. package/lib/providers/exploreState/initializer/utils.js +2 -0
  82. package/lib/providers/exploreState.d.ts +5 -1
  83. package/lib/providers/exploreState.js +9 -1
  84. package/lib/styles/common/mui/textField.d.ts +11 -0
  85. package/lib/styles/common/mui/textField.js +22 -0
  86. package/lib/tests/testIds.d.ts +2 -0
  87. package/lib/tests/testIds.js +2 -0
  88. package/lib/views/ExploreView/exploreView.js +8 -2
  89. package/lib/views/ExploreView/hooks/UseUpdateFilterSort/hook.d.ts +2 -0
  90. package/lib/views/ExploreView/hooks/UseUpdateFilterSort/hook.js +12 -0
  91. package/lib/views/ExploreView/hooks/UseUpdateFilterSort/types.d.ts +6 -0
  92. package/lib/views/ExploreView/hooks/UseUpdateFilterSort/types.js +1 -0
  93. package/package.json +1 -1
  94. package/src/common/categories/config/range/typeGuards.ts +14 -0
  95. package/src/common/filters/sort/config/types.ts +14 -0
  96. package/src/common/filters/sort/config/utils.ts +11 -0
  97. package/src/common/filters/sort/models/utils.ts +57 -0
  98. package/src/components/Filter/components/SearchAllFilters/common/constants.ts +24 -37
  99. package/src/components/Filter/components/SearchAllFilters/components/OutlinedInput/constants.ts +9 -0
  100. package/src/components/Filter/components/SearchAllFilters/components/OutlinedInput/outlinedInput.tsx +31 -0
  101. package/src/components/Filter/components/SearchAllFilters/components/OutlinedInput/utils.ts +22 -0
  102. package/src/components/Filter/components/SearchAllFilters/components/VariableSizeList/VariableSizeList.tsx +12 -13
  103. package/src/components/Filter/components/SearchAllFilters/context/context.ts +12 -0
  104. package/src/components/Filter/components/SearchAllFilters/context/hook.ts +11 -0
  105. package/src/components/Filter/components/SearchAllFilters/context/types.ts +12 -0
  106. package/src/components/Filter/components/SearchAllFilters/searchAllFilters.styles.ts +8 -9
  107. package/src/components/Filter/components/SearchAllFilters/searchAllFilters.tsx +70 -132
  108. package/src/components/Filter/components/SearchAllFilters/stories/args.ts +15 -0
  109. package/src/components/Filter/components/SearchAllFilters/stories/searchAllFilters.stories.tsx +29 -0
  110. package/src/components/Filter/components/SearchAllFilters/types.ts +16 -0
  111. package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/columnFiltersAdapter.tsx +23 -2
  112. package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/hook.ts +22 -0
  113. package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/types.ts +7 -0
  114. package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/utils.ts +33 -0
  115. package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/types.ts +12 -1
  116. package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/utils.ts +179 -21
  117. package/src/components/Filter/components/controls/Controls/components/FilterSort/constants.ts +22 -0
  118. package/src/components/Filter/components/controls/Controls/components/FilterSort/filterSort.styles.ts +34 -0
  119. package/src/components/Filter/components/controls/Controls/components/FilterSort/filterSort.tsx +73 -0
  120. package/src/components/Filter/components/controls/Controls/components/FilterSort/stories/filterSort.stories.tsx +15 -0
  121. package/src/components/Filter/components/controls/Controls/components/FilterSort/types.ts +7 -0
  122. package/src/components/Filter/components/controls/Controls/controls.styles.ts +2 -1
  123. package/src/components/Filter/components/controls/Controls/controls.tsx +11 -3
  124. package/src/components/Filter/components/controls/Controls/types.ts +10 -0
  125. package/src/components/Filter/components/surfaces/popper/Popper/popper.styles.ts +20 -0
  126. package/src/components/Filter/components/surfaces/types.ts +5 -1
  127. package/src/components/Index/components/EntityView/components/views/ChartView/components/Chart/hooks/UsePlotOptions/hook.ts +2 -2
  128. package/src/components/Index/components/EntityView/components/views/ChartView/components/Chart/utils.ts +0 -15
  129. package/src/config/entities.ts +2 -0
  130. package/src/hooks/useCategoryFilter.ts +8 -19
  131. package/src/providers/exploreState/actions/updateFilterSort/action.ts +30 -0
  132. package/src/providers/exploreState/actions/updateFilterSort/dispatch.ts +16 -0
  133. package/src/providers/exploreState/actions/updateFilterSort/types.ts +9 -0
  134. package/src/providers/exploreState/actions/updateFilterSort/utils.ts +30 -0
  135. package/src/providers/exploreState/initializer/constants.ts +2 -0
  136. package/src/providers/exploreState/initializer/utils.ts +2 -0
  137. package/src/providers/exploreState.tsx +14 -1
  138. package/src/styles/common/mui/textField.ts +33 -0
  139. package/src/tests/testIds.ts +2 -0
  140. package/src/views/ExploreView/exploreView.tsx +19 -1
  141. package/src/views/ExploreView/hooks/UseUpdateFilterSort/hook.ts +20 -0
  142. package/src/views/ExploreView/hooks/UseUpdateFilterSort/types.ts +7 -0
  143. package/tests/buildCategoryViews.test.ts +282 -0
  144. package/tests/filterSortUtils.test.ts +180 -0
  145. package/tests/getFilterSortType.test.ts +45 -0
  146. package/lib/components/Filter/components/SearchAllFilters/components/AutocompletePopper/autocompletePopper.styles.d.ts +0 -3
  147. package/lib/components/Filter/components/SearchAllFilters/components/AutocompletePopper/autocompletePopper.styles.js +0 -15
  148. package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.stories.d.ts +0 -6
  149. package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.stories.js +0 -82
  150. package/lib/components/Filter/components/SearchAllFiltersSearch/components/SearchCloseButton/searchCloseButton.d.ts +0 -1
  151. package/lib/components/Filter/components/SearchAllFiltersSearch/components/SearchCloseButton/searchCloseButton.js +0 -13
  152. package/lib/components/Filter/components/SearchAllFiltersSearch/searchAllFiltersSearch.d.ts +0 -2
  153. package/lib/components/Filter/components/SearchAllFiltersSearch/searchAllFiltersSearch.js +0 -12
  154. package/lib/components/Filter/components/SearchAllFiltersSearch/searchAllFiltersSearch.styles.d.ts +0 -5
  155. package/lib/components/Filter/components/SearchAllFiltersSearch/searchAllFiltersSearch.styles.js +0 -34
  156. package/src/components/Filter/components/SearchAllFilters/components/AutocompletePopper/autocompletePopper.styles.ts +0 -16
  157. package/src/components/Filter/components/SearchAllFilters/searchAllFilters.stories.tsx +0 -92
  158. package/src/components/Filter/components/SearchAllFiltersSearch/components/SearchCloseButton/searchCloseButton.tsx +0 -25
  159. package/src/components/Filter/components/SearchAllFiltersSearch/searchAllFiltersSearch.styles.ts +0 -35
  160. package/src/components/Filter/components/SearchAllFiltersSearch/searchAllFiltersSearch.tsx +0 -29
@@ -1,55 +1,42 @@
1
- import { PaperProps, PopperProps } from "@mui/material";
1
+ import { AutocompleteProps, PaperProps, PopperProps } from "@mui/material";
2
2
  import { DividerItem, ITEM_TYPE, NoResultsItem } from "./entites";
3
3
 
4
4
  export const DEFAULT_LIST_HEIGHT = 0;
5
5
 
6
6
  export const DIVIDER_HEIGHT = 17;
7
7
 
8
- export const DEFAULT_PAPER_PROPS: Partial<PaperProps> = {
9
- sx: {
10
- width: 368,
11
- },
12
- variant: "menu",
13
- };
14
- export const DEFAULT_POPPER_PROPS: Partial<PopperProps> = {
15
- modifiers: [
16
- {
17
- name: "offset",
18
- options: {
19
- offset: [0, 8],
20
- },
21
- },
22
- ],
8
+ const POPPER_MENU_PAPER_PROPS: Partial<PaperProps> = { variant: "menu" };
9
+
10
+ const POPPER_MENU_POPPER_PROPS: Partial<PopperProps> = {
11
+ modifiers: [{ name: "offset", options: { offset: [0, 8] } }],
23
12
  placement: "bottom-start",
24
13
  };
25
14
 
26
- export const DEFAULT_SLOT_PROPS = {
27
- paper: DEFAULT_PAPER_PROPS,
28
- popper: DEFAULT_POPPER_PROPS,
15
+ export const POPPER_MENU_SLOT_PROPS: AutocompleteProps<
16
+ string,
17
+ false,
18
+ false,
19
+ true
20
+ >["slotProps"] = {
21
+ paper: POPPER_MENU_PAPER_PROPS,
22
+ popper: POPPER_MENU_POPPER_PROPS,
29
23
  };
30
24
 
31
- export const DRAWER_PAPER_PROPS: Partial<PaperProps> = {
32
- elevation: 0,
33
- sx: {
34
- width: 312,
35
- },
36
- };
25
+ const POPPER_DRAWER_PAPER_PROPS: Partial<PaperProps> = { elevation: 0 };
37
26
 
38
- export const DRAWER_POPPER_PROPS: Partial<PopperProps> = {
39
- modifiers: [
40
- {
41
- name: "offset",
42
- options: {
43
- offset: [-16, 8],
44
- },
45
- },
46
- ],
27
+ const POPPER_DRAWER_POPPER_PROPS: Partial<PopperProps> = {
28
+ modifiers: [{ name: "offset", options: { offset: [-16, 8] } }],
47
29
  popperOptions: { strategy: "absolute" },
48
30
  };
49
31
 
50
- export const DRAWER_SLOT_PROPS = {
51
- paper: DRAWER_PAPER_PROPS,
52
- popper: DRAWER_POPPER_PROPS,
32
+ export const POPPER_DRAWER_SLOT_PROPS: AutocompleteProps<
33
+ string,
34
+ false,
35
+ false,
36
+ true
37
+ >["slotProps"] = {
38
+ paper: POPPER_DRAWER_PAPER_PROPS,
39
+ popper: POPPER_DRAWER_POPPER_PROPS,
53
40
  };
54
41
 
55
42
  export const DIVIDER_ITEM: DividerItem = {
@@ -0,0 +1,9 @@
1
+ import { OutlinedInputProps } from "@mui/material";
2
+ import { TEXT_FIELD_PROPS as MUI_TEXT_FIELD_PROPS } from "../../../../../../styles/common/mui/textField";
3
+
4
+ export const TEXT_FIELD_PROPS: OutlinedInputProps = {
5
+ color: MUI_TEXT_FIELD_PROPS.COLOR.SECONDARY,
6
+ fullWidth: true,
7
+ placeholder: "Search all filters...",
8
+ size: MUI_TEXT_FIELD_PROPS.SIZE.SMALL,
9
+ };
@@ -0,0 +1,31 @@
1
+ import { AutocompleteRenderInputParams } from "@mui/material";
2
+ import React from "react";
3
+ import { ClearInputAdornment } from "../../../../../common/OutlinedInput/components/InputAdornment/components/ClearInputAdornment/clearInputAdornment";
4
+ import { SearchInputAdornment } from "../../../../../common/OutlinedInput/components/InputAdornment/components/SearchInputAdornment/searchInputAdornment";
5
+ import { StyledOutlinedInput } from "../../../../../common/OutlinedInput/outlinedInput.styles";
6
+ import { useAutocomplete } from "../../context/hook";
7
+ import { TEXT_FIELD_PROPS } from "./constants";
8
+ import { isButtonIn } from "./utils";
9
+
10
+ export const OutlinedInput = (
11
+ props: AutocompleteRenderInputParams
12
+ ): JSX.Element => {
13
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Intended behavior, destructure InputLabelProps, as they are not used on the component.
14
+ const { InputLabelProps, InputProps, ...outlinedInputProps } = props;
15
+ const { onClear, open, searchTerm, surfaceType } = useAutocomplete();
16
+ return (
17
+ <StyledOutlinedInput
18
+ {...TEXT_FIELD_PROPS}
19
+ {...InputProps}
20
+ {...outlinedInputProps}
21
+ endAdornment={
22
+ <ClearInputAdornment
23
+ in={isButtonIn(surfaceType, searchTerm, open)}
24
+ onClick={onClear}
25
+ />
26
+ }
27
+ hasValue={!!searchTerm}
28
+ startAdornment={<SearchInputAdornment />}
29
+ />
30
+ );
31
+ };
@@ -0,0 +1,22 @@
1
+ import { SURFACE_TYPE } from "../../../surfaces/types";
2
+
3
+ /**
4
+ * Returns true if the clear button should display.
5
+ * Displays always for popper drawer surface type when open.
6
+ * Displays when there is a search term for other surface types when open.
7
+ * @param surfaceType - Surface type.
8
+ * @param searchTerm - Search term.
9
+ * @param open - Autocomplete open state.
10
+ * @returns True if the clear button should display.
11
+ */
12
+ export function isButtonIn(
13
+ surfaceType: SURFACE_TYPE,
14
+ searchTerm: string,
15
+ open: boolean
16
+ ): boolean {
17
+ if (!open) return false;
18
+
19
+ if (surfaceType === SURFACE_TYPE.POPPER_DRAWER) return true;
20
+
21
+ return !!searchTerm;
22
+ }
@@ -15,10 +15,6 @@ import {
15
15
  VariableSizeListProps as ListProps,
16
16
  } from "react-window";
17
17
  import { SelectCategoryView } from "../../../../../../common/entities";
18
- import {
19
- BREAKPOINT_FN_NAME,
20
- useBreakpointHelper,
21
- } from "../../../../../../hooks/useBreakpointHelper";
22
18
  import { OnFilterFn } from "../../../../../../hooks/useCategoryFilter";
23
19
  import { useWindowResize } from "../../../../../../hooks/useWindowResize";
24
20
  import {
@@ -29,6 +25,7 @@ import {
29
25
  } from "../../../../common/constants";
30
26
  import { getSortMatchesFn } from "../../../../common/utils";
31
27
  import { StyledList } from "../../../FilterList/filterList.styles";
28
+ import { SURFACE_TYPE } from "../../../surfaces/types";
32
29
  import {
33
30
  DIVIDER_HEIGHT,
34
31
  DIVIDER_ITEM,
@@ -51,6 +48,7 @@ export interface VariableSizeListProps {
51
48
  overscanCount?: ListProps["overscanCount"];
52
49
  searchTerm: string;
53
50
  selectCategoryViews: SelectCategoryView[];
51
+ surfaceType: SURFACE_TYPE;
54
52
  width?: ListProps["width"]; // Width of list; default to 100% width of parent element.
55
53
  }
56
54
 
@@ -125,13 +123,13 @@ export const VariableSizeList = forwardRef<
125
123
  overscanCount = MAX_DISPLAYABLE_LIST_ITEMS * 2,
126
124
  searchTerm,
127
125
  selectCategoryViews,
126
+ surfaceType,
128
127
  width = "100%",
129
128
  }: VariableSizeListProps,
130
129
  autocompleteListRef
131
130
  ): JSX.Element {
132
131
  const filteredItems = applyMenuFilter(selectCategoryViews, searchTerm);
133
132
  let resizeRequired = true;
134
- const bpDownMd = useBreakpointHelper(BREAKPOINT_FN_NAME.DOWN, "md");
135
133
  const { height: windowHeight } = useWindowResize();
136
134
  const [height, setHeight] = useState<number>(initHeight);
137
135
  const itemSizeByItemKeyRef = useRef<ItemSizeByItemKey>(new Map());
@@ -153,10 +151,10 @@ export const VariableSizeList = forwardRef<
153
151
  outerRef.current,
154
152
  innerRef.current,
155
153
  windowHeight,
156
- bpDownMd
154
+ surfaceType
157
155
  )
158
156
  );
159
- }, [bpDownMd, windowHeight]);
157
+ }, [surfaceType, windowHeight]);
160
158
 
161
159
  // Clears VariableSizeList cache (offsets and measurements) when values are updated (filtered).
162
160
  // Facilitates correct positioning of list items when list is updated.
@@ -198,7 +196,7 @@ export const VariableSizeList = forwardRef<
198
196
  outerRef.current,
199
197
  innerRef.current,
200
198
  windowHeight,
201
- bpDownMd
199
+ surfaceType
202
200
  )
203
201
  );
204
202
  }
@@ -266,20 +264,21 @@ function applyMenuFilter(
266
264
  * @param outerListElem - Outer list element to reference list position from.
267
265
  * @param innerListElem - Element containing list items.
268
266
  * @param windowHeight - Window height.
269
- * @param bpDownMd - True if viewport is "md" or smaller.
267
+ * @param surfaceType - Type of surface "POPPER_MENU" or "POPPER_DRAWER".
270
268
  * @returns calculated height.
271
269
  */
272
270
  function calculateListHeight(
273
271
  outerListElem: HTMLDivElement,
274
272
  innerListElem: HTMLUListElement,
275
273
  windowHeight: number,
276
- bpDownMd: boolean
274
+ surfaceType: SURFACE_TYPE
277
275
  ): number {
278
276
  // Calculate max possible list height, based on window height and top position of the list element.
279
277
  const maxHeight = windowHeight - outerListElem.getBoundingClientRect().top;
280
- if (bpDownMd) {
281
- return maxHeight;
282
- }
278
+
279
+ // Return the maximum possible height if the list is in a popper drawer.
280
+ if (surfaceType === SURFACE_TYPE.POPPER_DRAWER) return maxHeight;
281
+
283
282
  // Grab the first and last element in the list.
284
283
  const { firstElementChild: firstListEl, lastElementChild: lastListEl } =
285
284
  innerListElem;
@@ -0,0 +1,12 @@
1
+ import { createContext } from "react";
2
+ import { SURFACE_TYPE } from "../../surfaces/types";
3
+ import { AutocompleteContextProps } from "./types";
4
+
5
+ export const AutocompleteContext = createContext<AutocompleteContextProps>({
6
+ onClear: (): void => undefined,
7
+ onFilter: (): void => undefined,
8
+ open: false,
9
+ searchTerm: "",
10
+ selectCategoryViews: [],
11
+ surfaceType: SURFACE_TYPE.POPPER_MENU,
12
+ });
@@ -0,0 +1,11 @@
1
+ import { useContext } from "react";
2
+ import { AutocompleteContext } from "./context";
3
+ import { AutocompleteContextProps } from "./types";
4
+
5
+ /**
6
+ * Returns autocomplete context.
7
+ * @returns autocomplete context.
8
+ */
9
+ export const useAutocomplete = (): AutocompleteContextProps => {
10
+ return useContext(AutocompleteContext);
11
+ };
@@ -0,0 +1,12 @@
1
+ import { SelectCategoryView } from "../../../../../common/entities";
2
+ import { OnFilterFn } from "../../../../../hooks/useCategoryFilter";
3
+ import { SURFACE_TYPE } from "../../surfaces/types";
4
+
5
+ export interface AutocompleteContextProps {
6
+ onClear: () => void;
7
+ onFilter: OnFilterFn;
8
+ open: boolean;
9
+ searchTerm: string;
10
+ selectCategoryViews: SelectCategoryView[];
11
+ surfaceType: SURFACE_TYPE;
12
+ }
@@ -1,15 +1,14 @@
1
1
  import styled from "@emotion/styled";
2
- import { Autocomplete as MAutocomplete } from "@mui/material";
3
- import { PALETTE } from "../../../../styles/common/constants/palette";
2
+ import { Autocomplete } from "@mui/material";
4
3
 
5
- export const Autocomplete = styled(MAutocomplete)`
6
- &.Mui-expanded {
4
+ export const StyledAutocomplete = styled(Autocomplete)`
5
+ &.MuiAutocomplete-root {
7
6
  .MuiOutlinedInput-root {
8
- .MuiIconButton-root {
9
- .MuiSvgIcon-root {
10
- color: ${PALETTE.INK_MAIN};
11
- }
7
+ padding: 0 12px;
8
+
9
+ .MuiAutocomplete-input {
10
+ padding: 10px 0;
12
11
  }
13
12
  }
14
13
  }
15
- ` as typeof MAutocomplete;
14
+ ` as typeof Autocomplete;
@@ -1,61 +1,25 @@
1
- import {
2
- AutocompleteRenderInputParams,
3
- ListProps as MListProps,
4
- } from "@mui/material";
5
- import React, {
6
- ChangeEvent,
7
- createContext,
8
- useContext,
9
- useEffect,
10
- useRef,
11
- useState,
12
- } from "react";
1
+ import { ListProps as MListProps } from "@mui/material";
2
+ import React, { useCallback, useRef, useState } from "react";
13
3
  import { isSelectCategoryView } from "../../../../common/categories/views/select/typeGuards";
14
- import { CategoryView } from "../../../../common/categories/views/types";
15
- import { SelectCategoryView } from "../../../../common/entities";
16
4
  import { SELECTOR } from "../../../../common/selectors";
17
- import {
18
- BREAKPOINT_FN_NAME,
19
- useBreakpointHelper,
20
- } from "../../../../hooks/useBreakpointHelper";
21
- import { OnFilterFn } from "../../../../hooks/useCategoryFilter";
22
5
  import { TEST_IDS } from "../../../../tests/testIds";
23
- import { useDrawer } from "../../../common/Drawer/provider/hook";
24
- import { SearchCloseButton } from "../SearchAllFiltersSearch/components/SearchCloseButton/searchCloseButton";
25
- import { SearchAllFiltersSearch } from "../SearchAllFiltersSearch/searchAllFiltersSearch";
26
- import { DEFAULT_SLOT_PROPS, DRAWER_SLOT_PROPS } from "./common/constants";
6
+ import {
7
+ StyledPopper,
8
+ StyledPopperDrawer,
9
+ } from "../surfaces/popper/Popper/popper.styles";
10
+ import { SURFACE_TYPE } from "../surfaces/types";
11
+ import {
12
+ POPPER_DRAWER_SLOT_PROPS,
13
+ POPPER_MENU_SLOT_PROPS,
14
+ } from "./common/constants";
27
15
  import { OVERFLOW_STYLE } from "./common/entites";
28
16
  import { setElementsOverflowStyle } from "./common/utils";
29
- import { AutocompletePopper } from "./components/AutocompletePopper/autocompletePopper.styles";
17
+ import { OutlinedInput } from "./components/OutlinedInput/outlinedInput";
30
18
  import { VariableSizeList } from "./components/VariableSizeList/VariableSizeList";
31
- import { Autocomplete } from "./searchAllFilters.styles";
32
-
33
- export interface SearchAllFiltersProps {
34
- categoryViews: CategoryView[];
35
- onFilter: OnFilterFn;
36
- }
37
-
38
- interface ListboxContextValue {
39
- onClearSearch: () => void;
40
- onCloseSearch: () => void;
41
- onFilter: OnFilterFn;
42
- open: boolean;
43
- searchTerm: string;
44
- selectCategoryViews: SelectCategoryView[];
45
- }
46
-
47
- const renderInput = (params: AutocompleteRenderInputParams): JSX.Element => (
48
- <SearchAllFiltersSearch {...params} />
49
- );
50
-
51
- export const ListboxContext = createContext<ListboxContextValue>({
52
- onClearSearch: (): void => undefined,
53
- onCloseSearch: (): void => undefined,
54
- onFilter: (): void => undefined,
55
- open: false,
56
- searchTerm: "",
57
- selectCategoryViews: [],
58
- });
19
+ import { AutocompleteContext } from "./context/context";
20
+ import { useAutocomplete } from "./context/hook";
21
+ import { StyledAutocomplete } from "./searchAllFilters.styles";
22
+ import { SearchAllFiltersProps } from "./types";
59
23
 
60
24
  const Listbox = React.forwardRef<HTMLUListElement, MListProps>(function Listbox(
61
25
  props,
@@ -64,8 +28,8 @@ const Listbox = React.forwardRef<HTMLUListElement, MListProps>(function Listbox(
64
28
  props = Object.assign({}, props, {
65
29
  children: undefined, // Content is controlled by VariableSizeList
66
30
  });
67
- const { onFilter, searchTerm, selectCategoryViews } =
68
- useContext(ListboxContext);
31
+ const { onFilter, searchTerm, selectCategoryViews, surfaceType } =
32
+ useAutocomplete();
69
33
  return (
70
34
  <VariableSizeList
71
35
  autocompleteListProps={props}
@@ -73,120 +37,94 @@ const Listbox = React.forwardRef<HTMLUListElement, MListProps>(function Listbox(
73
37
  ref={ref}
74
38
  searchTerm={searchTerm}
75
39
  selectCategoryViews={selectCategoryViews}
40
+ surfaceType={surfaceType}
76
41
  />
77
42
  );
78
43
  });
79
44
 
80
45
  export const SearchAllFilters = ({
81
46
  categoryViews,
47
+ className,
82
48
  onFilter,
49
+ surfaceType = SURFACE_TYPE.POPPER_MENU,
50
+ ...props /* Mui AutocompleteProps */
83
51
  }: SearchAllFiltersProps): JSX.Element => {
84
- const { open: isDrawerOpen } = useDrawer();
85
- const bpUpMd = useBreakpointHelper(BREAKPOINT_FN_NAME.UP, "md");
86
52
  const autocompleteRef = useRef<HTMLDivElement>(null);
87
53
  const [open, setOpen] = useState(false);
88
54
  const [searchTerm, setSearchTerm] = useState("");
89
- const selectCategoryViews = categoryViews.filter((view) =>
90
- isSelectCategoryView(view)
91
- );
92
-
93
- // Handles background scroll action ("md" and up).
94
- const handleBackgroundScroll = (overflowStyle: OVERFLOW_STYLE): void => {
95
- if (bpUpMd) {
96
- setElementsOverflowStyle(
97
- [
98
- document.querySelector(SELECTOR.BODY),
99
- document.getElementById(SELECTOR.SIDEBAR_POSITIONER),
100
- ],
101
- overflowStyle
102
- );
103
- }
104
- };
55
+ const selectCategoryViews = categoryViews.filter(isSelectCategoryView);
105
56
 
106
- // Callback fired when the value is changed.
107
- const onChange = (event: ChangeEvent<HTMLInputElement>): void => {
108
- setSearchTerm(event.target.value);
109
- };
110
-
111
- // Clear search
112
- const onClearSearch = (): void => {
113
- setSearchTerm("");
114
- };
57
+ // Handles background scroll action.
58
+ const handleBackgroundScroll = useCallback(
59
+ (overflowStyle: OVERFLOW_STYLE): void => {
60
+ if (surfaceType === SURFACE_TYPE.POPPER_MENU) {
61
+ setElementsOverflowStyle(
62
+ [
63
+ document.querySelector(SELECTOR.BODY),
64
+ document.getElementById(SELECTOR.SIDEBAR_POSITIONER),
65
+ ],
66
+ overflowStyle
67
+ );
68
+ }
69
+ },
70
+ [surfaceType]
71
+ );
115
72
 
116
- // Close search.
117
- const onCloseSearch = (): void => {
73
+ const onClose = useCallback((): void => {
118
74
  setSearchTerm("");
119
75
  setOpen(false);
120
76
  handleBackgroundScroll(OVERFLOW_STYLE.NONE);
121
- };
122
-
123
- // Callback fired when the popup requests to be opened.
124
- const onOpen = (): void => {
125
- handleBackgroundScroll(OVERFLOW_STYLE.HIDDEN);
126
- };
77
+ setTimeout(() => {
78
+ autocompleteRef.current?.querySelector("input")?.blur();
79
+ }, 100);
80
+ }, [handleBackgroundScroll]);
127
81
 
128
- // Open search.
129
- const onOpenSearch = (): void => {
130
- if (open) {
131
- return;
132
- }
82
+ const onOpen = useCallback((): void => {
133
83
  setOpen(true);
134
- };
135
-
136
- useEffect(() => {
137
- if (!open) {
138
- autocompleteRef.current?.querySelector("input")?.blur();
139
- }
140
- }, [open]);
84
+ handleBackgroundScroll(OVERFLOW_STYLE.HIDDEN);
85
+ }, [handleBackgroundScroll]);
141
86
 
142
- // Close search when filter drawer is closed.
143
- useEffect(() => {
144
- if (!isDrawerOpen) {
145
- setSearchTerm("");
146
- setOpen(false);
147
- }
148
- }, [isDrawerOpen]);
87
+ const onClear = useCallback((): void => {
88
+ setSearchTerm("");
89
+ if (surfaceType === SURFACE_TYPE.POPPER_DRAWER) onClose();
90
+ }, [onClose, surfaceType]);
149
91
 
150
92
  return (
151
- <ListboxContext.Provider
93
+ <AutocompleteContext.Provider
152
94
  value={{
153
- onClearSearch,
154
- onCloseSearch,
95
+ onClear,
155
96
  onFilter,
156
97
  open,
157
98
  searchTerm,
158
99
  selectCategoryViews,
100
+ surfaceType,
159
101
  }}
160
102
  >
161
- <Autocomplete
162
- clearOnBlur={bpUpMd}
103
+ <StyledAutocomplete
104
+ className={className}
163
105
  data-testid={TEST_IDS.SEARCH_ALL_FILTERS}
164
106
  filterOptions={(options): string[] => options}
165
107
  freeSolo
166
- ListboxComponent={Listbox}
167
- onBlur={bpUpMd ? onCloseSearch : undefined}
168
- onClose={bpUpMd ? onCloseSearch : undefined}
169
- onFocus={onOpenSearch}
108
+ onClose={onClose}
109
+ onInputChange={(_, v = "") => setSearchTerm(v)}
170
110
  onOpen={onOpen}
171
111
  open={open}
172
112
  options={[""]} // Placeholder options, since item rendering is fully controlled by VariableSizeList
173
- PopperComponent={AutocompletePopper}
174
113
  ref={autocompleteRef}
175
- renderInput={(props): JSX.Element =>
176
- renderInput({
177
- ...props,
178
- InputProps: {
179
- ...props.InputProps,
180
- endAdornment: <SearchCloseButton />,
181
- },
182
- inputProps: {
183
- ...props.inputProps,
184
- onChange,
185
- },
186
- })
114
+ renderInput={OutlinedInput}
115
+ slotProps={
116
+ surfaceType === SURFACE_TYPE.POPPER_MENU
117
+ ? POPPER_MENU_SLOT_PROPS
118
+ : POPPER_DRAWER_SLOT_PROPS
119
+ }
120
+ slots={
121
+ surfaceType === SURFACE_TYPE.POPPER_MENU
122
+ ? { listbox: Listbox, popper: StyledPopper }
123
+ : { listbox: Listbox, popper: StyledPopperDrawer }
187
124
  }
188
- slotProps={bpUpMd ? DEFAULT_SLOT_PROPS : DRAWER_SLOT_PROPS}
125
+ value={searchTerm}
126
+ {...props}
189
127
  />
190
- </ListboxContext.Provider>
128
+ </AutocompleteContext.Provider>
191
129
  );
192
130
  };
@@ -0,0 +1,15 @@
1
+ import { fn } from "@storybook/test";
2
+ import { ComponentProps } from "react";
3
+ import {
4
+ BIOLOGICAL_SEX,
5
+ DONOR_COUNT,
6
+ GENUS_SPECIES,
7
+ } from "../../Filters/stories/constants";
8
+ import { SURFACE_TYPE } from "../../surfaces/types";
9
+ import { SearchAllFilters } from "../searchAllFilters";
10
+
11
+ export const DEFAULT_ARGS: ComponentProps<typeof SearchAllFilters> = {
12
+ categoryViews: [BIOLOGICAL_SEX, GENUS_SPECIES, DONOR_COUNT],
13
+ onFilter: fn(),
14
+ surfaceType: SURFACE_TYPE.POPPER_MENU,
15
+ };
@@ -0,0 +1,29 @@
1
+ import { Box } from "@mui/material";
2
+ import { Meta, StoryObj } from "@storybook/react";
3
+ import React from "react";
4
+ import { PALETTE } from "../../../../../styles/common/constants/palette";
5
+ import { SearchAllFilters } from "../searchAllFilters";
6
+ import { DEFAULT_ARGS } from "./args";
7
+
8
+ const meta: Meta<typeof SearchAllFilters> = {
9
+ component: SearchAllFilters,
10
+ decorators: [
11
+ (Story): JSX.Element => (
12
+ <Box sx={{ backgroundColor: PALETTE.COMMON_WHITE, minWidth: 264 }}>
13
+ <Story />
14
+ </Box>
15
+ ),
16
+ ],
17
+ };
18
+
19
+ export default meta;
20
+
21
+ type Story = StoryObj<typeof meta>;
22
+
23
+ const DefaultStory = (): JSX.Element => {
24
+ return <SearchAllFilters {...DEFAULT_ARGS} />;
25
+ };
26
+
27
+ export const Default: Story = {
28
+ render: () => <DefaultStory />,
29
+ };
@@ -0,0 +1,16 @@
1
+ import { AutocompleteProps } from "@mui/material";
2
+ import { CategoryView } from "../../../../common/categories/views/types";
3
+ import { OnFilterFn } from "../../../../hooks/useCategoryFilter";
4
+ import { BaseComponentProps } from "../../../types";
5
+ import { SURFACE_TYPE } from "../surfaces/types";
6
+
7
+ export interface SearchAllFiltersProps
8
+ extends Omit<
9
+ AutocompleteProps<string, false, false, true>,
10
+ "options" | "renderInput"
11
+ >,
12
+ BaseComponentProps {
13
+ categoryViews: CategoryView[];
14
+ onFilter: OnFilterFn;
15
+ surfaceType?: SURFACE_TYPE;
16
+ }