@hyphen/hyphen-components 9.0.0-beta.0 → 9.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.
- 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/Box/Box.mdx +3 -0
- package/src/components/Button/Button.mdx +13 -1
- 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/docs/GetStarted.mdx +7 -0
- package/src/docs/PolymorphicComposition.mdx +184 -0
- 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
|
|
3
|
+
"version": "9.0.0",
|
|
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
|
|
59
|
+
"@hyphen/hyphen-design-tokens": "^9.0.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@babel/core": "^7.27.4",
|
|
@@ -13,6 +13,9 @@ A `<Box>` is a layout component to build UIs with consistent padding and spacing
|
|
|
13
13
|
- Allows you to specify the spacing between child elements using `gap`
|
|
14
14
|
- Many props accept `ResponsiveProp` that take an object with keys that correspond to [breakpoint tokens](?path=/docs/foundation-design-tokens--docs#breakpoints).
|
|
15
15
|
|
|
16
|
+
See [Polymorphic Composition](?path=/docs/about-polymorphic-composition--docs)
|
|
17
|
+
for native element, router component, ref, and extracted prop object patterns.
|
|
18
|
+
|
|
16
19
|
<Canvas of={Stories.Overview} />
|
|
17
20
|
|
|
18
21
|
## Props
|
|
@@ -75,4 +75,16 @@ The interface should make it clear why the button is disabled and what needs to
|
|
|
75
75
|
|
|
76
76
|
## As Child
|
|
77
77
|
|
|
78
|
-
Apply the `asChild` prop to apply the button styles to
|
|
78
|
+
Apply the `asChild` prop to apply the button styles to one child element. This
|
|
79
|
+
keeps navigation semantics when a link needs to look like a button and prevents
|
|
80
|
+
nested interactive elements.
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<Button asChild>
|
|
84
|
+
<a href="/settings">Settings</a>
|
|
85
|
+
</Button>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Place navigation props on the child and Button props on `Button`. See
|
|
89
|
+
[Polymorphic Composition](?path=/docs/about-polymorphic-composition--docs) for
|
|
90
|
+
router links, custom ref-forwarding children, and accessibility guidance.
|
|
@@ -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/docs/GetStarted.mdx
CHANGED
|
@@ -45,3 +45,10 @@ function App() {
|
|
|
45
45
|
|
|
46
46
|
ReactDOM.render(<App />, document.querySelector('#app'));
|
|
47
47
|
```
|
|
48
|
+
|
|
49
|
+
### 6. Compose with the right element
|
|
50
|
+
|
|
51
|
+
Use `as` or `asChild` when a Hyphen component needs to render with different
|
|
52
|
+
HTML semantics or reuse a router link or trigger. See
|
|
53
|
+
[Polymorphic Composition](?path=/docs/about-polymorphic-composition--docs) for
|
|
54
|
+
the supported patterns and accessibility guidance.
|