@databiosphere/findable-ui 27.0.0 → 28.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 (55) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +17 -0
  3. package/lib/components/Index/components/EntitiesView/components/ChartView/chartView.js +1 -1
  4. package/lib/components/Index/components/EntitiesView/components/ChartView/components/Chart/barX/plot.js +3 -2
  5. package/lib/components/Index/components/EntitiesView/components/ChartView/components/Chart/barX/utils.d.ts +21 -0
  6. package/lib/components/Index/components/EntitiesView/components/ChartView/components/Chart/barX/utils.js +34 -0
  7. package/lib/components/Index/components/EntitiesView/components/EntityList/entityList.d.ts +2 -1
  8. package/lib/components/Index/components/EntitiesView/components/EntityList/entityList.js +3 -5
  9. package/lib/components/Index/components/EntitiesView/components/EntityList/types.d.ts +4 -1
  10. package/lib/components/Index/components/Hero/components/Summaries/stories/summaries.stories.d.ts +6 -0
  11. package/lib/components/Index/components/Hero/components/Summaries/{summaries.stories.js → stories/summaries.stories.js} +2 -6
  12. package/lib/components/Index/components/Hero/stories/hero.stories.d.ts +6 -0
  13. package/lib/components/Index/components/Hero/stories/hero.stories.js +16 -0
  14. package/lib/components/Index/index.d.ts +1 -1
  15. package/lib/components/Index/index.js +6 -2
  16. package/lib/components/Index/stories/index.stories.d.ts +6 -0
  17. package/lib/components/Index/stories/index.stories.js +17 -0
  18. package/lib/components/Index/table/coreOptions/columns/cellFactory.d.ts +9 -0
  19. package/lib/components/Index/table/coreOptions/columns/cellFactory.js +13 -0
  20. package/lib/components/Index/table/hook.d.ts +3 -0
  21. package/lib/components/Index/table/hook.js +166 -0
  22. package/lib/components/Index/table/types.d.ts +4 -0
  23. package/lib/components/Index/table/types.js +1 -0
  24. package/lib/components/Index/types.d.ts +6 -2
  25. package/lib/components/Table/table.d.ts +5 -20
  26. package/lib/components/Table/table.js +10 -138
  27. package/lib/components/TableCreator/tableCreator.d.ts +5 -7
  28. package/lib/components/TableCreator/tableCreator.js +3 -35
  29. package/lib/views/ExploreView/exploreView.js +1 -3
  30. package/package.json +1 -1
  31. package/src/components/Index/components/EntitiesView/components/ChartView/chartView.tsx +1 -1
  32. package/src/components/Index/components/EntitiesView/components/ChartView/components/Chart/barX/plot.ts +4 -1
  33. package/src/components/Index/components/EntitiesView/components/ChartView/components/Chart/barX/utils.ts +43 -0
  34. package/src/components/Index/components/EntitiesView/components/EntityList/entityList.tsx +7 -14
  35. package/src/components/Index/components/EntitiesView/components/EntityList/types.ts +5 -1
  36. package/src/components/Index/components/Hero/components/Summaries/{summaries.stories.tsx → stories/summaries.stories.tsx} +4 -8
  37. package/src/components/Index/components/Hero/stories/hero.stories.tsx +22 -0
  38. package/src/components/Index/index.tsx +21 -3
  39. package/src/components/Index/stories/index.stories.tsx +23 -0
  40. package/src/components/Index/table/coreOptions/columns/cellFactory.tsx +22 -0
  41. package/src/components/Index/table/hook.ts +234 -0
  42. package/src/components/Index/table/types.ts +5 -0
  43. package/src/components/Index/types.ts +6 -2
  44. package/src/components/Table/table.tsx +16 -199
  45. package/src/components/TableCreator/tableCreator.tsx +7 -79
  46. package/src/views/ExploreView/exploreView.tsx +4 -10
  47. package/tests/chart.test.tsx +19 -8
  48. package/tests/chartView.test.tsx +1 -1
  49. package/lib/components/Index/components/Hero/components/Summaries/summaries.stories.d.ts +0 -13
  50. package/lib/components/Index/components/Hero/hero.stories.d.ts +0 -23
  51. package/lib/components/Index/components/Hero/hero.stories.js +0 -22
  52. package/lib/components/Index/index.stories.d.ts +0 -6
  53. package/lib/components/Index/index.stories.js +0 -26
  54. package/src/components/Index/components/Hero/hero.stories.tsx +0 -28
  55. package/src/components/Index/index.stories.tsx +0 -31
