@databiosphere/findable-ui 33.0.0 → 34.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 (180) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +11 -0
  3. package/jest.config.js +4 -0
  4. package/lib/common/entities.d.ts +3 -1
  5. package/lib/components/DataDictionary/components/Entities/entities.d.ts +1 -1
  6. package/lib/components/DataDictionary/components/Entities/entities.js +3 -2
  7. package/lib/components/DataDictionary/components/Entities/types.d.ts +3 -4
  8. package/lib/components/DataDictionary/components/Entity/entity.d.ts +1 -1
  9. package/lib/components/DataDictionary/components/Entity/entity.js +12 -6
  10. package/lib/components/DataDictionary/components/Entity/entity.styles.js +7 -1
  11. package/lib/components/DataDictionary/components/Entity/types.d.ts +4 -4
  12. package/lib/components/DataDictionary/components/Entity/utils.d.ts +9 -0
  13. package/lib/components/DataDictionary/components/Entity/utils.js +18 -0
  14. package/lib/components/DataDictionary/components/Filters/components/ColumnFilters/columnFilters.d.ts +4 -0
  15. package/lib/components/DataDictionary/components/Filters/components/ColumnFilters/columnFilters.js +9 -0
  16. package/lib/components/DataDictionary/components/Filters/components/ColumnFilters/types.d.ts +5 -0
  17. package/lib/components/DataDictionary/components/Filters/components/ColumnFilters/types.js +1 -0
  18. package/lib/components/DataDictionary/components/Filters/filters.d.ts +4 -0
  19. package/lib/components/DataDictionary/components/Filters/filters.js +7 -0
  20. package/lib/components/DataDictionary/components/Filters/filters.styles.d.ts +7 -0
  21. package/lib/components/DataDictionary/components/Filters/filters.styles.js +13 -0
  22. package/lib/components/DataDictionary/components/Filters/stories/constants.d.ts +4 -0
  23. package/lib/components/DataDictionary/components/Filters/stories/constants.js +25 -0
  24. package/lib/components/DataDictionary/components/Filters/stories/filters.stories.d.ts +6 -0
  25. package/lib/components/DataDictionary/components/Filters/stories/filters.stories.js +31 -0
  26. package/lib/components/DataDictionary/components/Filters/stories/hook.d.ts +5 -0
  27. package/lib/components/DataDictionary/components/Filters/stories/hook.js +5 -0
  28. package/lib/components/DataDictionary/components/Filters/stories/types.d.ts +4 -0
  29. package/lib/components/DataDictionary/components/Filters/stories/types.js +1 -0
  30. package/lib/components/DataDictionary/components/Filters/types.d.ts +5 -0
  31. package/lib/components/DataDictionary/components/Filters/types.js +1 -0
  32. package/lib/components/DataDictionary/components/Layout/components/EntitiesLayout/entitiesLayout.styles.js +3 -1
  33. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.d.ts +2 -0
  34. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.js +5 -0
  35. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.styles.d.ts +5 -0
  36. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.styles.js +24 -0
  37. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/types.d.ts +5 -0
  38. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/types.js +1 -0
  39. package/lib/components/DataDictionary/components/Layout/components/OutlineLayout/outlineLayout.styles.js +1 -1
  40. package/lib/components/DataDictionary/components/Layout/components/TitleLayout/titleLayout.styles.js +1 -0
  41. package/lib/components/DataDictionary/components/Layout/constants.d.ts +4 -0
  42. package/lib/components/DataDictionary/components/Layout/constants.js +4 -0
  43. package/lib/components/DataDictionary/components/Outline/utils.d.ts +5 -5
  44. package/lib/components/DataDictionary/components/Outline/utils.js +23 -6
  45. package/lib/components/DataDictionary/components/Table/hook.d.ts +3 -3
  46. package/lib/components/DataDictionary/components/Table/hook.js +11 -3
  47. package/lib/components/DataDictionary/components/Table/options/columnFilters/constants.d.ts +2 -0
  48. package/lib/components/DataDictionary/components/Table/options/columnFilters/constants.js +8 -0
  49. package/lib/components/DataDictionary/components/Table/options/columnFilters/hook.d.ts +6 -0
  50. package/lib/components/DataDictionary/components/Table/options/columnFilters/hook.js +14 -0
  51. package/lib/components/DataDictionary/components/Table/options/expanded/constants.d.ts +2 -0
  52. package/lib/components/DataDictionary/components/Table/options/expanded/constants.js +5 -0
  53. package/lib/components/DataDictionary/components/Table/options/faceted/constants.d.ts +2 -0
  54. package/lib/components/DataDictionary/components/Table/options/faceted/constants.js +6 -0
  55. package/lib/components/DataDictionary/components/Table/options/grouping/constants.d.ts +2 -0
  56. package/lib/components/DataDictionary/components/Table/options/grouping/constants.js +5 -0
  57. package/lib/components/DataDictionary/components/Table/options/hook.d.ts +1 -1
  58. package/lib/components/DataDictionary/components/Table/options/hook.js +17 -0
  59. package/lib/components/DataDictionary/components/Table/options/visibility/constants.d.ts +2 -0
  60. package/lib/components/DataDictionary/components/Table/options/visibility/constants.js +3 -0
  61. package/lib/components/DataDictionary/components/Table/table.d.ts +1 -1
  62. package/lib/components/DataDictionary/components/Table/table.js +2 -2
  63. package/lib/components/DataDictionary/components/Table/types.d.ts +4 -1
  64. package/lib/components/DataDictionary/components/Table/utils.d.ts +18 -0
  65. package/lib/components/DataDictionary/components/Table/utils.js +27 -0
  66. package/lib/components/DataDictionary/dataDictionary.d.ts +1 -1
  67. package/lib/components/DataDictionary/dataDictionary.js +8 -6
  68. package/lib/components/DataDictionary/hooks/UseDataDictionary/hook.js +16 -5
  69. package/lib/components/DataDictionary/hooks/UseDataDictionary/types.d.ts +5 -4
  70. package/lib/components/DataDictionary/types.d.ts +1 -0
  71. package/lib/components/Detail/components/Table/components/TableBody/tableBody.d.ts +8 -2
  72. package/lib/components/Detail/components/Table/components/TableBody/tableBody.js +2 -2
  73. package/lib/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.d.ts +8 -2
  74. package/lib/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.js +2 -2
  75. package/lib/components/Detail/components/Table/components/TableRows/tableRows.d.ts +8 -2
  76. package/lib/components/Detail/components/Table/components/TableRows/tableRows.js +2 -2
  77. package/lib/components/Filter/components/FilterLabel/filterLabel.styles.d.ts +1 -1
  78. package/lib/components/Filter/components/FilterList/filterList.styles.d.ts +2 -0
  79. package/lib/components/Filter/components/FilterList/filterList.styles.js +28 -15
  80. package/lib/components/Filter/components/SearchAllFiltersSearch/searchAllFiltersSearch.styles.d.ts +1 -1
  81. package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Authentication/components/Button/button.styles.d.ts +1 -1
  82. package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Search/components/Button/button.styles.d.ts +1 -1
  83. package/lib/components/Layout/components/Outline/components/ContentsTab/contentsTab.styles.d.ts +1 -1
  84. package/lib/components/Layout/components/Outline/outline.styles.d.ts +1 -1
  85. package/lib/components/Login/components/Button/button.styles.d.ts +1 -1
  86. package/lib/components/Table/common/utils.d.ts +6 -0
  87. package/lib/components/Table/common/utils.js +14 -0
  88. package/lib/components/Table/components/TableFeatures/ColumnFilter/columnFilter.d.ts +7 -0
  89. package/lib/components/Table/components/TableFeatures/ColumnFilter/columnFilter.js +33 -0
  90. package/lib/components/Table/components/TableFeatures/ColumnFilter/columnFilter.styles.d.ts +3 -0
  91. package/lib/components/Table/components/TableFeatures/ColumnFilter/columnFilter.styles.js +19 -0
  92. package/lib/components/Table/components/TableFeatures/ColumnFilter/constants.d.ts +2 -0
  93. package/lib/components/Table/components/TableFeatures/ColumnFilter/constants.js +14 -0
  94. package/lib/components/Table/components/TableFeatures/ColumnFilter/types.d.ts +7 -0
  95. package/lib/components/Table/components/TableFeatures/ColumnFilter/types.js +1 -0
  96. package/lib/components/Table/components/TableFeatures/ColumnFilter/utils.d.ts +6 -0
  97. package/lib/components/Table/components/TableFeatures/ColumnFilter/utils.js +23 -0
  98. package/lib/components/Table/featureOptions/facetedColumn/utils.d.ts +6 -0
  99. package/lib/components/Table/featureOptions/facetedColumn/utils.js +9 -0
  100. package/lib/components/common/ButtonGroup/constants.d.ts +2 -0
  101. package/lib/components/common/ButtonGroup/constants.js +11 -0
  102. package/lib/components/common/Tabs/tabs.styles.d.ts +1 -1
  103. package/lib/mocks/@storybook/addon-actions.d.ts +9 -0
  104. package/lib/mocks/@storybook/addon-actions.js +9 -0
  105. package/lib/styles/common/mui/buttonGroup.d.ts +13 -0
  106. package/lib/styles/common/mui/buttonGroup.js +34 -0
  107. package/lib/styles/common/mui/typography.js +2 -0
  108. package/lib/tests/mui/constants.d.ts +1 -0
  109. package/lib/tests/mui/constants.js +1 -0
  110. package/lib/tests/utils.d.ts +6 -0
  111. package/lib/tests/utils.js +8 -0
  112. package/lib/theme/common/components.d.ts +0 -6
  113. package/lib/theme/common/components.js +17 -31
  114. package/lib/theme/components/index.d.ts +1 -0
  115. package/lib/theme/components/index.js +1 -0
  116. package/lib/theme/components/muiButtonGroup.d.ts +2 -0
  117. package/lib/theme/components/muiButtonGroup.js +76 -0
  118. package/lib/theme/theme.js +1 -1
  119. package/package.json +1 -1
  120. package/src/common/entities.ts +3 -1
  121. package/src/components/DataDictionary/components/Entities/entities.tsx +5 -9
  122. package/src/components/DataDictionary/components/Entities/types.ts +3 -4
  123. package/src/components/DataDictionary/components/Entity/entity.styles.ts +9 -1
  124. package/src/components/DataDictionary/components/Entity/entity.tsx +18 -8
  125. package/src/components/DataDictionary/components/Entity/types.ts +4 -4
  126. package/src/components/DataDictionary/components/Entity/utils.ts +25 -0
  127. package/src/components/DataDictionary/components/Filters/components/ColumnFilters/columnFilters.tsx +21 -0
  128. package/src/components/DataDictionary/components/Filters/components/ColumnFilters/types.ts +6 -0
  129. package/src/components/DataDictionary/components/Filters/filters.styles.ts +14 -0
  130. package/src/components/DataDictionary/components/Filters/filters.tsx +16 -0
  131. package/src/components/DataDictionary/components/Filters/stories/constants.ts +31 -0
  132. package/src/components/DataDictionary/components/Filters/stories/filters.stories.tsx +42 -0
  133. package/src/components/DataDictionary/components/Filters/stories/hook.ts +9 -0
  134. package/src/components/DataDictionary/components/Filters/stories/types.ts +3 -0
  135. package/src/components/DataDictionary/components/Filters/types.ts +6 -0
  136. package/src/components/DataDictionary/components/Layout/components/EntitiesLayout/entitiesLayout.styles.ts +4 -1
  137. package/src/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.styles.ts +27 -0
  138. package/src/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.tsx +10 -0
  139. package/src/components/DataDictionary/components/Layout/components/FiltersLayout/types.ts +6 -0
  140. package/src/components/DataDictionary/components/Layout/components/OutlineLayout/outlineLayout.styles.ts +1 -1
  141. package/src/components/DataDictionary/components/Layout/components/TitleLayout/titleLayout.styles.ts +1 -0
  142. package/src/components/DataDictionary/components/Layout/constants.ts +4 -0
  143. package/src/components/DataDictionary/components/Outline/utils.ts +35 -13
  144. package/src/components/DataDictionary/components/Table/hook.ts +17 -5
  145. package/src/components/DataDictionary/components/Table/options/columnFilters/constants.ts +16 -0
  146. package/src/components/DataDictionary/components/Table/options/columnFilters/hook.ts +32 -0
  147. package/src/components/DataDictionary/components/Table/options/expanded/constants.ts +13 -0
  148. package/src/components/DataDictionary/components/Table/options/faceted/constants.ts +14 -0
  149. package/src/components/DataDictionary/components/Table/options/grouping/constants.ts +9 -0
  150. package/src/components/DataDictionary/components/Table/options/hook.ts +26 -3
  151. package/src/components/DataDictionary/components/Table/options/visibility/constants.ts +5 -0
  152. package/src/components/DataDictionary/components/Table/table.tsx +2 -0
  153. package/src/components/DataDictionary/components/Table/types.ts +8 -1
  154. package/src/components/DataDictionary/components/Table/utils.ts +40 -0
  155. package/src/components/DataDictionary/dataDictionary.tsx +9 -5
  156. package/src/components/DataDictionary/hooks/UseDataDictionary/hook.ts +19 -5
  157. package/src/components/DataDictionary/hooks/UseDataDictionary/types.ts +5 -4
  158. package/src/components/DataDictionary/types.ts +1 -0
  159. package/src/components/Detail/components/Table/components/TableBody/tableBody.tsx +14 -3
  160. package/src/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx +9 -2
  161. package/src/components/Detail/components/Table/components/TableRows/tableRows.tsx +9 -2
  162. package/src/components/Filter/components/FilterList/filterList.styles.ts +34 -15
  163. package/src/components/Table/common/utils.ts +16 -0
  164. package/src/components/Table/components/TableFeatures/ColumnFilter/columnFilter.styles.ts +23 -0
  165. package/src/components/Table/components/TableFeatures/ColumnFilter/columnFilter.tsx +98 -0
  166. package/src/components/Table/components/TableFeatures/ColumnFilter/constants.ts +16 -0
  167. package/src/components/Table/components/TableFeatures/ColumnFilter/types.ts +10 -0
  168. package/src/components/Table/components/TableFeatures/ColumnFilter/utils.ts +27 -0
  169. package/src/components/Table/featureOptions/facetedColumn/utils.ts +14 -0
  170. package/src/components/common/ButtonGroup/constants.ts +13 -0
  171. package/src/mocks/@storybook/addon-actions.ts +10 -0
  172. package/src/styles/common/mui/buttonGroup.ts +46 -0
  173. package/src/styles/common/mui/typography.ts +2 -0
  174. package/src/tests/mui/constants.ts +1 -0
  175. package/src/tests/utils.ts +9 -0
  176. package/src/theme/common/components.ts +17 -32
  177. package/src/theme/components/index.ts +1 -0
  178. package/src/theme/components/muiButtonGroup.ts +79 -0
  179. package/src/theme/theme.ts +1 -1
  180. package/tests/dataDictionaryColumnFilters.test.tsx +101 -0
