norma-library 0.4.7 → 0.4.9

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.
Files changed (79) hide show
  1. package/dist/esm/components/ChatMessage.d.ts +3 -0
  2. package/dist/esm/components/ChatMessage.js +63 -0
  3. package/dist/esm/components/ChatMessage.js.map +1 -0
  4. package/dist/esm/components/DataGrid/base/dropdown.d.ts +4 -0
  5. package/dist/esm/components/DataGrid/base/dropdown.js +126 -0
  6. package/dist/esm/components/DataGrid/base/dropdown.js.map +1 -0
  7. package/dist/esm/components/DataGrid/base/number-filter.d.ts +4 -0
  8. package/dist/esm/components/DataGrid/base/number-filter.js +30 -0
  9. package/dist/esm/components/DataGrid/base/number-filter.js.map +1 -0
  10. package/dist/esm/components/DataGrid/base/sorting.d.ts +5 -0
  11. package/dist/esm/components/DataGrid/base/sorting.js +15 -0
  12. package/dist/esm/components/DataGrid/base/sorting.js.map +1 -0
  13. package/dist/esm/components/DataGrid/icons.d.ts +4 -0
  14. package/dist/esm/components/DataGrid/icons.js +15 -0
  15. package/dist/esm/components/DataGrid/icons.js.map +1 -0
  16. package/dist/esm/components/DataGrid/index.d.ts +5 -0
  17. package/dist/esm/components/DataGrid/index.js +146 -0
  18. package/dist/esm/components/DataGrid/index.js.map +1 -0
  19. package/dist/esm/components/DataGrid/shared.d.ts +20 -0
  20. package/dist/esm/components/DataGrid/shared.js +141 -0
  21. package/dist/esm/components/DataGrid/shared.js.map +1 -0
  22. package/dist/esm/components/DataGrid/styled.d.ts +10 -0
  23. package/dist/esm/components/DataGrid/styled.js +73 -0
  24. package/dist/esm/components/DataGrid/styled.js.map +1 -0
  25. package/dist/esm/components/Icons.js +1 -1
  26. package/dist/esm/components/ProgressBar.d.ts +0 -3
  27. package/dist/esm/components/ProgressBar.js +1 -1
  28. package/dist/esm/components/ProgressBar.js.map +1 -1
  29. package/dist/esm/components/TimeLine.d.ts +3 -0
  30. package/dist/esm/components/TimeLine.js +59 -0
  31. package/dist/esm/components/TimeLine.js.map +1 -0
  32. package/dist/esm/components/index.d.ts +3 -0
  33. package/dist/esm/components/index.js +3 -0
  34. package/dist/esm/components/index.js.map +1 -1
  35. package/dist/esm/helpers/colors.d.ts +3 -1
  36. package/dist/esm/helpers/colors.js +39 -10
  37. package/dist/esm/helpers/colors.js.map +1 -1
  38. package/dist/esm/interfaces/ChatMessage.d.ts +12 -0
  39. package/dist/esm/interfaces/ChatMessage.js +2 -0
  40. package/dist/esm/interfaces/ChatMessage.js.map +1 -0
  41. package/dist/esm/interfaces/DataGrid.d.ts +40 -0
  42. package/dist/esm/interfaces/DataGrid.js +2 -0
  43. package/dist/esm/interfaces/DataGrid.js.map +1 -0
  44. package/dist/esm/interfaces/TimeLine.d.ts +11 -0
  45. package/dist/esm/interfaces/TimeLine.js +2 -0
  46. package/dist/esm/interfaces/TimeLine.js.map +1 -0
  47. package/dist/esm/interfaces/index.d.ts +4 -1
  48. package/dist/esm/interfaces/index.js +4 -1
  49. package/dist/esm/interfaces/index.js.map +1 -1
  50. package/dist/esm/types/index.d.ts +12 -2
  51. package/dist/esm/types/index.js.map +1 -1
  52. package/norma-library.tar +0 -0
  53. package/package.json +3 -2
  54. package/src/components/ChatMessage.tsx +89 -0
  55. package/src/components/DataGrid/allData.json +2918 -0
  56. package/src/components/DataGrid/base/dropdown.tsx +235 -0
  57. package/src/components/DataGrid/base/number-filter.tsx +43 -0
  58. package/src/components/DataGrid/base/sorting.tsx +35 -0
  59. package/src/components/DataGrid/icons.tsx +61 -0
  60. package/src/components/DataGrid/index.tsx +319 -0
  61. package/src/components/DataGrid/shared.ts +179 -0
  62. package/src/components/DataGrid/styled.ts +102 -0
  63. package/src/components/DataGrid/styles/dropdown.module.css +86 -0
  64. package/src/components/DataGrid/styles/number-filter.module.css +16 -0
  65. package/src/components/DataGrid/styles/styles.module.css +107 -0
  66. package/src/components/Icons.tsx +1 -1
  67. package/src/components/ProgressBar.tsx +2 -1
  68. package/src/components/TimeLine.tsx +103 -0
  69. package/src/components/index.ts +3 -0
  70. package/src/helpers/colors.ts +44 -10
  71. package/src/interfaces/ChatMessage.ts +12 -0
  72. package/src/interfaces/DataGrid.ts +51 -0
  73. package/src/interfaces/TimeLine.ts +16 -0
  74. package/src/interfaces/index.ts +4 -1
  75. package/src/sample-data.json +178 -0
  76. package/src/stories/ChatMessage.stories.tsx +85 -0
  77. package/src/stories/DataGrid.stories.tsx +28 -0
  78. package/src/stories/TimeLine.stories.tsx +43 -0
  79. package/src/types/index.ts +26 -1
