@databiosphere/findable-ui 17.0.0 → 19.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 (201) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +22 -0
  3. package/lib/apis/azul/common/filterTransformer.js +1 -1
  4. package/lib/apis/azul/common/utils.d.ts +1 -1
  5. package/lib/apis/azul/common/utils.js +5 -1
  6. package/lib/common/entities.d.ts +3 -3
  7. package/lib/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.js +2 -0
  8. package/lib/components/Detail/components/Table/components/TableRows/tableRows.js +1 -15
  9. package/lib/components/Export/components/ExportForm/components/ExportFileSummaryForm/exportFileSummaryForm.js +9 -10
  10. package/lib/components/Filter/common/utils.js +1 -1
  11. package/lib/components/Filter/components/VariableSizeList/VariableSizeList.d.ts +1 -1
  12. package/lib/components/Filter/components/VariableSizeListItem/variableSizeListItem.d.ts +1 -1
  13. package/lib/components/Links/components/Link/components/ExploreViewLink/exploreViewLink.js +23 -12
  14. package/lib/components/Table/common/columnDef.js +1 -0
  15. package/lib/components/Table/common/gridTable.styles.js +5 -11
  16. package/lib/components/Table/common/utils.d.ts +3 -29
  17. package/lib/components/Table/common/utils.js +26 -61
  18. package/lib/components/Table/components/TableBody/hooks/virtualizer/constants.d.ts +3 -0
  19. package/lib/components/Table/components/TableBody/hooks/virtualizer/constants.js +3 -0
  20. package/lib/components/Table/components/TableBody/hooks/virtualizer/hook.d.ts +8 -0
  21. package/lib/components/Table/components/TableBody/hooks/virtualizer/hook.js +18 -0
  22. package/lib/components/Table/components/TableBody/hooks/virtualizer/types.d.ts +4 -0
  23. package/lib/components/Table/components/TableBody/tableBody.d.ts +3 -2
  24. package/lib/components/Table/components/TableBody/tableBody.js +7 -28
  25. package/lib/components/Table/components/TableBody/utils.d.ts +12 -0
  26. package/lib/components/Table/components/TableBody/utils.js +17 -0
  27. package/lib/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.d.ts +3 -1
  28. package/lib/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.js +6 -14
  29. package/lib/components/Table/components/TableFeatures/ColumnGrouping/utils.d.ts +28 -0
  30. package/lib/components/Table/components/TableFeatures/ColumnGrouping/utils.js +52 -0
  31. package/lib/components/Table/components/TableFeatures/ColumnVisibility/utils.d.ts +21 -0
  32. package/lib/components/Table/components/TableFeatures/ColumnVisibility/utils.js +37 -0
  33. package/lib/components/Table/components/TableFeatures/RowSorting/utils.d.ts +29 -0
  34. package/lib/components/Table/components/TableFeatures/RowSorting/utils.js +68 -0
  35. package/lib/components/Table/components/TableHead/tableHead.d.ts +2 -6
  36. package/lib/components/Table/components/TableHead/tableHead.js +6 -4
  37. package/lib/components/Table/components/TableHead/types.d.ts +6 -0
  38. package/lib/components/Table/components/TableHead/types.js +1 -0
  39. package/lib/components/Table/components/TableHead/utils.d.ts +19 -0
  40. package/lib/components/Table/components/TableHead/utils.js +34 -0
  41. package/lib/components/Table/components/TableRow/tableRow.styles.d.ts +1 -0
  42. package/lib/components/Table/components/TableRow/tableRow.styles.js +14 -2
  43. package/lib/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.d.ts +3 -2
  44. package/lib/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.js +8 -4
  45. package/lib/components/Table/components/TableRows/components/CollapsableRows/hook.d.ts +9 -0
  46. package/lib/components/Table/components/TableRows/components/CollapsableRows/hook.js +17 -0
  47. package/lib/components/Table/components/TableRows/tableRows.d.ts +3 -3
  48. package/lib/components/Table/components/TableRows/tableRows.js +9 -5
  49. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/columnGrouping.d.ts +3 -0
  50. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/columnGrouping.js +26 -0
  51. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/columnGrouping.styles.d.ts +2 -0
  52. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/columnGrouping.styles.js +16 -0
  53. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/components/MenuItems/menuItems.d.ts +3 -0
  54. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/components/MenuItems/menuItems.js +12 -0
  55. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/components/MenuItems/types.d.ts +7 -0
  56. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/components/MenuItems/types.js +1 -0
  57. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/constants.d.ts +4 -0
  58. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/constants.js +13 -0
  59. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/types.d.ts +4 -0
  60. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/types.js +1 -0
  61. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/utils.d.ts +17 -0
  62. package/lib/components/Table/components/TableToolbar/components/ColumnGrouping/utils.js +36 -0
  63. package/lib/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.d.ts +2 -3
  64. package/lib/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.js +3 -11
  65. package/lib/components/Table/components/TableToolbar/tableToolbar.js +4 -2
  66. package/lib/components/Table/features/RowPosition/constants.js +2 -2
  67. package/lib/components/Table/features/RowPosition/utils.d.ts +2 -2
  68. package/lib/components/Table/features/RowPosition/utils.js +12 -5
  69. package/lib/components/Table/options/updater.d.ts +10 -0
  70. package/lib/components/Table/options/updater.js +24 -0
  71. package/lib/components/Table/table.js +22 -17
  72. package/lib/components/TableCreator/common/constants.d.ts +2 -2
  73. package/lib/components/TableCreator/common/constants.js +2 -1
  74. package/lib/components/TableCreator/common/utils.d.ts +5 -2
  75. package/lib/components/TableCreator/common/utils.js +11 -4
  76. package/lib/components/TableCreator/options/expanded/constants.d.ts +2 -0
  77. package/lib/components/TableCreator/options/expanded/constants.js +6 -0
  78. package/lib/components/TableCreator/options/expanded/hook.d.ts +2 -0
  79. package/lib/components/TableCreator/options/expanded/hook.js +4 -0
  80. package/lib/components/TableCreator/options/grouping/constants.d.ts +2 -0
  81. package/lib/components/TableCreator/options/grouping/constants.js +5 -0
  82. package/lib/components/TableCreator/options/grouping/hook.d.ts +2 -0
  83. package/lib/components/TableCreator/options/grouping/hook.js +9 -0
  84. package/lib/components/TableCreator/options/hook.d.ts +2 -0
  85. package/lib/components/TableCreator/options/hook.js +25 -0
  86. package/lib/components/TableCreator/options/rowSelection/constants.d.ts +2 -0
  87. package/lib/components/TableCreator/options/rowSelection/constants.js +5 -0
  88. package/lib/components/TableCreator/options/rowSelection/hook.d.ts +2 -0
  89. package/lib/components/TableCreator/options/rowSelection/hook.js +4 -0
  90. package/lib/components/TableCreator/options/sorting/constants.d.ts +2 -0
  91. package/lib/components/TableCreator/options/sorting/constants.js +5 -0
  92. package/lib/components/TableCreator/options/sorting/hook.d.ts +2 -0
  93. package/lib/components/TableCreator/options/sorting/hook.js +4 -0
  94. package/lib/components/TableCreator/tableCreator.d.ts +3 -5
  95. package/lib/components/TableCreator/tableCreator.js +4 -2
  96. package/lib/components/common/DropdownMenu/dropdownMenu.d.ts +2 -3
  97. package/lib/components/common/DropdownMenu/dropdownMenu.js +7 -7
  98. package/lib/components/common/DropdownMenu/dropdownMenu.styles.d.ts +1 -1
  99. package/lib/components/common/DropdownMenu/dropdownMenu.styles.js +1 -1
  100. package/lib/components/common/Menu/hooks/useMenu.d.ts +5 -6
  101. package/lib/config/entities.d.ts +7 -7
  102. package/lib/config/utils.d.ts +0 -7
  103. package/lib/config/utils.js +0 -12
  104. package/lib/hooks/useCategoryFilter.js +5 -1
  105. package/lib/providers/exploreState/actions/updateGrouping/action.d.ts +10 -0
  106. package/lib/providers/exploreState/actions/updateGrouping/action.js +16 -0
  107. package/lib/providers/exploreState/actions/updateGrouping/dispatch.d.ts +7 -0
  108. package/lib/providers/exploreState/actions/updateGrouping/dispatch.js +12 -0
  109. package/lib/providers/exploreState/actions/updateGrouping/types.d.ts +9 -0
  110. package/lib/providers/exploreState/actions/updateGrouping/types.js +1 -0
  111. package/lib/providers/exploreState/actions/updateGrouping/utils.d.ts +10 -0
  112. package/lib/providers/exploreState/actions/updateGrouping/utils.js +26 -0
  113. package/lib/providers/exploreState/entities.d.ts +3 -4
  114. package/lib/providers/exploreState/initializer/utils.js +41 -8
  115. package/lib/providers/exploreState/payloads/entities.d.ts +2 -1
  116. package/lib/providers/exploreState/utils.d.ts +6 -4
  117. package/lib/providers/exploreState/utils.js +7 -4
  118. package/lib/providers/exploreState.d.ts +3 -1
  119. package/lib/providers/exploreState.js +15 -5
  120. package/lib/providers/fileManifestState.js +2 -4
  121. package/lib/viewModelBuilders/common/utils.d.ts +6 -6
  122. package/lib/viewModelBuilders/common/utils.js +10 -10
  123. package/lib/views/ExploreView/exploreView.js +3 -3
  124. package/package.json +1 -1
  125. package/src/apis/azul/common/filterTransformer.ts +1 -1
  126. package/src/apis/azul/common/utils.ts +4 -2
  127. package/src/common/entities.ts +3 -3
  128. package/src/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx +2 -0
  129. package/src/components/Detail/components/Table/components/TableRows/tableRows.tsx +3 -18
  130. package/src/components/Export/components/ExportForm/components/ExportFileSummaryForm/exportFileSummaryForm.tsx +28 -32
  131. package/src/components/Filter/common/utils.ts +1 -1
  132. package/src/components/Filter/components/VariableSizeList/VariableSizeList.tsx +1 -1
  133. package/src/components/Filter/components/VariableSizeListItem/variableSizeListItem.tsx +1 -1
  134. package/src/components/Links/components/Link/components/ExploreViewLink/exploreViewLink.tsx +27 -13
  135. package/src/components/Table/common/columnDef.ts +1 -0
  136. package/src/components/Table/common/gridTable.styles.ts +5 -11
  137. package/src/components/Table/common/utils.ts +45 -108
  138. package/src/components/Table/components/TableBody/hooks/virtualizer/constants.ts +3 -0
  139. package/src/components/Table/components/TableBody/hooks/virtualizer/hook.ts +23 -0
  140. package/src/components/Table/components/TableBody/hooks/virtualizer/types.ts +5 -0
  141. package/src/components/Table/components/TableBody/tableBody.tsx +14 -30
  142. package/src/components/Table/components/TableBody/utils.ts +21 -0
  143. package/src/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.tsx +14 -15
  144. package/src/components/Table/components/TableFeatures/ColumnGrouping/utils.ts +70 -0
  145. package/src/components/Table/components/TableFeatures/ColumnVisibility/utils.ts +52 -0
  146. package/src/components/Table/components/TableFeatures/RowSorting/utils.ts +87 -0
  147. package/src/components/Table/components/TableHead/tableHead.tsx +21 -29
  148. package/src/components/Table/components/TableHead/types.ts +7 -0
  149. package/src/components/Table/components/TableHead/utils.ts +42 -0
  150. package/src/components/Table/components/TableRow/tableRow.styles.ts +19 -2
  151. package/src/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx +8 -2
  152. package/src/components/Table/components/TableRows/components/CollapsableRows/hook.ts +20 -0
  153. package/src/components/Table/components/TableRows/tableRows.tsx +18 -15
  154. package/src/components/Table/components/TableToolbar/components/ColumnGrouping/columnGrouping.styles.ts +17 -0
  155. package/src/components/Table/components/TableToolbar/components/ColumnGrouping/columnGrouping.tsx +54 -0
  156. package/src/components/Table/components/TableToolbar/components/ColumnGrouping/components/MenuItems/menuItems.tsx +28 -0
  157. package/src/components/Table/components/TableToolbar/components/ColumnGrouping/components/MenuItems/types.ts +8 -0
  158. package/src/components/Table/components/TableToolbar/components/ColumnGrouping/constants.ts +17 -0
  159. package/src/components/Table/components/TableToolbar/components/ColumnGrouping/types.ts +5 -0
  160. package/src/components/Table/components/TableToolbar/components/ColumnGrouping/utils.ts +45 -0
  161. package/src/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.tsx +7 -20
  162. package/src/components/Table/components/TableToolbar/tableToolbar.tsx +8 -2
  163. package/src/components/Table/features/RowPosition/constants.ts +2 -2
  164. package/src/components/Table/features/RowPosition/utils.ts +10 -5
  165. package/src/components/Table/options/updater.ts +29 -0
  166. package/src/components/Table/table.tsx +43 -25
  167. package/src/components/TableCreator/common/constants.ts +4 -6
  168. package/src/components/TableCreator/common/utils.ts +14 -7
  169. package/src/components/TableCreator/options/expanded/constants.ts +14 -0
  170. package/src/components/TableCreator/options/expanded/hook.ts +6 -0
  171. package/src/components/TableCreator/options/grouping/constants.ts +6 -0
  172. package/src/components/TableCreator/options/grouping/hook.ts +17 -0
  173. package/src/components/TableCreator/options/hook.ts +31 -0
  174. package/src/components/TableCreator/options/rowSelection/constants.ts +10 -0
  175. package/src/components/TableCreator/options/rowSelection/hook.ts +8 -0
  176. package/src/components/TableCreator/options/sorting/constants.ts +10 -0
  177. package/src/components/TableCreator/options/sorting/hook.ts +6 -0
  178. package/src/components/TableCreator/tableCreator.tsx +4 -11
  179. package/src/components/common/DropdownMenu/dropdownMenu.styles.ts +1 -1
  180. package/src/components/common/DropdownMenu/dropdownMenu.tsx +19 -17
  181. package/src/components/common/Menu/hooks/useMenu.ts +8 -9
  182. package/src/config/entities.ts +11 -10
  183. package/src/config/utils.ts +0 -14
  184. package/src/hooks/useCategoryFilter.ts +5 -1
  185. package/src/hooks/useFileManifest/common/utils.ts +2 -2
  186. package/src/providers/exploreState/actions/updateGrouping/action.ts +26 -0
  187. package/src/providers/exploreState/actions/updateGrouping/dispatch.ts +16 -0
  188. package/src/providers/exploreState/actions/updateGrouping/types.ts +11 -0
  189. package/src/providers/exploreState/actions/updateGrouping/utils.ts +33 -0
  190. package/src/providers/exploreState/entities.ts +3 -3
  191. package/src/providers/exploreState/initializer/utils.ts +58 -10
  192. package/src/providers/exploreState/payloads/entities.ts +2 -0
  193. package/src/providers/exploreState/utils.ts +10 -7
  194. package/src/providers/exploreState.tsx +29 -6
  195. package/src/providers/fileManifestState.tsx +2 -4
  196. package/src/viewModelBuilders/common/utils.ts +10 -10
  197. package/src/views/ExploreView/exploreView.tsx +2 -4
  198. package/types/data-explorer-ui.d.ts +8 -1
  199. package/lib/components/TableCreator/common/entities.d.ts +0 -5
  200. package/src/components/TableCreator/common/entities.ts +0 -6
  201. /package/lib/components/{TableCreator/common/entities.js → Table/components/TableBody/hooks/virtualizer/types.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { TableCell } from "@mui/material";
2
- import { flexRender, Row, RowData, Table } from "@tanstack/react-table";
2
+ import { flexRender, Row, RowData } from "@tanstack/react-table";
3
3
  import { Virtualizer } from "@tanstack/react-virtual";
4
4
  import React, { Fragment } from "react";
5
5
  import {
@@ -9,38 +9,41 @@ import {
9
9
  import { TableRow } from "../TableRow/tableRow.styles";
10
10
 
11
11
  export interface TableRowsProps<T extends RowData> {
12
- tableInstance: Table<T>;
12
+ rows: Row<T>[];
13
13
  virtualizer: Virtualizer<Window, Element>;
14
14
  }
15
15
 
16
16
  export const TableRows = <T extends RowData>({
17
- tableInstance,
17
+ rows,
18
18
  virtualizer,
19
19
  }: TableRowsProps<T>): JSX.Element => {
20
- const { getRowModel } = tableInstance;
21
- const { rows } = getRowModel();
22
20
  const virtualItems = virtualizer.getVirtualItems();
23
21
  return (
24
22
  <Fragment>
25
23
  {virtualItems.map((virtualRow) => {
26
24
  const row = rows[virtualRow.index] as Row<T>;
27
- const { getIsPreview } = row;
25
+ const { getIsGrouped, getIsPreview } = row;
28
26
  return (
29
27
  <TableRow
30
28
  key={row.id}
31
29
  data-index={virtualRow.index}
30
+ isGrouped={getIsGrouped()}
32
31
  isPreview={getIsPreview()}
33
32
  ref={virtualizer.measureElement}
34
33
  >
35
- {row.getVisibleCells().map((cell) => (
36
- <TableCell
37
- key={cell.id}
38
- align={getTableCellAlign(cell.column)}
39
- padding={getTableCellPadding(cell.column.id)}
40
- >
41
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
42
- </TableCell>
43
- ))}
34
+ {row.getVisibleCells().map((cell) => {
35
+ if (cell.getIsAggregated()) return null; // Display of aggregated cells is currently not supported.
36
+ if (cell.getIsPlaceholder()) return null; // Display of placeholder cells is currently not supported.
37
+ return (
38
+ <TableCell
39
+ key={cell.id}
40
+ align={getTableCellAlign(cell.column)}
41
+ padding={getTableCellPadding(cell.column.id)}
42
+ >
43
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
44
+ </TableCell>
45
+ );
46
+ })}
44
47
  </TableRow>
45
48
  );
46
49
  })}
@@ -0,0 +1,17 @@
1
+ import styled from "@emotion/styled";
2
+ import { MenuItem } from "@mui/material";
3
+
4
+ export const StyledMenuItem = styled(MenuItem)`
5
+ &:hover {
6
+ background-color: transparent;
7
+
8
+ .MuiListItemText-root {
9
+ .MuiListItemText-primary {
10
+ text-decoration: underline;
11
+ text-decoration-skip-ink: none;
12
+ text-underline-color: currentColor;
13
+ text-underline-position: from-font;
14
+ }
15
+ }
16
+ }
17
+ ` as typeof MenuItem;
@@ -0,0 +1,54 @@
1
+ import { ListItemText } from "@mui/material";
2
+ import { RowData } from "@tanstack/react-table";
3
+ import React from "react";
4
+ import { DropdownButton } from "../../../../../common/Button/components/DropdownButton/dropdownButton";
5
+ import { DropdownMenu } from "../../../../../common/DropdownMenu/dropdownMenu";
6
+ import { handleClearGroupingState } from "../../../TableFeatures/ColumnGrouping/utils";
7
+ import { StyledMenuItem } from "./columnGrouping.styles";
8
+ import { MenuItems } from "./components/MenuItems/menuItems";
9
+ import { LIST_ITEM_TEXT_PROPS, MENU_ITEM_PROPS, MENU_PROPS } from "./constants";
10
+ import { ColumnGroupingProps } from "./types";
11
+ import { getButtonLabel, getColumnGrouping } from "./utils";
12
+
13
+ export const ColumnGrouping = <T extends RowData>({
14
+ tableInstance,
15
+ }: ColumnGroupingProps<T>): JSX.Element | null => {
16
+ const {
17
+ getState,
18
+ options: { enableGrouping },
19
+ } = tableInstance;
20
+ const { grouping } = getState();
21
+ const groupingByColumnId = getColumnGrouping(tableInstance);
22
+ if (!enableGrouping) return null;
23
+ if (groupingByColumnId.size === 0) return null;
24
+ return (
25
+ <DropdownMenu
26
+ {...MENU_PROPS}
27
+ button={(props) => (
28
+ <DropdownButton {...props}>
29
+ {getButtonLabel(groupingByColumnId, grouping)}
30
+ </DropdownButton>
31
+ )}
32
+ >
33
+ {({ closeMenu }): JSX.Element[] => [
34
+ <MenuItems
35
+ key="column-grouping"
36
+ closeMenu={closeMenu}
37
+ groupingByColumnId={groupingByColumnId}
38
+ tableInstance={tableInstance}
39
+ />,
40
+ <StyledMenuItem
41
+ {...MENU_ITEM_PROPS}
42
+ key="reset-grouping-state"
43
+ disabled={grouping.length === 0}
44
+ onClick={() => {
45
+ handleClearGroupingState(tableInstance);
46
+ closeMenu();
47
+ }}
48
+ >
49
+ <ListItemText {...LIST_ITEM_TEXT_PROPS}>Clear Grouping</ListItemText>
50
+ </StyledMenuItem>,
51
+ ]}
52
+ </DropdownMenu>
53
+ );
54
+ };
@@ -0,0 +1,28 @@
1
+ import { ListItemText, MenuItem } from "@mui/material";
2
+ import { RowData } from "@tanstack/react-table";
3
+ import React from "react";
4
+ import { handleToggleGrouping } from "../../../../../TableFeatures/ColumnGrouping/utils";
5
+ import { MENU_ITEM_PROPS } from "../../constants";
6
+ import { MenuItemsProps } from "./types";
7
+
8
+ export const MenuItems = <T extends RowData>({
9
+ closeMenu,
10
+ groupingByColumnId,
11
+ tableInstance,
12
+ }: MenuItemsProps<T>): JSX.Element[] => {
13
+ const columnByMenuItem = [...groupingByColumnId.values()];
14
+ return columnByMenuItem.map(([menuItem, column]) => (
15
+ <MenuItem
16
+ {...MENU_ITEM_PROPS}
17
+ key={column.id}
18
+ disabled={!column.getCanGroup()}
19
+ onClick={() => {
20
+ handleToggleGrouping(tableInstance, column);
21
+ closeMenu();
22
+ }}
23
+ selected={column.getIsGrouped()}
24
+ >
25
+ <ListItemText disableTypography>{menuItem}</ListItemText>
26
+ </MenuItem>
27
+ ));
28
+ };
@@ -0,0 +1,8 @@
1
+ import { Column, RowData, Table } from "@tanstack/react-table";
2
+ import { UseMenu } from "../../../../../../../common/Menu/hooks/useMenu";
3
+
4
+ export interface MenuItemsProps<T extends RowData> {
5
+ closeMenu: UseMenu<HTMLButtonElement>["onClose"];
6
+ groupingByColumnId: Map<string, [string, Column<T>]>;
7
+ tableInstance: Table<T>;
8
+ }
@@ -0,0 +1,17 @@
1
+ import { ListItemTextProps, MenuItemProps, MenuProps } from "@mui/material";
2
+
3
+ export const LIST_ITEM_TEXT_PROPS: Partial<ListItemTextProps> = {
4
+ primaryTypographyProps: {
5
+ color: "primary",
6
+ component: "span",
7
+ variant: "inherit",
8
+ },
9
+ };
10
+
11
+ export const MENU_PROPS: Partial<MenuProps> = {
12
+ variant: "menu",
13
+ };
14
+
15
+ export const MENU_ITEM_PROPS: Partial<MenuItemProps> = {
16
+ component: "li",
17
+ };
@@ -0,0 +1,5 @@
1
+ import { RowData, Table } from "@tanstack/react-table";
2
+
3
+ export interface ColumnGroupingProps<T extends RowData> {
4
+ tableInstance: Table<T>;
5
+ }
@@ -0,0 +1,45 @@
1
+ import { Column, GroupingState, RowData, Table } from "@tanstack/react-table";
2
+
3
+ /**
4
+ * Retrieves the button label for the column grouping dropdown.
5
+ * Currently, the grouping state supports grouping by a single column only.
6
+ * @param groupingByColumnId - Map of column groupings by column ID.
7
+ * @param groupingState - Grouping state.
8
+ * @returns button label.
9
+ */
10
+ export function getButtonLabel<T extends RowData>(
11
+ groupingByColumnId: Map<string, [string, Column<T>]>,
12
+ groupingState: GroupingState
13
+ ): string {
14
+ const grouping = groupingByColumnId.get(groupingState[0]);
15
+ if (!grouping) return "Group by";
16
+ return `Group by: ${grouping[0]}`;
17
+ }
18
+
19
+ /**
20
+ * Retrieves a map of column groupings by column ID from the given table instance.
21
+ * Columns that are visible, group-able with a `string` header are included and are keyed by
22
+ * their column ID. The value is a tuple containing the column header and the column instance.
23
+ * @param table - Table.
24
+ * @returns map of column grouping by column id.
25
+ */
26
+ export function getColumnGrouping<T extends RowData>(
27
+ table: Table<T>
28
+ ): Map<string, [string, Column<T>]> {
29
+ const groupingByColumnId = new Map<string, [string, Column<T>]>();
30
+ for (const column of table.getAllColumns()) {
31
+ const {
32
+ columnDef: { header },
33
+ getCanGroup,
34
+ getIsVisible,
35
+ id,
36
+ } = column;
37
+ if (!getCanGroup()) continue;
38
+ if (!getIsVisible()) continue;
39
+ // Currently, headers are configured as strings.
40
+ // Only include columns that have a string header (for now).
41
+ if (typeof header !== "string") continue;
42
+ groupingByColumnId.set(id, [header, column]);
43
+ }
44
+ return groupingByColumnId;
45
+ }
@@ -1,10 +1,7 @@
1
1
  import { MenuProps as MMenuProps } from "@mui/material";
2
2
  import React from "react";
3
- import { DropdownButton as DXDropdownButton } from "../../../../../../../common/Button/components/DropdownButton/dropdownButton";
4
- import {
5
- DropdownMenuButtonProps,
6
- DropdownMenuItemProps,
7
- } from "../../../../../../../common/DropdownMenu/common/entities";
3
+ import { DropdownButton } from "../../../../../../../common/Button/components/DropdownButton/dropdownButton";
4
+ import { DropdownMenuItemProps } from "../../../../../../../common/DropdownMenu/common/entities";
8
5
  import { DropdownMenuProps as DXDropdownMenuProps } from "../../../../../../../common/DropdownMenu/dropdownMenu";
9
6
  import { DropdownMenu as RowSelectionDropdownMenu } from "./dropdownMenu.styles";
10
7
 
@@ -14,16 +11,15 @@ const DEFAULT_MENU_PROPS: Partial<MMenuProps> = {
14
11
  };
15
12
 
16
13
  export interface DropdownMenuProps {
17
- Button?: DXDropdownMenuProps["Button"];
18
- buttonLabel?: string;
14
+ button?: DXDropdownMenuProps["button"];
19
15
  children: ({ closeMenu }: DropdownMenuItemProps) => JSX.Element[];
20
16
  className?: string;
21
17
  }
22
18
 
23
19
  export const DropdownMenu = ({
24
- Button = (props: DropdownMenuButtonProps): JSX.Element =>
25
- renderButton({ children: buttonLabel, ...props }),
26
- buttonLabel = "Edit",
20
+ button = (props): JSX.Element => (
21
+ <DropdownButton {...props}>Edit</DropdownButton>
22
+ ),
27
23
  children,
28
24
  className,
29
25
  ...props /* Spread props to allow for Mui Menu specific prop overrides e.g. "anchorOrigin". */
@@ -32,19 +28,10 @@ export const DropdownMenu = ({
32
28
  <RowSelectionDropdownMenu
33
29
  {...DEFAULT_MENU_PROPS}
34
30
  className={className}
35
- Button={Button}
31
+ button={button}
36
32
  {...props}
37
33
  >
38
34
  {({ closeMenu }): JSX.Element[] => children({ closeMenu })}
39
35
  </RowSelectionDropdownMenu>
40
36
  );
41
37
  };
42
-
43
- /**
44
- * Return the dropdown button.
45
- * @param props - Button props e.g. "onClick".
46
- * @returns button element.
47
- */
48
- function renderButton(props: DropdownMenuButtonProps): JSX.Element {
49
- return <DXDropdownButton {...props} />;
50
- }
@@ -7,6 +7,7 @@ import { getEditColumnOptions, isAnyRowSelected } from "../../common/utils";
7
7
  import { CheckboxMenu } from "../CheckboxMenu/checkboxMenu";
8
8
  import { DownloadEntityResults } from "../DownloadEntityResults/downloadEntityResults";
9
9
  import { PaginationSummary } from "../PaginationSummary/paginationSummary";
10
+ import { ColumnGrouping } from "./components/ColumnGrouping/columnGrouping";
10
11
  import { RowPreview } from "./components/RowPreview/rowPreview";
11
12
  import { RowSelection } from "./components/RowSelection/rowSelection";
12
13
  import { Toolbar, ToolbarActions } from "./tableToolbar.styles";
@@ -25,13 +26,17 @@ export const TableToolbar = <T extends RowData>({
25
26
  const { exploreState } = useExploreState();
26
27
  const { paginationState } = exploreState;
27
28
  const { currentPage, pages, pageSize, rows } = paginationState;
28
- const { getSelectedRowModel, resetColumnVisibility } = tableInstance;
29
+ const {
30
+ getSelectedRowModel,
31
+ options: { enableGrouping },
32
+ resetColumnVisibility,
33
+ } = tableInstance;
29
34
  const { enableDownload, rowPreviewView } = listView || {};
30
35
  const isLastPage = currentPage === pages;
31
36
  const editColumnOptions = getEditColumnOptions(tableInstance);
32
37
  const showToolbar =
33
38
  rowDirection === ROW_DIRECTION.DEFAULT &&
34
- (editColumnOptions || enableDownload);
39
+ (editColumnOptions || enableDownload || enableGrouping);
35
40
 
36
41
  /**
37
42
  * Resets column visibility to default state.
@@ -63,6 +68,7 @@ export const TableToolbar = <T extends RowData>({
63
68
  rows={tableInstance.getFilteredRowModel().rows}
64
69
  />
65
70
  )}
71
+ <ColumnGrouping tableInstance={tableInstance} />
66
72
  <CheckboxMenu
67
73
  label="Edit Columns"
68
74
  onReset={onResetColumnVisibility}
@@ -23,9 +23,9 @@ export const ROW_POSITION: TableFeature = {
23
23
  };
24
24
  },
25
25
  createTable: <T extends RowData>(table: Table<T>): void => {
26
- const originalGetRowModel = table.getRowModel.bind(table);
27
26
  table.getRowModel = (): RowModel<T> => {
28
- return getRowModel(table, originalGetRowModel);
27
+ const rowModel = table.getPaginationRowModel();
28
+ return getRowModel(table, rowModel);
29
29
  };
30
30
  },
31
31
  getInitialState: (initialState?: InitialTableState): Partial<TableState> => {
@@ -11,17 +11,21 @@ import { DEFAULT_PAGINATION } from "../constants";
11
11
  /**
12
12
  * Returns row model, with getter for row position.
13
13
  * @param table - Table.
14
- * @param getRowModel - Table getRowModel function.
14
+ * @param rowModel - Row model.
15
15
  * @returns row model.
16
16
  */
17
17
  export function getRowModel<T extends RowData>(
18
18
  table: Table<T>,
19
- getRowModel: Table<T>[`getRowModel`]
19
+ rowModel: RowModel<T>
20
20
  ): RowModel<T> {
21
- const rowModel = getRowModel();
22
- rowModel.rows.forEach(({ id }, i) => {
21
+ let i = 0;
22
+ rowModel.flatRows.forEach(({ getIsGrouped, id }) => {
23
+ const isGroupedRow = getIsGrouped();
24
+ const index = isGroupedRow ? -1 : i; // Capture the current value of i for this iteration.
23
25
  rowModel.rowsById[id].getRowPosition = (): number =>
24
- calculateRowPosition(table, i);
26
+ calculateRowPosition(table, index);
27
+ if (isGroupedRow) return; // Iterate only for non-grouped rows.
28
+ i++;
25
29
  });
26
30
  return rowModel;
27
31
  }
@@ -51,6 +55,7 @@ function calculateRowPosition<T extends RowData>(
51
55
  table: Table<T>,
52
56
  index: number
53
57
  ): number {
58
+ if (index < 0) return index; // Grouped rows have a position of -1.
54
59
  const { getState } = table;
55
60
  const {
56
61
  pagination: { pageIndex, pageSize },
@@ -0,0 +1,29 @@
1
+ import { Updater } from "@tanstack/react-table";
2
+
3
+ /**
4
+ * Type guard to check if the given value is TanStack's updater function.
5
+ * TanStack updater can either be a function that computes the new value based on the old value,
6
+ * or a direct value. This type guard identifies whether the provided updater is a function.
7
+ * @param updaterOrValue - The value to check.
8
+ * @returns True if the value is a function, false otherwise.
9
+ */
10
+ function isUpdaterFunction<T>(
11
+ updaterOrValue: Updater<T>
12
+ ): updaterOrValue is (old: T) => T {
13
+ return typeof updaterOrValue === "function";
14
+ }
15
+
16
+ /**
17
+ * Utility function to resolve TanStack updater into a new value.
18
+ * If the updater is a function, it is called with the `old` value to compute the new value.
19
+ * If the updater is not a function, it is returned as-is.
20
+ * @param updaterOrValue - The updater, either a function or a direct value.
21
+ * @param old - The (old) value.
22
+ * @returns Resolved value.
23
+ */
24
+ export function resolveUpdater<T>(updaterOrValue: Updater<T>, old: T): T {
25
+ if (isUpdaterFunction(updaterOrValue)) {
26
+ return updaterOrValue(old);
27
+ }
28
+ return updaterOrValue;
29
+ }
@@ -16,7 +16,7 @@ import {
16
16
  useReactTable,
17
17
  VisibilityState,
18
18
  } from "@tanstack/react-table";
19
- import React, { useEffect, useMemo } from "react";
19
+ import React, { useCallback, useEffect, useMemo } from "react";
20
20
  import { track } from "../../common/analytics/analytics";
21
21
  import {
22
22
  EVENT_NAME,
@@ -98,8 +98,13 @@ TableProps<T>): JSX.Element => {
98
98
  rowPreview,
99
99
  tabValue,
100
100
  } = exploreState;
101
- const { columnsVisibility, enableRowSelection, rowSelection, sorting } =
102
- entityPageState[tabValue];
101
+ const {
102
+ columnsVisibility,
103
+ enableRowSelection,
104
+ grouping,
105
+ rowSelection,
106
+ sorting,
107
+ } = entityPageState[tabValue];
103
108
  const { currentPage, pages, pageSize, rows: pageCount } = paginationState;
104
109
  const { disablePagination = false, enableRowPreview = false } =
105
110
  listView || {};
@@ -113,15 +118,19 @@ TableProps<T>): JSX.Element => {
113
118
  );
114
119
 
115
120
  const onSortingChange = (updater: Updater<ColumnSort[]>): void => {
121
+ // TODO(cc) memoize `onSortingChange` with `useCallback`.
122
+ // TODO(cc) copy `onSortingChange` to ../options/sorting/hook.ts see src/components/Table/options/grouping/hook.ts for example.
116
123
  exploreDispatch({
117
124
  payload: typeof updater === "function" ? updater(sorting) : updater,
118
125
  type: ExploreActionKind.UpdateSorting,
119
126
  });
120
127
  // Execute GTM tracking.
128
+ // TODO(cc) update tracking to handle sorting of multiple columns.
129
+ // TODO(cc) GTM tracking when `onSortingChange` is triggered only tracks the first column sorted, and takes the value from explore state which is not updated yet.
121
130
  track(EVENT_NAME.ENTITY_TABLE_SORTED, {
122
131
  [EVENT_PARAM.ENTITY_NAME]: exploreState.tabValue,
123
- [EVENT_PARAM.COLUMN_NAME]: sorting[0].id,
124
- [EVENT_PARAM.SORT_DIRECTION]: sorting[0].desc
132
+ [EVENT_PARAM.COLUMN_NAME]: sorting?.[0]?.id, // TODO(cc) sorting should always be at least `[]` and never `undefined`.
133
+ [EVENT_PARAM.SORT_DIRECTION]: sorting?.[0]?.desc // TODO(cc) sorting should always be at least `[]` and never `undefined`.
125
134
  ? SORT_DIRECTION.DESC
126
135
  : SORT_DIRECTION.ASC,
127
136
  });
@@ -130,6 +139,7 @@ TableProps<T>): JSX.Element => {
130
139
  const onColumnVisibilityChange = (
131
140
  updater: Updater<VisibilityState>
132
141
  ): void => {
142
+ // TODO(cc) memoize `onColumnVisibilityChange` with `useCallback`.
133
143
  exploreDispatch({
134
144
  payload:
135
145
  typeof updater === "function" ? updater(columnsVisibility) : updater,
@@ -137,22 +147,31 @@ TableProps<T>): JSX.Element => {
137
147
  });
138
148
  };
139
149
 
140
- const onRowPreviewChange = (updater: Updater<RowPreviewState>): void => {
141
- exploreDispatch({
142
- payload: typeof updater === "function" ? updater(rowPreview) : updater,
143
- type: ExploreActionKind.UpdateRowPreview,
144
- });
145
- };
150
+ const onRowPreviewChange = useCallback(
151
+ (updater: Updater<RowPreviewState>): void => {
152
+ exploreDispatch({
153
+ payload: typeof updater === "function" ? updater(rowPreview) : updater,
154
+ type: ExploreActionKind.UpdateRowPreview,
155
+ });
156
+ },
157
+ [exploreDispatch, rowPreview]
158
+ );
146
159
 
147
- const onRowSelectionChange = (updater: Updater<RowSelectionState>): void => {
148
- exploreDispatch({
149
- payload: typeof updater === "function" ? updater(rowSelection) : updater,
150
- type: ExploreActionKind.UpdateRowSelection,
151
- });
152
- };
160
+ const onRowSelectionChange = useCallback(
161
+ (updater: Updater<RowSelectionState>): void => {
162
+ // TODO(cc) refactor `onRowSelectionChange` to /options/rowSelection/hook.ts see onGroupingChange.
163
+ exploreDispatch({
164
+ payload:
165
+ typeof updater === "function" ? updater(rowSelection) : updater,
166
+ type: ExploreActionKind.UpdateRowSelection,
167
+ });
168
+ },
169
+ [exploreDispatch, rowSelection]
170
+ );
153
171
 
154
172
  const state: Partial<TableState> = {
155
173
  columnVisibility: columnsVisibility,
174
+ grouping,
156
175
  pagination,
157
176
  rowPreview,
158
177
  rowSelection,
@@ -180,11 +199,9 @@ TableProps<T>): JSX.Element => {
180
199
  data: items,
181
200
  enableColumnFilters: true, // client-side filtering.
182
201
  enableFilters: true, // client-side filtering.
183
- enableMultiSort: clientFiltering,
202
+ enableMultiSort: clientFiltering, // TODO(cc) move to sorting options; default to false and let the table options in config flag this value.
184
203
  enableRowPreview,
185
204
  enableRowSelection,
186
- enableSorting: true, // client-side filtering.
187
- enableSortingRemoval: false, // client-side filtering.
188
205
  getCoreRowModel: getCoreRowModel(),
189
206
  getFacetedRowModel: clientFiltering ? getFacetedRowModel() : undefined,
190
207
  getFacetedUniqueValues: clientFiltering
@@ -215,8 +232,8 @@ TableProps<T>): JSX.Element => {
215
232
  } = tableInstance;
216
233
  const allColumns = getAllColumns();
217
234
  const { columnFilters } = getState();
218
- const { rows: results } = getRowModel();
219
- const noResults = !loading && (!results || results.length === 0);
235
+ const { rows } = getRowModel();
236
+ const noResults = !loading && (!rows || rows.length === 0);
220
237
  const scrollTop = useScroll();
221
238
  const visibleColumns = getVisibleFlatColumns();
222
239
  const gridTemplateColumns = getGridTemplateColumns(visibleColumns);
@@ -280,8 +297,8 @@ TableProps<T>): JSX.Element => {
280
297
  loading: false,
281
298
  paginationResponse: {
282
299
  ...DEFAULT_PAGINATION_STATE,
283
- pageSize: results.length,
284
- rows: results.length,
300
+ pageSize: rows.filter(({ getIsGrouped }) => !getIsGrouped()).length,
301
+ rows: rows.filter(({ getIsGrouped }) => !getIsGrouped()).length,
285
302
  },
286
303
  selectCategories: buildCategoryViews(allColumns, columnFilters),
287
304
  },
@@ -294,7 +311,7 @@ TableProps<T>): JSX.Element => {
294
311
  columnFilters,
295
312
  exploreDispatch,
296
313
  listItems,
297
- results,
314
+ rows,
298
315
  ]);
299
316
 
300
317
  function canNextPage(): boolean {
@@ -325,6 +342,7 @@ TableProps<T>): JSX.Element => {
325
342
  tableInstance={tableInstance}
326
343
  />
327
344
  <TableBody
345
+ rows={rows}
328
346
  rowDirection={rowDirection}
329
347
  tableInstance={tableInstance}
330
348
  />
@@ -1,22 +1,20 @@
1
1
  import { RowData } from "@tanstack/react-table";
2
+ import { ColumnConfig } from "../../../config/entities";
2
3
  import { RowSelectionCell } from "../../Table/components/TableCell/components/RowSelectionCell/rowSelectionCell";
3
- import { BaseColumnConfig } from "./entities";
4
4
 
5
5
  export const ACCESSOR_KEYS = {
6
6
  ROW_POSITION: "rowPosition",
7
7
  SELECT: "select",
8
8
  };
9
9
 
10
- export const COLUMN_CONFIGS: Record<
11
- string,
12
- BaseColumnConfig<RowData, unknown>
13
- > = {
10
+ export const COLUMN_CONFIGS: Record<string, ColumnConfig<RowData>> = {
14
11
  SELECT: {
15
12
  columnPinned: false,
16
13
  columnVisible: false,
17
14
  componentConfig: { component: RowSelectionCell },
18
15
  disableHiding: true,
19
- disableSorting: true,
16
+ enableGrouping: false,
17
+ enableSorting: false,
20
18
  header: ACCESSOR_KEYS.SELECT,
21
19
  id: ACCESSOR_KEYS.SELECT,
22
20
  meta: {
@@ -1,34 +1,41 @@
1
1
  import { ColumnDef } from "@tanstack/react-table";
2
- import { BaseColumnConfig } from "./entities";
2
+ import { ColumnConfig } from "../../../config/entities";
3
3
 
4
4
  /**
5
5
  * Builds a base column definition.
6
+ * The following properties are set by default:
7
+ * - Grouping is not enabled `enableGrouping: false`.
8
+ * - Sorting is enabled - `enableSorting: true`.
6
9
  * @param baseColumnConfig - Base column configuration.
7
10
  * @returns column definition.
8
11
  */
9
- export function buildBaseColumnDef<T, TValue>(
10
- baseColumnConfig: BaseColumnConfig<T, TValue>
12
+ export function buildBaseColumnDef<T>(
13
+ baseColumnConfig: ColumnConfig<T>
11
14
  ): ColumnDef<T> {
12
15
  const {
13
16
  columnPinned,
17
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Destructure to avoid passing it to the columnDef.
18
+ columnVisible,
19
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Destructure to avoid passing it to the columnDef.
20
+ componentConfig,
14
21
  disableHiding,
15
- disableSorting,
16
22
  header,
17
23
  id,
18
24
  meta,
19
25
  width,
26
+ ...columnDef
20
27
  } = baseColumnConfig;
21
28
  return {
29
+ ...columnDef,
22
30
  accessorKey: id,
23
31
  enableHiding: !disableHiding,
24
- enableSorting: !disableSorting,
25
32
  header,
26
33
  id,
27
34
  meta: {
28
- ...meta,
29
35
  columnPinned,
30
- header: meta ? meta.header : header,
36
+ header: typeof header === "string" ? header : undefined,
31
37
  width,
38
+ ...meta,
32
39
  },
33
40
  };
34
41
  }
@@ -0,0 +1,14 @@
1
+ import {
2
+ ExpandedOptions,
3
+ getExpandedRowModel,
4
+ RowData,
5
+ } from "@tanstack/react-table";
6
+
7
+ export const EXPANDED_OPTIONS: Pick<
8
+ ExpandedOptions<RowData>,
9
+ "autoResetExpanded" | "enableExpanding" | "getExpandedRowModel"
10
+ > = {
11
+ autoResetExpanded: false,
12
+ enableExpanding: false,
13
+ getExpandedRowModel: getExpandedRowModel(),
14
+ };
@@ -0,0 +1,6 @@
1
+ import { ExpandedOptions, RowData } from "@tanstack/react-table";
2
+ import { EXPANDED_OPTIONS } from "./constants";
3
+
4
+ export function useExpandedOptions<T extends RowData>(): ExpandedOptions<T> {
5
+ return { ...EXPANDED_OPTIONS };
6
+ }