@indico-data/design-system 2.49.0 → 2.51.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/lib/components/tanstackTable/TankstackTable.types.d.ts +40 -0
- package/lib/components/tanstackTable/TanstackTable.stories.d.ts +15 -0
- package/lib/components/tanstackTable/TanstakTable.d.ts +4 -0
- package/lib/components/tanstackTable/__tests__/TanstackTable.test.d.ts +1 -0
- package/lib/components/tanstackTable/__tests__/__mocks__/test-mock-data.d.ts +8 -0
- package/lib/components/tanstackTable/components/ActionBar/ActionBar.d.ts +17 -0
- package/lib/components/tanstackTable/components/ActionBar/ActionBar.stories.d.ts +10 -0
- package/lib/components/tanstackTable/components/ActionBar/__tests__/ActionBar.test.d.ts +1 -0
- package/lib/components/tanstackTable/components/ActionBar/index.d.ts +1 -0
- package/lib/components/tanstackTable/components/NoResults/NoResults.d.ts +7 -0
- package/lib/components/tanstackTable/components/NoResults/__tests__/NoResult.test.d.ts +1 -0
- package/lib/components/tanstackTable/components/NoResults/index.d.ts +1 -0
- package/lib/components/tanstackTable/components/TableBody/TableBody.d.ts +12 -0
- package/lib/components/tanstackTable/components/TableBody/index.d.ts +1 -0
- package/lib/components/tanstackTable/components/TableHeader/TableHeader.d.ts +6 -0
- package/lib/components/tanstackTable/components/TableHeader/index.d.ts +1 -0
- package/lib/components/tanstackTable/components/TablePagination/TablePagination.d.ts +9 -0
- package/lib/components/tanstackTable/components/TablePagination/__tests__/TablePagination.test.d.ts +1 -0
- package/lib/components/tanstackTable/components/TablePagination/index.d.ts +1 -0
- package/lib/components/tanstackTable/docs/pinnedColumns/PinnedColumn.stories.d.ts +7 -0
- package/lib/components/tanstackTable/docs/withRowClick/WithRowClick.stories.d.ts +7 -0
- package/lib/components/tanstackTable/helpers.d.ts +830 -0
- package/lib/components/tanstackTable/index.d.ts +2 -0
- package/lib/components/tanstackTable/mock-data/mock-data.d.ts +14 -0
- package/lib/components/tanstackTable/mock-data/table-configuration.d.ts +3 -0
- package/lib/components/tanstackTable/useTanstackTable.d.ts +16 -0
- package/lib/index.css +407 -80
- package/lib/index.d.ts +62 -17
- package/lib/index.esm.css +407 -80
- package/lib/index.esm.js +20455 -56
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +20455 -55
- package/lib/index.js.map +1 -1
- package/lib/stylesAndAnimations/utilityClasses/UtilityClassesData.d.ts +7 -0
- package/lib/stylesAndAnimations/utilityClasses/UtilityClassesTable.d.ts +1 -0
- package/lib/stylesAndAnimations/utilityClasses/UtilityClassesTable.stories.d.ts +6 -0
- package/package.json +2 -1
- package/src/components/tanstackTable/TankstackTable.types.ts +39 -0
- package/src/components/tanstackTable/TanstackTable.mdx +122 -0
- package/src/components/tanstackTable/TanstackTable.stories.tsx +260 -0
- package/src/components/tanstackTable/TanstakTable.tsx +157 -0
- package/src/components/tanstackTable/__tests__/TanstackTable.test.tsx +87 -0
- package/src/components/tanstackTable/__tests__/__mocks__/test-mock-data.tsx +83 -0
- package/src/components/tanstackTable/components/ActionBar/ActionBar.mdx +10 -0
- package/src/components/tanstackTable/components/ActionBar/ActionBar.scss +30 -0
- package/src/components/tanstackTable/components/ActionBar/ActionBar.stories.tsx +98 -0
- package/src/components/tanstackTable/components/ActionBar/ActionBar.tsx +51 -0
- package/src/components/tanstackTable/components/ActionBar/__tests__/ActionBar.test.tsx +87 -0
- package/src/components/tanstackTable/components/ActionBar/index.ts +1 -0
- package/src/components/tanstackTable/components/NoResults/NoResults.scss +24 -0
- package/src/components/tanstackTable/components/NoResults/NoResults.tsx +22 -0
- package/src/components/tanstackTable/components/NoResults/__tests__/NoResult.test.tsx +25 -0
- package/src/components/tanstackTable/components/NoResults/index.ts +1 -0
- package/src/components/tanstackTable/components/TableBody/TableBody.tsx +87 -0
- package/src/components/tanstackTable/components/TableBody/index.ts +1 -0
- package/src/components/tanstackTable/components/TableHeader/TableHeader.tsx +49 -0
- package/src/components/tanstackTable/components/TableHeader/index.ts +1 -0
- package/src/components/tanstackTable/components/TablePagination/TablePagination.tsx +45 -0
- package/src/components/tanstackTable/components/TablePagination/__tests__/TablePagination.test.tsx +18 -0
- package/src/components/tanstackTable/components/TablePagination/index.ts +1 -0
- package/src/components/tanstackTable/docs/pinnedColumns/PinnedColumn.mdx +34 -0
- package/src/components/tanstackTable/docs/pinnedColumns/PinnedColumn.stories.tsx +40 -0
- package/src/components/tanstackTable/docs/withRowClick/WithRowClick.mdx +48 -0
- package/src/components/tanstackTable/docs/withRowClick/WithRowClick.stories.tsx +32 -0
- package/src/components/tanstackTable/helpers.ts +45 -0
- package/src/components/tanstackTable/index.ts +2 -0
- package/src/components/tanstackTable/mock-data/mock-data.ts +256 -0
- package/src/components/tanstackTable/mock-data/table-configuration.tsx +219 -0
- package/src/components/tanstackTable/styles/_variables.scss +35 -0
- package/src/components/tanstackTable/styles/table.scss +204 -0
- package/src/components/tanstackTable/styles/test.scss +19 -0
- package/src/components/tanstackTable/tanstack-table.d.ts +18 -0
- package/src/components/tanstackTable/useTanstackTable.tsx +42 -0
- package/src/index.ts +1 -0
- package/src/legacy/components/loading-indicators/CirclePulse/CirclePulse.tsx +1 -0
- package/src/storybookDocs/Permafrost.mdx +22 -11
- package/src/styles/_borders.scss +2 -1
- package/src/styles/index.scss +1 -0
- package/src/stylesAndAnimations/borders/BorderColor.tsx +14 -6
- package/src/stylesAndAnimations/utilityClasses/UtilityClasses.mdx +24 -0
- package/src/stylesAndAnimations/utilityClasses/UtilityClassesData.ts +230 -0
- package/src/stylesAndAnimations/utilityClasses/UtilityClassesTable.stories.tsx +13 -0
- package/src/stylesAndAnimations/utilityClasses/UtilityClassesTable.tsx +146 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Canvas, Meta, Controls } from '@storybook/blocks';
|
|
2
|
+
import * as TableStories from './PinnedColumn.stories';
|
|
3
|
+
|
|
4
|
+
<Meta title="Layout/Tanstack Table/Pinned Columns" name="Tanstack Table Pinned Column" />
|
|
5
|
+
|
|
6
|
+
# Tanstack Table Pinned Columns
|
|
7
|
+
|
|
8
|
+
<Canvas of={TableStories.PinnedColumns} />
|
|
9
|
+
|
|
10
|
+
This component enables the rapid creation of responsive, paginated tables using the React TanStack Table library.
|
|
11
|
+
It supports configuring pinned columns by extracting the necessary properties from your column creation object.
|
|
12
|
+
For more details on all configuration options and features, please refer to the official [TanStack Table Pinning Documentation](https://tanstack.com/table/latest/docs/guide/column-pinning#pin-columns-by-default).
|
|
13
|
+
|
|
14
|
+
To enable pinned columns, pass the following properties to your table.
|
|
15
|
+
In your column definition, extract the pinning information from the header object and pass it to your component in this case PinHeaderColumns as shown:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
header: ({ header }) => (
|
|
19
|
+
<PinHeaderColumns
|
|
20
|
+
content="First Name"
|
|
21
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
22
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
23
|
+
/>
|
|
24
|
+
),
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This code toggles the pinned state of the column: if the column is already pinned, clicking will unpin it; otherwise, it will pin the column to the left
|
|
29
|
+
|
|
30
|
+
Additionally, the table component accepts a defaultPinnedColumns prop, which is an array of column IDs that will be pinned by default when the table is rendered. This ensures that important columns—such as selection checkboxes or key data fields—remain visible as users scroll through the table.
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<TanstackTable defaultPinnedColumns={['select', 'firstName', 'lastName']} />
|
|
34
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import { TanstackTable } from '../../TanstakTable';
|
|
4
|
+
import { people, Person } from '../../mock-data/mock-data';
|
|
5
|
+
import { columns } from '../../mock-data/table-configuration';
|
|
6
|
+
import { ColumnDef } from '@tanstack/react-table';
|
|
7
|
+
|
|
8
|
+
const meta: Meta = {
|
|
9
|
+
title: 'Layout/Tanstack Table/Pinned Columns',
|
|
10
|
+
component: TanstackTable,
|
|
11
|
+
args: {
|
|
12
|
+
data: people as (Person & { id: string })[],
|
|
13
|
+
columns: columns as ColumnDef<Person & { id: string }>[],
|
|
14
|
+
defaultPinnedColumns: ['select'],
|
|
15
|
+
onClickRow: null,
|
|
16
|
+
},
|
|
17
|
+
decorators: [
|
|
18
|
+
(Story) => (
|
|
19
|
+
<div style={{ width: '100%', height: '500px', overflow: 'hidden' }}>
|
|
20
|
+
<Story />
|
|
21
|
+
</div>
|
|
22
|
+
),
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
|
|
28
|
+
type Story = StoryObj<typeof TanstackTable<Person>>;
|
|
29
|
+
|
|
30
|
+
export const PinnedColumns: Story = {
|
|
31
|
+
args: {
|
|
32
|
+
defaultPinnedColumns: ['select', 'firstName', 'lastName'],
|
|
33
|
+
actionBarClassName: 'tanstack-table__action-bar-test',
|
|
34
|
+
},
|
|
35
|
+
render: (args) => (
|
|
36
|
+
<div style={{ width: '700px', height: '500px', overflow: 'hidden' }}>
|
|
37
|
+
<TanstackTable<Person> {...args} />
|
|
38
|
+
</div>
|
|
39
|
+
),
|
|
40
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Canvas, Meta, Controls } from '@storybook/blocks';
|
|
2
|
+
import * as TableStories from './WithRowClick.stories';
|
|
3
|
+
|
|
4
|
+
<Meta title="Layout/Tanstack Table/With Row Click" name="TanstackTable" />
|
|
5
|
+
|
|
6
|
+
<Canvas of={TableStories.WithRowClick} />
|
|
7
|
+
|
|
8
|
+
# Tanstack Table With Row Click
|
|
9
|
+
|
|
10
|
+
When a row is clicked, the component first checks if an onClickRow callback is provided. If it exists, it performs two actions:
|
|
11
|
+
|
|
12
|
+
Toggle Row Behavior:
|
|
13
|
+
The toggleRow function is called with the row's ID. This function checks if the row's ID is already in the isClickedRow state array. If it is, the ID is removed; if not, it's added. This toggles the row's "clicked" state, which is then used to conditionally apply the is-clicked CSS class for visual feedback.
|
|
14
|
+
|
|
15
|
+
Row Click Callback:
|
|
16
|
+
After toggling the row's state, the onClickRow function is invoked with the clicked row as its argument, allowing you to perform additional custom actions when a row is clicked.
|
|
17
|
+
|
|
18
|
+
Here's a simplified flow of the behavior:
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
onClick={() => {
|
|
22
|
+
if (!!onClickRow) {
|
|
23
|
+
toggleRow(row.id); // Toggle the row's clicked state
|
|
24
|
+
onClickRow(row); // Execute additional actions for the clicked row
|
|
25
|
+
}
|
|
26
|
+
}}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This design makes it easy to both track and visually indicate which rows have been interacted with, while also providing a hook for further custom behavior via the onClickRow callback.
|
|
30
|
+
|
|
31
|
+
The 'is-selected' class is added when the row is selected (via row.getIsSelected()), resulting in a specific background for selected rows. The 'show-hover' class is applied if the onClickRow function is provided, enabling a distinct hover effect that indicates interactivity. Finally, the 'is-clicked' class is added when the row has been clicked (i.e., its ID is included in isClickedRow), which changes the background to visually differentiate clicked rows from both hovered and selected ones.
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<tr
|
|
35
|
+
className={classNames('tanstack-table__tbody__tr', {
|
|
36
|
+
'is-selected': row.getIsSelected(),
|
|
37
|
+
'show-hover': !!onClickRow,
|
|
38
|
+
'is-clicked': isClickedRow.includes(row.id),
|
|
39
|
+
})}
|
|
40
|
+
key={row.id}
|
|
41
|
+
onClick={() => {
|
|
42
|
+
if (!!onClickRow) {
|
|
43
|
+
toggleRow(row.id);
|
|
44
|
+
onClickRow(row);
|
|
45
|
+
}
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import { TanstackTable } from '../../TanstakTable';
|
|
4
|
+
import { people, Person } from '../../mock-data/mock-data';
|
|
5
|
+
import { columns } from '../../mock-data/table-configuration';
|
|
6
|
+
import { ColumnDef, Row } from '@tanstack/react-table';
|
|
7
|
+
|
|
8
|
+
const meta: Meta = {
|
|
9
|
+
title: 'Layout/Tanstack Table/With Row Click',
|
|
10
|
+
component: TanstackTable,
|
|
11
|
+
args: {
|
|
12
|
+
data: people as (Person & { id: string })[],
|
|
13
|
+
columns: columns as ColumnDef<Person & { id: string }>[],
|
|
14
|
+
defaultPinnedColumns: ['select'],
|
|
15
|
+
onClickRow: (row: Row<Person>) => {
|
|
16
|
+
console.log(row);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
decorators: [
|
|
20
|
+
(Story) => (
|
|
21
|
+
<div style={{ width: '100%', height: '500px', overflow: 'hidden' }}>
|
|
22
|
+
<Story />
|
|
23
|
+
</div>
|
|
24
|
+
),
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default meta;
|
|
29
|
+
|
|
30
|
+
type Story = StoryObj<typeof TanstackTable<Person>>;
|
|
31
|
+
|
|
32
|
+
export const WithRowClick: Story = {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Column } from '@tanstack/react-table';
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
|
|
4
|
+
// Sets style attributes for pinned columns
|
|
5
|
+
const getCommonPinningStyles = <T>(column: Column<T>): CSSProperties => {
|
|
6
|
+
const isPinned = column.getIsPinned();
|
|
7
|
+
const isLastLeftPinnedColumn = isPinned === 'left' && column.getIsLastColumn('left');
|
|
8
|
+
return {
|
|
9
|
+
boxShadow: isLastLeftPinnedColumn ? '-4px 0 4px -4px gray inset' : undefined,
|
|
10
|
+
left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined,
|
|
11
|
+
position: isPinned ? 'sticky' : 'relative',
|
|
12
|
+
zIndex: isPinned ? 1 : 0,
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const getThStyles = <T>(column: Column<T>) => {
|
|
17
|
+
const styles = { ...getCommonPinningStyles(column) };
|
|
18
|
+
|
|
19
|
+
if (column.columnDef.meta?.styles?.definedColumnSize) {
|
|
20
|
+
styles.width = column.getSize();
|
|
21
|
+
styles.maxWidth = column.getSize();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return styles;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const getTdStyles = <T>(
|
|
28
|
+
column: Column<T>,
|
|
29
|
+
textAlign?: 'left' | 'center' | 'right',
|
|
30
|
+
hasDefinedColumnSize?: boolean,
|
|
31
|
+
width?: number,
|
|
32
|
+
) => {
|
|
33
|
+
const styles: CSSProperties = { ...getCommonPinningStyles(column) };
|
|
34
|
+
|
|
35
|
+
if (textAlign) {
|
|
36
|
+
styles.textAlign = textAlign;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (hasDefinedColumnSize) {
|
|
40
|
+
styles.width = width;
|
|
41
|
+
styles.maxWidth = width;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return styles;
|
|
45
|
+
};
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
export type Person = {
|
|
2
|
+
firstName: string;
|
|
3
|
+
lastName: string;
|
|
4
|
+
age: number;
|
|
5
|
+
visits: number;
|
|
6
|
+
progress: number;
|
|
7
|
+
status: 'relationship' | 'complicated' | 'single';
|
|
8
|
+
subRows?: Person[];
|
|
9
|
+
id: string;
|
|
10
|
+
country: string;
|
|
11
|
+
city: string;
|
|
12
|
+
civility: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const people: Person[] = [
|
|
16
|
+
{
|
|
17
|
+
firstName: 'John',
|
|
18
|
+
lastName: 'Doe',
|
|
19
|
+
age: 28,
|
|
20
|
+
visits: 10,
|
|
21
|
+
progress: 75,
|
|
22
|
+
status: 'single',
|
|
23
|
+
id: '1',
|
|
24
|
+
country: 'USA',
|
|
25
|
+
city: 'New York',
|
|
26
|
+
civility: 'Mr.',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
firstName: 'Jane',
|
|
30
|
+
lastName: 'Smith',
|
|
31
|
+
age: 32,
|
|
32
|
+
visits: 15,
|
|
33
|
+
progress: 50,
|
|
34
|
+
status: 'relationship',
|
|
35
|
+
id: '2',
|
|
36
|
+
country: 'USA',
|
|
37
|
+
city: 'Los Angeles',
|
|
38
|
+
civility: 'Ms.',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
firstName: 'Alice',
|
|
42
|
+
lastName: 'Johnson',
|
|
43
|
+
age: 24,
|
|
44
|
+
visits: 5,
|
|
45
|
+
progress: 90,
|
|
46
|
+
status: 'single',
|
|
47
|
+
id: '3',
|
|
48
|
+
country: 'Canada',
|
|
49
|
+
city: 'Toronto',
|
|
50
|
+
civility: 'Ms.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
firstName: 'Bob',
|
|
54
|
+
lastName: 'Brown',
|
|
55
|
+
age: 40,
|
|
56
|
+
visits: 20,
|
|
57
|
+
progress: 30,
|
|
58
|
+
status: 'complicated',
|
|
59
|
+
id: '4',
|
|
60
|
+
country: 'UK',
|
|
61
|
+
city: 'London',
|
|
62
|
+
civility: 'Mr.',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
firstName: 'Charlie',
|
|
66
|
+
lastName: 'Davis',
|
|
67
|
+
age: 35,
|
|
68
|
+
visits: 8,
|
|
69
|
+
progress: 60,
|
|
70
|
+
status: 'relationship',
|
|
71
|
+
id: '5',
|
|
72
|
+
country: 'Australia',
|
|
73
|
+
city: 'Sydney',
|
|
74
|
+
civility: 'Mr.',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
firstName: 'Emily',
|
|
78
|
+
lastName: 'Wilson',
|
|
79
|
+
age: 27,
|
|
80
|
+
visits: 12,
|
|
81
|
+
progress: 80,
|
|
82
|
+
status: 'single',
|
|
83
|
+
id: '6',
|
|
84
|
+
country: 'USA',
|
|
85
|
+
city: 'Chicago',
|
|
86
|
+
civility: 'Ms.',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
firstName: 'David',
|
|
90
|
+
lastName: 'Martinez',
|
|
91
|
+
age: 45,
|
|
92
|
+
visits: 25,
|
|
93
|
+
progress: 40,
|
|
94
|
+
status: 'complicated',
|
|
95
|
+
id: '7',
|
|
96
|
+
country: 'Mexico',
|
|
97
|
+
city: 'Mexico City',
|
|
98
|
+
civility: 'Mr.',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
firstName: 'Sophia',
|
|
102
|
+
lastName: 'Garcia',
|
|
103
|
+
age: 30,
|
|
104
|
+
visits: 18,
|
|
105
|
+
progress: 70,
|
|
106
|
+
status: 'relationship',
|
|
107
|
+
id: '8',
|
|
108
|
+
country: 'Spain',
|
|
109
|
+
city: 'Madrid',
|
|
110
|
+
civility: 'Ms.',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
firstName: 'Liam',
|
|
114
|
+
lastName: 'Rodriguez',
|
|
115
|
+
age: 22,
|
|
116
|
+
visits: 7,
|
|
117
|
+
progress: 85,
|
|
118
|
+
status: 'single',
|
|
119
|
+
id: '9',
|
|
120
|
+
country: 'USA',
|
|
121
|
+
city: 'Boston',
|
|
122
|
+
civility: 'Mr.',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
firstName: 'Olivia',
|
|
126
|
+
lastName: 'Lee',
|
|
127
|
+
age: 29,
|
|
128
|
+
visits: 11,
|
|
129
|
+
progress: 65,
|
|
130
|
+
status: 'complicated',
|
|
131
|
+
id: '10',
|
|
132
|
+
country: 'Canada',
|
|
133
|
+
city: 'Vancouver',
|
|
134
|
+
civility: 'Ms.',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
firstName: 'Noah',
|
|
138
|
+
lastName: 'Walker',
|
|
139
|
+
age: 33,
|
|
140
|
+
visits: 9,
|
|
141
|
+
progress: 55,
|
|
142
|
+
status: 'relationship',
|
|
143
|
+
id: '11',
|
|
144
|
+
country: 'USA',
|
|
145
|
+
city: 'San Francisco',
|
|
146
|
+
civility: 'Mr.',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
firstName: 'Ava',
|
|
150
|
+
lastName: 'Hall',
|
|
151
|
+
age: 26,
|
|
152
|
+
visits: 14,
|
|
153
|
+
progress: 95,
|
|
154
|
+
status: 'single',
|
|
155
|
+
id: '12',
|
|
156
|
+
country: 'UK',
|
|
157
|
+
city: 'Manchester',
|
|
158
|
+
civility: 'Ms.',
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
firstName: 'Ethan',
|
|
162
|
+
lastName: 'Allen',
|
|
163
|
+
age: 38,
|
|
164
|
+
visits: 21,
|
|
165
|
+
progress: 45,
|
|
166
|
+
status: 'complicated',
|
|
167
|
+
id: '13',
|
|
168
|
+
country: 'USA',
|
|
169
|
+
city: 'Houston',
|
|
170
|
+
civility: 'Mr.',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
firstName: 'Mia',
|
|
174
|
+
lastName: 'Young',
|
|
175
|
+
age: 31,
|
|
176
|
+
visits: 16,
|
|
177
|
+
progress: 50,
|
|
178
|
+
status: 'relationship',
|
|
179
|
+
id: '14',
|
|
180
|
+
country: 'Australia',
|
|
181
|
+
city: 'Melbourne',
|
|
182
|
+
civility: 'Ms.',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
firstName: 'William',
|
|
186
|
+
lastName: 'Hernandez',
|
|
187
|
+
age: 42,
|
|
188
|
+
visits: 19,
|
|
189
|
+
progress: 35,
|
|
190
|
+
status: 'complicated',
|
|
191
|
+
id: '15',
|
|
192
|
+
country: 'USA',
|
|
193
|
+
city: 'Phoenix',
|
|
194
|
+
civility: 'Mr.',
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
firstName: 'Isabella',
|
|
198
|
+
lastName: 'King',
|
|
199
|
+
age: 23,
|
|
200
|
+
visits: 6,
|
|
201
|
+
progress: 88,
|
|
202
|
+
status: 'single',
|
|
203
|
+
id: '16',
|
|
204
|
+
country: 'Canada',
|
|
205
|
+
city: 'Ottawa',
|
|
206
|
+
civility: 'Ms.',
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
firstName: 'James',
|
|
210
|
+
lastName: 'Wright',
|
|
211
|
+
age: 37,
|
|
212
|
+
visits: 17,
|
|
213
|
+
progress: 60,
|
|
214
|
+
status: 'relationship',
|
|
215
|
+
id: '17',
|
|
216
|
+
country: 'UK',
|
|
217
|
+
city: 'Birmingham',
|
|
218
|
+
civility: 'Mr.',
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
firstName: 'Amelia',
|
|
222
|
+
lastName: 'Lopez',
|
|
223
|
+
age: 34,
|
|
224
|
+
visits: 13,
|
|
225
|
+
progress: 72,
|
|
226
|
+
status: 'complicated',
|
|
227
|
+
id: '18',
|
|
228
|
+
country: 'Spain',
|
|
229
|
+
city: 'Barcelona',
|
|
230
|
+
civility: 'Ms.',
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
firstName: 'Benjamin',
|
|
234
|
+
lastName: 'Hill',
|
|
235
|
+
age: 29,
|
|
236
|
+
visits: 10,
|
|
237
|
+
progress: 80,
|
|
238
|
+
status: 'relationship',
|
|
239
|
+
id: '19',
|
|
240
|
+
country: 'USA',
|
|
241
|
+
city: 'Seattle',
|
|
242
|
+
civility: 'Mr.',
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
firstName: 'Charlotte',
|
|
246
|
+
lastName: 'Scott',
|
|
247
|
+
age: 28,
|
|
248
|
+
visits: 8,
|
|
249
|
+
progress: 65,
|
|
250
|
+
status: 'single',
|
|
251
|
+
id: '20',
|
|
252
|
+
country: 'USA',
|
|
253
|
+
city: 'Austin',
|
|
254
|
+
civility: 'Ms.',
|
|
255
|
+
},
|
|
256
|
+
];
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { ColumnDef } from '@tanstack/react-table';
|
|
2
|
+
import { Person } from './mock-data';
|
|
3
|
+
import { Checkbox } from '@/components/forms/checkbox/Checkbox';
|
|
4
|
+
import { Button } from '@/components/button';
|
|
5
|
+
import styled from 'styled-components';
|
|
6
|
+
|
|
7
|
+
const PinHeaderColumns = ({
|
|
8
|
+
content,
|
|
9
|
+
onPinClick,
|
|
10
|
+
isPinned,
|
|
11
|
+
}: {
|
|
12
|
+
content: string;
|
|
13
|
+
onPinClick: () => void;
|
|
14
|
+
isPinned: boolean;
|
|
15
|
+
}) => {
|
|
16
|
+
return (
|
|
17
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
18
|
+
{onPinClick ? (
|
|
19
|
+
<Button
|
|
20
|
+
data-testid={`sticky-header-pin-button`}
|
|
21
|
+
variant="link"
|
|
22
|
+
size="sm"
|
|
23
|
+
iconLeft="pin"
|
|
24
|
+
onClick={onPinClick}
|
|
25
|
+
ariaLabel={isPinned ? 'Unpin column' : 'Pin column'}
|
|
26
|
+
className={`tanstack-table__column--${isPinned ? 'is-pinned' : 'is-not-pinned'} pa-0`}
|
|
27
|
+
/>
|
|
28
|
+
) : null}
|
|
29
|
+
<span>{content}</span>{' '}
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const CheckboxContainer = styled.div`
|
|
35
|
+
padding: 14px;
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
export const columns = [
|
|
39
|
+
{
|
|
40
|
+
id: 'select',
|
|
41
|
+
size: 48,
|
|
42
|
+
meta: {
|
|
43
|
+
styles: {
|
|
44
|
+
definedColumnSize: true,
|
|
45
|
+
header: {
|
|
46
|
+
hasNoPadding: true,
|
|
47
|
+
},
|
|
48
|
+
cell: {
|
|
49
|
+
hasNoPadding: true,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
header: ({ table }) => (
|
|
54
|
+
<CheckboxContainer>
|
|
55
|
+
<Checkbox
|
|
56
|
+
name="select-all"
|
|
57
|
+
id="select-all"
|
|
58
|
+
label=""
|
|
59
|
+
isChecked={table.getIsAllPageRowsSelected()}
|
|
60
|
+
onChange={() => {
|
|
61
|
+
table
|
|
62
|
+
.getRowModel()
|
|
63
|
+
.rows.forEach((row) =>
|
|
64
|
+
row.toggleSelected(!table.getRowModel().rows[0].getIsSelected()),
|
|
65
|
+
);
|
|
66
|
+
}}
|
|
67
|
+
isDisabled={false}
|
|
68
|
+
aria-label="select-rows-header"
|
|
69
|
+
/>
|
|
70
|
+
</CheckboxContainer>
|
|
71
|
+
),
|
|
72
|
+
cell: ({ row }) => (
|
|
73
|
+
<CheckboxContainer>
|
|
74
|
+
<Checkbox
|
|
75
|
+
name="select"
|
|
76
|
+
id={row.id}
|
|
77
|
+
label=""
|
|
78
|
+
aria-label={`checkbox-${row.id}`}
|
|
79
|
+
isChecked={row.getIsSelected()}
|
|
80
|
+
isDisabled={!row.getCanSelect()}
|
|
81
|
+
onChange={row.getToggleSelectedHandler()}
|
|
82
|
+
/>
|
|
83
|
+
</CheckboxContainer>
|
|
84
|
+
),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 'firstName',
|
|
88
|
+
accessorKey: 'firstName',
|
|
89
|
+
header: ({ header }) => (
|
|
90
|
+
<PinHeaderColumns
|
|
91
|
+
content="First Name"
|
|
92
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
93
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
94
|
+
/>
|
|
95
|
+
),
|
|
96
|
+
cell: (info) => info.getValue(),
|
|
97
|
+
footer: (props) => props.column.id,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
accessorFn: (row) => row.lastName,
|
|
101
|
+
id: 'lastName',
|
|
102
|
+
cell: (info) => info.getValue(),
|
|
103
|
+
header: ({ header }) => (
|
|
104
|
+
<PinHeaderColumns
|
|
105
|
+
content="Last Name"
|
|
106
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
107
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
108
|
+
/>
|
|
109
|
+
),
|
|
110
|
+
footer: (props) => props.column.id,
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
{
|
|
114
|
+
id: 'age',
|
|
115
|
+
accessorKey: 'age',
|
|
116
|
+
header: ({ header }) => (
|
|
117
|
+
<PinHeaderColumns
|
|
118
|
+
content="Age"
|
|
119
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
120
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
121
|
+
/>
|
|
122
|
+
),
|
|
123
|
+
meta: {
|
|
124
|
+
styles: {
|
|
125
|
+
cell: {
|
|
126
|
+
textAlign: 'right',
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
footer: (props) => props.column.id,
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
{
|
|
134
|
+
id: 'visits',
|
|
135
|
+
accessorKey: 'visits',
|
|
136
|
+
header: ({ header }) => (
|
|
137
|
+
<PinHeaderColumns
|
|
138
|
+
content="Visits"
|
|
139
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
140
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
141
|
+
/>
|
|
142
|
+
),
|
|
143
|
+
meta: {
|
|
144
|
+
styles: {
|
|
145
|
+
cell: {
|
|
146
|
+
textAlign: 'right',
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
footer: (props) => props.column.id,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: 'status',
|
|
154
|
+
accessorKey: 'status',
|
|
155
|
+
header: ({ header }) => (
|
|
156
|
+
<PinHeaderColumns
|
|
157
|
+
content="Status"
|
|
158
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
159
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
160
|
+
/>
|
|
161
|
+
),
|
|
162
|
+
footer: (props) => props.column.id,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
id: 'progress',
|
|
166
|
+
accessorKey: 'progress',
|
|
167
|
+
header: ({ header }) => (
|
|
168
|
+
<PinHeaderColumns
|
|
169
|
+
content="Profile Progress"
|
|
170
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
171
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
172
|
+
/>
|
|
173
|
+
),
|
|
174
|
+
meta: {
|
|
175
|
+
styles: {
|
|
176
|
+
cell: {
|
|
177
|
+
textAlign: 'center',
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
footer: (props) => props.column.id,
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: 'country',
|
|
185
|
+
accessorKey: 'country',
|
|
186
|
+
header: ({ header }) => (
|
|
187
|
+
<PinHeaderColumns
|
|
188
|
+
content="Country"
|
|
189
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
190
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
191
|
+
/>
|
|
192
|
+
),
|
|
193
|
+
footer: (props) => props.column.id,
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: 'city',
|
|
197
|
+
accessorKey: 'city',
|
|
198
|
+
header: ({ header }) => (
|
|
199
|
+
<PinHeaderColumns
|
|
200
|
+
content="City"
|
|
201
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
202
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
203
|
+
/>
|
|
204
|
+
),
|
|
205
|
+
footer: (props) => props.column.id,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
id: 'civility',
|
|
209
|
+
accessorKey: 'civility',
|
|
210
|
+
header: ({ header }) => (
|
|
211
|
+
<PinHeaderColumns
|
|
212
|
+
content="Civility"
|
|
213
|
+
onPinClick={() => header.column.pin(header.column.getIsPinned() ? false : 'left')}
|
|
214
|
+
isPinned={header.column.getIsPinned() === 'left' ? true : false}
|
|
215
|
+
/>
|
|
216
|
+
),
|
|
217
|
+
footer: (props) => props.column.id,
|
|
218
|
+
},
|
|
219
|
+
] as ColumnDef<Person>[];
|