@@ -0,0 +1,235 @@
1
+ import React, { useState, useEffect, Fragment } from "react";
2
+ import NumberFilter from "./number-filter";
3
+ import {
4
+ Button,
5
+ Typography,
6
+ FormControl,
7
+ InputLabel,
8
+ OutlinedInput,
9
+ InputAdornment,
10
+ IconButton,
11
+ } from "@mui/material";
12
+ import Divider from "@mui/material/Divider";
13
+ import MenuList from "@mui/material/MenuList";
14
+ import MenuItem from "@mui/material/MenuItem";
15
+ import ListItemIcon from "@mui/material/ListItemIcon";
16
+ import ListItemText from "@mui/material/ListItemText";
17
+
18
+ import List from "@mui/material/List";
19
+ import ListItem from "@mui/material/ListItem";
20
+ import ListItemButton from "@mui/material/ListItemButton";
21
+ import Checkbox from "@mui/material/Checkbox";
22
+
23
+ import { Search } from "@mui/icons-material";
24
+ import { DropdownFilterProps } from "@/interfaces";
25
+ import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
26
+
27
+ import { DropDownStyled } from "../styled";
28
+
29
+ import { ArrowSmallDownIcon, ArrowSmallUpIcon, FunnelIcon } from "../icons";
30
+
31
+ const DropdownFilter = ({
32
+ onOrder,
33
+ onFilter,
34
+ onSelected,
35
+ onFilterSelected,
36
+ itemsSelected,
37
+ onSelectAll,
38
+ onChecketAll,
39
+ data,
40
+ }: DropdownFilterProps) => {
41
+ const [openFilter, setOpenFilter] = useState<boolean>(false);
42
+ const [selectAll, setSelectAll] = useState(onSelectAll);
43
+ const [selecteds, setItemsSelected] =
44
+ useState<(string | number)[]>(itemsSelected);
45
+
46
+ const handleFilter = () => {
47
+ setOpenFilter((prevState) => !prevState);
48
+ };
49
+
50
+ const handleFilterSelected = () => {
51
+ if (itemsSelected.length > 0) {
52
+ onFilterSelected();
53
+ } else {
54
+ onSelected([]);
55
+ onFilter("");
56
+ onFilterSelected();
57
+ }
58
+ };
59
+
60
+ const handleCheckboxChange = (option: string) => {
61
+ const updatedSelection = selecteds.includes(option)
62
+ ? selecteds.filter((selected) => selected !== option)
63
+ : [...selecteds, option];
64
+
65
+ setItemsSelected(updatedSelection);
66
+ onSelected(updatedSelection);
67
+ };
68
+
69
+ const handleSelectAll = () => {
70
+ setSelectAll(selectAll ? false : true);
71
+ onChecketAll(selectAll ? false : true);
72
+
73
+ if (!selectAll) {
74
+ const allItems = data.map((item: any) => item.toString());
75
+ setItemsSelected(allItems);
76
+ onSelected(allItems);
77
+ } else {
78
+ setItemsSelected([]);
79
+ onSelected([]);
80
+ }
81
+ };
82
+
83
+ useEffect(() => {
84
+ setItemsSelected(selectAll ? data.map(String) : []);
85
+ onSelected(selectAll ? data.map(String) : []);
86
+ }, [selectAll]);
87
+
88
+ useEffect(() => {
89
+ setItemsSelected(itemsSelected);
90
+ }, [selecteds]);
91
+
92
+ return (
93
+ <DropDownStyled>
94
+ <Fragment>
95
+ <MenuList>
96
+ <MenuItem
97
+ onClick={() => {
98
+ onOrder("down");
99
+ setOpenFilter(false);
100
+ }}
101
+ >
102
+ <ListItemIcon>
103
+ <ArrowSmallUpIcon width="16" height="16" />
104
+ </ListItemIcon>
105
+ <ListItemText>Classificar de A a Z</ListItemText>
106
+ </MenuItem>
107
+ <MenuItem
108
+ onClick={() => {
109
+ onOrder("up");
110
+ setOpenFilter(false);
111
+ }}
112
+ >
113
+ <ListItemIcon>
114
+ <ArrowSmallDownIcon width="16" height="16" />
115
+ </ListItemIcon>
116
+ <ListItemText>Classificar de Z a A</ListItemText>
117
+ </MenuItem>
118
+ <MenuItem onClick={handleFilter}>
119
+ <ListItemIcon>
120
+ <FunnelIcon width="16" height="16" />
121
+ </ListItemIcon>
122
+ <ListItemText>Filtro por números</ListItemText>
123
+ <Typography variant="body2" color="text.secondary">
124
+ <KeyboardArrowRightIcon
125
+ fontSize="medium"
126
+ style={{ position: "relative", top: "5px" }}
127
+ />
128
+ </Typography>
129
+ {openFilter && (
130
+ <React.Fragment>
131
+ <NumberFilter onClick={() => console.log("Me clicou")} />
132
+ </React.Fragment>
133
+ )}
134
+ </MenuItem>
135
+ <Divider />
136
+ <FormControl sx={{ m: 1 }} variant="outlined">
137
+ <InputLabel htmlFor="outlined-adornment-search" size="small">
138
+ Buscar
139
+ </InputLabel>
140
+ <OutlinedInput
141
+ id="outlined-adornment-search"
142
+ endAdornment={
143
+ <InputAdornment position="end">
144
+ <IconButton edge="end">
145
+ <Search />
146
+ </IconButton>
147
+ </InputAdornment>
148
+ }
149
+ onChange={(event) => {
150
+ onFilter(event.target.value);
151
+ }}
152
+ label="Buscar"
153
+ fullWidth
154
+ size="small"
155
+ />
156
+ </FormControl>
157
+ <Divider />
158
+ <List
159
+ sx={{
160
+ bgcolor: "#f2f2f2",
161
+ padding: " 5px",
162
+ overflow: " auto",
163
+ width: " 100%",
164
+ height: " 120px",
165
+ }}
166
+ >
167
+ <ListItem disablePadding onClick={handleSelectAll}>
168
+ <ListItemButton role={undefined} sx={{ py: 0, minHeight: 32 }}>
169
+ <ListItemIcon>
170
+ <Checkbox
171
+ edge="start"
172
+ tabIndex={-1}
173
+ checked={selectAll}
174
+ disableRipple
175
+ inputProps={{ "aria-labelledby": "all" }}
176
+ />
177
+ </ListItemIcon>
178
+ <ListItemText
179
+ id={"all"}
180
+ primary={selectAll ? "Deselect All" : "Select All"}
181
+ primaryTypographyProps={{
182
+ fontSize: 14,
183
+ fontWeight: "medium",
184
+ }}
185
+ />
186
+ </ListItemButton>
187
+ </ListItem>
188
+ {data.map((item: any, key: number) => {
189
+ const labelId = `checkbox-list-label-${item.toString()}`;
190
+ return (
191
+ <ListItem
192
+ key={key}
193
+ disablePadding
194
+ onClick={() => handleCheckboxChange(item.toString())}
195
+ >
196
+ <ListItemButton
197
+ role={undefined}
198
+ sx={{ py: 0, minHeight: 32 }}
199
+ >
200
+ <ListItemIcon>
201
+ <Checkbox
202
+ edge="start"
203
+ tabIndex={-1}
204
+ disableRipple
205
+ inputProps={{ "aria-labelledby": labelId }}
206
+ checked={selecteds.includes(item.toString())}
207
+ />
208
+ </ListItemIcon>
209
+ <ListItemText
210
+ id={labelId}
211
+ primary={`${item}`}
212
+ primaryTypographyProps={{
213
+ fontSize: 14,
214
+ fontWeight: "medium",
215
+ }}
216
+ />
217
+ </ListItemButton>
218
+ </ListItem>
219
+ );
220
+ })}
221
+ </List>
222
+ </MenuList>
223
+ <Button
224
+ variant="outlined"
225
+ sx={{ align: "right" }}
226
+ onClick={handleFilterSelected}
227
+ >
228
+ Confirm
229
+ </Button>
230
+ </Fragment>
231
+ </DropDownStyled>
232
+ );
233
+ };
234
+
235
+ export default DropdownFilter;
@@ -0,0 +1,43 @@
1
+ import React from "react";
2
+
3
+ import List from "@mui/material/List";
4
+ import ListItem from "@mui/material/ListItem";
5
+ import ListItemText from "@mui/material/ListItemText";
6
+ import { NumberFilterProps } from "@/interfaces";
7
+
8
+ const items = [
9
+ "Equal",
10
+ "Does not equal",
11
+ "Greater than",
12
+ "Greater than or equal to",
13
+ "Less than",
14
+ "Less than or equal to",
15
+ "Between",
16
+ ];
17
+
18
+ const NumberFilter: React.FC<NumberFilterProps> = () => {
19
+ return (
20
+ <List
21
+ sx={{
22
+ bgcolor: "#FFF",
23
+ position: "absolute",
24
+ minHeight: "190px",
25
+ top: "0",
26
+ left: "auto",
27
+ right: "auto",
28
+ minWidth: "240px",
29
+ zIndex: "9",
30
+ padding: "5px 10px",
31
+ boxShadow: "0 0 10px #ccc",
32
+ }}
33
+ >
34
+ {items.map((value, key) => (
35
+ <ListItem key={key} disableGutters>
36
+ <ListItemText primary={`${value}...`} />
37
+ </ListItem>
38
+ ))}
39
+ </List>
40
+ );
41
+ };
42
+
43
+ export default NumberFilter;
@@ -0,0 +1,35 @@
1
+ import React from "react";
2
+
3
+ import { SortingProps } from "@/interfaces";
4
+ // import { Icons } from "@/components/Icons";
5
+
6
+ export function ArrowSmallUpIcon(props: any) {
7
+ return (
8
+ <svg
9
+ fill="currentColor"
10
+ viewBox="0 0 24 24"
11
+ xmlns="http://www.w3.org/2000/svg"
12
+ aria-hidden="true"
13
+ {...props}
14
+ >
15
+ <path
16
+ clipRule="evenodd"
17
+ fillRule="evenodd"
18
+ d="M12 20.25a.75.75 0 01-.75-.75V6.31l-5.47 5.47a.75.75 0 01-1.06-1.06l6.75-6.75a.75.75 0 011.06 0l6.75 6.75a.75.75 0 11-1.06 1.06l-5.47-5.47V19.5a.75.75 0 01-.75.75z"
19
+ />
20
+ </svg>
21
+ );
22
+ }
23
+
24
+ const Sorting: React.FC<SortingProps> = ({ sort, active }) => {
25
+ const sortIcon = <ArrowSmallUpIcon />;
26
+ const opacityValue = active ? 1 : 0.5;
27
+
28
+ return (
29
+ <button type="button" style={{ opacity: opacityValue }} className="arrows">
30
+ {sort && sortIcon}
31
+ </button>
32
+ );
33
+ };
34
+
35
+ export default Sorting;
@@ -0,0 +1,61 @@
1
+ import React from "react";
2
+
3
+ export function FunnelIcon(props: any) {
4
+ return (
5
+ <svg
6
+ fill="none"
7
+ stroke="currentColor"
8
+ strokeWidth={1.5}
9
+ viewBox="0 0 24 24"
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ aria-hidden="true"
12
+ {...props}
13
+ >
14
+ <path
15
+ strokeLinecap="round"
16
+ strokeLinejoin="round"
17
+ d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 01-.659 1.591l-5.432 5.432a2.25 2.25 0 00-.659 1.591v2.927a2.25 2.25 0 01-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 00-.659-1.591L3.659 7.409A2.25 2.25 0 013 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0112 3z"
18
+ />
19
+ </svg>
20
+ );
21
+ }
22
+
23
+ export function ArrowSmallUpIcon(props: any) {
24
+ return (
25
+ <svg
26
+ fill="none"
27
+ stroke="currentColor"
28
+ strokeWidth={1.5}
29
+ viewBox="0 0 24 24"
30
+ xmlns="http://www.w3.org/2000/svg"
31
+ aria-hidden="true"
32
+ {...props}
33
+ >
34
+ <path
35
+ strokeLinecap="round"
36
+ strokeLinejoin="round"
37
+ d="M12 19.5v-15m0 0l-6.75 6.75M12 4.5l6.75 6.75"
38
+ />
39
+ </svg>
40
+ );
41
+ }
42
+
43
+ export function ArrowSmallDownIcon(props: any) {
44
+ return (
45
+ <svg
46
+ fill="none"
47
+ stroke="currentColor"
48
+ strokeWidth={1.5}
49
+ viewBox="0 0 24 24"
50
+ xmlns="http://www.w3.org/2000/svg"
51
+ aria-hidden="true"
52
+ {...props}
53
+ >
54
+ <path
55
+ strokeLinecap="round"
56
+ strokeLinejoin="round"
57
+ d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75"
58
+ />
59
+ </svg>
60
+ );
61
+ }
@@ -0,0 +1,319 @@
1
+ import React, { useEffect, useMemo, useState, useRef } from "react";
2
+
3
+ import { Box, Stack, ThemeProvider, useMediaQuery, Paper } from "@mui/material";
4
+
5
+ import Table from "@mui/material/Table";
6
+ import TableBody from "@mui/material/TableBody";
7
+ import TableCell from "@mui/material/TableCell";
8
+ import TableContainer from "@mui/material/TableContainer";
9
+ import TableHead from "@mui/material/TableHead";
10
+ import TableRow from "@mui/material/TableRow";
11
+
12
+ import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";
13
+ import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
14
+
15
+ import { DataGridBaseProps, DataSourceItem } from "../../interfaces";
16
+
17
+ import { themes } from "../../helpers";
18
+
19
+ import DropdownFilter from "./base/dropdown";
20
+ import { Pagination as MuiPagination } from "@mui/material";
21
+
22
+ import {
23
+ filterDataSource,
24
+ generateRandomDataSource,
25
+ groupByDataSource,
26
+ sortDataSourceByColumn,
27
+ } from "./shared";
28
+
29
+ import {
30
+ ButtonStyled,
31
+ DataGridHeaderStyled,
32
+ HeaderCogStyled,
33
+ TableCellStyled,
34
+ TableRowStyled,
35
+ TotalRecordsStyled,
36
+ } from "./styled";
37
+
38
+ export function ArrowSmallUpIcon(props: any) {
39
+ return (
40
+ <svg
41
+ fill="currentColor"
42
+ viewBox="0 0 24 24"
43
+ xmlns="http://www.w3.org/2000/svg"
44
+ aria-hidden="true"
45
+ {...props}
46
+ >
47
+ <path
48
+ clipRule="evenodd"
49
+ fillRule="evenodd"
50
+ d="M12 20.25a.75.75 0 01-.75-.75V6.31l-5.47 5.47a.75.75 0 01-1.06-1.06l6.75-6.75a.75.75 0 011.06 0l6.75 6.75a.75.75 0 11-1.06 1.06l-5.47-5.47V19.5a.75.75 0 01-.75.75z"
51
+ />
52
+ </svg>
53
+ );
54
+ }
55
+
56
+ export function Cog6ToothIcon(props: any) {
57
+ return (
58
+ <svg
59
+ fill="none"
60
+ stroke="currentColor"
61
+ strokeWidth={1.5}
62
+ viewBox="0 0 24 24"
63
+ xmlns="http://www.w3.org/2000/svg"
64
+ aria-hidden="true"
65
+ {...props}
66
+ >
67
+ <path
68
+ strokeLinecap="round"
69
+ strokeLinejoin="round"
70
+ d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z"
71
+ />
72
+ <path
73
+ strokeLinecap="round"
74
+ strokeLinejoin="round"
75
+ d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
76
+ />
77
+ </svg>
78
+ );
79
+ }
80
+
81
+ const dataSource = generateRandomDataSource(30);
82
+
83
+ export const DataGrid: React.FC<DataGridBaseProps> = ({ data = [] }) => {
84
+ const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
85
+ const theme = useMemo(
86
+ () => (prefersDarkMode ? themes.light : themes.light),
87
+ [prefersDarkMode]
88
+ );
89
+
90
+ const pageSize = 10;
91
+ const columns = data[0].columns;
92
+
93
+ const [selectedItems, setSelectedItems] = useState<(string | number)[]>([]);
94
+
95
+ const [sorting, setSorting] = useState("down");
96
+ const [selectAll, setSelectAll] = useState<boolean>(false);
97
+
98
+ const [currentActiveSorting, setCurrentActiveSorting] =
99
+ useState<string>("id");
100
+
101
+ const [currentDropDownActive, setCurrentDropDownActive] = useState<
102
+ string | null
103
+ >(null);
104
+
105
+ const [originalDataSource, setOriginalDataSource] =
106
+ useState<DataSourceItem[]>(dataSource);
107
+ const [newDataSource, setDataSource] = useState<DataSourceItem[]>(dataSource);
108
+ const [totalRecords, setTotalRecords] = useState(dataSource.length);
109
+ const [totalPages, setTotalPages] = useState(
110
+ Math.ceil(dataSource.length / pageSize)
111
+ );
112
+
113
+ const [currentPage, setCurrentPage] = useState(1);
114
+ const startIndex = (currentPage - 1) * pageSize;
115
+ const endIndex = Math.min(startIndex + pageSize, totalRecords);
116
+
117
+ const sortRefs = useRef<(React.RefObject<HTMLTableCellElement> | null)[]>(
118
+ new Array(columns.length).fill(null)
119
+ );
120
+
121
+ const handleItemSelected = (items: (string | number)[]) => {
122
+ setSelectedItems(items);
123
+ };
124
+
125
+ const handleDropDown = (item: any) => {
126
+ setCurrentDropDownActive(item === currentDropDownActive ? null : item);
127
+ if (item !== currentDropDownActive) {
128
+ setCurrentActiveSorting(item);
129
+ setSorting("down");
130
+ }
131
+ };
132
+
133
+ const handleSorting = (sort: string) => {
134
+ setSorting(sort === "up" ? "up" : "down");
135
+ currentDropDownActive && setCurrentActiveSorting(currentDropDownActive);
136
+ handleDropDown(currentDropDownActive);
137
+ };
138
+
139
+ const handleFilter = (filter: string) => {
140
+ const dataSourceFiltered = filterDataSource(
141
+ originalDataSource,
142
+ currentActiveSorting,
143
+ filter
144
+ );
145
+ setOriginalDataSource(dataSourceFiltered);
146
+ setCurrentPage(1);
147
+ };
148
+
149
+ const handleFilterSelected = () => {
150
+ if (selectedItems.length > 0) {
151
+ const filteredData = originalDataSource.filter((item: DataSourceItem) => {
152
+ const columnValue = currentActiveSorting
153
+ ? item[currentActiveSorting]
154
+ : undefined;
155
+
156
+ if (typeof columnValue === "string") {
157
+ return selectedItems.includes(columnValue);
158
+ } else if (typeof columnValue === "number") {
159
+ return selectedItems.includes(columnValue.toString());
160
+ }
161
+ return false;
162
+ });
163
+
164
+ const sortedData = sortDataSourceByColumn(
165
+ filteredData,
166
+ currentActiveSorting,
167
+ sorting
168
+ );
169
+ setTotalRecords(sortedData.length);
170
+ setTotalPages(Math.ceil(sortedData.length / pageSize));
171
+ setCurrentPage(1);
172
+ setDataSource(sortedData.slice(startIndex, endIndex));
173
+ } else {
174
+ const sortedData = sortDataSourceByColumn(
175
+ dataSource,
176
+ currentActiveSorting,
177
+ sorting
178
+ );
179
+ setTotalRecords(sortedData.length);
180
+ setTotalPages(Math.ceil(sortedData.length / pageSize));
181
+ setCurrentPage(1);
182
+ setDataSource(sortedData.slice(startIndex, endIndex));
183
+ }
184
+ handleDropDown(currentDropDownActive);
185
+ };
186
+
187
+ const handleChangePage = (page: number) => {
188
+ setCurrentPage(page);
189
+ const startIndex = (page - 1) * pageSize;
190
+ const endIndex = Math.min(startIndex + pageSize, totalRecords);
191
+ setDataSource(originalDataSource.slice(startIndex, endIndex));
192
+ };
193
+
194
+ useEffect(() => {
195
+ if (selectedItems.length <= 0) {
196
+ const sortedData = sortDataSourceByColumn(
197
+ dataSource,
198
+ currentActiveSorting,
199
+ sorting
200
+ );
201
+ setDataSource(sortedData.slice(startIndex, endIndex));
202
+ setTotalRecords(sortedData.length);
203
+ setTotalPages(Math.ceil(sortedData.length / pageSize));
204
+ setCurrentPage(1);
205
+ }
206
+ }, [selectedItems]);
207
+
208
+ return (
209
+ <ThemeProvider theme={theme}>
210
+ <Box sx={{ width: "100%", minHeight: 480 }}>
211
+ <DataGridHeaderStyled>
212
+ <TotalRecordsStyled>
213
+ {totalRecords} results found for this search
214
+ </TotalRecordsStyled>
215
+ <HeaderCogStyled type="button">
216
+ <Cog6ToothIcon width={24} height={24} />
217
+ </HeaderCogStyled>
218
+ </DataGridHeaderStyled>
219
+ <TableContainer component={Paper} sx={{ overflowX: "inherit" }}>
220
+ <Table
221
+ sx={{ minWidth: 650, width: "100%" }}
222
+ aria-label="a dense table"
223
+ >
224
+ <TableHead>
225
+ <TableRow>
226
+ {columns &&
227
+ columns.map((item: any, key: any) => (
228
+ <TableCellStyled
229
+ key={key}
230
+ ref={(ref) =>
231
+ (sortRefs.current[key] =
232
+ ref as React.RefObject<HTMLTableCellElement> | null)
233
+ }
234
+ >
235
+ <Stack
236
+ direction="row"
237
+ spacing={2}
238
+ sx={{ position: "relative" }}
239
+ >
240
+ <ButtonStyled
241
+ variant="text"
242
+ size="small"
243
+ color={
244
+ currentActiveSorting === item.field
245
+ ? "primary"
246
+ : "inherit"
247
+ }
248
+ endIcon={
249
+ currentActiveSorting === item.field &&
250
+ sorting === "up" ? (
251
+ <ArrowDropUpIcon />
252
+ ) : (
253
+ <ArrowDropDownIcon />
254
+ )
255
+ }
256
+ onClick={() => {
257
+ handleDropDown(item.field);
258
+ }}
259
+ >
260
+ {item.headerText}
261
+ </ButtonStyled>
262
+ {currentDropDownActive &&
263
+ currentDropDownActive === item.field && (
264
+ <DropdownFilter
265
+ format={item.format}
266
+ onOrder={handleSorting}
267
+ onFilter={handleFilter}
268
+ onSelected={handleItemSelected}
269
+ itemsSelected={selectedItems}
270
+ onFilterSelected={handleFilterSelected}
271
+ onChecketAll={setSelectAll}
272
+ onSelectAll={selectAll}
273
+ data={groupByDataSource(dataSource, item.field)}
274
+ />
275
+ )}
276
+ </Stack>
277
+ </TableCellStyled>
278
+ ))}
279
+ </TableRow>
280
+ </TableHead>
281
+ <TableBody>
282
+ {newDataSource &&
283
+ newDataSource.map((item: DataSourceItem, key: number) => (
284
+ <TableRowStyled
285
+ key={key}
286
+ sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
287
+ >
288
+ {Object.keys(item).map((columnKey) => (
289
+ <TableCell component="th" scope="row" key={columnKey}>
290
+ {item[columnKey]}
291
+ </TableCell>
292
+ ))}
293
+ </TableRowStyled>
294
+ ))}
295
+ </TableBody>
296
+ </Table>
297
+ <Stack
298
+ spacing={2}
299
+ sx={{
300
+ display: "flex",
301
+ justifyContent: "center",
302
+ alignItems: "center",
303
+ borderTop: "1px solid #ccc",
304
+ padding: 2,
305
+ }}
306
+ >
307
+ <MuiPagination
308
+ variant="outlined"
309
+ shape="rounded"
310
+ count={totalPages}
311
+ page={currentPage}
312
+ onChange={(_event, page) => handleChangePage(page)}
313
+ />
314
+ </Stack>
315
+ </TableContainer>
316
+ </Box>
317
+ </ThemeProvider>
318
+ );
319
+ };