@addev-be/ui 0.1.18

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 (98) hide show
  1. package/assets/fonts/montserrat-200.woff2 +0 -0
  2. package/assets/fonts/montserrat-400.woff2 +0 -0
  3. package/assets/fonts/montserrat-500.woff2 +0 -0
  4. package/assets/fonts/montserrat-700.woff2 +0 -0
  5. package/assets/icons/arrow-down-a-z.svg +1 -0
  6. package/assets/icons/arrow-up-z-a.svg +1 -0
  7. package/assets/icons/arrows-rotate.svg +1 -0
  8. package/assets/icons/arrows-up-down.svg +1 -0
  9. package/assets/icons/check.svg +1 -0
  10. package/assets/icons/copy.svg +1 -0
  11. package/assets/icons/down.svg +1 -0
  12. package/assets/icons/filter-full.svg +1 -0
  13. package/assets/icons/filter-slash.svg +1 -0
  14. package/assets/icons/filter.svg +1 -0
  15. package/assets/icons/hashtag.svg +1 -0
  16. package/assets/icons/image-slash.svg +1 -0
  17. package/assets/icons/left.svg +1 -0
  18. package/assets/icons/magnifier.svg +1 -0
  19. package/assets/icons/phone.svg +1 -0
  20. package/assets/icons/plus.svg +1 -0
  21. package/assets/icons/right.svg +1 -0
  22. package/assets/icons/spinner-third.svg +1 -0
  23. package/assets/icons/table-columns.svg +1 -0
  24. package/assets/icons/up.svg +1 -0
  25. package/assets/icons/user-tie.svg +1 -0
  26. package/eslint.config.js +28 -0
  27. package/package.json +49 -0
  28. package/src/Icons.tsx +80 -0
  29. package/src/components/data/DataGrid/AdvancedRequestDataGrid.tsx +236 -0
  30. package/src/components/data/DataGrid/DataGridCell.tsx +78 -0
  31. package/src/components/data/DataGrid/DataGridColumnsModal/helpers.ts +14 -0
  32. package/src/components/data/DataGrid/DataGridColumnsModal/hooks.tsx +58 -0
  33. package/src/components/data/DataGrid/DataGridColumnsModal/index.tsx +181 -0
  34. package/src/components/data/DataGrid/DataGridColumnsModal/styles.ts +104 -0
  35. package/src/components/data/DataGrid/DataGridEditableCell.tsx +54 -0
  36. package/src/components/data/DataGrid/DataGridFilterMenu/hooks.tsx +75 -0
  37. package/src/components/data/DataGrid/DataGridFilterMenu/index.tsx +190 -0
  38. package/src/components/data/DataGrid/DataGridFilterMenu/styles.ts +100 -0
  39. package/src/components/data/DataGrid/DataGridFooter.tsx +64 -0
  40. package/src/components/data/DataGrid/DataGridHeader.tsx +129 -0
  41. package/src/components/data/DataGrid/DataGridHeaderCell.tsx +166 -0
  42. package/src/components/data/DataGrid/FilterModalContent/index.tsx +125 -0
  43. package/src/components/data/DataGrid/FilterModalContent/styles.ts +22 -0
  44. package/src/components/data/DataGrid/FilterValuesScroller.tsx +131 -0
  45. package/src/components/data/DataGrid/VirtualScroller.tsx +51 -0
  46. package/src/components/data/DataGrid/helpers/advancedRequests.tsx +61 -0
  47. package/src/components/data/DataGrid/helpers/columns.tsx +259 -0
  48. package/src/components/data/DataGrid/helpers/filters.ts +219 -0
  49. package/src/components/data/DataGrid/helpers/index.ts +3 -0
  50. package/src/components/data/DataGrid/hooks/index.ts +30 -0
  51. package/src/components/data/DataGrid/hooks/useDataGrid.tsx +225 -0
  52. package/src/components/data/DataGrid/hooks/useDataGridCopy.ts +166 -0
  53. package/src/components/data/DataGrid/hooks/useDataGridSettings.ts +49 -0
  54. package/src/components/data/DataGrid/index.tsx +145 -0
  55. package/src/components/data/DataGrid/styles.ts +284 -0
  56. package/src/components/data/DataGrid/types.ts +232 -0
  57. package/src/components/data/index.ts +3 -0
  58. package/src/components/forms/Button.tsx +99 -0
  59. package/src/components/forms/IconButton.tsx +57 -0
  60. package/src/components/forms/IndeterminateCheckbox.tsx +46 -0
  61. package/src/components/forms/Select.tsx +40 -0
  62. package/src/components/forms/index.ts +5 -0
  63. package/src/components/forms/styles.ts +20 -0
  64. package/src/components/index.ts +3 -0
  65. package/src/components/layout/Dropdown/index.tsx +79 -0
  66. package/src/components/layout/Dropdown/styles.ts +44 -0
  67. package/src/components/layout/Loading/index.tsx +28 -0
  68. package/src/components/layout/Loading/styles.ts +29 -0
  69. package/src/components/layout/Modal/index.tsx +51 -0
  70. package/src/components/layout/Modal/styles.ts +110 -0
  71. package/src/components/layout/index.ts +3 -0
  72. package/src/config/index.ts +14 -0
  73. package/src/helpers/getScrollbarSize.ts +14 -0
  74. package/src/helpers/numbers.ts +20 -0
  75. package/src/hooks/index.ts +2 -0
  76. package/src/hooks/useElementSize.ts +24 -0
  77. package/src/hooks/useWindowSize.ts +20 -0
  78. package/src/index.ts +7 -0
  79. package/src/providers/PortalsProvider/index.tsx +54 -0
  80. package/src/providers/PortalsProvider/styles.ts +27 -0
  81. package/src/providers/SettingsProvider/index.tsx +70 -0
  82. package/src/providers/ThemeProvider/ThemeProvider.ts +55 -0
  83. package/src/providers/ThemeProvider/defaultTheme.ts +444 -0
  84. package/src/providers/ThemeProvider/index.ts +3 -0
  85. package/src/providers/ThemeProvider/types.ts +123 -0
  86. package/src/providers/UiProviders/index.tsx +65 -0
  87. package/src/providers/UiProviders/styles.ts +10 -0
  88. package/src/providers/hooks.ts +8 -0
  89. package/src/providers/index.ts +5 -0
  90. package/src/services/WebSocketService.ts +147 -0
  91. package/src/services/advancedRequests.ts +100 -0
  92. package/src/services/base.ts +31 -0
  93. package/src/services/hooks.ts +13 -0
  94. package/src/services/index.ts +2 -0
  95. package/src/styles/animations.scss +30 -0
  96. package/src/styles/index.scss +42 -0
  97. package/src/typings.d.ts +6 -0
  98. package/tsconfig.json +18 -0
