@hyphen/hyphen-components 9.0.0-beta.0 → 9.0.0-beta.1
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.
- package/dist/css/utilities.css +1 -1
- package/dist/css/utilities.css.map +1 -1
- package/dist/hyphen-components.cjs.development.js +11 -2
- package/dist/hyphen-components.cjs.development.js.map +1 -1
- package/dist/hyphen-components.cjs.production.min.js +2 -2
- package/dist/hyphen-components.cjs.production.min.js.map +1 -1
- package/dist/hyphen-components.esm.js +11 -2
- package/dist/hyphen-components.esm.js.map +1 -1
- package/dist/index.d.ts +10 -10
- package/package.json +2 -2
- package/src/components/Table/Table.mdx +20 -0
- package/src/components/Table/Table.tsx +7 -7
- package/src/components/Table/TableBody/TableBody.test.tsx +89 -1
- package/src/components/Table/TableBody/TableBody.tsx +23 -8
- package/src/components/Table/TableHead/TableHead.tsx +6 -6
- package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.tsx +6 -6
- package/src/components/Table/common/TableRow/TableRow.test.tsx +1 -1
- package/src/components/Table/common/TableRow/TableRow.tsx +11 -9
- package/src/lib/getColumnKeys.ts +5 -3
- package/src/types/index.ts +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ declare type ResponsiveProp<T> = {
|
|
|
55
55
|
};
|
|
56
56
|
type Row = UnknownPropertiesObjType;
|
|
57
57
|
type Cell = Row[string];
|
|
58
|
-
declare type Column = {
|
|
58
|
+
declare type Column<TRow extends object = Row> = {
|
|
59
59
|
/**
|
|
60
60
|
* Text alignment for column cells (including header alignment). Cells will default to left if not defined.
|
|
61
61
|
*/
|
|
@@ -63,11 +63,11 @@ declare type Column = {
|
|
|
63
63
|
/**
|
|
64
64
|
* CSS Class to be applied uniformly to all individual cells in a column.
|
|
65
65
|
*/
|
|
66
|
-
cellClassName?: string | ((cell?: Cell, row?:
|
|
66
|
+
cellClassName?: string | ((cell?: Cell, row?: TRow, rowIndex?: number) => string);
|
|
67
67
|
/**
|
|
68
68
|
* The key value to be rendered based on the table `rows`.
|
|
69
69
|
*/
|
|
70
|
-
dataKey?: string
|
|
70
|
+
dataKey?: Extract<keyof TRow, string>;
|
|
71
71
|
/**
|
|
72
72
|
* Placeholder for empty cells Applies only to the cells of the particular column with this prop.
|
|
73
73
|
*/
|
|
@@ -93,7 +93,7 @@ declare type Column = {
|
|
|
93
93
|
* Render method for column cell data. Provides ability to render any aspect of the cell/row with custom
|
|
94
94
|
* markup.
|
|
95
95
|
*/
|
|
96
|
-
render?: (cell?: Cell, row?:
|
|
96
|
+
render?: (cell?: Cell, row?: TRow, rowIndex?: number) => ReactNode;
|
|
97
97
|
/**
|
|
98
98
|
* Whether the column is stuck to the left or right.
|
|
99
99
|
*/
|
|
@@ -2401,20 +2401,20 @@ interface SwitchProps {
|
|
|
2401
2401
|
}
|
|
2402
2402
|
declare const Switch: FC<SwitchProps>;
|
|
2403
2403
|
|
|
2404
|
-
interface TableProps {
|
|
2404
|
+
interface TableProps<TRow extends object = Row> {
|
|
2405
2405
|
/**
|
|
2406
2406
|
* Columns for the table. See Column definition below for details.
|
|
2407
2407
|
*/
|
|
2408
|
-
columns: Column[];
|
|
2408
|
+
columns: Column<TRow>[];
|
|
2409
2409
|
/**
|
|
2410
2410
|
* The data rows to be displayed
|
|
2411
2411
|
*/
|
|
2412
|
-
rows:
|
|
2412
|
+
rows: TRow[];
|
|
2413
2413
|
/**
|
|
2414
2414
|
* Key that represents a unique value for a row. This is necessary in
|
|
2415
2415
|
* order to supply React with a node key on each row.
|
|
2416
2416
|
*/
|
|
2417
|
-
rowKey: string
|
|
2417
|
+
rowKey: Extract<keyof TRow, string>;
|
|
2418
2418
|
/**
|
|
2419
2419
|
* Additional classes to add.
|
|
2420
2420
|
*/
|
|
@@ -2484,7 +2484,7 @@ interface TableProps {
|
|
|
2484
2484
|
*/
|
|
2485
2485
|
truncateOverflow?: boolean;
|
|
2486
2486
|
}
|
|
2487
|
-
declare const Table:
|
|
2487
|
+
declare const Table: <TRow extends object = Row>({ columns, rows, rowKey, align, className, emptyCellPlaceholder, hoverableRows, isBorderless, isCompact, hasStickyHeader, isLoading, isScrollable, isStriped, onSort, sortedColumn, useFixedTableLayout, truncateOverflow, }: TableProps<TRow>) => React__default.JSX.Element;
|
|
2488
2488
|
|
|
2489
2489
|
type Theme = 'dark' | 'light' | 'system';
|
|
2490
2490
|
type ThemeProviderProps = {
|
|
@@ -2729,7 +2729,7 @@ declare function generateResponsiveClasses(classRoot: string, value: ResponsiveP
|
|
|
2729
2729
|
|
|
2730
2730
|
declare function getAutoCompleteValue(value: string | boolean): string;
|
|
2731
2731
|
|
|
2732
|
-
declare const getColumnKeys: (columns: Column[]) => Key[];
|
|
2732
|
+
declare const getColumnKeys: <TRow extends object = Row>(columns: Column<TRow>[]) => Key[];
|
|
2733
2733
|
|
|
2734
2734
|
declare function getDimensionStyles(dimension: CssDimensionAbbreviation, value?: DimensionSize | ResponsiveProp<DimensionSize> | string): {
|
|
2735
2735
|
[key: string]: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyphen/hyphen-components",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "@hyphen"
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"react-select": "^5.10.0",
|
|
57
57
|
"react-select-event": "^5.5.1",
|
|
58
58
|
"uuid": "^11.1.1",
|
|
59
|
-
"@hyphen/hyphen-design-tokens": "^9.0.0-beta.
|
|
59
|
+
"@hyphen/hyphen-design-tokens": "^9.0.0-beta.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@babel/core": "^7.27.4",
|
|
@@ -30,6 +30,26 @@ An example showcasing the props required to render a list of customers in a tabl
|
|
|
30
30
|
|
|
31
31
|
<Canvas of={Stories.CommonExample} />
|
|
32
32
|
|
|
33
|
+
## TypeScript row types
|
|
34
|
+
|
|
35
|
+
`Table` accepts interfaces and infers its row type from `rows`. Type separately declared columns with `Column<TRow>[]` to validate `dataKey` values and type the `row` argument passed to render callbacks.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
interface Customer {
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const columns: Column<Customer>[] = [
|
|
44
|
+
{
|
|
45
|
+
dataKey: 'name',
|
|
46
|
+
render: (_cell, row) => row?.name,
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
<Table columns={columns} rows={customers} rowKey="id" />;
|
|
51
|
+
```
|
|
52
|
+
|
|
33
53
|
## Loading
|
|
34
54
|
|
|
35
55
|
Use the `isLoading` prop on the `<Table />` component to display an overlay that prevents user interaction. Useful for when
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { Column, Row, EventWithColumnKey } from '../../types';
|
|
4
4
|
import { Spinner } from '../Spinner/Spinner';
|
|
@@ -6,20 +6,20 @@ import styles from './Table.module.scss';
|
|
|
6
6
|
import { TableBody } from './TableBody/TableBody';
|
|
7
7
|
import { TableHead } from './TableHead/TableHead';
|
|
8
8
|
|
|
9
|
-
export interface TableProps {
|
|
9
|
+
export interface TableProps<TRow extends object = Row> {
|
|
10
10
|
/**
|
|
11
11
|
* Columns for the table. See Column definition below for details.
|
|
12
12
|
*/
|
|
13
|
-
columns: Column[];
|
|
13
|
+
columns: Column<TRow>[];
|
|
14
14
|
/**
|
|
15
15
|
* The data rows to be displayed
|
|
16
16
|
*/
|
|
17
|
-
rows:
|
|
17
|
+
rows: TRow[];
|
|
18
18
|
/**
|
|
19
19
|
* Key that represents a unique value for a row. This is necessary in
|
|
20
20
|
* order to supply React with a node key on each row.
|
|
21
21
|
*/
|
|
22
|
-
rowKey: string
|
|
22
|
+
rowKey: Extract<keyof TRow, string>;
|
|
23
23
|
/**
|
|
24
24
|
* Additional classes to add.
|
|
25
25
|
*/
|
|
@@ -90,7 +90,7 @@ export interface TableProps {
|
|
|
90
90
|
truncateOverflow?: boolean;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
export const Table
|
|
93
|
+
export const Table = <TRow extends object = Row,>({
|
|
94
94
|
columns,
|
|
95
95
|
rows,
|
|
96
96
|
rowKey,
|
|
@@ -108,7 +108,7 @@ export const Table: FC<TableProps> = ({
|
|
|
108
108
|
sortedColumn = undefined,
|
|
109
109
|
useFixedTableLayout = false,
|
|
110
110
|
truncateOverflow = false,
|
|
111
|
-
}) => {
|
|
111
|
+
}: TableProps<TRow>) => {
|
|
112
112
|
const containerClasses = classNames(styles.container, {
|
|
113
113
|
[styles['full-height']]: !!isScrollable?.y,
|
|
114
114
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
3
|
+
import type { Column } from '../../../types';
|
|
3
4
|
import { TableBody } from './TableBody';
|
|
4
5
|
|
|
5
6
|
const columns = [
|
|
@@ -14,6 +15,18 @@ const rows = [
|
|
|
14
15
|
{ id: 3, color: 'green', flavor: 'strawberry' },
|
|
15
16
|
];
|
|
16
17
|
|
|
18
|
+
const inputColumns: Column<(typeof rows)[number]>[] = [
|
|
19
|
+
{
|
|
20
|
+
dataKey: 'color',
|
|
21
|
+
render: (_cell, row) => (
|
|
22
|
+
<input
|
|
23
|
+
aria-label={`Color for row ${row?.id}`}
|
|
24
|
+
defaultValue={row?.color}
|
|
25
|
+
/>
|
|
26
|
+
),
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
|
|
17
30
|
describe('TableBody', () => {
|
|
18
31
|
test("It renders with striped rows if passed 'isStriped' prop", () => {
|
|
19
32
|
render(<TableBody columns={columns} rows={rows} rowKey="id" isStriped />);
|
|
@@ -35,4 +48,79 @@ describe('TableBody', () => {
|
|
|
35
48
|
const tableBody = screen.getByRole('rowgroup');
|
|
36
49
|
expect(tableBody).toHaveClass('my-custom-class');
|
|
37
50
|
});
|
|
51
|
+
|
|
52
|
+
test('It preserves row identity when rows are reordered', () => {
|
|
53
|
+
const { rerender } = render(
|
|
54
|
+
<table>
|
|
55
|
+
<TableBody columns={inputColumns} rows={rows} rowKey="id" />
|
|
56
|
+
</table>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
fireEvent.change(screen.getByLabelText('Color for row 1'), {
|
|
60
|
+
target: { value: 'purple' },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
rerender(
|
|
64
|
+
<table>
|
|
65
|
+
<TableBody
|
|
66
|
+
columns={inputColumns}
|
|
67
|
+
rows={[...rows].reverse()}
|
|
68
|
+
rowKey="id"
|
|
69
|
+
/>
|
|
70
|
+
</table>
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
expect(screen.getByLabelText('Color for row 1')).toHaveValue('purple');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('It avoids duplicate keys when row key values cannot be used', () => {
|
|
77
|
+
const consoleError = jest.spyOn(console, 'error').mockImplementation();
|
|
78
|
+
const rowsWithoutUsableKeys = [
|
|
79
|
+
{ id: undefined, color: 'red' },
|
|
80
|
+
{ id: undefined, color: 'blue' },
|
|
81
|
+
{ id: null, color: 'green' },
|
|
82
|
+
{ id: null, color: 'yellow' },
|
|
83
|
+
{ id: {}, color: 'black' },
|
|
84
|
+
{ id: {}, color: 'white' },
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
render(
|
|
88
|
+
<table>
|
|
89
|
+
<TableBody
|
|
90
|
+
columns={[{ dataKey: 'color' }]}
|
|
91
|
+
rows={rowsWithoutUsableKeys}
|
|
92
|
+
rowKey="id"
|
|
93
|
+
/>
|
|
94
|
+
</table>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const duplicateKeyWarnings = consoleError.mock.calls.filter((call) =>
|
|
98
|
+
call.some(
|
|
99
|
+
(argument) =>
|
|
100
|
+
typeof argument === 'string' &&
|
|
101
|
+
argument.includes('Encountered two children with the same key')
|
|
102
|
+
)
|
|
103
|
+
);
|
|
104
|
+
consoleError.mockRestore();
|
|
105
|
+
|
|
106
|
+
expect(duplicateKeyWarnings).toHaveLength(0);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('It handles nullish row values at runtime', () => {
|
|
110
|
+
const rowsWithNullishValues = [undefined, null] as unknown as typeof rows;
|
|
111
|
+
|
|
112
|
+
expect(() =>
|
|
113
|
+
render(
|
|
114
|
+
<table>
|
|
115
|
+
<TableBody
|
|
116
|
+
columns={columns}
|
|
117
|
+
rows={rowsWithNullishValues}
|
|
118
|
+
rowKey="id"
|
|
119
|
+
/>
|
|
120
|
+
</table>
|
|
121
|
+
)
|
|
122
|
+
).not.toThrow();
|
|
123
|
+
|
|
124
|
+
expect(screen.getAllByRole('row')).toHaveLength(2);
|
|
125
|
+
});
|
|
38
126
|
});
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import styles from './TableBody.module.scss';
|
|
4
4
|
import { Column, Row } from '../../../types';
|
|
5
5
|
import { TableRow } from '../common/TableRow/TableRow';
|
|
6
6
|
|
|
7
|
-
export interface TableBodyProps {
|
|
7
|
+
export interface TableBodyProps<TRow extends object = Row> {
|
|
8
8
|
/**
|
|
9
9
|
* The table columns to be rendered
|
|
10
10
|
*/
|
|
11
|
-
columns: Column[];
|
|
11
|
+
columns: Column<TRow>[];
|
|
12
12
|
/**
|
|
13
13
|
* The unique key to identify a React node for each row.
|
|
14
14
|
*/
|
|
15
|
-
rowKey:
|
|
15
|
+
rowKey: Extract<keyof TRow, string>;
|
|
16
16
|
/**
|
|
17
17
|
* The table rows to be rendered
|
|
18
18
|
*/
|
|
19
|
-
rows:
|
|
19
|
+
rows: TRow[];
|
|
20
20
|
/**
|
|
21
21
|
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
22
22
|
* for a specific column.
|
|
@@ -54,9 +54,10 @@ export interface TableBodyProps {
|
|
|
54
54
|
truncateOverflow?: boolean;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export const TableBody
|
|
57
|
+
export const TableBody = <TRow extends object = Row,>({
|
|
58
58
|
columns,
|
|
59
59
|
rows,
|
|
60
|
+
rowKey,
|
|
60
61
|
align = 'left',
|
|
61
62
|
className = '',
|
|
62
63
|
emptyCellPlaceholder = '',
|
|
@@ -65,7 +66,7 @@ export const TableBody: FC<TableBodyProps> = ({
|
|
|
65
66
|
isCompact = false,
|
|
66
67
|
isStriped = false,
|
|
67
68
|
truncateOverflow = false,
|
|
68
|
-
}) => {
|
|
69
|
+
}: TableBodyProps<TRow>) => {
|
|
69
70
|
const tableBodyClasses = classNames(
|
|
70
71
|
styles['table-body'],
|
|
71
72
|
{
|
|
@@ -75,6 +76,20 @@ export const TableBody: FC<TableBodyProps> = ({
|
|
|
75
76
|
className
|
|
76
77
|
);
|
|
77
78
|
|
|
79
|
+
const getRowKey = (row: TRow, rowIndex: number): string => {
|
|
80
|
+
const keyValue = row?.[rowKey];
|
|
81
|
+
|
|
82
|
+
if (
|
|
83
|
+
typeof keyValue === 'string' ||
|
|
84
|
+
typeof keyValue === 'number' ||
|
|
85
|
+
typeof keyValue === 'bigint'
|
|
86
|
+
) {
|
|
87
|
+
return `row-key-${String(keyValue)}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return `row-index-${rowIndex}`;
|
|
91
|
+
};
|
|
92
|
+
|
|
78
93
|
return (
|
|
79
94
|
<tbody className={tableBodyClasses}>
|
|
80
95
|
{rows.map((row, rowIndex) => (
|
|
@@ -83,7 +98,7 @@ export const TableBody: FC<TableBodyProps> = ({
|
|
|
83
98
|
row={row}
|
|
84
99
|
rowIndex={rowIndex}
|
|
85
100
|
align={align}
|
|
86
|
-
key={rowIndex}
|
|
101
|
+
key={getRowKey(row, rowIndex)}
|
|
87
102
|
emptyCellPlaceholder={emptyCellPlaceholder}
|
|
88
103
|
truncateOverflow={truncateOverflow}
|
|
89
104
|
isBorderless={isBorderless}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import { Column, EventWithColumnKey } from '../../../types';
|
|
3
|
+
import { Column, EventWithColumnKey, Row } from '../../../types';
|
|
4
4
|
import { TableRow } from '../common/TableRow/TableRow';
|
|
5
5
|
|
|
6
|
-
export interface TableHeadProps {
|
|
6
|
+
export interface TableHeadProps<TRow extends object = Row> {
|
|
7
7
|
/**
|
|
8
8
|
* The table columns to be rendered
|
|
9
9
|
*/
|
|
10
|
-
columns: Column[];
|
|
10
|
+
columns: Column<TRow>[];
|
|
11
11
|
/**
|
|
12
12
|
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
13
13
|
* for a specific column.
|
|
@@ -47,7 +47,7 @@ export interface TableHeadProps {
|
|
|
47
47
|
truncateOverflow?: boolean;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export const TableHead
|
|
50
|
+
export const TableHead = <TRow extends object = Row,>({
|
|
51
51
|
columns,
|
|
52
52
|
align = 'left',
|
|
53
53
|
className = '',
|
|
@@ -57,7 +57,7 @@ export const TableHead: FC<TableHeadProps> = ({
|
|
|
57
57
|
onSort = undefined,
|
|
58
58
|
sortedColumn = undefined,
|
|
59
59
|
truncateOverflow = false,
|
|
60
|
-
}) => {
|
|
60
|
+
}: TableHeadProps<TRow>) => {
|
|
61
61
|
const tableHeadClasses = classNames(className);
|
|
62
62
|
|
|
63
63
|
return (
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { Key, KeyboardEvent, MouseEvent, ReactNode } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { Box } from '../../../Box/Box';
|
|
4
4
|
import { Icon } from '../../../Icon/Icon';
|
|
5
|
-
import { Column, EventWithColumnKey } from '../../../../types';
|
|
5
|
+
import { Column, EventWithColumnKey, Row } from '../../../../types';
|
|
6
6
|
import styles from './TableHeaderCell.module.scss';
|
|
7
7
|
|
|
8
|
-
export interface TableHeaderCellProps {
|
|
8
|
+
export interface TableHeaderCellProps<TRow extends object = Row> {
|
|
9
9
|
/**
|
|
10
10
|
* Title to display for the column.
|
|
11
11
|
*/
|
|
12
|
-
column: Column
|
|
12
|
+
column: Column<TRow>;
|
|
13
13
|
/**
|
|
14
14
|
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
15
15
|
* for a specific column.
|
|
@@ -69,7 +69,7 @@ export interface TableHeaderCellProps {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
// eslint-disable-line import/prefer-default-export
|
|
72
|
-
export const TableHeaderCell
|
|
72
|
+
export const TableHeaderCell = <TRow extends object = Row,>({
|
|
73
73
|
column,
|
|
74
74
|
align = 'left',
|
|
75
75
|
className = undefined,
|
|
@@ -83,7 +83,7 @@ export const TableHeaderCell: FC<TableHeaderCellProps> = ({
|
|
|
83
83
|
sticky = undefined,
|
|
84
84
|
truncateOverflow = false,
|
|
85
85
|
width = undefined,
|
|
86
|
-
}) => {
|
|
86
|
+
}: TableHeaderCellProps<TRow>) => {
|
|
87
87
|
const isColumnSorted = (columnDataKey: Key | undefined): boolean =>
|
|
88
88
|
!!sortedColumn && sortedColumn.dataKey === columnDataKey;
|
|
89
89
|
|
|
@@ -33,7 +33,7 @@ describe('TableRow', () => {
|
|
|
33
33
|
render(
|
|
34
34
|
<TableRow row={row} rowIndex={rowIndex} columns={customClassCell} />
|
|
35
35
|
);
|
|
36
|
-
expect(func).toHaveBeenCalledWith(
|
|
36
|
+
expect(func).toHaveBeenCalledWith(row.id, row, rowIndex);
|
|
37
37
|
const element = document.getElementsByClassName('my-custom-class')[0];
|
|
38
38
|
expect(element).toBeInTheDocument();
|
|
39
39
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import styles from './TableRow.module.scss';
|
|
4
4
|
import { Column, EventWithColumnKey, Row } from '../../../../types';
|
|
@@ -6,11 +6,11 @@ import { getColumnKeys } from '../../../../lib/getColumnKeys';
|
|
|
6
6
|
import TableBodyCell from '../../TableBody/TableBodyCell/TableBodyCell';
|
|
7
7
|
import { TableHeaderCell } from '../../TableHead/TableHeaderCell/TableHeaderCell';
|
|
8
8
|
|
|
9
|
-
export interface TableRowProps {
|
|
9
|
+
export interface TableRowProps<TRow extends object = Row> {
|
|
10
10
|
/**
|
|
11
11
|
* The table columns to be rendered
|
|
12
12
|
*/
|
|
13
|
-
columns: Column[];
|
|
13
|
+
columns: Column<TRow>[];
|
|
14
14
|
/**
|
|
15
15
|
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
16
16
|
* for a specific column.
|
|
@@ -52,7 +52,7 @@ export interface TableRowProps {
|
|
|
52
52
|
/**
|
|
53
53
|
* The specific row to be rendered.
|
|
54
54
|
*/
|
|
55
|
-
row?:
|
|
55
|
+
row?: TRow;
|
|
56
56
|
/**
|
|
57
57
|
* The unique key to identify a React node for each row.
|
|
58
58
|
*/
|
|
@@ -71,7 +71,7 @@ export interface TableRowProps {
|
|
|
71
71
|
truncateOverflow?: boolean;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
export const TableRow
|
|
74
|
+
export const TableRow = <TRow extends object = Row,>({
|
|
75
75
|
columns,
|
|
76
76
|
align = 'left',
|
|
77
77
|
className = '',
|
|
@@ -86,7 +86,7 @@ export const TableRow: FC<TableRowProps> = ({
|
|
|
86
86
|
row = undefined,
|
|
87
87
|
rowIndex = undefined,
|
|
88
88
|
truncateOverflow = false,
|
|
89
|
-
}) => {
|
|
89
|
+
}: TableRowProps<TRow>) => {
|
|
90
90
|
const tableRowClasses = classNames(
|
|
91
91
|
styles['table-row'],
|
|
92
92
|
{ [styles.hoverable]: isHoverable },
|
|
@@ -110,7 +110,7 @@ export const TableRow: FC<TableRowProps> = ({
|
|
|
110
110
|
return React.isValidElement(value);
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
-
const renderCellContent = (column: Column): ReactNode => {
|
|
113
|
+
const renderCellContent = (column: Column<TRow>): ReactNode => {
|
|
114
114
|
if (column.render) {
|
|
115
115
|
const cellValue = column.dataKey && row ? row[column.dataKey] : undefined;
|
|
116
116
|
return column.render(cellValue, row, rowIndex);
|
|
@@ -120,10 +120,12 @@ export const TableRow: FC<TableRowProps> = ({
|
|
|
120
120
|
return isRenderableCell(cellValue) ? cellValue : null;
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
const getCellClassName = (column: Column): string | undefined => {
|
|
123
|
+
const getCellClassName = (column: Column<TRow>): string | undefined => {
|
|
124
124
|
if (column.cellClassName) {
|
|
125
125
|
if (typeof column.cellClassName === 'function') {
|
|
126
|
-
|
|
126
|
+
const cellValue =
|
|
127
|
+
column.dataKey && row ? row[column.dataKey] : undefined;
|
|
128
|
+
return column.cellClassName(cellValue, row, rowIndex);
|
|
127
129
|
}
|
|
128
130
|
return column.cellClassName;
|
|
129
131
|
}
|
package/src/lib/getColumnKeys.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Key } from 'react';
|
|
2
|
-
import { Column } from '../types';
|
|
2
|
+
import { Column, Row } from '../types';
|
|
3
3
|
|
|
4
4
|
// eslint-disable-next-line import/prefer-default-export
|
|
5
|
-
export const getColumnKeys =
|
|
5
|
+
export const getColumnKeys = <TRow extends object = Row>(
|
|
6
|
+
columns: Column<TRow>[]
|
|
7
|
+
): Key[] => {
|
|
6
8
|
const INTERNAL_KEY_PREFIX = 'columnKeyPrefix';
|
|
7
|
-
const columnKeys:
|
|
9
|
+
const columnKeys: Key[] = [];
|
|
8
10
|
const keys: Record<string, boolean> = {};
|
|
9
11
|
|
|
10
12
|
columns.forEach((column) => {
|
package/src/types/index.ts
CHANGED
|
@@ -149,7 +149,7 @@ export type Row = UnknownPropertiesObjType;
|
|
|
149
149
|
|
|
150
150
|
export type Cell = Row[string];
|
|
151
151
|
|
|
152
|
-
export declare type Column = {
|
|
152
|
+
export declare type Column<TRow extends object = Row> = {
|
|
153
153
|
/**
|
|
154
154
|
* Text alignment for column cells (including header alignment). Cells will default to left if not defined.
|
|
155
155
|
*/
|
|
@@ -159,11 +159,11 @@ export declare type Column = {
|
|
|
159
159
|
*/
|
|
160
160
|
cellClassName?:
|
|
161
161
|
| string
|
|
162
|
-
| ((cell?: Cell, row?:
|
|
162
|
+
| ((cell?: Cell, row?: TRow, rowIndex?: number) => string);
|
|
163
163
|
/**
|
|
164
164
|
* The key value to be rendered based on the table `rows`.
|
|
165
165
|
*/
|
|
166
|
-
dataKey?: string
|
|
166
|
+
dataKey?: Extract<keyof TRow, string>;
|
|
167
167
|
/**
|
|
168
168
|
* Placeholder for empty cells Applies only to the cells of the particular column with this prop.
|
|
169
169
|
*/
|
|
@@ -189,7 +189,7 @@ export declare type Column = {
|
|
|
189
189
|
* Render method for column cell data. Provides ability to render any aspect of the cell/row with custom
|
|
190
190
|
* markup.
|
|
191
191
|
*/
|
|
192
|
-
render?: (cell?: Cell, row?:
|
|
192
|
+
render?: (cell?: Cell, row?: TRow, rowIndex?: number) => ReactNode;
|
|
193
193
|
/**
|
|
194
194
|
* Whether the column is stuck to the left or right.
|
|
195
195
|
*/
|