Skip to content

Commit 7b61ee7

Browse files
committed
Revert "feat: Adds support for table data grouping (#126)"
This reverts commit e6ebc22.
1 parent e6ebc22 commit 7b61ee7

File tree

14 files changed

+173
-1359
lines changed

14 files changed

+173
-1359
lines changed

package-lock.json

Lines changed: 26 additions & 970 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,10 @@
4242
"LICENSE",
4343
"NOTICE"
4444
],
45-
"dependencies": {
46-
"@cloudscape-design/component-toolkit": "^1.0.0-beta"
47-
},
4845
"peerDependencies": {
4946
"react": ">=16.8.0"
5047
},
5148
"devDependencies": {
52-
"@cloudscape-design/build-tools": "github:cloudscape-design/build-tools#main",
5349
"@testing-library/react": "^11.2.7",
5450
"@types/react": "^16.14.21",
5551
"@types/react-dom": "^16.9.14",
@@ -77,9 +73,6 @@
7773
"lint-staged": {
7874
"*.{js,jsx,ts,tsx}": [
7975
"eslint --fix"
80-
],
81-
"package-lock.json": [
82-
"prepare-package-lock"
8376
]
8477
},
8578
"overrides": {

src/__tests__/stubs.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import * as React from 'react';
44
import { render as testRender } from '@testing-library/react';
55
import { UseCollectionResult, CollectionRef } from '../index.js';
6-
import { getTrackableValue } from '@cloudscape-design/component-toolkit/internal';
6+
import { getTrackableValue } from '../operations/trackby-utils.js';
77

88
export type Item = { id: string; date?: Date };
99

src/__tests__/use-collection-expadable-rows.test.tsx

Lines changed: 99 additions & 227 deletions
Large diffs are not rendered by default.

src/__tests__/utils.tsx

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,28 @@
44
import React from 'react';
55
import { useCollection, UseCollectionOptions, UseCollectionResult } from '..';
66
import { render } from '@testing-library/react';
7-
import { getTrackableValue } from '@cloudscape-design/component-toolkit/internal';
8-
import { Item } from './stubs';
7+
import { getTrackableValue } from '../operations/trackby-utils.js';
98

109
export function renderUseCollection<T>(allItems: readonly T[], options: UseCollectionOptions<T>) {
11-
const current: {
12-
result: UseCollectionResult<T>;
10+
const result: {
11+
collection: UseCollectionResult<T>;
1312
rerender: (allItems: readonly T[], options: UseCollectionOptions<T>) => void;
1413
// Derived props for simpler assertions
1514
visibleItems: T[];
1615
} = {} as any;
1716

1817
const onResult = (collection: UseCollectionResult<T>) => {
19-
current.result = collection;
20-
current.visibleItems = getVisibleItems(collection);
18+
result.collection = collection;
19+
result.visibleItems = getVisibleItems(collection);
2120
};
2221
const { rerender } = render(<App allItems={allItems} options={options} onResult={onResult} />);
2322

24-
current.rerender = (allItems: readonly T[], options: UseCollectionOptions<T>) =>
23+
result.rerender = (allItems: readonly T[], options: UseCollectionOptions<T>) =>
2524
rerender(<App allItems={allItems} options={options} onResult={onResult} />);
2625

27-
return current;
26+
return result;
2827
}
2928

30-
// Generates random items tree to be used for property-based tests.
31-
export const generateRandomNestedItems = ({ totalItems }: { totalItems: number }) => {
32-
const items: Item[] = [];
33-
let nextIndex = 0;
34-
let level = 1;
35-
while (nextIndex < totalItems - 1) {
36-
for (; nextIndex < totalItems && nextIndex < nextIndex + Math.floor(Math.random() * 5); nextIndex++) {
37-
const levelParents = items.filter(i => i.id.split('.').length === level - 1);
38-
const parent = levelParents[Math.floor(Math.random() * levelParents.length)];
39-
items.push({ id: !parent ? `${nextIndex}` : `${parent.id}.${nextIndex}` });
40-
}
41-
level = Math.random() > 0.5 ? level + 1 : level;
42-
}
43-
return items;
44-
};
45-
4629
function App<T>({
4730
allItems,
4831
options,

src/interfaces.ts

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,6 @@ export interface SelectionChangeDetail<T> {
2626
selectedItems: ReadonlyArray<T>;
2727
}
2828

29-
export interface GroupSelectionState<T> {
30-
inverted: boolean;
31-
toggledItems: readonly T[];
32-
}
33-
34-
export interface GroupSelectionChangeDetail<T> {
35-
groupSelection: GroupSelectionState<T>;
36-
}
37-
3829
export type TrackBy<T> = string | ((item: T) => string);
3930

4031
export interface UseCollectionOptions<T> {
@@ -66,23 +57,15 @@ export interface ExpandableRowsProps<ItemType> {
6657
getId(item: ItemType): string;
6758
getParentId(item: ItemType): null | string;
6859
defaultExpandedItems?: ReadonlyArray<ItemType>;
69-
// When set, only leaf nodes (those with no children) are reflected in the counters,
70-
// and selection is replaced by group selection.
71-
dataGrouping?: DataGroupingProps;
7260
}
7361

74-
// There is no configuration for data grouping yet, but it might come in future releases.
75-
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
76-
export interface DataGroupingProps {}
77-
7862
export interface CollectionState<T> {
7963
filteringText: string;
8064
propertyFilteringQuery: PropertyFilterQuery;
8165
currentPageIndex: number;
8266
sortingState?: SortingState<T>;
8367
selectedItems: ReadonlyArray<T>;
8468
expandedItems: ReadonlyArray<T>;
85-
groupSelection: GroupSelectionState<T>;
8669
}
8770

8871
export interface CollectionActions<T> {
@@ -92,7 +75,6 @@ export interface CollectionActions<T> {
9275
setSelectedItems(selectedItems: ReadonlyArray<T>): void;
9376
setPropertyFiltering(query: PropertyFilterQuery): void;
9477
setExpandedItems(items: ReadonlyArray<T>): void;
95-
setGroupSelection(state: GroupSelectionState<T>): void;
9678
}
9779

9880
interface UseCollectionResultBase<T> {
@@ -104,29 +86,17 @@ interface UseCollectionResultBase<T> {
10486
onSortingChange?(event: CustomEventLike<SortingState<T>>): void;
10587
sortingColumn?: SortingColumn<T>;
10688
sortingDescending?: boolean;
107-
// When expandableRows.dataGrouping={}, the selected items are derived from the expandableRows.groupSelection,
108-
// and include all effectively selected leaf nodes.
10989
selectedItems?: ReadonlyArray<T>;
11090
onSelectionChange?(event: CustomEventLike<SelectionChangeDetail<T>>): void;
11191
expandableRows?: {
11292
getItemChildren: (item: T) => T[];
11393
isItemExpandable: (item: T) => boolean;
11494
expandedItems: ReadonlyArray<T>;
11595
onExpandableItemToggle(event: CustomEventLike<{ item: T; expanded: boolean }>): void;
116-
// The groupSelection property is only added in case selection is configured, and expandableRows.dataGrouping={}.
117-
groupSelection?: GroupSelectionState<T>;
118-
onGroupSelectionChange(event: CustomEventLike<GroupSelectionChangeDetail<T>>): void;
119-
// The counts reflect the number of nested selectable/selected nodes (deeply), including the given one.
120-
// When expandableRows.dataGrouping={}, only leaf nodes are considered. They return 1 when called on leaf nodes.
121-
getItemsCount?: (item: T) => number;
122-
getSelectedItemsCount?: (item: T) => number;
12396
};
12497
trackBy?: string | ((item: T) => string);
12598
ref: React.RefObject<CollectionRef>;
126-
// The counts reflect the number of selectable/selected nodes (deeply).
127-
// When expandableRows.dataGrouping={}, only leaf nodes are considered.
12899
totalItemsCount: number;
129-
totalSelectedItemsCount: number;
130100
firstIndex: number;
131101
};
132102
filterProps: {

src/operations/index.ts

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,71 +6,50 @@ import { createPropertyFilterPredicate } from './property-filter.js';
66
import { createComparator } from './sort.js';
77
import { createPageProps } from './pagination.js';
88
import { composeFilters } from './compose-filters.js';
9-
import { getTrackableValue, SelectionTree } from '@cloudscape-design/component-toolkit/internal';
9+
import { getTrackableValue } from './trackby-utils.js';
1010
import { computeFlatItems, computeTreeItems } from './items-tree.js';
1111

1212
export function processItems<T>(
1313
allItems: ReadonlyArray<T>,
14-
state: Partial<CollectionState<T>>,
15-
{ filtering, sorting, pagination, propertyFiltering, expandableRows, selection }: UseCollectionOptions<T>
14+
{ filteringText, sortingState, currentPageIndex, propertyFilteringQuery }: Partial<CollectionState<T>>,
15+
{ filtering, sorting, pagination, propertyFiltering, expandableRows }: UseCollectionOptions<T>
1616
): {
1717
items: readonly T[];
1818
allPageItems: readonly T[];
1919
pagesCount: number | undefined;
2020
actualPageIndex: number | undefined;
21-
totalItemsCount: number;
2221
filteredItemsCount: number | undefined;
23-
selectedItems: undefined | T[];
24-
getItemsCount?: (item: T) => number;
25-
getSelectedItemsCount?: (item: T) => number;
2622
getChildren: (item: T) => T[];
2723
} {
2824
const filterPredicate = composeFilters(
29-
createPropertyFilterPredicate(propertyFiltering, state.propertyFilteringQuery),
30-
createFilterPredicate(filtering, state.filteringText)
25+
createPropertyFilterPredicate(propertyFiltering, propertyFilteringQuery),
26+
createFilterPredicate(filtering, filteringText)
3127
);
32-
const sortingComparator = createComparator(sorting, state.sortingState);
33-
const { items, totalItemsCount, getChildren, getItemsCount } = expandableRows
28+
const sortingComparator = createComparator(sorting, sortingState);
29+
const { items, size, getChildren } = expandableRows
3430
? computeTreeItems(allItems, expandableRows, filterPredicate, sortingComparator)
3531
: computeFlatItems(allItems, filterPredicate, sortingComparator);
36-
const filteredItemsCount = filterPredicate ? totalItemsCount : undefined;
3732

38-
let getSelectedItemsCount: undefined | ((item: T) => number) = undefined;
39-
let selectedItems: undefined | T[] = undefined;
40-
if (selection && expandableRows?.dataGrouping && state.groupSelection) {
41-
const trackBy = selection?.trackBy ?? expandableRows?.getId;
42-
const selectionTreeProps = { getChildren: getChildren, trackBy };
43-
const selectionTree = new SelectionTree(items, selectionTreeProps, state.groupSelection);
44-
getSelectedItemsCount = selectionTree.getSelectedItemsCount;
45-
selectedItems = selectionTree.getSelectedItems();
46-
}
33+
const filteredItemsCount = filterPredicate ? size : undefined;
4734

48-
const pageProps = createPageProps(pagination, state.currentPageIndex, items);
35+
const pageProps = createPageProps(pagination, currentPageIndex, items);
4936
if (pageProps) {
5037
return {
5138
items: items.slice((pageProps.pageIndex - 1) * pageProps.pageSize, pageProps.pageIndex * pageProps.pageSize),
5239
allPageItems: items,
53-
totalItemsCount,
5440
filteredItemsCount,
5541
pagesCount: pageProps?.pagesCount,
5642
actualPageIndex: pageProps?.pageIndex,
57-
selectedItems,
58-
getItemsCount,
59-
getSelectedItemsCount,
6043
getChildren,
6144
};
6245
}
6346

6447
return {
6548
items: items,
6649
allPageItems: items,
67-
totalItemsCount,
6850
filteredItemsCount,
6951
pagesCount: undefined,
7052
actualPageIndex: undefined,
71-
selectedItems,
72-
getItemsCount,
73-
getSelectedItemsCount,
7453
getChildren,
7554
};
7655
}

src/operations/items-tree.ts

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { DataGroupingProps } from '../interfaces';
5-
64
interface TreeProps<T> {
75
getId(item: T): string;
86
getParentId(item: T): null | string;
9-
dataGrouping?: DataGroupingProps;
107
}
118

129
export function computeFlatItems<T>(
@@ -20,7 +17,7 @@ export function computeFlatItems<T>(
2017
if (sortingComparator) {
2118
items = items.slice().sort(sortingComparator);
2219
}
23-
return { items, totalItemsCount: items.length, getChildren: () => [], getItemsCount: () => 0 };
20+
return { items, size: items.length, getChildren: () => [] };
2421
}
2522

2623
export function computeTreeItems<T>(
@@ -30,9 +27,8 @@ export function computeTreeItems<T>(
3027
sortingComparator: null | ((a: T, b: T) => number)
3128
) {
3229
const idToChildren = new Map<string, T[]>();
33-
const idToCount = new Map<string, number>();
3430
let items: T[] = [];
35-
let totalItemsCount = 0;
31+
let size = allItems.length;
3632

3733
for (const item of allItems) {
3834
const parentId = treeProps.getParentId(item);
@@ -51,10 +47,13 @@ export function computeTreeItems<T>(
5147
const filterNode = (item: T): boolean => {
5248
const children = getChildren(item);
5349
const filteredChildren = children.filter(filterNode);
50+
size -= children.length - filteredChildren.length;
5451
setChildren(item, filteredChildren);
5552
return filterPredicate(item) || filteredChildren.length > 0;
5653
};
54+
const prevLength = items.length;
5755
items = items.filter(filterNode);
56+
size -= prevLength - items.length;
5857
}
5958

6059
if (sortingComparator) {
@@ -67,19 +66,5 @@ export function computeTreeItems<T>(
6766
sortLevel(items);
6867
}
6968

70-
function computeCounts(item: T) {
71-
const children = getChildren(item);
72-
let itemCount = !treeProps.dataGrouping || children.length === 0 ? 1 : 0;
73-
for (const child of children) {
74-
itemCount += computeCounts(child);
75-
}
76-
idToCount.set(treeProps.getId(item), itemCount);
77-
return itemCount;
78-
}
79-
for (const item of items) {
80-
totalItemsCount += computeCounts(item);
81-
}
82-
const getItemsCount = treeProps.dataGrouping ? (item: T) => idToCount.get(treeProps.getId(item)) ?? 0 : undefined;
83-
84-
return { items, totalItemsCount, getChildren, getItemsCount };
69+
return { items, size, getChildren };
8570
}

src/operations/trackby-utils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { TrackBy } from '../interfaces';
5+
6+
export const getTrackableValue = <T>(trackBy: TrackBy<T> | undefined, item: T): string | T => {
7+
if (!trackBy) {
8+
return item;
9+
}
10+
if (typeof trackBy === 'function') {
11+
return trackBy(item);
12+
}
13+
return (item as any)[trackBy];
14+
};

src/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
declare global {
99
const process: { env: { NODE_ENV?: string } };
1010
const console: { warn: (...args: Array<any>) => void };
11-
type AbortSignal = any; // Used in the component-toolkit dependency
1211
}
1312

1413
// dummy export to make typescript treat this file as ES module

0 commit comments

Comments
 (0)