Skip to content

Commit

Permalink
LG-3313: v10 Row props (#1916)
Browse files Browse the repository at this point in the history
* Passing all row props to adapter

* changeseT

* spreading props to nested cells

* Spreading props on table and headerrow

* spreading header cell props

* removing unused props from table spreads

* update test cases

* fixing validate issue

* Changeset

* remove redundant changeset

* add ticket links for ts issues

* lint

---------

Co-authored-by: Adam Thompson <2414030+TheSonOfThomp@users.noreply.github.com>
Co-authored-by: Brooke Scarlett Yalof <brooke.yalof@mongodb.com>
  • Loading branch information
3 people authored Aug 29, 2023
1 parent c89d17a commit f8bfa38
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/nice-shrimps-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/table': patch
---

Fixes bug in V11Adapter where not all props on rows and cells were not being passed to their rendered elements
42 changes: 36 additions & 6 deletions packages/table/src/V11Adapter/V11Adapter.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,23 +109,43 @@ const NestedRows = () => {
<Table
data={defaultData.slice(0, 8)}
columns={
<HeaderRow>
<TableHeader key="name" label="Name" dataType="string" />
<HeaderRow data-testid="test-header-row">
<TableHeader
key="name"
label="Name"
dataType="string"
data-testid="test-header-cell"
/>
<TableHeader key="age" label="Age" dataType="number" />
<TableHeader key="color" label="Color" dataType="string" />
<TableHeader key="location" label="Location" />
</HeaderRow>
}
data-testid="test-table"
>
{({ datum }: any) => (
<Row>
<Cell>{datum.name}</Cell>
<Row data-testid={datum.name === 'Alice' ? 'test-row' : undefined}>
<Cell
data-testid={datum.name === 'Alice' ? 'test-cell' : undefined}
>
{datum.name}
</Cell>
<Cell>{datum.age}</Cell>
<Cell>{datum.color}</Cell>
<Cell>{datum.location}</Cell>
{datum.name !== 'Donna' && (
<Row>
<Cell>expanded name: {datum.name}</Cell>
<Row
data-testid={
datum.name === 'Alice' ? 'test-nested-row' : undefined
}
>
<Cell
data-testid={
datum.name === 'Alice' ? 'test-nested-cell' : undefined
}
>
expanded name: {datum.name}
</Cell>
<Cell>expanded age: {datum.age}</Cell>
<Cell>expanded color: {datum.color}</Cell>
<Cell>expanded location: {datum.location}</Cell>
Expand Down Expand Up @@ -365,6 +385,16 @@ describe('packages/table/Table', () => {
const { getAllByRole } = render(<NestedRows />);
expect(getAllByRole('rowgroup').length).toBe(9); // 1 for thead, 9 for tbody
});
test('all data- attributes are passed to all elements', async () => {
const { getByTestId } = render(<NestedRows />);
expect(getByTestId('test-table')).toBeInTheDocument();
expect(getByTestId('test-header-row')).toBeInTheDocument();
expect(getByTestId('test-header-cell')).toBeInTheDocument();
expect(getByTestId('test-row')).toBeInTheDocument();
expect(getByTestId('test-cell')).toBeInTheDocument();
expect(getByTestId('test-nested-row')).toBeInTheDocument();
expect(getByTestId('test-nested-cell')).toBeInTheDocument();
});
// eslint-disable-next-line jest/no-disabled-tests
test.skip('clicking expand icon button renders collapse button and nested row content', async () => {
const { getByLabelText, getAllByLabelText, queryByText } = render(
Expand Down
90 changes: 70 additions & 20 deletions packages/table/src/V11Adapter/V11Adapter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { VirtualItem } from 'react-virtual';
import { flexRender } from '@tanstack/react-table';

import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';
import { isComponentType } from '@leafygreen-ui/lib';
import { consoleOnce, isComponentType } from '@leafygreen-ui/lib';

import { Cell, HeaderCell } from '../Cell';
import ExpandedContent from '../ExpandedContent/ExpandedContent';
Expand All @@ -19,6 +19,7 @@ import Table from '../Table';
import TableBody from '../TableBody';
import TableHead from '../TableHead';
import { TableProps as V10TableProps } from '../TableV10/Table';
import { TableHeaderProps } from '../TableV10/TableHeader';
import useLeafyGreenTable, {
LeafyGreenTableCell,
LeafyGreenTableRow,
Expand Down Expand Up @@ -47,17 +48,17 @@ const V11Adapter = <T extends LGRowData>({
headerLabels,
className,
}: V11AdapterProps<T>) => {
const { darkMode } = useDarkMode();
const containerRef = useRef(null);
const OldTable = flattenChildren(children)[0];

if (!isComponentType(OldTable, 'Table')) {
console.error(
consoleOnce.error(
'The first and only child of `Table.V11Adapter` must be a `V10Table` component',
);
}

const OldTableProps = (OldTable as ReactElement).props;
const { darkMode } = useDarkMode(OldTableProps.darkMode);
type TData = typeof OldTableProps.data extends Array<infer U> ? U : never;

const {
Expand Down Expand Up @@ -91,6 +92,24 @@ const V11Adapter = <T extends LGRowData>({

const iterables = useVirtualScrolling ? table.virtualRows ?? [] : rows;

const columnsChildren = React.Children.toArray(columns);
const oldHeaderRow = columnsChildren[0] as ReactElement;

const oldHeaderCellProps: Array<TableHeaderProps<any>> = [];

if (columnsChildren.length < 2) {
React.Children.toArray(oldHeaderRow.props.children).map(child => {
const { label, dataType, ...props } = (child as ReactElement).props;
oldHeaderCellProps.push(props);
});
}

const {
data: oldData,
columns: oldColumns,
...oldTableProps
} = (OldTable as ReactElement).props;

return (
<Table
darkMode={darkMode}
Expand All @@ -100,12 +119,19 @@ const V11Adapter = <T extends LGRowData>({
}
className={className}
ref={containerRef}
{...oldTableProps}
>
<TableHead>
<HeaderRow>
{table.getHeaderGroups()[0].headers.map(header => {
<HeaderRow {...oldHeaderRow.props}>
{table.getHeaderGroups()[0].headers.map((header, i) => {
return (
<HeaderCell key={header.id} header={header}>
// https://jira.mongodb.org/browse/LG-3538
// @ts-expect-error
<HeaderCell
key={header.id}
header={header}
{...oldHeaderCellProps[i]}
>
{flexRender(
header.column.columnDef.header,
header.getContext(),
Expand All @@ -127,24 +153,35 @@ const V11Adapter = <T extends LGRowData>({
virtualRow={
useVirtualScrolling ? (iterable as VirtualItem) : undefined
}
// https://jira.mongodb.org/browse/LG-3538
// @ts-expect-error rowProps is an additional prop passed by the `processData` function
{...row.original.rowProps}
>
{row.getVisibleCells().map((cell: LeafyGreenTableCell<any>) => {
if (cell?.column?.id) {
if (cell?.column?.id === 'select') {
return (
<Cell key={cell.column.id}>
{/* https://jira.mongodb.org/browse/LG-3538 */}
{/* @ts-expect-error `cell` is instantiated in `processColumns` */}
{cell.column.columnDef?.cell({ row, table })}
</Cell>
);
} else {
const cellChild =
// index by row.index (not the index of the loop) to get the sorted order
// https://jira.mongodb.org/browse/LG-3538
// @ts-expect-error `processedData` is structured to be indexable by `row.index`
processedData[row.index]?.[cell.column.id]?.();
const {
children,
isHeader,
isDisabled,
...cellChildProps
} = cellChild.props;
return cellChild ? (
<Cell key={cell.id} {...cellChild?.props}>
<>{cellChild?.props.children}</>
<Cell key={cell.id} {...cellChildProps}>
<>{children}</>
</Cell>
) : (
<></>
Expand All @@ -158,18 +195,31 @@ const V11Adapter = <T extends LGRowData>({
<ExpandedContent row={row} />
)}
{row.subRows &&
row.subRows.map(subRow => (
<Row key={subRow.id} row={subRow}>
{subRow.getVisibleCells().map(subRowCell => {
return (
<Cell key={subRowCell.id}>
{/* @ts-expect-error subRow.original returns the object in the user's defined shape, and should be string indexable */}
{subRow.original[subRowCell.column.id]()}
</Cell>
);
})}
</Row>
))}
row.subRows.map(subRow => {
// https://jira.mongodb.org/browse/LG-3538
// @ts-expect-error rowProps is an additional prop passed by the `processData` function
const { children, ...subRowProps } = subRow.original.rowProps;
return (
<Row key={subRow.id} row={subRow} {...subRowProps}>
{subRow.getVisibleCells().map(srCell => {
// https://jira.mongodb.org/browse/LG-3538
// @ts-expect-error subRow.original returns the object in the user's defined shape, and should be string indexable
const subRowCell = subRow.original[srCell.column.id]();
const {
children,
isHeader,
isDisabled,
...subRowCellProps
} = subRowCell.props;
return (
<Cell key={subRowCell.id} {...subRowCellProps}>
{children}
</Cell>
);
})}
</Row>
);
})}
</Row>
);
})}
Expand Down
4 changes: 3 additions & 1 deletion packages/table/src/V11Adapter/processColumns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ const processColumns = <T extends LGRowData>(
) => {
const indexA = rowA.index;
const indexB = rowB.index;
// https://jira.mongodb.org/browse/LG-3538
// @ts-expect-error each datum is designed to be indexable by string
return data[indexA][columnId] > data[indexB][columnId]
? -1
: // @ts-expect-error each datum is designed to be indexable by string
: // https://jira.mongodb.org/browse/LG-3538
// @ts-expect-error each datum is designed to be indexable by string
data[indexB][columnId] > data[indexA][columnId]
? 1
: 0;
Expand Down
16 changes: 13 additions & 3 deletions packages/table/src/V11Adapter/processData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,26 @@ const processData = <T extends LGRowData>(
...acc,
// TODO: remove as any
[(processedColumns[index] as any)?.accessorKey]: () =>
(currVal as ReactElement).props.children,
currVal as ReactElement,
};
},
{},
);
newDatum.subRows.push(processedSubRow);
const {
children,
expanded,
indentLevel,
isAnyAncestorCollapsed,
...rowProps
} = (subRow as ReactElement).props;
newDatum.subRows.push({
...processedSubRow,
rowProps,
});
}
});

return newDatum;
return { ...newDatum, rowProps: (evaluatedRow as ReactElement).props };
});
return processedData;
};
Expand Down

0 comments on commit f8bfa38

Please sign in to comment.