@@ -1,5 +1,5 @@
1
1
  import { TableBody as MTableBody } from "@mui/material";
2
- import { RowData, Table } from "@tanstack/react-table";
2
+ import { Row, RowData, Table } from "@tanstack/react-table";
3
3
  import React from "react";
4
4
  import { ROW_DIRECTION } from "../../../../../Table/common/entities";
5
5
  import { TableView } from "../../table";
@@ -8,21 +8,32 @@ import { TableRows } from "../TableRows/tableRows";
8
8
 
9
9
  export interface TableBodyProps<T extends RowData> {
10
10
  rowDirection: ROW_DIRECTION;
11
+ /**
12
+ * Optional override for the rows rendered by <TableBody>.
13
+ * - Omit to show the table’s full leaf-level row model.
14
+ * - Pass `group.subRows` (or any other subset) to display a “mini-table” for a single group e.g. the rows that belong to one Data-Dictionary entity.
15
+ */
16
+ rows?: Row<T>[];
11
17
  tableInstance: Table<T>;
12
18
  tableView?: TableView;
13
19
  }
14
20
 
15
21
  export const TableBody = <T extends RowData>({
16
22
  rowDirection,
23
+ rows,
17
24
  tableInstance,
18
25
  tableView,
19
26
  }: TableBodyProps<T>): JSX.Element => {
20
27
  return (
21
28
  <MTableBody>
22
29
  {rowDirection === ROW_DIRECTION.DEFAULT ? (
23
- <TableRows tableInstance={tableInstance} tableView={tableView} />
30
+ <TableRows
31
+ rows={rows}
32
+ tableInstance={tableInstance}
33
+ tableView={tableView}
34
+ />
24
35
  ) : (
25
- <CollapsableRows tableInstance={tableInstance} />
36
+ <CollapsableRows rows={rows} tableInstance={tableInstance} />
26
37
  )}
27
38
  </MTableBody>
28
39
  );
@@ -1,4 +1,4 @@
1
- import { RowData, Table } from "@tanstack/react-table";
1
+ import { Row, RowData, Table } from "@tanstack/react-table";
2
2
  import React, { Fragment } from "react";
3
3
  import { isCollapsableRowDisabled } from "../../../../../../../Table/common/utils";
4
4
  import { CollapsableCell } from "../../../../../../../Table/components/TableCell/components/CollapsableCell/collapsableCell";
@@ -6,10 +6,17 @@ import { TableRow } from "../../../../../../../Table/components/TableRow/tableRo
6
6
  import { useCollapsableRows } from "../../../../../../../Table/components/TableRows/components/CollapsableRows/hook";
7
7
 
8
8
  export interface CollapsableRowsProps<T extends RowData> {
9
+ /**
10
+ * Optional override for the rows rendered by <CollapsableRows>.
11
+ * - Omit to show the table’s full leaf-level row model.
12
+ * - Pass `group.subRows` (or any other subset) to display a “mini-table” for a single group e.g. the rows that belong to one Data-Dictionary entity.
13
+ */
14
+ rows?: Row<T>[];
9
15
  tableInstance: Table<T>;
10
16
  }
11
17
 
12
18
  export const CollapsableRows = <T extends RowData>({
19
+ rows: leafOrSubRows,
13
20
  tableInstance,
14
21
  }: CollapsableRowsProps<T>): JSX.Element => {
15
22
  const { getRowModel } = tableInstance;
@@ -17,7 +24,7 @@ export const CollapsableRows = <T extends RowData>({
17
24
  useCollapsableRows(tableInstance);
18
25
  return (
19
26
  <Fragment>
20
- {rows.map((row) => {
27
+ {(leafOrSubRows || rows).map((row) => {
21
28
  if (row.depth > 0) return null; // Hide sub rows.
22
29
  return (
23
30
  <TableRow key={row.id} isPreview={row.getIsPreview()}>
@@ -1,5 +1,5 @@
1
1
  import { TableCell } from "@mui/material";
2
- import { flexRender, RowData, Table } from "@tanstack/react-table";
2
+ import { flexRender, Row, RowData, Table } from "@tanstack/react-table";
3
3
  import React, { Fragment } from "react";
4
4
  import {
5
5
  getTableCellAlign,
@@ -9,11 +9,18 @@ import { TableRow } from "../../../../../Table/components/TableRow/tableRow.styl
9
9
  import { TableView } from "../../table";
10
10
 
11
11
  export interface TableRowsProps<T extends RowData> {
12
+ /**
13
+ * Optional override for the rows rendered by <TableRows>.
14
+ * - Omit to show the table’s full leaf-level row model.
15
+ * - Pass `group.subRows` (or any other subset) to display a “mini-table” for a single group e.g. the rows that belong to one Data-Dictionary entity.
16
+ */
17
+ rows?: Row<T>[];
12
18
  tableInstance: Table<T>;
13
19
  tableView?: TableView;
14
20
  }
15
21
 
16
22
  export const TableRows = <T extends RowData>({
23
+ rows: leafOrSubRows,
17
24
  tableInstance,
18
25
  tableView,
19
26
  }: TableRowsProps<T>): JSX.Element => {
@@ -23,7 +30,7 @@ export const TableRows = <T extends RowData>({
23
30
  const { size: tableCellSize = "medium" } = tableCell || {};
24
31
  return (
25
32
  <Fragment>
26
- {rows.map((row) => {
33
+ {(leafOrSubRows || rows).map((row) => {
27
34
  return (
28
35
  <TableRow
29
36
  key={row.id}
@@ -1,7 +1,38 @@
1
+ import { css } from "@emotion/react";
1
2
  import styled from "@emotion/styled";
2
- import { List as MList } from "@mui/material";
3
+ import {
4
+ listItemButtonClasses,
5
+ listItemTextClasses,
6
+ List as MList,
7
+ } from "@mui/material";
8
+ import { PALETTE } from "../../../../styles/common/constants/palette";
3
9
  import { LIST_MARGIN } from "../../common/constants";
4
10
 
11
+ export const MuiListItemButtonRoot = css`
12
+ .${listItemButtonClasses.root} {
13
+ gap: 8px;
14
+ padding: 10px 16px;
15
+
16
+ &.Mui-disabled {
17
+ color: ${PALETTE.SMOKE_MAIN};
18
+ opacity: 1;
19
+ }
20
+ }
21
+ `;
22
+
23
+ export const MuiListItemTextRoot = css`
24
+ .${listItemTextClasses.root} {
25
+ align-items: center;
26
+ display: grid;
27
+ gap: 8px;
28
+ grid-template-columns: 1fr auto;
29
+
30
+ > span {
31
+ min-width: 0; /* required; flexbox child min-width property is "auto" by default making overflow-wrap ineffectual */
32
+ }
33
+ }
34
+ `;
35
+
5
36
  export const List = styled(MList)`
6
37
  && {
7
38
  overflow-wrap: break-word;
@@ -20,20 +51,8 @@ export const List = styled(MList)`
20
51
  }
21
52
 
22
53
  // List item
23
- .MuiListItemButton-root {
24
- gap: 8px;
25
- padding: 10px 16px;
26
- }
54
+ ${MuiListItemButtonRoot}
27
55
 
28
56
  // List item text
29
- .MuiListItemText-root {
30
- align-items: center;
31
- display: grid;
32
- gap: 8px;
33
- grid-template-columns: 1fr auto;
34
-
35
- > span {
36
- min-width: 0; /* required; flexbox child min-width property is "auto" by default making overflow-wrap ineffectual */
37
- }
38
- }
57
+ ${MuiListItemTextRoot}
39
58
  `;
@@ -84,6 +84,22 @@ export function buildCategoryViews<T extends RowData>(
84
84
  return categoryViews;
85
85
  }
86
86
 
87
+ /**
88
+ * Returns the header for a column as a string.
89
+ * @param column - Column.
90
+ * @returns column header.
91
+ */
92
+ export function getColumnHeader<T extends RowData>(column: Column<T>): string {
93
+ const { columnDef, id = "" } = column;
94
+ const { header, meta } = columnDef;
95
+
96
+ // Return header if it is a string.
97
+ if (typeof header === "string") return header;
98
+
99
+ // Return header from meta or id.
100
+ return meta?.header || id;
101
+ }
102
+
87
103
  /**
88
104
  * Format data to TSV string.
89
105
  * @param data - Table data.
@@ -0,0 +1,23 @@
1
+ import styled from "@emotion/styled";
2
+ import { Menu, menuClasses, paperClasses } from "@mui/material";
3
+ import { MAX_LIST_HEIGHT_PX } from "../../../../Filter/common/constants";
4
+ import {
5
+ MuiListItemButtonRoot,
6
+ MuiListItemTextRoot,
7
+ } from "../../../../Filter/components/FilterList/filterList.styles";
8
+
9
+ export const StyledMenu = styled(Menu)`
10
+ .${paperClasses.root} {
11
+ margin: 4px 0;
12
+ width: 288px;
13
+
14
+ .${menuClasses.list} {
15
+ max-height: ${MAX_LIST_HEIGHT_PX}px;
16
+ overflow-wrap: break-word;
17
+
18
+ ${MuiListItemButtonRoot}
19
+
20
+ ${MuiListItemTextRoot}
21
+ }
22
+ }
23
+ `;
@@ -0,0 +1,98 @@
1
+ import {
2
+ Checkbox,
3
+ ListItemButton,
4
+ ListItemText,
5
+ Button as MButton,
6
+ Typography,
7
+ } from "@mui/material";
8
+ import { RowData } from "@tanstack/react-table";
9
+ import React, { Fragment } from "react";
10
+ import { SVG_ICON_PROPS } from "../../../../../styles/common/mui/svgIcon";
11
+ import { TYPOGRAPHY_PROPS } from "../../../../../styles/common/mui/typography";
12
+ import { CheckedIcon } from "../../../../common/CustomIcon/components/CheckedIcon/checkedIcon";
13
+ import { UncheckedIcon } from "../../../../common/CustomIcon/components/UncheckedIcon/uncheckedIcon";
14
+ import { DropDownIcon } from "../../../../common/Form/components/Select/components/DropDownIcon/dropDownIcon";
15
+ import { useMenu } from "../../../../common/Menu/hooks/useMenu";
16
+ import { getColumnHeader } from "../../../common/utils";
17
+ import { getSortedFacetedValues } from "../../../featureOptions/facetedColumn/utils";
18
+ import { StyledMenu } from "./columnFilter.styles";
19
+ import { MENU_PROPS } from "./constants";
20
+ import { ColumnFilterProps } from "./types";
21
+ import { updater } from "./utils";
22
+
23
+ /**
24
+ * Column filter component with supported filter functions:
25
+ * - `arrIncludesSome`
26
+ */
27
+
28
+ export const ColumnFilter = <T extends RowData>({
29
+ Button = MButton,
30
+ className,
31
+ column,
32
+ ...props /* MuiMenuProps */
33
+ }: ColumnFilterProps<T>): JSX.Element => {
34
+ const { anchorEl, onClose, onOpen, open } = useMenu();
35
+ const facetedUniqueValues = column.getFacetedUniqueValues();
36
+ const sortedValues = getSortedFacetedValues(facetedUniqueValues);
37
+ const filterValue = (column.getFilterValue() || []) as unknown[];
38
+ return (
39
+ <Fragment>
40
+ <Button
41
+ key={column.id}
42
+ endIcon={<DropDownIcon color={SVG_ICON_PROPS.COLOR.INK_LIGHT} />}
43
+ onClick={onOpen}
44
+ >
45
+ {getColumnHeader(column)}
46
+ </Button>
47
+ <StyledMenu
48
+ {...MENU_PROPS}
49
+ {...props}
50
+ className={className}
51
+ anchorEl={anchorEl}
52
+ onClose={onClose}
53
+ open={open}
54
+ >
55
+ {sortedValues.map(([value, occurrence]) => (
56
+ <ListItemButton
57
+ key={String(value)}
58
+ selected={filterValue.includes(value)}
59
+ onClick={() => column.setFilterValue(updater(value))}
60
+ >
61
+ <Checkbox
62
+ checked={filterValue.includes(value)}
63
+ checkedIcon={<CheckedIcon />}
64
+ icon={<UncheckedIcon />}
65
+ />
66
+ <ListItemText
67
+ disableTypography
68
+ primary={<span>{String(value)}</span>}
69
+ secondary={
70
+ <Typography
71
+ color={TYPOGRAPHY_PROPS.COLOR.INK_LIGHT}
72
+ variant={TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_SMALL_400}
73
+ >
74
+ {occurrence}
75
+ </Typography>
76
+ }
77
+ />
78
+ </ListItemButton>
79
+ ))}
80
+ <ListItemButton
81
+ disabled={!column.getIsFiltered()}
82
+ onClick={() => column.setFilterValue(undefined)}
83
+ >
84
+ <Typography
85
+ color={
86
+ column.getIsFiltered()
87
+ ? TYPOGRAPHY_PROPS.COLOR.PRIMARY
88
+ : TYPOGRAPHY_PROPS.COLOR.INHERIT
89
+ }
90
+ variant={TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_500}
91
+ >
92
+ Clear All
93
+ </Typography>
94
+ </ListItemButton>
95
+ </StyledMenu>
96
+ </Fragment>
97
+ );
98
+ };
@@ -0,0 +1,16 @@
1
+ import { MenuProps } from "@mui/material";
2
+
3
+ export const MENU_PROPS: Omit<MenuProps, "anchorEl" | "onClose" | "open"> = {
4
+ anchorOrigin: {
5
+ horizontal: "right",
6
+ vertical: "bottom",
7
+ },
8
+ marginThreshold: 8,
9
+ slotProps: {
10
+ paper: { variant: "menu" },
11
+ },
12
+ transformOrigin: {
13
+ horizontal: "right",
14
+ vertical: "top",
15
+ },
16
+ };
@@ -0,0 +1,10 @@
1
+ import { Button, MenuProps } from "@mui/material";
2
+ import { Column, RowData } from "@tanstack/react-table";
3
+ import { BaseComponentProps } from "../../../../types";
4
+
5
+ export interface ColumnFilterProps<T extends RowData>
6
+ extends BaseComponentProps,
7
+ Omit<MenuProps, "anchorEl" | "onClose" | "open"> {
8
+ Button?: typeof Button;
9
+ column: Column<T>;
10
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Returns an updater function for column filter.
3
+ * @param value - Value.
4
+ * @returns An updater function that returns the new filter value.
5
+ */
6
+ export function updater(
7
+ value: unknown
8
+ ): (old: unknown[] | undefined) => unknown[] | undefined {
9
+ return (old: unknown[] | undefined) => {
10
+ // If no old value, return new value.
11
+ if (!old) return [value];
12
+
13
+ // If value already exists, remove it.
14
+ if (old.includes(value)) {
15
+ // Filter out the value.
16
+ const next = old.filter((v) => v !== value);
17
+
18
+ // If no values remain, return undefined.
19
+ if (next.length === 0) return undefined;
20
+
21
+ return next;
22
+ }
23
+
24
+ // Otherwise, add the value.
25
+ return [...old, value];
26
+ };
27
+ }
@@ -0,0 +1,14 @@
1
+ import { COLLATOR_CASE_INSENSITIVE } from "../../../../common/constants";
2
+
3
+ /**
4
+ * Sorts Map entries by key.
5
+ * @param facetedValues - Map of faceted values.
6
+ * @returns Sorted array of [key, value] entries.
7
+ */
8
+ export function getSortedFacetedValues(
9
+ facetedValues: Map<unknown, number>
10
+ ): [unknown, number][] {
11
+ return [...facetedValues].sort((a, b) =>
12
+ COLLATOR_CASE_INSENSITIVE.compare(String(a), String(b))
13
+ );
14
+ }
@@ -0,0 +1,13 @@
1
+ import { ButtonGroupProps } from "@mui/material";
2
+ import { BUTTON_GROUP_PROPS as MUI_BUTTON_GROUP_PROPS } from "../../../styles/common/mui/buttonGroup";
3
+
4
+ export const BUTTON_GROUP_PROPS: Record<string, Partial<ButtonGroupProps>> = {
5
+ PRIMARY_CONTAINED: {
6
+ color: MUI_BUTTON_GROUP_PROPS.COLOR.PRIMARY,
7
+ variant: MUI_BUTTON_GROUP_PROPS.VARIANT.CONTAINED,
8
+ },
9
+ SECONDARY_OUTLINED: {
10
+ color: MUI_BUTTON_GROUP_PROPS.COLOR.SECONDARY,
11
+ variant: MUI_BUTTON_GROUP_PROPS.VARIANT.OUTLINED,
12
+ },
13
+ };
@@ -0,0 +1,10 @@
1
+ import { jest } from "@jest/globals";
2
+
3
+ /**
4
+ * Mock for Storybook's @storybook/addon-actions function.
5
+ * The mock keeps the same function signature as the real Storybook action,
6
+ * does not trigger any Storybook logic, and simply returns a Jest mock function
7
+ * for use in tests.
8
+ * @returns A Jest mock function.
9
+ */
10
+ export const action = (): jest.Mock => jest.fn();
@@ -0,0 +1,46 @@
1
+ import { buttonGroupClasses, ButtonGroupProps } from "@mui/material";
2
+
3
+ type ButtonGroupPropsOptions = {
4
+ CLASSES: typeof CLASSES;
5
+ COLOR: typeof COLOR;
6
+ SIZE: typeof SIZE;
7
+ VARIANT: typeof VARIANT;
8
+ };
9
+
10
+ const CLASSES: Record<string, ButtonGroupProps["classes"]> = {
11
+ COLOR_PRIMARY: buttonGroupClasses.colorPrimary,
12
+ COLOR_SECONDARY: buttonGroupClasses.colorSecondary,
13
+ CONTAINED: buttonGroupClasses.contained,
14
+ GROUPED: buttonGroupClasses.grouped,
15
+ OUTLINED: buttonGroupClasses.outlined,
16
+ ROOT: buttonGroupClasses.root,
17
+ };
18
+
19
+ const COLOR: Record<string, ButtonGroupProps["color"]> = {
20
+ ERROR: "error",
21
+ INFO: "info",
22
+ INHERIT: "inherit",
23
+ PRIMARY: "primary",
24
+ SECONDARY: "secondary",
25
+ SUCCESS: "success",
26
+ WARNING: "warning",
27
+ };
28
+
29
+ const SIZE: Record<string, ButtonGroupProps["size"]> = {
30
+ LARGE: "large",
31
+ MEDIUM: "medium",
32
+ SMALL: "small",
33
+ };
34
+
35
+ const VARIANT: Record<string, ButtonGroupProps["variant"]> = {
36
+ CONTAINED: "contained",
37
+ OUTLINED: "outlined",
38
+ TEXT: "text",
39
+ };
40
+
41
+ export const BUTTON_GROUP_PROPS: ButtonGroupPropsOptions = {
42
+ CLASSES,
43
+ COLOR,
44
+ SIZE,
45
+ VARIANT,
46
+ };
@@ -10,12 +10,14 @@ const COLOR: Record<string, TypographyOwnProps["color"]> = {
10
10
  INHERIT: "inherit",
11
11
  INK_LIGHT: "ink.light",
12
12
  INK_MAIN: "ink.main",
13
+ PRIMARY: "primary",
13
14
  };
14
15
 
15
16
  const VARIANT: Record<string, TypographyOwnProps["variant"]> = {
16
17
  INHERIT: "inherit",
17
18
  TEXT_BODY_400: "text-body-400",
18
19
  TEXT_BODY_400_2_LINES: "text-body-400-2lines",
20
+ TEXT_BODY_500: "text-body-500",
19
21
  TEXT_BODY_SMALL_400: "text-body-small-400",
20
22
  TEXT_HEADING_LARGE: "text-heading-large",
21
23
  TEXT_HEADING_SMALL: "text-heading-small",
@@ -1,5 +1,6 @@
1
1
  export const MUI_CLASSES = {
2
2
  ACTIVE: "Mui-active",
3
3
  COMPLETED: "Mui-completed",
4
+ DISABLED: "Mui-disabled",
4
5
  SELECTED: "Mui-selected",
5
6
  };
@@ -32,6 +32,15 @@ export function getStartsWithRegex(text: string): RegExp {
32
32
  return new RegExp(`^${escapeRegExp(text)}`);
33
33
  }
34
34
 
35
+ /**
36
+ * Retrieves an element by its role.
37
+ * @param role - The role of the element.
38
+ * @returns The element.
39
+ */
40
+ export function getRole<T extends HTMLElement = HTMLElement>(role: string): T {
41
+ return screen.getByRole(role);
42
+ }
43
+
35
44
  /**
36
45
  * Retrieves an element by its text content.
37
46
  * @param text - The text content of the element.
@@ -3,6 +3,7 @@ import { DropDownIcon } from "../../components/common/Form/components/Select/com
3
3
  import { COLOR_MIXES } from "../../styles/common/constants/colorMixes";
4
4
  import { PALETTE } from "../../styles/common/constants/palette";
5
5
  import { SHADOWS } from "../../styles/common/constants/shadows";
6
+ import { BUTTON_PROPS } from "../../styles/common/mui/button";
6
7
  import { CHIP_PROPS } from "../../styles/common/mui/chip";
7
8
  import { desktopUp, mobileUp, tabletUp } from "./breakpoints";
8
9
  import {
@@ -200,6 +201,22 @@ export const MuiButton = (theme: Theme): Components["MuiButton"] => {
200
201
  },
201
202
  endIcon: {
202
203
  margin: 0,
204
+ variants: [
205
+ {
206
+ props: { size: BUTTON_PROPS.SIZE.MEDIUM },
207
+ style: {
208
+ marginLeft: -6,
209
+ marginRight: -6,
210
+ },
211
+ },
212
+ {
213
+ props: { size: BUTTON_PROPS.SIZE.SMALL },
214
+ style: {
215
+ marginLeft: -6,
216
+ marginRight: -6,
217
+ },
218
+ },
219
+ ],
203
220
  },
204
221
  outlinedSecondary: {
205
222
  backgroundColor: "transparent",
@@ -317,38 +334,6 @@ export const MuiButtonBase = (theme: Theme): Components["MuiButtonBase"] => {
317
334
  };
318
335
  };
319
336
 
320
- /**
321
- * MuiButtonGroup Component
322
- * @param theme - Theme.
323
- * @returns MuiButtonGroup component theme styles.
324
- */
325
- export const MuiButtonGroup = (theme: Theme): Components["MuiButtonGroup"] => {
326
- return {
327
- defaultProps: {
328
- disableElevation: true,
329
- disableRipple: true,
330
- },
331
- styleOverrides: {
332
- grouped: {
333
- minWidth: 0,
334
- padding: "6px 8px",
335
- },
336
- groupedContainedPrimary: {
337
- borderColor: theme.palette.primary.dark,
338
- boxShadow: `0 1px 0 0 ${theme.palette.primary.dark}`,
339
- // eslint-disable-next-line sort-keys -- disabling key order for readability
340
- "&:hover": {
341
- boxShadow: `0 1px 0 0 ${theme.palette.primary.dark}`,
342
- },
343
- // eslint-disable-next-line sort-keys -- disabling key order for readability
344
- "&:active": {
345
- boxShadow: "none",
346
- },
347
- },
348
- },
349
- };
350
- };
351
-
352
337
  /**
353
338
  * MuiCard Component
354
339
  */
@@ -1,3 +1,4 @@
1
1
  export { MuiAlert } from "./muiAlert";
2
2
  export { MuiAlertTitle } from "./muiAlertTitle";
3
+ export { MuiButtonGroup } from "./muiButtonGroup";
3
4
  export { MuiTableCell } from "./muiTableCell";
@@ -0,0 +1,79 @@
1
+ import { Components } from "@mui/material";
2
+ import { COLOR_MIXES } from "../../styles/common/constants/colorMixes";
3
+ import { PALETTE } from "../../styles/common/constants/palette";
4
+ import { BUTTON_GROUP_PROPS } from "../../styles/common/mui/buttonGroup";
5
+
6
+ const SELECTORS = {
7
+ GROUPED: `.${BUTTON_GROUP_PROPS.CLASSES.GROUPED}`,
8
+ };
9
+
10
+ export const MuiButtonGroup: Components["MuiButtonGroup"] = {
11
+ defaultProps: {
12
+ disableElevation: true,
13
+ disableRipple: true,
14
+ },
15
+ styleOverrides: {
16
+ root: {
17
+ variants: [
18
+ /* PRIMARY CONTAINED */
19
+ {
20
+ props: {
21
+ color: BUTTON_GROUP_PROPS.COLOR.PRIMARY,
22
+ variant: BUTTON_GROUP_PROPS.VARIANT.CONTAINED,
23
+ },
24
+ style: {
25
+ [SELECTORS.GROUPED]: {
26
+ borderColor: PALETTE.PRIMARY_DARK,
27
+ boxShadow: `0 1px 0 0 ${PALETTE.PRIMARY_DARK}`,
28
+ minWidth: 0,
29
+ // eslint-disable-next-line sort-keys -- disabling key order for readability
30
+ "&:hover": {
31
+ boxShadow: `0 1px 0 0 ${PALETTE.PRIMARY_DARK}`,
32
+ },
33
+ // eslint-disable-next-line sort-keys -- disabling key order for readability
34
+ "&:active": {
35
+ boxShadow: "none",
36
+ },
37
+ },
38
+ },
39
+ },
40
+ /* SECONDARY OUTLINED */
41
+ {
42
+ props: {
43
+ color: BUTTON_GROUP_PROPS.COLOR.SECONDARY,
44
+ variant: BUTTON_GROUP_PROPS.VARIANT.OUTLINED,
45
+ },
46
+ style: {
47
+ [SELECTORS.GROUPED]: {
48
+ backgroundColor: PALETTE.COMMON_WHITE,
49
+ boxShadow: `inset 0 0 0 1px ${PALETTE.SMOKE_DARK}, 0 1px 0 0 ${COLOR_MIXES.COMMON_BLACK_08}`,
50
+ color: PALETTE.INK_MAIN,
51
+ minWidth: 0,
52
+ // eslint-disable-next-line sort-keys -- disabling key order for readability
53
+ "&:hover": {
54
+ backgroundColor: PALETTE.SMOKE_LIGHTEST,
55
+ boxShadow: `inset 0 0 0 1px ${PALETTE.SMOKE_DARK}, 0 1px 0 0 ${COLOR_MIXES.COMMON_BLACK_08}`,
56
+ },
57
+ // eslint-disable-next-line sort-keys -- disabling key order for readability
58
+ "&:active": {
59
+ backgroundColor: PALETTE.SMOKE_LIGHTEST,
60
+ boxShadow: `inset 0 0 0 1px ${PALETTE.SMOKE_DARK}`,
61
+ },
62
+ },
63
+ },
64
+ },
65
+ /* SMALL */
66
+ {
67
+ props: {
68
+ size: BUTTON_GROUP_PROPS.SIZE.SMALL,
69
+ },
70
+ style: {
71
+ [SELECTORS.GROUPED]: {
72
+ padding: "6px 8px",
73
+ },
74
+ },
75
+ },
76
+ ],
77
+ },
78
+ },
79
+ };
@@ -80,7 +80,7 @@ export function createAppTheme(customOptions: ThemeOptions = {}): Theme {
80
80
  MuiBreadcrumbs: C.MuiBreadcrumbs(theme),
81
81
  MuiButton: C.MuiButton(theme),
82
82
  MuiButtonBase: C.MuiButtonBase(theme),
83
- MuiButtonGroup: C.MuiButtonGroup(theme),
83
+ MuiButtonGroup: M.MuiButtonGroup,
84
84
  MuiCard: C.MuiCard,
85
85
  MuiCheckbox: C.MuiCheckbox(theme),
86
86
  MuiChip: C.MuiChip(theme),