@@ -0,0 +1,234 @@
1
+ import {
2
+ ColumnDef,
3
+ ColumnSort,
4
+ getCoreRowModel,
5
+ getFacetedRowModel,
6
+ getFilteredRowModel,
7
+ getPaginationRowModel,
8
+ getSortedRowModel,
9
+ RowData,
10
+ RowSelectionState,
11
+ TableState,
12
+ Updater,
13
+ useReactTable,
14
+ } from "@tanstack/react-table";
15
+ import { useCallback, useEffect, useMemo } from "react";
16
+ import { track } from "../../../common/analytics/analytics";
17
+ import {
18
+ EVENT_NAME,
19
+ EVENT_PARAM,
20
+ SORT_DIRECTION,
21
+ } from "../../../common/analytics/entities";
22
+ import { useConfig } from "../../../hooks/useConfig";
23
+ import { useExploreMode } from "../../../hooks/useExploreMode/useExploreMode";
24
+ import { useExploreState } from "../../../hooks/useExploreState";
25
+ import { ExploreActionKind } from "../../../providers/exploreState";
26
+ import { DEFAULT_PAGINATION_STATE } from "../../../providers/exploreState/initializer/constants";
27
+ import { arrIncludesSome } from "../../Table/columnDef/columnFilters/filterFn";
28
+ import { COLUMN_DEF } from "../../Table/common/columnDef";
29
+ import {
30
+ buildCategoryViews,
31
+ getFacetedUniqueValuesWithArrayValues,
32
+ getTableStatePagination,
33
+ isClientFilteringEnabled,
34
+ sortingFn,
35
+ } from "../../Table/common/utils";
36
+ import { ROW_POSITION } from "../../Table/features/RowPosition/constants";
37
+ import { ROW_PREVIEW } from "../../Table/features/RowPreview/constants";
38
+ import { RowPreviewState } from "../../Table/features/RowPreview/entities";
39
+ import { buildBaseColumnDef } from "../../TableCreator/common/utils";
40
+ import { useTableOptions } from "../../TableCreator/options/hook";
41
+ import { createCell } from "./coreOptions/columns/cellFactory";
42
+ import { UseTable } from "./types";
43
+
44
+ // eslint-disable-next-line sonarjs/cognitive-complexity -- TODO fix component length / complexity
45
+ export const useTable = <T extends RowData>(): UseTable<T> => {
46
+ const { entityConfig } = useConfig();
47
+ const exploreMode = useExploreMode();
48
+ const { exploreDispatch, exploreState } = useExploreState();
49
+ const tableOptions = useTableOptions<T>();
50
+ const {
51
+ entityPageState,
52
+ filterState,
53
+ listItems,
54
+ paginationState,
55
+ rowPreview,
56
+ tabValue,
57
+ } = exploreState;
58
+ const { getId: getRowId, list } = entityConfig;
59
+ const { columns: columnsConfig } = list;
60
+ const { columnVisibility, grouping, rowSelection, sorting } =
61
+ entityPageState[tabValue];
62
+ const { currentPage, pageSize, rows: pageCount } = paginationState;
63
+ const clientFiltering = isClientFilteringEnabled(exploreMode);
64
+ const pagination = useMemo(
65
+ () => getTableStatePagination(currentPage - 1, pageSize),
66
+ [currentPage, pageSize]
67
+ );
68
+
69
+ const columnDefs: ColumnDef<T>[] = useMemo(
70
+ () =>
71
+ columnsConfig.reduce(
72
+ (
73
+ acc,
74
+ {
75
+ /**
76
+ * Applies the custom `arrIncludesSome` filter function as the default for multi-value filtering.
77
+ * Although `ColumnFilter["value"]` is typed as `unknown`, in practice it's consistently an array (`unknown[]`) in entity lists.
78
+ * This custom filter function supports multi-select filtering, even when individual cell values are single strings.
79
+ * This override of TanStack's default `arrIncludesSome` resolves a limitation where the base implementation
80
+ * does not support matching an array of filter values against a single string cell value.
81
+ * For range filtering, specify TanStack's `inNumberRange` filter function on the column definition.
82
+ */
83
+ filterFn = "arrIncludesSome",
84
+ ...columnConfig
85
+ }
86
+ ) => {
87
+ acc.push({
88
+ ...buildBaseColumnDef<T>(columnConfig),
89
+ cell: createCell(columnConfig),
90
+ filterFn,
91
+ sortingFn,
92
+ });
93
+ return acc;
94
+ },
95
+ [
96
+ /* Initialize column definitions with the "row position" column */
97
+ COLUMN_DEF.ROW_POSITION,
98
+ /* Initialize column definitions with the "row selection" column */
99
+ COLUMN_DEF.ROW_SELECTION,
100
+ ] as ColumnDef<T>[]
101
+ ),
102
+ [columnsConfig]
103
+ );
104
+
105
+ const onSortingChange = (updater: Updater<ColumnSort[]>): void => {
106
+ // TODO(cc) memoize `onSortingChange` with `useCallback`.
107
+ // TODO(cc) copy `onSortingChange` to ../options/sorting/hook.ts see src/components/Table/options/grouping/hook.ts for example.
108
+ exploreDispatch({
109
+ payload: typeof updater === "function" ? updater(sorting) : updater,
110
+ type: ExploreActionKind.UpdateSorting,
111
+ });
112
+ // Execute GTM tracking.
113
+ // TODO(cc) update tracking to handle sorting of multiple columns.
114
+ // 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.
115
+ track(EVENT_NAME.ENTITY_TABLE_SORTED, {
116
+ [EVENT_PARAM.ENTITY_NAME]: exploreState.tabValue,
117
+ [EVENT_PARAM.COLUMN_NAME]: sorting?.[0]?.id, // TODO(cc) sorting should always be at least `[]` and never `undefined`.
118
+ [EVENT_PARAM.SORT_DIRECTION]: sorting?.[0]?.desc // TODO(cc) sorting should always be at least `[]` and never `undefined`.
119
+ ? SORT_DIRECTION.DESC
120
+ : SORT_DIRECTION.ASC,
121
+ });
122
+ };
123
+
124
+ const onRowPreviewChange = useCallback(
125
+ (updater: Updater<RowPreviewState>): void => {
126
+ exploreDispatch({
127
+ payload: typeof updater === "function" ? updater(rowPreview) : updater,
128
+ type: ExploreActionKind.UpdateRowPreview,
129
+ });
130
+ },
131
+ [exploreDispatch, rowPreview]
132
+ );
133
+
134
+ const onRowSelectionChange = useCallback(
135
+ (updater: Updater<RowSelectionState>): void => {
136
+ // TODO(cc) refactor `onRowSelectionChange` to /options/rowSelection/hook.ts see onGroupingChange.
137
+ exploreDispatch({
138
+ payload:
139
+ typeof updater === "function" ? updater(rowSelection) : updater,
140
+ type: ExploreActionKind.UpdateRowSelection,
141
+ });
142
+ },
143
+ [exploreDispatch, rowSelection]
144
+ );
145
+
146
+ const state: Partial<TableState> = {
147
+ columnVisibility,
148
+ grouping,
149
+ pagination,
150
+ rowPreview,
151
+ rowSelection,
152
+ sorting,
153
+ };
154
+
155
+ /**
156
+ * TODO: Update `ColumnConfig` to follow the `ColumnDef` API of TanStack Table.
157
+ * - Standardize column definitions to leverage the full power of TanStack Table's feature set and improve compatibility.
158
+ * TODO: Define `sorting` directly within `ListConfig` via the `tableOptions.initialState` property.
159
+ * - This will simplify the configuration structure and centralize table state definitions, reducing redundancy and improving clarity.
160
+ */
161
+ const table = useReactTable<T>({
162
+ _features: [ROW_POSITION, ROW_PREVIEW],
163
+ columns: columnDefs,
164
+ data: listItems || [],
165
+ enableColumnFilters: true, // client-side filtering.
166
+ enableFilters: true, // client-side filtering.
167
+ enableMultiSort: clientFiltering, // TODO(cc) move to sorting options; default to false and let the table options in config flag this value.
168
+ filterFns: { arrIncludesSome },
169
+ getCoreRowModel: getCoreRowModel(),
170
+ getFacetedRowModel: clientFiltering ? getFacetedRowModel() : undefined,
171
+ getFacetedUniqueValues: clientFiltering
172
+ ? getFacetedUniqueValuesWithArrayValues()
173
+ : undefined,
174
+ getFilteredRowModel: clientFiltering ? getFilteredRowModel() : undefined,
175
+ getPaginationRowModel: getPaginationRowModel(),
176
+ getRowId,
177
+ getSortedRowModel: clientFiltering ? getSortedRowModel() : undefined,
178
+ manualPagination: true,
179
+ manualSorting: !clientFiltering,
180
+ onRowPreviewChange,
181
+ onRowSelectionChange,
182
+ onSortingChange,
183
+ pageCount,
184
+ state,
185
+ ...tableOptions,
186
+ });
187
+
188
+ const { getAllColumns, getRowModel, getState } = table;
189
+
190
+ const allColumns = getAllColumns();
191
+ const { columnFilters } = getState();
192
+ const { rows } = getRowModel();
193
+
194
+ // Sets react table column filters `columnFilters` state - for client-side filtering only - with update of filterState.
195
+ useEffect(() => {
196
+ if (clientFiltering) {
197
+ table.setColumnFilters(
198
+ filterState.map(({ categoryKey, value }) => ({
199
+ id: categoryKey,
200
+ value,
201
+ }))
202
+ );
203
+ }
204
+ }, [clientFiltering, filterState, table]);
205
+
206
+ // Process explore response - client-side filtering only.
207
+ useEffect(() => {
208
+ if (!listItems || listItems.length === 0) return;
209
+ if (clientFiltering) {
210
+ exploreDispatch({
211
+ payload: {
212
+ listItems,
213
+ loading: false,
214
+ paginationResponse: {
215
+ ...DEFAULT_PAGINATION_STATE,
216
+ pageSize: rows.filter(({ getIsGrouped }) => !getIsGrouped()).length,
217
+ rows: rows.filter(({ getIsGrouped }) => !getIsGrouped()).length,
218
+ },
219
+ selectCategories: buildCategoryViews(allColumns, columnFilters),
220
+ },
221
+ type: ExploreActionKind.ProcessExploreResponse,
222
+ });
223
+ }
224
+ }, [
225
+ allColumns,
226
+ clientFiltering,
227
+ columnFilters,
228
+ exploreDispatch,
229
+ listItems,
230
+ rows,
231
+ ]);
232
+
233
+ return { table };
234
+ };
@@ -0,0 +1,5 @@
1
+ import { RowData, Table } from "@tanstack/react-table";
2
+
3
+ export interface UseTable<T extends RowData> {
4
+ table: Table<T>;
5
+ }
@@ -1,10 +1,14 @@
1
1
  import { BaseComponentProps } from "components/types";