@@ -0,0 +1,225 @@
1
+ /* eslint-disable @typescript-eslint/no-unnecessary-type-constraint */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+
4
+ import { DEFAULT_ROW_HEIGHT, VIRTUAL_SCROLL_TOLERANCE } from '../styles';
5
+ import {
6
+ DataGridColumns,
7
+ DataGridContext,
8
+ DataGridContextProps,
9
+ DataGridFilters,
10
+ DataGridProps,
11
+ DataGridSort,
12
+ } from '../types';
13
+ import {
14
+ createContext,
15
+ useCallback,
16
+ useEffect,
17
+ useMemo,
18
+ useRef,
19
+ useState,
20
+ } from 'react';
21
+ import { useDataGridCopy, useSortedColumns } from '.';
22
+
23
+ import { applyFilter } from '../helpers';
24
+ import { merge } from 'lodash';
25
+ import { useDataGridSettings } from './useDataGridSettings';
26
+ import { useElementSize } from '../../../../hooks';
27
+
28
+ export const useDataGrid = <R,>(
29
+ props: DataGridProps<R>
30
+ ): [DataGridContextProps<R>, DataGridContext<R>] => {
31
+ const {
32
+ rows,
33
+ onFiltersChanged,
34
+ onSortsChanged,
35
+ loadCopyRows,
36
+ rowHeight = DEFAULT_ROW_HEIGHT,
37
+ onVisibleRowsChange,
38
+ } = props;
39
+ const [columns, setColumns] = useState<DataGridColumns<R>>(props.columns);
40
+
41
+ const visibleColumns = useSortedColumns(columns);
42
+
43
+ /** SETTINGS */
44
+
45
+ const { settings, setSettings, saveSettings } = useDataGridSettings(
46
+ props.name
47
+ );
48
+
49
+ const setColumnWidth = useCallback(
50
+ (key: string, width: number) => {
51
+ setSettings((prev) => ({ ...prev, [key]: { ...prev[key], width } }));
52
+ },
53
+ [setSettings]
54
+ );
55
+
56
+ // Update columns when settings change
57
+ useEffect(() => {
58
+ setColumns((prev) => merge({}, prev, settings));
59
+ }, [settings]);
60
+
61
+ /** ROWS SELECTION **/
62
+
63
+ const [selectedRows, setSelectedRows] = useState<R[]>([]);
64
+
65
+ /** ROWS FILTERING **/
66
+
67
+ const [filters, setFilters] = useState<DataGridFilters<R>>({});
68
+ const [filteredRows, setFilteredRows] = useState<R[]>(rows ?? []);
69
+
70
+ useEffect(() => {
71
+ onFiltersChanged?.(filters);
72
+ }, [filters, onFiltersChanged]);
73
+
74
+ useEffect(() => {
75
+ const filteredRows =
76
+ props.filter === false
77
+ ? rows
78
+ : Object.entries(filters).reduce(
79
+ (tempRows, [, filter]) =>
80
+ applyFilter(tempRows, filter as any /* TODO : fix typings */),
81
+ rows
82
+ );
83
+ setFilteredRows(filteredRows ?? []);
84
+ }, [filters, props.filter, rows]);
85
+
86
+ /** CELL EDITING */
87
+
88
+ const [editingCell, setEditingCell] = useState<[number, number]>([-1, -1]);
89
+
90
+ /** ROWS SORTING **/
91
+
92
+ const [sorts, setSorts] = useState<Record<string, DataGridSort>>({});
93
+ const [sortedRows, setSortedRows] = useState<R[]>(rows);
94
+
95
+ useEffect(() => {
96
+ const sortedRows = [...filteredRows];
97
+ if (props.sort !== false) {
98
+ Object.entries(sorts).forEach(([sortKey, sort]) => {
99
+ // Get the sort column and make sure it exists and is sortable
100
+ const sortColumn = columns[sortKey];
101
+ if (!sortColumn || typeof sortColumn.sortGetter !== 'function') return;
102
+
103
+ // Sort the rows using the sortGetter function of the column
104
+ const sortDirection = sort === 'asc' ? 1 : -1;
105
+ sortedRows.sort((a: R, b: R) => {
106
+ const aValue = sortColumn.sortGetter!(a);
107
+ const bValue = sortColumn.sortGetter!(b);
108
+ if (aValue === bValue) return 0;
109
+ return aValue > bValue ? sortDirection : -sortDirection;
110
+ });
111
+ });
112
+ }
113
+ setSortedRows(sortedRows);
114
+ }, [columns, filteredRows, sorts, onSortsChanged, props.sort]);
115
+
116
+ useEffect(() => {
117
+ onSortsChanged?.(sorts);
118
+ }, [sorts, onSortsChanged]);
119
+
120
+ /** VIRTUAL SCROLLING */
121
+
122
+ const scrollableRef = useRef<HTMLTableSectionElement | null>(null);
123
+ const { height } = useElementSize(scrollableRef.current);
124
+
125
+ const [scrollTop, setScrollTop] = useState(0);
126
+ const [index, length] =
127
+ // props.showAllRows ? [0, sortedRows.length] :
128
+ [Math.floor(scrollTop / rowHeight), Math.ceil(height / rowHeight)];
129
+
130
+ const onScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
131
+ const target = e.target as HTMLDivElement;
132
+ setScrollTop(target.scrollTop);
133
+ }, []);
134
+
135
+ const indexWithTolerance = Math.max(0, index - VIRTUAL_SCROLL_TOLERANCE);
136
+ const lengthWithTolerance = length + 2 * VIRTUAL_SCROLL_TOLERANCE;
137
+ const visibleRows = sortedRows.slice(
138
+ indexWithTolerance,
139
+ indexWithTolerance + lengthWithTolerance
140
+ );
141
+
142
+ useEffect(() => {
143
+ onVisibleRowsChange?.(indexWithTolerance, lengthWithTolerance);
144
+ }, [indexWithTolerance, lengthWithTolerance, onVisibleRowsChange]);
145
+
146
+ /** COPYING */
147
+
148
+ const { copyTable } = useDataGridCopy(sortedRows, columns, loadCopyRows);
149
+
150
+ const contextValue = useMemo<DataGridContextProps<R>>(
151
+ () => ({
152
+ ...props,
153
+ columns,
154
+ visibleColumns,
155
+ sortedRows,
156
+ selectedRows,
157
+ setSelectedRows,
158
+ sorts,
159
+ setSorts,
160
+ filters,
161
+ setFilters,
162
+ editingCell,
163
+ setEditingCell,
164
+ copyTable,
165
+ setColumnWidth,
166
+ settings,
167
+ setSettings,
168
+ saveSettings,
169
+ visibleRows,
170
+ scrollableRef,
171
+ onScroll,
172
+ index,
173
+ length,
174
+ }),
175
+ [
176
+ columns,
177
+ copyTable,
178
+ editingCell,
179
+ filters,
180
+ index,
181
+ length,
182
+ onScroll,
183
+ props,
184
+ saveSettings,
185
+ selectedRows,
186
+ setColumnWidth,
187
+ setSettings,
188
+ settings,
189
+ sortedRows,
190
+ sorts,
191
+ visibleColumns,
192
+ visibleRows,
193
+ ]
194
+ );
195
+
196
+ const context = useMemo(
197
+ () =>
198
+ createContext<DataGridContextProps<R>>({
199
+ rows: [],
200
+ columns: {},
201
+ visibleColumns: [],
202
+ rowKey: '' as keyof R,
203
+ sortedRows: [],
204
+ selectedRows: [],
205
+ setSelectedRows: () => {},
206
+ setSorts: () => {},
207
+ setFilters: () => {},
208
+ editingCell: [-1, -1],
209
+ setEditingCell: () => {},
210
+ copyTable: async () => {},
211
+ setColumnWidth: () => {},
212
+ saveSettings: () => {},
213
+ settings: {},
214
+ setSettings: () => {},
215
+ visibleRows: [],
216
+ scrollableRef: { current: null },
217
+ onScroll: () => {},
218
+ index: 0,
219
+ length: 0,
220
+ }),
221
+ []
222
+ );
223
+
224
+ return useMemo(() => [contextValue, context], [context, contextValue]);
225
+ };
@@ -0,0 +1,166 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import { DataGridColumn, DataGridColumns } from '../types';
4
+
5
+ import { useCallback } from 'react';
6
+
7
+ export const useDataGridCopy = <R>(
8
+ rows: R[],
9
+ columns: DataGridColumns<R>,
10
+ loadCopyRows?: () => Promise<R[]>
11
+ ) => {
12
+ const generateHeadersHtml = useCallback(() => {
13
+ return `<tr>
14
+ ${Object.values(columns ?? {})
15
+ .map(
16
+ (col) =>
17
+ `<th style="
18
+ text-align: left;
19
+ font-weight: bold;
20
+ white-space: nowrap;
21
+ ">
22
+ ${col.name}
23
+ </th>`
24
+ )
25
+ .join('\n')}
26
+ </tr>`;
27
+ }, [columns]);
28
+
29
+ const generateFootersHtml = useCallback(
30
+ (rowsToCopy: R[]) => {
31
+ return `<tr>
32
+ ${Object.values(columns ?? {})
33
+ .map(
34
+ (col) =>
35
+ `<td style="
36
+ font-weight: bold;
37
+ white-space: nowrap;
38
+ ">
39
+ ${
40
+ col.footer
41
+ ? col.footer(rowsToCopy, rowsToCopy, [])
42
+ : ''
43
+ }
44
+ </td>`
45
+ )
46
+ .join('\n')}
47
+ </tr>`;
48
+ },
49
+ [columns]
50
+ );
51
+
52
+ const generateCellText = useCallback((col: DataGridColumn<R>, value: any) => {
53
+ return col.excelValue ? col.excelValue(value) : value?.toString() ?? '';
54
+ }, []);
55
+
56
+ const generateCellHtml = useCallback(
57
+ (col: DataGridColumn<R, any>, value: any) => `<td style="
58
+ ${
59
+ col.excelFormatter
60
+ ? "mso-number-format: '" + col.excelFormatter(col) + "';"
61
+ : ''
62
+ }
63
+ white-space: nowrap;
64
+ ">
65
+ ${generateCellText(col, value)}
66
+ </td>`,
67
+ [generateCellText]
68
+ );
69
+
70
+ const generateCopyHtml = useCallback(
71
+ (rowsToCopy: R[], includeHeaders: boolean, includeFooters: boolean) => {
72
+ console.log('generateCopyHtml', rowsToCopy, columns);
73
+ return `
74
+ <table>
75
+ ${includeHeaders ? generateHeadersHtml() : ''}
76
+ ${(rowsToCopy || [])
77
+ .map(
78
+ (row) =>
79
+ `<tr>
80
+ ${Object.values(columns ?? {})
81
+ .map((col) => {
82
+ const value: any =
83
+ col.getter && row ? col.getter(row) : '';
84
+ return generateCellHtml(col, value);
85
+ })
86
+ .join('\n')}
87
+ </tr>`
88
+ )
89
+ .join('\n')}
90
+ ${includeFooters ? generateFootersHtml(rowsToCopy) : ''}
91
+ </table>
92
+ `;
93
+ },
94
+ [columns, generateCellHtml, generateFootersHtml, generateHeadersHtml]
95
+ );
96
+
97
+ const generateHeadersText = useCallback(() => {
98
+ return Object.values(columns ?? {})
99
+ .map((col) => col.name)
100
+ .join('\t');
101
+ }, [columns]);
102
+
103
+ const generateFootersText = useCallback(
104
+ (rowsToCopy: R[]) => {
105
+ return Object.values(columns ?? {})
106
+ .map((col) =>
107
+ col.footer ? col.footer(rowsToCopy, rowsToCopy, []) : ''
108
+ )
109
+ .join('\t');
110
+ },
111
+ [columns]
112
+ );
113
+
114
+ const generateCopyText = useCallback(
115
+ (rowsToCopy: R[], includeHeaders: boolean, includeFooters: boolean) => {
116
+ return [
117
+ includeHeaders ? generateHeadersText() : '',
118
+ ...(rowsToCopy || []).map((row) =>
119
+ Object.values(columns ?? {})
120
+ .map((col) => {
121
+ const value: any = col.getter && row ? col.getter(row) : '';
122
+ return col.excelValue
123
+ ? col.excelValue(value)
124
+ : value != null && value !== undefined
125
+ ? value.toString()
126
+ : '';
127
+ })
128
+ .join('\t')
129
+ ),
130
+ includeFooters ? generateFootersText(rowsToCopy) : '',
131
+ ]
132
+ .filter((s) => s != null)
133
+ .join('\n');
134
+ },
135
+ [columns, generateFootersText, generateHeadersText]
136
+ );
137
+
138
+ const copyTable = useCallback(
139
+ async (includeHeaders = true, includeFooters = true) => {
140
+ const rowsToCopy = loadCopyRows ? await loadCopyRows() : rows;
141
+
142
+ const copyHtml = generateCopyHtml(
143
+ rowsToCopy,
144
+ includeHeaders,
145
+ includeFooters
146
+ );
147
+ const copyText = generateCopyText(
148
+ rowsToCopy,
149
+ includeHeaders,
150
+ includeFooters
151
+ );
152
+
153
+ await navigator['clipboard'].write([
154
+ new ClipboardItem({
155
+ 'text/plain': new Blob([copyText], { type: 'text/plain' }),
156
+ 'text/html': new Blob([copyHtml], { type: 'text/html' }),
157
+ }),
158
+ ]);
159
+ },
160
+ [generateCopyHtml, generateCopyText, loadCopyRows, rows]
161
+ );
162
+
163
+ return {
164
+ copyTable,
165
+ };
166
+ };
@@ -0,0 +1,49 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+
3
+ import { DataGridSettings } from '../types';
4
+ import { useSettings } from '../../../../providers';
5
+
6
+ export const useDataGridSettings = (name?: string) => {
7
+ // TODO: Implement settings context
8
+ const { settings, updateSettings } = useSettings();
9
+ const [dataGridSettings, setDataGridSettings] = useState<DataGridSettings>(
10
+ {}
11
+ );
12
+
13
+ useEffect(() => {
14
+ if (name) {
15
+ const settingName = `user.datagrid.settings.${name}`;
16
+ const gridSettingsJson = settings?.[settingName] || '{}';
17
+ console.log('read datagrid settings for', settingName, gridSettingsJson);
18
+ let gridSettings: DataGridSettings = {};
19
+ try {
20
+ gridSettings = JSON.parse(gridSettingsJson);
21
+ } catch (error) {
22
+ console.error('[GRID] cannot decode datagrid settings for', {
23
+ name,
24
+ gridSettingsJson,
25
+ error,
26
+ });
27
+ }
28
+ setDataGridSettings(gridSettings);
29
+ }
30
+ }, [name, settings]);
31
+
32
+ const saveSettings = useCallback(
33
+ (newValue?: DataGridSettings) => {
34
+ if (name) {
35
+ const settingName = `user.datagrid.settings.${name}`;
36
+ const newSettings = newValue ?? dataGridSettings;
37
+ const newSettingsJson = JSON.stringify(newSettings);
38
+ updateSettings({ [settingName]: newSettingsJson });
39
+ }
40
+ },
41
+ [dataGridSettings, name, updateSettings]
42
+ );
43
+
44
+ return {
45
+ settings: dataGridSettings,
46
+ setSettings: setDataGridSettings,
47
+ saveSettings,
48
+ };
49
+ };
@@ -0,0 +1,145 @@
1
+ import * as styles from './styles';
2
+
3
+ import { useCallback, useEffect } from 'react';
4
+
5
+ import { DataGridCell } from './DataGridCell';
6
+ import { DataGridFooter } from './DataGridFooter';
7
+ import { DataGridHeader } from './DataGridHeader';
8
+ import { DataGridProps } from './types';
9
+ import { VirtualScroller } from './VirtualScroller';
10
+ import { useDataGrid } from './hooks';
11
+
12
+ /* eslint-disable @typescript-eslint/no-explicit-any */
13
+ /* eslint-disable @typescript-eslint/no-unnecessary-type-constraint */
14
+
15
+ export const DataGrid = <R,>(props: DataGridProps<R>) => {
16
+ const {
17
+ className,
18
+ // onRowDoubleClick,
19
+ onSelectionChange,
20
+ onVisibleRowsChange,
21
+ rowKey,
22
+ } = props;
23
+ const [contextProps, DataGridContext] = useDataGrid(props);
24
+ const {
25
+ selectedRows,
26
+ setSelectedRows,
27
+ columns,
28
+ visibleColumns,
29
+ rowHeight = 32,
30
+ headerRowHeight = 40,
31
+ scrollableRef,
32
+ onScroll,
33
+ } = contextProps;
34
+
35
+ const hasFooter = Object.values(columns).some((col) => col.footer);
36
+
37
+ const setRowSelection = useCallback(
38
+ (row: R, selected: boolean) => {
39
+ if (selected) {
40
+ if (!selectedRows.includes(row))
41
+ setSelectedRows([...selectedRows, row]);
42
+ } else {
43
+ setSelectedRows(selectedRows.filter((p) => p !== row));
44
+ }
45
+ },
46
+ [selectedRows, setSelectedRows]
47
+ );
48
+
49
+ useEffect(() => {
50
+ onSelectionChange?.(selectedRows);
51
+ }, [onSelectionChange, selectedRows]);
52
+
53
+ const rowTemplate = useCallback(
54
+ (row: R, rowIndex: number) => {
55
+ const { className, style } = props.rowClassNameGetter?.(row) ?? {
56
+ className: '',
57
+ style: undefined,
58
+ };
59
+ if (!row) {
60
+ return (
61
+ <styles.DataGridRow key={`loading-row-${rowIndex}`}>
62
+ {!!props.selectable && (
63
+ <styles.LoadingCell className="animate-pulse">
64
+ <div
65
+ // className="bg-gray-200 rounded-full dark:bg-gray-700 w-full h-full"
66
+ />
67
+ </styles.LoadingCell>
68
+ )}
69
+ {visibleColumns.map((_, index) => (
70
+ <styles.LoadingCell
71
+ className="animate-pulse"
72
+ key={`loading-${rowIndex}-${index}`}
73
+ >
74
+ <div
75
+ // className="bg-gray-200 rounded-full dark:bg-gray-700 w-full h-full"
76
+ />
77
+ </styles.LoadingCell>
78
+ ))}
79
+ </styles.DataGridRow>
80
+ );
81
+ }
82
+ const key = String(
83
+ typeof rowKey === 'function' ? rowKey(row) : row[rowKey]
84
+ );
85
+ return (
86
+ <styles.DataGridRow key={key}>
87
+ {!!props.selectable && (
88
+ <styles.SelectionCell key="__select_checkbox__">
89
+ <input
90
+ type="checkbox"
91
+ // className="h-4 w-4 rounded border-gray-300 text-green-600 focus:ring-green-600"
92
+ value={key as string}
93
+ checked={selectedRows.includes(row)}
94
+ onChange={(e) => setRowSelection(row, e.target.checked)}
95
+ />
96
+ </styles.SelectionCell>
97
+ )}
98
+ {visibleColumns.map(([key, col], index) => (
99
+ <DataGridCell
100
+ key={`loading-${rowIndex}-${index}`}
101
+ className={className}
102
+ style={style}
103
+ row={row}
104
+ rowIndex={rowIndex}
105
+ column={col}
106
+ columnIndex={index}
107
+ context={DataGridContext}
108
+ columnKey={key}
109
+ />
110
+ ))}
111
+ </styles.DataGridRow>
112
+ );
113
+ },
114
+ [
115
+ DataGridContext,
116
+ props,
117
+ rowKey,
118
+ selectedRows,
119
+ setRowSelection,
120
+ visibleColumns,
121
+ ]
122
+ );
123
+
124
+ return (
125
+ <DataGridContext.Provider value={contextProps}>
126
+ <styles.DataGridContainer
127
+ ref={scrollableRef}
128
+ onScroll={onScroll}
129
+ $headerRowHeight={headerRowHeight}
130
+ $rowHeight={rowHeight}
131
+ $rowsCount={contextProps.sortedRows.length}
132
+ className={className}
133
+ >
134
+ <DataGridHeader context={DataGridContext} />
135
+ <VirtualScroller
136
+ onRangeChange={onVisibleRowsChange}
137
+ hasFooter={hasFooter}
138
+ rowTemplate={rowTemplate}
139
+ context={DataGridContext}
140
+ />
141
+ {hasFooter && <DataGridFooter context={DataGridContext} />}
142
+ </styles.DataGridContainer>
143
+ </DataGridContext.Provider>
144
+ );
145
+ };