@groupeactual/ui-kit 1.0.27-beta.4 → 1.0.27-beta.5
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/cjs/index.js +9 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/Datatable/Datatable.d.ts +16 -0
- package/dist/cjs/types/components/Datatable/datatable.helper.d.ts +9 -0
- package/dist/cjs/types/components/Datatable/datatable.interface.d.ts +12 -0
- package/dist/cjs/types/components/Datatable/index.d.ts +1 -0
- package/dist/cjs/types/components/Pagination/Pagination.d.ts +2 -2
- package/dist/cjs/types/components/Pagination/pagination.helper.d.ts +1 -0
- package/dist/cjs/types/components/index.d.ts +1 -0
- package/dist/es/index.d.ts +72 -46
- package/dist/es/index.mjs +9 -9
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/types/components/Datatable/Datatable.d.ts +16 -0
- package/dist/es/types/components/Datatable/datatable.helper.d.ts +9 -0
- package/dist/es/types/components/Datatable/datatable.interface.d.ts +12 -0
- package/dist/es/types/components/Datatable/index.d.ts +1 -0
- package/dist/es/types/components/Pagination/Pagination.d.ts +2 -2
- package/dist/es/types/components/Pagination/pagination.helper.d.ts +1 -0
- package/dist/es/types/components/index.d.ts +1 -0
- package/package.json +2 -2
- package/src/components/Datatable/Datatable.tsx +174 -0
- package/src/components/Datatable/datatable.helper.ts +15 -0
- package/src/components/Datatable/datatable.interface.ts +15 -0
- package/src/components/Datatable/index.ts +1 -0
- package/src/components/Pagination/Pagination.tsx +53 -36
- package/src/components/Pagination/pagination.helper.ts +2 -0
- package/src/components/Stepper/Step.tsx +2 -1
- package/src/components/index.ts +1 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Column, Row } from './datatable.interface';
|
|
2
|
+
interface Props<T extends Row> {
|
|
3
|
+
values: T[];
|
|
4
|
+
columns: Column<T>[];
|
|
5
|
+
withHeader?: boolean;
|
|
6
|
+
withPagination?: boolean;
|
|
7
|
+
defaultRowPerPage?: number;
|
|
8
|
+
totalPerPageTrad?: string;
|
|
9
|
+
totalTrad?: string;
|
|
10
|
+
limitsPerPageArray?: number[];
|
|
11
|
+
}
|
|
12
|
+
declare const Datatable: {
|
|
13
|
+
<T extends Row>({ values, columns, withHeader, withPagination, defaultRowPerPage, totalPerPageTrad, totalTrad, limitsPerPageArray }: Props<T>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
displayName: string;
|
|
15
|
+
};
|
|
16
|
+
export default Datatable;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compares two objects based on a specified property in descending order.
|
|
3
|
+
*
|
|
4
|
+
* @param a - The first object in the comparison.
|
|
5
|
+
* @param b - The second object in the comparison.
|
|
6
|
+
* @param orderBy - The property of the objects to base the comparison on.
|
|
7
|
+
* @returns A number indicating the order of the objects.
|
|
8
|
+
*/
|
|
9
|
+
export declare const descendingComparator: <T>(a: T, b: T, orderBy?: string) => 0 | 1 | -1;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export type Order = 'asc' | 'desc';
|
|
3
|
+
export interface Column<T> {
|
|
4
|
+
name: string;
|
|
5
|
+
render: (record: T) => JSX.Element;
|
|
6
|
+
title?: string;
|
|
7
|
+
width?: string;
|
|
8
|
+
sortable?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface Row {
|
|
11
|
+
details?: ReactNode;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Datatable';
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
interface Props {
|
|
2
2
|
totalString: string;
|
|
3
3
|
totalPerPageString: string;
|
|
4
|
-
totalPages: number;
|
|
5
4
|
limitsPerPage: number[];
|
|
5
|
+
totalRows: number;
|
|
6
6
|
setLimit?: (limit: number) => void;
|
|
7
7
|
setPage?: (page: number) => void;
|
|
8
8
|
page?: number;
|
|
9
9
|
limit?: number;
|
|
10
10
|
}
|
|
11
11
|
declare const Pagination: {
|
|
12
|
-
({ totalString, totalPerPageString,
|
|
12
|
+
({ totalString, totalPerPageString, limitsPerPage, setLimit, setPage, page, totalRows, limit }: Props): import("react/jsx-runtime").JSX.Element;
|
|
13
13
|
displayName: string;
|
|
14
14
|
};
|
|
15
15
|
export default Pagination;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getTotalPages: (totalRows: number, limitPerPage: number) => number;
|
|
@@ -23,3 +23,4 @@ export { default as BannerNotification } from './BannerNotification/BannerNotifi
|
|
|
23
23
|
export { default as Stepper } from './Stepper/Stepper';
|
|
24
24
|
export { default as Switch } from './Form/Switch/Switch';
|
|
25
25
|
export { default as DatePicker } from './Form/DatePicker';
|
|
26
|
+
export { default as Datatable } from './Datatable/Datatable';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@groupeactual/ui-kit",
|
|
3
|
-
"version": "1.0.27-beta.
|
|
3
|
+
"version": "1.0.27-beta.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A simple template for a custom React component library",
|
|
6
6
|
"devDependencies": {
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"notistack": "^3.0.1",
|
|
55
55
|
"react": "^18.2.0",
|
|
56
56
|
"react-dom": "^18.2.0",
|
|
57
|
-
"@groupeactual/design-tokens": "1.0.27-beta.
|
|
57
|
+
"@groupeactual/design-tokens": "1.0.27-beta.5"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"react": "^18.2.0",
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { useMemo, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { faArrowDown, faArrowUp } from '@fortawesome/pro-regular-svg-icons';
|
|
4
|
+
import { DatatableStyle } from '@groupeactual/design-tokens';
|
|
5
|
+
import {
|
|
6
|
+
Box,
|
|
7
|
+
Table,
|
|
8
|
+
TableBody,
|
|
9
|
+
TableCell,
|
|
10
|
+
TableContainer,
|
|
11
|
+
TableHead,
|
|
12
|
+
TableRow,
|
|
13
|
+
TableSortLabel,
|
|
14
|
+
styled,
|
|
15
|
+
useTheme
|
|
16
|
+
} from '@mui/material';
|
|
17
|
+
|
|
18
|
+
import IconProvider from '../IconProvider';
|
|
19
|
+
import Pagination from '../Pagination';
|
|
20
|
+
import Text from '../Text';
|
|
21
|
+
import { descendingComparator } from './datatable.helper';
|
|
22
|
+
import { Column, Order, Row } from './datatable.interface';
|
|
23
|
+
|
|
24
|
+
interface Props<T extends Row> {
|
|
25
|
+
values: T[];
|
|
26
|
+
columns: Column<T>[];
|
|
27
|
+
withHeader?: boolean;
|
|
28
|
+
withPagination?: boolean;
|
|
29
|
+
defaultRowPerPage?: number;
|
|
30
|
+
totalPerPageTrad?: string;
|
|
31
|
+
totalTrad?: string;
|
|
32
|
+
limitsPerPageArray?: number[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const Datatable = <T extends Row>({
|
|
36
|
+
values,
|
|
37
|
+
columns,
|
|
38
|
+
withHeader = true,
|
|
39
|
+
withPagination = false,
|
|
40
|
+
defaultRowPerPage = 5,
|
|
41
|
+
totalPerPageTrad = 'résultats par page',
|
|
42
|
+
totalTrad = 'résultats',
|
|
43
|
+
limitsPerPageArray = [3, 5, 10, 20]
|
|
44
|
+
}: Props<T>) => {
|
|
45
|
+
const theme = useTheme();
|
|
46
|
+
const [order, setOrder] = useState<Order>('asc');
|
|
47
|
+
const [orderBy, setOrderBy] = useState<string>();
|
|
48
|
+
|
|
49
|
+
const isAsc = order === 'asc';
|
|
50
|
+
|
|
51
|
+
const [page, setPage] = useState(1);
|
|
52
|
+
const [rowsPerPage, setRowsPerPage] = useState(defaultRowPerPage);
|
|
53
|
+
|
|
54
|
+
const StyledDatatable = useMemo(
|
|
55
|
+
() => styled(Box)(DatatableStyle(theme)),
|
|
56
|
+
[theme]
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const visibleRows = useMemo(() => {
|
|
60
|
+
const sortedValues = values.sort(
|
|
61
|
+
order === 'desc'
|
|
62
|
+
? (a, b) => descendingComparator(a, b, orderBy)
|
|
63
|
+
: (a, b) => -descendingComparator(a, b, orderBy)
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
return withPagination
|
|
67
|
+
? sortedValues.slice(
|
|
68
|
+
(page - 1) * rowsPerPage,
|
|
69
|
+
(page - 1) * rowsPerPage + rowsPerPage
|
|
70
|
+
)
|
|
71
|
+
: sortedValues;
|
|
72
|
+
}, [page, rowsPerPage, order, orderBy, withPagination]);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<StyledDatatable>
|
|
76
|
+
{values.length > 0 && (
|
|
77
|
+
<TableContainer>
|
|
78
|
+
<Table>
|
|
79
|
+
{withHeader && (
|
|
80
|
+
<TableHead>
|
|
81
|
+
<TableRow>
|
|
82
|
+
{columns.map(({ name, title = '', sortable = false }) => {
|
|
83
|
+
const isOrderBy = orderBy === name;
|
|
84
|
+
return (
|
|
85
|
+
<TableCell
|
|
86
|
+
key={name}
|
|
87
|
+
sortDirection={orderBy === name ? order : false}
|
|
88
|
+
>
|
|
89
|
+
{(sortable && (
|
|
90
|
+
<TableSortLabel
|
|
91
|
+
active={orderBy === name}
|
|
92
|
+
onClick={() => {
|
|
93
|
+
setOrder(isAsc && isOrderBy ? 'desc' : 'asc');
|
|
94
|
+
setOrderBy(name);
|
|
95
|
+
}}
|
|
96
|
+
IconComponent={() => (
|
|
97
|
+
<>
|
|
98
|
+
<IconProvider
|
|
99
|
+
icon={faArrowUp}
|
|
100
|
+
color={
|
|
101
|
+
isAsc && isOrderBy
|
|
102
|
+
? '#000'
|
|
103
|
+
: theme.palette.greyLightDefaultBorder
|
|
104
|
+
}
|
|
105
|
+
/>
|
|
106
|
+
<IconProvider
|
|
107
|
+
icon={faArrowDown}
|
|
108
|
+
color={
|
|
109
|
+
!isAsc && isOrderBy
|
|
110
|
+
? '#000'
|
|
111
|
+
: theme.palette.greyLightDefaultBorder
|
|
112
|
+
}
|
|
113
|
+
/>
|
|
114
|
+
</>
|
|
115
|
+
)}
|
|
116
|
+
>
|
|
117
|
+
<Text>{title}</Text>
|
|
118
|
+
</TableSortLabel>
|
|
119
|
+
)) || <Text>{title}</Text>}
|
|
120
|
+
</TableCell>
|
|
121
|
+
);
|
|
122
|
+
})}
|
|
123
|
+
</TableRow>
|
|
124
|
+
</TableHead>
|
|
125
|
+
)}
|
|
126
|
+
<TableBody>
|
|
127
|
+
{visibleRows.map((record, index) => (
|
|
128
|
+
<>
|
|
129
|
+
<TableRow
|
|
130
|
+
sx={{
|
|
131
|
+
'& > *': {
|
|
132
|
+
borderBottom: record.details ? 'unset' : 'default'
|
|
133
|
+
}
|
|
134
|
+
}}
|
|
135
|
+
key={index}
|
|
136
|
+
>
|
|
137
|
+
{columns.map(({ name, width, render }) => (
|
|
138
|
+
<TableCell key={name} width={width}>
|
|
139
|
+
{render(record)}
|
|
140
|
+
</TableCell>
|
|
141
|
+
))}
|
|
142
|
+
</TableRow>
|
|
143
|
+
{record.details && (
|
|
144
|
+
<TableRow>
|
|
145
|
+
<TableCell colSpan={columns.length}>
|
|
146
|
+
{record.details}
|
|
147
|
+
</TableCell>
|
|
148
|
+
</TableRow>
|
|
149
|
+
)}
|
|
150
|
+
</>
|
|
151
|
+
))}
|
|
152
|
+
</TableBody>
|
|
153
|
+
</Table>
|
|
154
|
+
</TableContainer>
|
|
155
|
+
)}
|
|
156
|
+
{withPagination && (
|
|
157
|
+
<Pagination
|
|
158
|
+
page={page}
|
|
159
|
+
limit={rowsPerPage}
|
|
160
|
+
setPage={setPage}
|
|
161
|
+
setLimit={setRowsPerPage}
|
|
162
|
+
limitsPerPage={limitsPerPageArray}
|
|
163
|
+
totalPerPageString={totalPerPageTrad}
|
|
164
|
+
totalRows={values.length}
|
|
165
|
+
totalString={totalTrad}
|
|
166
|
+
/>
|
|
167
|
+
)}
|
|
168
|
+
</StyledDatatable>
|
|
169
|
+
);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
Datatable.displayName = 'Datatable';
|
|
173
|
+
|
|
174
|
+
export default Datatable;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compares two objects based on a specified property in descending order.
|
|
3
|
+
*
|
|
4
|
+
* @param a - The first object in the comparison.
|
|
5
|
+
* @param b - The second object in the comparison.
|
|
6
|
+
* @param orderBy - The property of the objects to base the comparison on.
|
|
7
|
+
* @returns A number indicating the order of the objects.
|
|
8
|
+
*/
|
|
9
|
+
export const descendingComparator = <T>(a: T, b: T, orderBy?: string) => {
|
|
10
|
+
if (!orderBy) {
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return b[orderBy] < a[orderBy] ? -1 : b[orderBy] > a[orderBy] ? 1 : 0;
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export type Order = 'asc' | 'desc';
|
|
4
|
+
|
|
5
|
+
export interface Column<T> {
|
|
6
|
+
name: string;
|
|
7
|
+
render: (record: T) => JSX.Element;
|
|
8
|
+
title?: string;
|
|
9
|
+
width?: string;
|
|
10
|
+
sortable?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Row {
|
|
14
|
+
details?: ReactNode;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Datatable';
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { PaginationStyle } from '@groupeactual/design-tokens';
|
|
2
4
|
import {
|
|
3
5
|
Box,
|
|
4
6
|
Divider,
|
|
5
7
|
Pagination as MUIPagination,
|
|
6
|
-
MenuItem,
|
|
7
|
-
Select,
|
|
8
8
|
styled,
|
|
9
9
|
useTheme
|
|
10
10
|
} from '@mui/material';
|
|
11
11
|
|
|
12
|
-
import
|
|
13
|
-
|
|
12
|
+
import Select from '../Form/Select';
|
|
14
13
|
import Text from '../Text';
|
|
14
|
+
import { getTotalPages } from './pagination.helper';
|
|
15
15
|
|
|
16
16
|
interface Props {
|
|
17
17
|
totalString: string;
|
|
18
18
|
totalPerPageString: string;
|
|
19
|
-
totalPages: number;
|
|
20
19
|
limitsPerPage: number[];
|
|
20
|
+
totalRows: number;
|
|
21
21
|
setLimit?: (limit: number) => void;
|
|
22
22
|
setPage?: (page: number) => void;
|
|
23
23
|
page?: number;
|
|
@@ -27,11 +27,11 @@ interface Props {
|
|
|
27
27
|
const Pagination = ({
|
|
28
28
|
totalString,
|
|
29
29
|
totalPerPageString,
|
|
30
|
-
totalPages,
|
|
31
30
|
limitsPerPage,
|
|
32
31
|
setLimit,
|
|
33
32
|
setPage,
|
|
34
33
|
page = 1,
|
|
34
|
+
totalRows,
|
|
35
35
|
limit
|
|
36
36
|
}: Props) => {
|
|
37
37
|
const theme = useTheme();
|
|
@@ -44,6 +44,28 @@ const Pagination = ({
|
|
|
44
44
|
const [internalLimit, setInternalLimit] = useState<number>(
|
|
45
45
|
limit ?? limitsPerPage[0]
|
|
46
46
|
);
|
|
47
|
+
|
|
48
|
+
const displayablePages = getTotalPages(totalRows, internalLimit);
|
|
49
|
+
|
|
50
|
+
const changePage = (newPage: number) => {
|
|
51
|
+
setInternalPage(newPage);
|
|
52
|
+
setPage?.(newPage);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const changeLimit = (newLimit: number) => {
|
|
56
|
+
setInternalLimit(newLimit);
|
|
57
|
+
setLimit?.(newLimit);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleChangeLimit = (newLimit: number) => {
|
|
61
|
+
const newDisplayablePages = getTotalPages(totalRows, newLimit);
|
|
62
|
+
|
|
63
|
+
if (newDisplayablePages < displayablePages) {
|
|
64
|
+
changePage(newDisplayablePages);
|
|
65
|
+
}
|
|
66
|
+
changeLimit(newLimit);
|
|
67
|
+
};
|
|
68
|
+
|
|
47
69
|
useEffect(() => {
|
|
48
70
|
if (page !== internalPage) {
|
|
49
71
|
setInternalPage(page);
|
|
@@ -57,41 +79,39 @@ const Pagination = ({
|
|
|
57
79
|
}, [limit]);
|
|
58
80
|
|
|
59
81
|
return (
|
|
60
|
-
|
|
82
|
+
<Box
|
|
83
|
+
display="flex"
|
|
84
|
+
flexDirection="row"
|
|
85
|
+
justifyContent="flex-end"
|
|
86
|
+
sx={{
|
|
87
|
+
padding: '12px 8px'
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
61
90
|
<Box display="flex">
|
|
62
91
|
<Text color="greyXDark" variant="body1Bold" pt="10px" pr="16px">
|
|
63
|
-
{totalString}
|
|
92
|
+
{totalRows} {totalString}
|
|
64
93
|
</Text>
|
|
65
|
-
{
|
|
94
|
+
{displayablePages > 1 && (
|
|
66
95
|
<>
|
|
67
96
|
<Divider
|
|
68
97
|
orientation="vertical"
|
|
69
98
|
sx={{ marginRight: '16px', color: 'greyXLight' }}
|
|
70
99
|
/>
|
|
71
100
|
<Select
|
|
72
|
-
|
|
73
|
-
// @TODO replace by Select from ui-kit when ready
|
|
74
|
-
height: '32px',
|
|
75
|
-
width: '75px',
|
|
76
|
-
fontSize: '14px',
|
|
77
|
-
fontWeight: 400
|
|
78
|
-
}}
|
|
101
|
+
label=""
|
|
79
102
|
className="dac-select-label"
|
|
80
103
|
labelId="select-label"
|
|
81
104
|
value={internalLimit}
|
|
82
|
-
onChange={
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
onChange={handleChangeLimit}
|
|
106
|
+
options={limitsPerPage}
|
|
107
|
+
getRenderValue={(value) => value.toString()}
|
|
108
|
+
width={75}
|
|
109
|
+
sx={{
|
|
110
|
+
'&.MuiInputBase-root': {
|
|
111
|
+
height: '32px !important'
|
|
86
112
|
}
|
|
87
113
|
}}
|
|
88
|
-
|
|
89
|
-
{limitsPerPage.map((limit, id) => (
|
|
90
|
-
<MenuItem key={id} value={limit}>
|
|
91
|
-
{limit}
|
|
92
|
-
</MenuItem>
|
|
93
|
-
))}
|
|
94
|
-
</Select>
|
|
114
|
+
/>
|
|
95
115
|
<Text
|
|
96
116
|
color="greyXDark"
|
|
97
117
|
variant="body1Regular"
|
|
@@ -108,23 +128,20 @@ const Pagination = ({
|
|
|
108
128
|
</>
|
|
109
129
|
)}
|
|
110
130
|
</Box>
|
|
111
|
-
{
|
|
131
|
+
{displayablePages > 1 && (
|
|
112
132
|
<Box display="flex" pr="4px">
|
|
113
133
|
<StyledPagination
|
|
114
134
|
variant="outlined"
|
|
115
135
|
shape="rounded"
|
|
116
|
-
count={
|
|
136
|
+
count={displayablePages}
|
|
117
137
|
page={internalPage}
|
|
118
|
-
onChange={(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
setPage(value);
|
|
122
|
-
}
|
|
123
|
-
}}
|
|
138
|
+
onChange={(_: React.ChangeEvent<unknown>, value: number) =>
|
|
139
|
+
changePage(value)
|
|
140
|
+
}
|
|
124
141
|
/>
|
|
125
142
|
</Box>
|
|
126
143
|
)}
|
|
127
|
-
|
|
144
|
+
</Box>
|
|
128
145
|
);
|
|
129
146
|
};
|
|
130
147
|
|
package/src/components/index.ts
CHANGED
|
@@ -23,3 +23,4 @@ export { default as BannerNotification } from './BannerNotification/BannerNotifi
|
|
|
23
23
|
export { default as Stepper } from './Stepper/Stepper';
|
|
24
24
|
export { default as Switch } from './Form/Switch/Switch';
|
|
25
25
|
export { default as DatePicker } from './Form/DatePicker';
|
|
26
|
+
export { default as Datatable } from './Datatable/Datatable';
|