2
+ import { EntityConfig } from "config/entities";
2
3
  import { ReactNode } from "react";
4
+ import { CategoryFilter } from "../../components/Filter/components/Filters/filters";
3
5
 
4
6
  export interface IndexProps extends BaseComponentProps {
5
- chart?: ReactNode;
6
- list?: ReactNode;
7
+ categoryFilters: CategoryFilter[];
8
+ entityListType: string;
9
+ entityName: EntityConfig["label"];
7
10
  ListHero?: ReactNode | ReactNode[];
11
+ loading: boolean;
8
12
  SideBarButton?: ReactNode;
9
13
  SubTitleHero?: ReactNode | ReactNode[];
10
14
  Summaries?: ReactNode;
@@ -1,28 +1,13 @@
1
1
  import { TableContainer } from "@mui/material";
2
- import {
3
- ColumnDef,
4
- ColumnSort,
5
- CoreOptions,
6
- getCoreRowModel,
7
- getFacetedRowModel,
8
- getFilteredRowModel,
9
- getPaginationRowModel,
10
- getSortedRowModel,
11
- RowData,
12
- RowSelectionState,
13
- TableState,
14
- Updater,
15
- useReactTable,
16
- } from "@tanstack/react-table";
17
- import React, { Fragment, useCallback, useEffect, useMemo } from "react";
2
+ import { RowData, Table as TanStackTable } from "@tanstack/react-table";
3
+ import React, { Fragment } from "react";
18
4
  import { track } from "../../common/analytics/analytics";
19
5
  import {
20
6
  EVENT_NAME,
21
7
  EVENT_PARAM,
22
8
  PAGINATION_DIRECTION,
23
- SORT_DIRECTION,
24
9
  } from "../../common/analytics/entities";
25
- import { ListConfig, ListViewConfig } from "../../config/entities";
10
+ import { ListViewConfig } from "../../config/entities";
26
11
  import {
27
12
  BREAKPOINT_FN_NAME,
28
13
  useBreakpointHelper,
@@ -31,173 +16,47 @@ import { useExploreMode } from "../../hooks/useExploreMode/useExploreMode";
31
16
  import { useExploreState } from "../../hooks/useExploreState";
32
17
  import { useScroll } from "../../hooks/useScroll";
33
18
  import { ExploreActionKind } from "../../providers/exploreState";
34
- import { DEFAULT_PAGINATION_STATE } from "../../providers/exploreState/initializer/constants";
35
19
  import { TABLET } from "../../theme/common/breakpoints";
36
20
  import { Loading, LOADING_PANEL_STYLE } from "../Loading/loading";
37
21
  import { NoResults } from "../NoResults/noResults";
38
22
  import { getColumnTrackSizing } from "../TableCreator/options/columnTrackSizing/utils";
39
- import { arrIncludesSome } from "./columnDef/columnFilters/filterFn";
40
23
  import { ROW_DIRECTION } from "./common/entities";
41
- import {
42
- buildCategoryViews,
43
- getFacetedUniqueValuesWithArrayValues,
44
- getTableStatePagination,
45
- isClientFilteringEnabled,
46
- } from "./common/utils";
24
+ import { isClientFilteringEnabled } from "./common/utils";
47
25
  import { Pagination as DXPagination } from "./components/Pagination/pagination";
48
26
  import { TableBody } from "./components/TableBody/tableBody";
49
27
  import { TableHead } from "./components/TableHead/tableHead";
50
28
  import { TableToolbar } from "./components/TableToolbar/tableToolbar";
51
- import { ROW_POSITION } from "./features/RowPosition/constants";
52
- import { ROW_PREVIEW } from "./features/RowPreview/constants";
53
- import { RowPreviewState } from "./features/RowPreview/entities";
54
29
  import { GridTable } from "./table.styles";
55
30
 
56
31
  export interface TableProps<T extends RowData> {
57
- columns: ColumnDef<T>[];
58
- getRowId?: CoreOptions<T>["getRowId"];
59
- items: T[];
60
32
  listView?: ListViewConfig;
61
- loading?: boolean;
62
- tableOptions?: ListConfig<T>["tableOptions"];
33
+ loading: boolean;
34
+ table: TanStackTable<T>;
63
35
  }
64
36
 
65
- /**
66
- * This table can be Controlled or Uncontrolled based on the set of props passed to it.
67
- * Controlled table will receive the navigation functions, and it will be used for dynamic loads.
68
- * Uncontrolled table will take advantage of React Table's state and will be used for static loads.
69
- * @param tableProps - Set of props required for displaying the table.
70
- * @param tableProps.columns - Set of columns to display.
71
- * @param tableProps.getRowId - Function to customize the row ID.
72
- * @param tableProps.items - Row data to display.
73
- * @param tableProps.listView - List view configuration.
74
- * @param tableProps.tableOptions - TanStack table options.
75
- * @returns Configured table element for display.
76
- */
77
37
  export const TableComponent = <T extends RowData>({
78
- columns,
79
- getRowId,
80
- items,
81
38
  listView,
82
- tableOptions,
83
- }: // eslint-disable-next-line sonarjs/cognitive-complexity -- TODO fix component length / complexity
84
- TableProps<T>): JSX.Element => {
39
+ loading,
40
+ table,
41
+ }: TableProps<T>): JSX.Element => {
85
42
  const tabletDown = useBreakpointHelper(BREAKPOINT_FN_NAME.DOWN, TABLET);
86
43
  const exploreMode = useExploreMode();
87
44
  const { exploreDispatch, exploreState } = useExploreState();
88
- const {
89
- entityPageState,
90
- filterState,
91
- listItems,
92
- loading = false,
93
- paginationState,
94
- rowPreview,
95
- tabValue,
96
- } = exploreState;
97
- const { columnVisibility, grouping, rowSelection, sorting } =
98
- entityPageState[tabValue];
99
- const { currentPage, pages, pageSize, rows: pageCount } = paginationState;
45
+ const { paginationState } = exploreState;
46
+ const { currentPage, pages } = paginationState;
100
47
  const { disablePagination = false } = listView || {};
101
48
  const clientFiltering = isClientFilteringEnabled(exploreMode);
102
49
  const rowDirection = tabletDown
103
50
  ? ROW_DIRECTION.VERTICAL
104
51
  : ROW_DIRECTION.DEFAULT;
105
- const pagination = useMemo(
106
- () => getTableStatePagination(currentPage - 1, pageSize),
107
- [currentPage, pageSize]
108
- );
109
-
110
- const onSortingChange = (updater: Updater<ColumnSort[]>): void => {
111
- // TODO(cc) memoize `onSortingChange` with `useCallback`.
112
- // TODO(cc) copy `onSortingChange` to ../options/sorting/hook.ts see src/components/Table/options/grouping/hook.ts for example.
113
- exploreDispatch({
114
- payload: typeof updater === "function" ? updater(sorting) : updater,
115
- type: ExploreActionKind.UpdateSorting,
116
- });
117
- // Execute GTM tracking.
118
- // TODO(cc) update tracking to handle sorting of multiple columns.
119
- // 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.
120
- track(EVENT_NAME.ENTITY_TABLE_SORTED, {
121
- [EVENT_PARAM.ENTITY_NAME]: exploreState.tabValue,
122
- [EVENT_PARAM.COLUMN_NAME]: sorting?.[0]?.id, // TODO(cc) sorting should always be at least `[]` and never `undefined`.
123
- [EVENT_PARAM.SORT_DIRECTION]: sorting?.[0]?.desc // TODO(cc) sorting should always be at least `[]` and never `undefined`.
124
- ? SORT_DIRECTION.DESC
125
- : SORT_DIRECTION.ASC,
126
- });
127
- };
128
52
 
129
- const onRowPreviewChange = useCallback(
130
- (updater: Updater<RowPreviewState>): void => {
131
- exploreDispatch({
132
- payload: typeof updater === "function" ? updater(rowPreview) : updater,
133
- type: ExploreActionKind.UpdateRowPreview,
134
- });
135
- },
136
- [exploreDispatch, rowPreview]
137
- );
138
-
139
- const onRowSelectionChange = useCallback(
140
- (updater: Updater<RowSelectionState>): void => {
141
- // TODO(cc) refactor `onRowSelectionChange` to /options/rowSelection/hook.ts see onGroupingChange.
142
- exploreDispatch({
143
- payload:
144
- typeof updater === "function" ? updater(rowSelection) : updater,
145
- type: ExploreActionKind.UpdateRowSelection,
146
- });
147
- },
148
- [exploreDispatch, rowSelection]
149
- );
150
-
151
- const state: Partial<TableState> = {
152
- columnVisibility,
153
- grouping,
154
- pagination,
155
- rowPreview,
156
- rowSelection,
157
- sorting,
158
- };
159
- /**
160
- * TODO: Update `ColumnConfig` to follow the `ColumnDef` API of TanStack Table.
161
- * - Standardize column definitions to leverage the full power of TanStack Table's feature set and improve compatibility.
162
- * TODO: Define `sorting` directly within `ListConfig` via the `tableOptions.initialState` property.
163
- * - This will simplify the configuration structure and centralize table state definitions, reducing redundancy and improving clarity.
164
- */
165
- const tableInstance = useReactTable({
166
- _features: [ROW_POSITION, ROW_PREVIEW],
167
- columns,
168
- data: items,
169
- enableColumnFilters: true, // client-side filtering.
170
- enableFilters: true, // client-side filtering.
171
- enableMultiSort: clientFiltering, // TODO(cc) move to sorting options; default to false and let the table options in config flag this value.
172
- filterFns: { arrIncludesSome },
173
- getCoreRowModel: getCoreRowModel(),
174
- getFacetedRowModel: clientFiltering ? getFacetedRowModel() : undefined,
175
- getFacetedUniqueValues: clientFiltering
176
- ? getFacetedUniqueValuesWithArrayValues()
177
- : undefined,
178
- getFilteredRowModel: clientFiltering ? getFilteredRowModel() : undefined,
179
- getPaginationRowModel: getPaginationRowModel(),
180
- getRowId,
181
- getSortedRowModel: clientFiltering ? getSortedRowModel() : undefined,
182
- manualPagination: true,
183
- manualSorting: !clientFiltering,
184
- onRowPreviewChange,
185
- onRowSelectionChange,
186
- onSortingChange,
187
- pageCount,
188
- state,
189
- ...tableOptions,
190
- });
191
53
  const {
192
- getAllColumns,
193
54
  getRowModel,
194
- getState,
195
55
  getVisibleFlatColumns,
196
56
  nextPage: tableNextPage,
197
57
  previousPage: tablePreviousPage,
198
- } = tableInstance;
199
- const allColumns = getAllColumns();
200
- const { columnFilters } = getState();
58
+ } = table;
59
+
201
60
  const { rows } = getRowModel();
202
61
  const noResults = !loading && (!rows || rows.length === 0);
203
62
  const scrollTop = useScroll();
@@ -239,45 +98,6 @@ TableProps<T>): JSX.Element => {
239
98
  scrollTop();
240
99
  };
241
100
 
242
- // Sets react table column filters `columnFilters` state - for client-side filtering only - with update of filterState.
243
- useEffect(() => {
244
- if (clientFiltering) {
245
- tableInstance.setColumnFilters(
246
- filterState.map(({ categoryKey, value }) => ({
247
- id: categoryKey,
248
- value,
249
- }))
250
- );
251
- }
252
- }, [clientFiltering, filterState, tableInstance]);
253
-
254
- // Process explore response - client-side filtering only.
255
- useEffect(() => {
256
- if (!listItems || listItems.length === 0) return;
257
- if (clientFiltering) {
258
- exploreDispatch({
259
- payload: {
260
- listItems,
261
- loading: false,
262
- paginationResponse: {
263
- ...DEFAULT_PAGINATION_STATE,
264
- pageSize: rows.filter(({ getIsGrouped }) => !getIsGrouped()).length,
265
- rows: rows.filter(({ getIsGrouped }) => !getIsGrouped()).length,
266
- },
267
- selectCategories: buildCategoryViews(allColumns, columnFilters),
268
- },
269
- type: ExploreActionKind.ProcessExploreResponse,
270
- });
271
- }
272
- }, [
273
- allColumns,
274
- clientFiltering,
275
- columnFilters,
276
- exploreDispatch,
277
- listItems,
278
- rows,
279
- ]);
280
-
281
101
  function canNextPage(): boolean {
282
102
  return currentPage < pages;
283
103
  }
@@ -293,7 +113,7 @@ TableProps<T>): JSX.Element => {
293
113
  <TableToolbar
294
114
  listView={listView}
295
115
  rowDirection={rowDirection}
296
- tableInstance={tableInstance}
116
+ tableInstance={table}
297
117
  />
298
118
  <Loading
299
119
  appear={false}
@@ -306,14 +126,11 @@ TableProps<T>): JSX.Element => {
306
126
  collapsable={true}
307
127
  gridTemplateColumns={getColumnTrackSizing(getVisibleFlatColumns())}
308
128
  >
309
- <TableHead
310
- rowDirection={rowDirection}
311
- tableInstance={tableInstance}
312
- />
129
+ <TableHead rowDirection={rowDirection} tableInstance={table} />
313
130
  <TableBody
314
131
  rows={rows}
315
132
  rowDirection={rowDirection}
316
- tableInstance={tableInstance}
133
+ tableInstance={table}
317
134
  />
318
135
  </GridTable>
319
136
  </TableContainer>
@@ -1,90 +1,18 @@
1
- import {
2
- CellContext,
3
- ColumnDef,
4
- CoreOptions,
5
- RowData,
6
- } from "@tanstack/react-table";
7
- import React, { useMemo } from "react";
8
- import { ColumnConfig, ListViewConfig } from "../../config/entities";
9
- import { ComponentCreator } from "../ComponentCreator/ComponentCreator";
10
- import { COLUMN_DEF } from "../Table/common/columnDef";
11
- import { sortingFn } from "../Table/common/utils";
1
+ import { RowData, Table as TanStackTable } from "@tanstack/react-table";
2
+ import React from "react";
3
+ import { ListViewConfig } from "../../config/entities";
12
4
  import { Table } from "../Table/table";
13
- import { buildBaseColumnDef } from "./common/utils";
14
- import { useTableOptions } from "./options/hook";
15
5
 
16
6
  export interface TableCreatorProps<T> {
17
- columns: ColumnConfig<T>[];
18
- getRowId?: CoreOptions<T>["getRowId"];
19
- items: T[];
20
7
  listView?: ListViewConfig;
21
- loading?: boolean;
8
+ loading: boolean;
9
+ table: TanStackTable<T>;
22
10
  }
23
11
 
24
- const createCell = <T extends RowData = RowData, TData = unknown>(
25
- config: ColumnConfig<T>
26
- ) =>
27
- function CellCreator(cellContext: CellContext<T, TData>): JSX.Element {
28
- return (
29
- <ComponentCreator
30
- components={[config.componentConfig]}
31
- response={cellContext.row.original}
32
- viewContext={{ cellContext }}
33
- />
34
- );
35
- };
36
-
37
12
  export const TableCreator = <T extends RowData>({
38
- columns,
39
- getRowId,
40
- items,
41
13
  listView,
42
14
  loading,
15
+ table,
43
16
  }: TableCreatorProps<T>): JSX.Element => {
44
- const tableOptions = useTableOptions<T>();
45
- const columnDefs: ColumnDef<T>[] = useMemo(
46
- () =>
47
- columns.reduce(
48
- (
49
- acc,
50
- {
51
- /**
52
- * Applies the custom `arrIncludesSome` filter function as the default for multi-value filtering.
53
- * Although `ColumnFilter["value"]` is typed as `unknown`, in practice it's consistently an array (`unknown[]`) in entity lists.
54
- * This custom filter function supports multi-select filtering, even when individual cell values are single strings.
55
- * This override of TanStack's default `arrIncludesSome` resolves a limitation where the base implementation
56
- * does not support matching an array of filter values against a single string cell value.
57
- * For range filtering, specify TanStack's `inNumberRange` filter function on the column definition.
58
- */
59
- filterFn = "arrIncludesSome",
60
- ...columnConfig
61
- }
62
- ) => {
63
- acc.push({
64
- ...buildBaseColumnDef(columnConfig),
65
- cell: createCell(columnConfig),
66
- filterFn,
67
- sortingFn: sortingFn,
68
- });
69
- return acc;
70
- },
71
- [
72
- /* Initialize column definitions with the "row position" column */
73
- COLUMN_DEF.ROW_POSITION,
74
- /* Initialize column definitions with the "row selection" column */
75
- COLUMN_DEF.ROW_SELECTION,
76
- ] as ColumnDef<T>[]
77
- ),
78
- [columns]
79
- );
80
- return (
81
- <Table<T>
82
- columns={columnDefs}
83
- getRowId={getRowId}
84
- items={items}
85
- listView={listView}
86
- loading={loading}
87
- tableOptions={tableOptions}
88
- />
89
- );
17
+ return <Table listView={listView} loading={loading} table={table} />;
90
18
  };
@@ -17,8 +17,6 @@ import {
17
17
  Filters,
18
18
  } from "../../components/Filter/components/Filters/filters";
19
19
  import { SearchAllFilters } from "../../components/Filter/components/SearchAllFilters/searchAllFilters";
20
- import { ChartView } from "../../components/Index/components/EntitiesView/components/ChartView/chartView";
21
- import { EntityList } from "../../components/Index/components/EntitiesView/components/EntityList/entityList";
22
20
  import { Tabs } from "../../components/Index/components/Tabs/tabs";
23
21
  import { Index as IndexView } from "../../components/Index/index";
24
22
  import { SidebarButton } from "../../components/Layout/components/Sidebar/components/SidebarButton/sidebarButton";
@@ -165,14 +163,10 @@ export const ExploreView = (props: ExploreViewProps): JSX.Element => {
165
163
  )}
166
164
  <IndexView
167
165
  className={props.className}
168
- chart={
169
- <ChartView
170
- categoryFilters={categoryFilters}
171
- entityName={label}
172
- loading={loading}
173
- />
174
- }
175
- list={<EntityList entityListType={entityListType} />}
166
+ categoryFilters={categoryFilters}
167
+ entityListType={entityListType}
168
+ entityName={label}
169
+ loading={loading}
176
170
  ListHero={renderComponent(listHero)}
177
171
  SideBarButton={
178
172
  tabletDown ? (