@addev-be/ui 0.2.6 → 0.2.8

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 (68) hide show
  1. package/assets/icons/arrow-down-1-9.svg +1 -0
  2. package/assets/icons/arrow-down-big-small.svg +1 -0
  3. package/assets/icons/arrow-up-9-1.svg +1 -0
  4. package/assets/icons/arrow-up-big-small.svg +1 -0
  5. package/assets/icons/chevron-down.svg +1 -0
  6. package/assets/icons/ellipsis.svg +1 -0
  7. package/assets/icons/sigma.svg +1 -0
  8. package/assets/icons/table-footer-slash.svg +5 -0
  9. package/assets/icons/table-footer.svg +4 -0
  10. package/assets/icons/table.svg +1 -0
  11. package/assets/icons/tally.svg +1 -0
  12. package/assets/icons/x-bar.svg +4 -0
  13. package/dist/Icons.d.ts +13 -1
  14. package/dist/Icons.js +25 -1
  15. package/dist/components/data/AdvancedRequestDataGrid/index.js +3 -3
  16. package/dist/components/data/DataGrid/DataGridColumnsModal/hooks.js +2 -1
  17. package/dist/components/data/DataGrid/DataGridFilterMenu/index.js +85 -7
  18. package/dist/components/data/DataGrid/DataGridFilterMenu/styles.d.ts +3 -9
  19. package/dist/components/data/DataGrid/DataGridFilterMenu/styles.js +10 -37
  20. package/dist/components/data/DataGrid/DataGridFooter.d.ts +1 -1
  21. package/dist/components/data/DataGrid/DataGridFooter.js +35 -12
  22. package/dist/components/data/DataGrid/DataGridHeader.js +1 -1
  23. package/dist/components/data/DataGrid/DataGridHeaderCell.js +6 -22
  24. package/dist/components/data/DataGrid/helpers/columns.d.ts +1 -1
  25. package/dist/components/data/DataGrid/helpers/columns.js +71 -16
  26. package/dist/components/data/DataGrid/hooks/useDataGrid.d.ts +1 -1
  27. package/dist/components/data/DataGrid/hooks/useDataGrid.js +60 -30
  28. package/dist/components/data/DataGrid/hooks/useDataGridCopy.d.ts +2 -2
  29. package/dist/components/data/DataGrid/hooks/useDataGridCopy.js +41 -39
  30. package/dist/components/data/DataGrid/index.d.ts +4 -2
  31. package/dist/components/data/DataGrid/index.js +22 -12
  32. package/dist/components/data/DataGrid/styles.d.ts +8 -4
  33. package/dist/components/data/DataGrid/styles.js +27 -17
  34. package/dist/components/data/DataGrid/types.d.ts +8 -1
  35. package/dist/components/data/SqlRequestDataGrid/helpers/columns.d.ts +1 -1
  36. package/dist/components/data/SqlRequestDataGrid/helpers/columns.js +24 -11
  37. package/dist/components/data/SqlRequestDataGrid/index.js +105 -33
  38. package/dist/components/ui/ContextMenu/index.d.ts +11 -0
  39. package/dist/components/ui/ContextMenu/index.js +58 -0
  40. package/dist/components/ui/ContextMenu/styles.d.ts +18 -0
  41. package/dist/components/ui/ContextMenu/styles.js +56 -0
  42. package/dist/services/advancedRequests.d.ts +1 -1
  43. package/dist/services/sqlRequests.d.ts +9 -4
  44. package/dist/services/sqlRequests.js +1 -0
  45. package/package.json +1 -1
  46. package/src/Icons.tsx +24 -0
  47. package/src/components/data/AdvancedRequestDataGrid/index.tsx +3 -5
  48. package/src/components/data/DataGrid/DataGridColumnsModal/hooks.tsx +2 -1
  49. package/src/components/data/DataGrid/DataGridFilterMenu/index.tsx +180 -22
  50. package/src/components/data/DataGrid/DataGridFilterMenu/styles.ts +13 -64
  51. package/src/components/data/DataGrid/DataGridFooter.tsx +20 -22
  52. package/src/components/data/DataGrid/DataGridHeader.tsx +5 -5
  53. package/src/components/data/DataGrid/DataGridHeaderCell.tsx +3 -38
  54. package/src/components/data/DataGrid/FilterValuesScroller.tsx +33 -27
  55. package/src/components/data/DataGrid/helpers/columns.tsx +103 -8
  56. package/src/components/data/DataGrid/helpers/filters.ts +29 -19
  57. package/src/components/data/DataGrid/hooks/useDataGrid.tsx +58 -17
  58. package/src/components/data/DataGrid/hooks/useDataGridCopy.ts +35 -30
  59. package/src/components/data/DataGrid/index.tsx +22 -14
  60. package/src/components/data/DataGrid/styles.ts +50 -9
  61. package/src/components/data/DataGrid/types.ts +24 -3
  62. package/src/components/data/SqlRequestDataGrid/helpers/columns.tsx +39 -3
  63. package/src/components/data/SqlRequestDataGrid/index.tsx +116 -21
  64. package/src/components/ui/ContextMenu/index.tsx +79 -0
  65. package/src/components/ui/ContextMenu/styles.ts +119 -0
  66. package/src/services/advancedRequests.ts +1 -1
  67. package/src/services/sqlRequests.ts +16 -5
  68. package/tsconfig.tsbuildinfo +1 -1
@@ -3,15 +3,9 @@
3
3
 
4
4
  import * as styles from './styles';
5
5
 
6
- import {
7
- ArrowDownAZIcon,
8
- ArrowUpZAIcon,
9
- ArrowsUpDownIcon,
10
- FilterFullIcon,
11
- FilterIcon,
12
- } from '../../../Icons';
13
6
  import { MouseEvent, useCallback, useMemo, useRef, useState } from 'react';
14
7
 
8
+ import { ChevronDownIcon } from '../../../Icons';
15
9
  import { DataGridFilterMenu } from './DataGridFilterMenu';
16
10
  import { DataGridHeaderCellProps } from './types';
17
11
  import { Dropdown } from '../../layout';
@@ -29,33 +23,12 @@ export const DataGridHeaderCell = <R,>({
29
23
  const contextValue = useDataGridContext(context);
30
24
  const {
31
25
  filters = {},
32
- sorts = {},
33
- setSorts,
34
26
  setColumnWidth,
35
27
  saveSettings,
36
28
  headerColor,
37
29
  } = contextValue;
38
30
  const filterButtonRef = useRef<HTMLButtonElement | null>(null);
39
31
 
40
- /** SORTING */
41
- const SortIcon = sorts[columnKey]
42
- ? sorts[columnKey] === 'desc'
43
- ? ArrowUpZAIcon
44
- : ArrowDownAZIcon
45
- : ArrowsUpDownIcon;
46
-
47
- const onSortButtonClicked = useCallback(
48
- (columnKey: string) => {
49
- const sort = sorts[columnKey];
50
- if (!sort || sort === 'desc') {
51
- setSorts({ [columnKey]: 'asc' });
52
- } else {
53
- setSorts({ [columnKey]: 'desc' });
54
- }
55
- },
56
- [setSorts, sorts]
57
- );
58
-
59
32
  /** RESIZING */
60
33
 
61
34
  const [isResizing, setIsResizing] = useState(false);
@@ -97,7 +70,7 @@ export const DataGridHeaderCell = <R,>({
97
70
  $sourceRect={filterButtonRect}
98
71
  onClose={() => setIsFilterDropdownVisible(false)}
99
72
  $width={320}
100
- $height={[200, 320]}
73
+ $height={[250, 400]}
101
74
  $autoPositionX
102
75
  >
103
76
  <DataGridFilterMenu
@@ -129,20 +102,12 @@ export const DataGridHeaderCell = <R,>({
129
102
  >
130
103
  {filterDropdown}
131
104
  <span>{column.name}</span>
132
- {!!column.sortGetter && (
133
- <IconButton
134
- color={headerColor}
135
- size="small"
136
- icon={SortIcon}
137
- onClick={() => onSortButtonClicked?.(columnKey)}
138
- />
139
- )}
140
105
  {!!column.filter && (
141
106
  <IconButton
142
107
  size="small"
143
108
  className={hasFilters ? 'danger' : ''}
144
109
  ref={filterButtonRef}
145
- icon={hasFilters ? FilterFullIcon : FilterIcon}
110
+ icon={ChevronDownIcon}
146
111
  color={hasFilters ? 'danger' : headerColor}
147
112
  onClick={onFilterButtonClicked}
148
113
  />
@@ -29,33 +29,39 @@ const CheckboxTemplate = ({
29
29
  className?: string;
30
30
  style?: React.CSSProperties;
31
31
  onToggle?: (values: DataGridFilterValue[]) => void;
32
- }) => (
33
- <div
34
- key={index}
35
- className={join(
36
- [
37
- // 'absolute left-0 right-0 flex flex-row cursor-pointer hover:bg-gray-50',
38
- className,
39
- ],
40
- ' '
41
- )}
42
- style={{ ...style, paddingLeft: `${value.level}rem` }}
43
- title={value.title}
44
- onClick={() => onToggle?.([value.value])}
45
- >
46
- <input
47
- type="checkbox"
48
- checked={selectedValues.includes(value.value)}
49
- readOnly
50
- // className="inline-block mr-2"
51
- />
52
- <span
53
- // className="mr-2 truncate"
32
+ }) => {
33
+ const checked = useMemo(
34
+ () => value.values.every((v) => selectedValues.includes(v)),
35
+ [selectedValues, value.values]
36
+ );
37
+ return (
38
+ <styles.FilterValueContainer
39
+ key={index}
40
+ className={join(
41
+ [
42
+ // 'absolute left-0 right-0 flex flex-row cursor-pointer hover:bg-gray-50',
43
+ className,
44
+ ],
45
+ ' '
46
+ )}
47
+ style={{ ...style, paddingLeft: `${value.level}rem` }}
48
+ title={value.title}
49
+ onClick={() => onToggle?.(value.values)}
54
50
  >
55
- {value.displayValue || '(Vides)'}
56
- </span>
57
- </div>
58
- );
51
+ <input
52
+ type="checkbox"
53
+ checked={checked}
54
+ readOnly
55
+ // className="inline-block mr-2"
56
+ />
57
+ <span
58
+ // className="mr-2 truncate"
59
+ >
60
+ {value.displayValue || '(Vides)'}
61
+ </span>
62
+ </styles.FilterValueContainer>
63
+ );
64
+ };
59
65
 
60
66
  type FilterValuesScrollerProps = {
61
67
  values: DataGridFilterValue[];
@@ -96,7 +102,7 @@ export const FilterValuesScroller = ({
96
102
  );
97
103
 
98
104
  const checkboxes = useMemo(
99
- () => getCheckboxes(values, renderer, formatter, groups),
105
+ () => getCheckboxes(values, '', renderer, formatter, groups),
100
106
  [values, groups, renderer, formatter]
101
107
  );
102
108
  const visibleCheckboxes = checkboxes.slice(
@@ -9,11 +9,15 @@ import {
9
9
  import { numberFilter, textFilter } from './filters';
10
10
 
11
11
  import moment from 'moment';
12
+ import { repeat } from 'lodash';
12
13
 
13
14
  export const isColumnVisible = <R,>(
14
15
  obj: DataGridColumn<R> | DataGridSettings
15
16
  ): boolean => obj?.order !== -1;
16
17
 
18
+ const buildExcelFormat = (decimals = 2, suffix = '') =>
19
+ `#0${decimals > 0 ? `.${repeat('0', decimals)}` : ''}${suffix}`;
20
+
17
21
  export const textColumn = <R extends Record<string, any>>(
18
22
  key: string,
19
23
  title: string,
@@ -24,6 +28,7 @@ export const textColumn = <R extends Record<string, any>>(
24
28
  render: (row) => row[key] ?? '',
25
29
  getter: (row) => row[key] ?? '',
26
30
  sortGetter: (row) => row[key] ?? '',
31
+ footer: (_, filteredRows) => `${filteredRows.length} éléments`,
27
32
  filter: textFilter(key),
28
33
  ...options,
29
34
  },
@@ -46,6 +51,7 @@ export const mailColumn = <R extends Record<string, any>>(
46
51
  ),
47
52
  getter: (row) => row[key] ?? '',
48
53
  sortGetter: (row) => row[key] ?? '',
54
+ footer: (_, filteredRows) => `${filteredRows.length} éléments`,
49
55
  filter: textFilter(key),
50
56
  ...options,
51
57
  },
@@ -68,6 +74,7 @@ export const phoneColumn = <R extends Record<string, any>>(
68
74
  ),
69
75
  getter: (row) => row[key] ?? '',
70
76
  sortGetter: (row) => row[key] ?? '',
77
+ footer: (_, filteredRows) => `${filteredRows.length} éléments`,
71
78
  filter: textFilter(key),
72
79
  ...options,
73
80
  },
@@ -80,10 +87,15 @@ export const dateColumn = <R extends Record<string, any>>(
80
87
  ): DataGridColumns<R> => ({
81
88
  [key]: {
82
89
  name: title,
90
+ type: 'date',
83
91
  render: (row) => moment(row[key]).format('DD/MM/YYYY') ?? '',
84
92
  getter: (row) => row[key] ?? '',
85
93
  sortGetter: (row) => row[key] ?? '',
86
- filter: textFilter(key),
94
+ footer: (_, filteredRows) => `${filteredRows.length} éléments`,
95
+ filter: {
96
+ ...textFilter(key),
97
+ renderer: (value) => moment(value).format('DD/MM/YYYY') ?? '',
98
+ },
87
99
  ...options,
88
100
  },
89
101
  });
@@ -98,6 +110,7 @@ export const monthColumn = <R extends Record<string, any>>(
98
110
  render: (row) => (row[key] ? `${row[key]} mois ` : ''),
99
111
  getter: (row) => row[key] ?? '',
100
112
  sortGetter: (row) => row[key] ?? '',
113
+ footer: (_, filteredRows) => `${filteredRows.length} éléments`,
101
114
  filter: textFilter(key),
102
115
  ...options,
103
116
  },
@@ -115,11 +128,33 @@ export const numberColumn = <R extends Record<string, any>>(
115
128
  excelFormatter: () => '#',
116
129
  getter: (row) => row[key] ?? '',
117
130
  sortGetter: (row) => row[key] ?? '',
131
+ footer: {
132
+ sum: (_, filteredRows) =>
133
+ formatNumber(
134
+ filteredRows.reduce((acc, row) => acc + (row[key] ?? 0), 0),
135
+ decimals
136
+ ),
137
+ average: (_, filteredRows) =>
138
+ formatNumber(
139
+ filteredRows.reduce((acc, row) => acc + (row[key] ?? 0), 0) /
140
+ (filteredRows.length || 1),
141
+ decimals
142
+ ),
143
+ count: (_, filteredRows) => `${filteredRows.length} éléments`,
144
+ max: (_, filteredRows) =>
145
+ formatNumber(
146
+ Math.max(...filteredRows.map((row) => row[key] ?? 0)),
147
+ decimals
148
+ ),
149
+ min: (_, filteredRows) =>
150
+ formatNumber(
151
+ Math.min(...filteredRows.map((row) => row[key] ?? 0)),
152
+ decimals
153
+ ),
154
+ },
118
155
  filter: {
119
- type: 'number',
120
- operator: 'equals',
121
- values: [0],
122
- getter: (value) => value ?? 0,
156
+ ...numberFilter(key),
157
+ renderer: (value) => formatNumber(value, decimals) ?? '',
123
158
  },
124
159
  ...options,
125
160
  },
@@ -134,10 +169,37 @@ export const moneyColumn = <R extends Record<string, any>>(
134
169
  [key]: {
135
170
  name: title,
136
171
  render: (row) => formatMoney(row[key], decimals) ?? '',
137
- excelFormatter: () => '#0.00',
172
+ excelFormatter: () => buildExcelFormat(decimals, ''),
138
173
  getter: (row) => row[key] ?? '',
139
174
  sortGetter: (row) => row[key] ?? '',
140
- filter: numberFilter(key),
175
+ filter: {
176
+ ...numberFilter(key),
177
+ renderer: (value) => formatMoney(value, decimals) ?? '',
178
+ },
179
+ footer: {
180
+ sum: (_, filteredRows) =>
181
+ formatMoney(
182
+ filteredRows.reduce((acc, row) => acc + (row[key] ?? 0), 0),
183
+ decimals
184
+ ),
185
+ average: (_, filteredRows) =>
186
+ formatMoney(
187
+ filteredRows.reduce((acc, row) => acc + (row[key] ?? 0), 0) /
188
+ (filteredRows.length || 1),
189
+ decimals
190
+ ),
191
+ count: (_, filteredRows) => `${filteredRows.length} éléments`,
192
+ max: (_, filteredRows) =>
193
+ formatMoney(
194
+ Math.max(...filteredRows.map((row) => row[key] ?? 0)),
195
+ decimals
196
+ ),
197
+ min: (_, filteredRows) =>
198
+ formatMoney(
199
+ Math.min(...filteredRows.map((row) => row[key] ?? 0)),
200
+ decimals
201
+ ),
202
+ },
141
203
  ...options,
142
204
  },
143
205
  });
@@ -145,15 +207,40 @@ export const moneyColumn = <R extends Record<string, any>>(
145
207
  export const percentageColumn = <R extends Record<string, any>>(
146
208
  key: string,
147
209
  title: string,
210
+ decimals = 2,
148
211
  options?: Partial<DataGridColumn<R>>
149
212
  ): DataGridColumns<R> => ({
150
213
  [key]: {
151
214
  name: title,
152
215
  render: (row) => formatPercentage(row[key]) ?? '',
153
- excelFormatter: () => '#0.00',
216
+ excelFormatter: () => buildExcelFormat(decimals),
154
217
  getter: (row) => row[key] ?? '',
155
218
  sortGetter: (row) => row[key] ?? '',
156
219
  filter: numberFilter(key),
220
+ footer: {
221
+ average: (_, filteredRows) =>
222
+ formatNumber(
223
+ filteredRows.reduce((acc, row) => acc + (row[key] ?? 0), 0) /
224
+ (filteredRows.length || 1),
225
+ decimals
226
+ ),
227
+ count: (_, filteredRows) => `${filteredRows.length} éléments`,
228
+ max: (_, filteredRows) =>
229
+ formatNumber(
230
+ Math.max(...filteredRows.map((row) => row[key] ?? 0)),
231
+ decimals
232
+ ),
233
+ min: (_, filteredRows) =>
234
+ formatNumber(
235
+ Math.min(...filteredRows.map((row) => row[key] ?? 0)),
236
+ decimals
237
+ ),
238
+ sum: (_, filteredRows) =>
239
+ formatNumber(
240
+ filteredRows.reduce((acc, row) => acc + (row[key] ?? 0), 0),
241
+ decimals
242
+ ),
243
+ },
157
244
  ...options,
158
245
  },
159
246
  });
@@ -174,6 +261,13 @@ export const checkboxColumn = <R extends Record<string, any>>(
174
261
  getter: (row) => row[key] ?? '',
175
262
  sortGetter: (row) => row[key] ?? '',
176
263
  filter: numberFilter(key),
264
+ footer: {
265
+ count: (_, filteredRows) => `${filteredRows.length} éléments`,
266
+ checked: (_, filteredRows) =>
267
+ `${filteredRows.filter((row) => !!row[key]).length} cochés`,
268
+ unchecked: (_, filteredRows) =>
269
+ `${filteredRows.filter((row) => !row[key]).length} décochés`,
270
+ },
177
271
  ...options,
178
272
  },
179
273
  });
@@ -191,6 +285,7 @@ export const colorColumn = <R extends Record<string, any>>(
191
285
  getter: (row) => row[key] ?? '',
192
286
  sortGetter: (row) => row[key] ?? '',
193
287
  filter: textFilter(key),
288
+ footer: (rows) => `${rows.length} éléments`,
194
289
  ...options,
195
290
  },
196
291
  });
@@ -168,8 +168,10 @@ export const getDateGroups = (dates: any[]): DataGridFilterGroup[] => {
168
168
  const grouperDates = groupDatesByYearAndMonth(dates);
169
169
  return Object.entries(grouperDates).map(([year, months]) => ({
170
170
  name: year,
171
+ displayValue: year,
171
172
  values: Object.values(months).flat(),
172
173
  groups: Object.entries(months).map(([month, dates]) => ({
174
+ displayValue: month,
173
175
  name: month,
174
176
  values: dates,
175
177
  })),
@@ -181,29 +183,37 @@ export const defaultRendererAndFormatter = (value: any) =>
181
183
 
182
184
  export const getCheckboxes = (
183
185
  values: DataGridFilterValue[],
186
+ displayValue: DataGridFilterValue,
184
187
  renderer: DataGridFilterRenderer,
185
188
  formatter: DataGridFilterFormatter,
186
189
  groups?: DataGridFilterGroup[],
187
190
  level = 0
188
- ): DataGridFilterCheckbox[] => [
189
- ...(groups ?? [])
190
- .map<DataGridFilterCheckbox[]>((group) =>
191
- getCheckboxes(
192
- group.values ?? [],
193
- renderer,
194
- formatter,
195
- group.groups,
196
- level + 1
197
- )
198
- )
199
- .flat(),
200
- ...values.map<DataGridFilterCheckbox>((value) => ({
201
- displayValue: renderer(value),
202
- title: formatter(value),
203
- value: value ?? '',
204
- level,
205
- })),
206
- ];
191
+ ): DataGridFilterCheckbox[] =>
192
+ groups
193
+ ? groups
194
+ .map<DataGridFilterCheckbox[]>((group) => [
195
+ {
196
+ displayValue: group.displayValue,
197
+ title: formatter(group.displayValue),
198
+ values: group.values ?? [],
199
+ level,
200
+ },
201
+ ...getCheckboxes(
202
+ group.values ?? [],
203
+ group.displayValue,
204
+ renderer,
205
+ formatter,
206
+ group.groups,
207
+ level + 1
208
+ ),
209
+ ])
210
+ .flat()
211
+ : values.map<DataGridFilterCheckbox>((value) => ({
212
+ displayValue: renderer(value),
213
+ title: formatter(value),
214
+ values: [value ?? ''],
215
+ level,
216
+ }));
207
217
 
208
218
  export const textFilter = (key: string): DataGridFilter<'text'> => ({
209
219
  type: 'text',
@@ -7,6 +7,7 @@ import {
7
7
  DataGridContext,
8
8
  DataGridContextProps,
9
9
  DataGridFilters,
10
+ DataGridFooterFunction,
10
11
  DataGridProps,
11
12
  DataGridSort,
12
13
  } from '../types';
@@ -26,7 +27,8 @@ import { useDataGridSettings } from './useDataGridSettings';
26
27
  import { useElementSize } from '../../../../hooks';
27
28
 
28
29
  export const useDataGrid = <R,>(
29
- props: DataGridProps<R>
30
+ props: DataGridProps<R>,
31
+ override?: Partial<DataGridContextProps<R>>
30
32
  ): [DataGridContextProps<R>, DataGridContext<R>] => {
31
33
  const {
32
34
  rows,
@@ -59,7 +61,7 @@ export const useDataGrid = <R,>(
59
61
  const gridTemplateColumns = useMemo(
60
62
  () =>
61
63
  [
62
- ...(selectable ? ['var(--space-8)'] : []),
64
+ ...(selectable ? ['var(--space-10)'] : []),
63
65
  ...visibleColumns.map(([, col]) => `${col.width ?? 150}px`),
64
66
  ].join(' '),
65
67
  [selectable, visibleColumns]
@@ -173,9 +175,39 @@ export const useDataGrid = <R,>(
173
175
  onVisibleRowsChange?.(indexWithTolerance, lengthWithTolerance);
174
176
  }, [indexWithTolerance, lengthWithTolerance, onVisibleRowsChange]);
175
177
 
178
+ /** FOOTERS */
179
+ const [footers, setFooters] = useState<Record<string, string>>(
180
+ props.initialFooters ?? {}
181
+ );
182
+
183
+ const footerFunctions = useMemo(
184
+ () =>
185
+ Object.entries(footers).reduce((acc, [columnKey, footerKey]) => {
186
+ const column = columns[columnKey];
187
+ if (!column) {
188
+ return acc;
189
+ }
190
+ if (typeof column.footer === 'function') {
191
+ acc[columnKey] = column.footer;
192
+ } else if (
193
+ typeof column.footer === 'object' &&
194
+ typeof column.footer[footerKey] === 'function'
195
+ ) {
196
+ acc[columnKey] = column.footer[footerKey];
197
+ }
198
+ return acc;
199
+ }, {} as Record<string, DataGridFooterFunction<R>>),
200
+ [columns, footers]
201
+ );
202
+
176
203
  /** COPYING */
177
204
 
178
- const { copyTable } = useDataGridCopy(sortedRows, columns, loadCopyRows);
205
+ const { copyTable } = useDataGridCopy({
206
+ rows,
207
+ visibleColumns,
208
+ footerFunctions,
209
+ loadCopyRows,
210
+ });
179
211
 
180
212
  const contextValue = useMemo<DataGridContextProps<R>>(
181
213
  () => ({
@@ -204,28 +236,35 @@ export const useDataGrid = <R,>(
204
236
  length,
205
237
  rowKeyGetter,
206
238
  gridTemplateColumns,
239
+ footers,
240
+ setFooters,
241
+ footerFunctions,
242
+ ...override,
207
243
  }),
208
244
  [
209
- columns,
210
- copyTable,
211
- editingCell,
212
- filters,
213
- index,
214
- length,
215
- onScroll,
216
245
  props,
217
- rowKeyGetter,
218
- saveSettings,
219
- selectedKeys,
246
+ columns,
247
+ visibleColumns,
248
+ sortedRows,
220
249
  selectedRows,
250
+ selectedKeys,
251
+ sorts,
252
+ filters,
253
+ editingCell,
254
+ copyTable,
221
255
  setColumnWidth,
222
- setSettings,
223
256
  settings,
224
- sortedRows,
225
- sorts,
226
- visibleColumns,
257
+ setSettings,
258
+ saveSettings,
227
259
  visibleRows,
260
+ onScroll,
261
+ index,
262
+ length,
263
+ rowKeyGetter,
228
264
  gridTemplateColumns,
265
+ footers,
266
+ footerFunctions,
267
+ override,
229
268
  ]
230
269
  );
231
270
 
@@ -256,6 +295,8 @@ export const useDataGrid = <R,>(
256
295
  index: 0,
257
296
  length: 0,
258
297
  gridTemplateColumns: '',
298
+ footers: {},
299
+ setFooters: () => {},
259
300
  }),
260
301
  []
261
302
  );
@@ -1,19 +1,23 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
- import { DataGridColumn, DataGridColumns } from '../types';
3
+ import { DataGridColumn, DataGridContextProps } from '../types';
4
4
 
5
5
  import { useCallback } from 'react';
6
6
 
7
- export const useDataGridCopy = <R>(
8
- rows: R[],
9
- columns: DataGridColumns<R>,
10
- loadCopyRows?: () => Promise<R[]>
11
- ) => {
7
+ export const useDataGridCopy = <R>({
8
+ rows,
9
+ visibleColumns = [],
10
+ loadCopyRows,
11
+ footerFunctions,
12
+ }: Pick<
13
+ DataGridContextProps<R>,
14
+ 'rows' | 'visibleColumns' | 'loadCopyRows' | 'footerFunctions'
15
+ >) => {
12
16
  const generateHeadersHtml = useCallback(() => {
13
17
  return `<tr>
14
- ${Object.values(columns ?? {})
18
+ ${visibleColumns
15
19
  .map(
16
- (col) =>
20
+ ([, col]) =>
17
21
  `<th style="
18
22
  text-align: left;
19
23
  font-weight: bold;
@@ -24,29 +28,32 @@ export const useDataGridCopy = <R>(
24
28
  )
25
29
  .join('\n')}
26
30
  </tr>`;
27
- }, [columns]);
31
+ }, [visibleColumns]);
28
32
 
29
33
  const generateFootersHtml = useCallback(
30
34
  (rowsToCopy: R[]) => {
35
+ console.log('generate footers html');
31
36
  return `<tr>
32
- ${Object.values(columns ?? {})
37
+ ${visibleColumns
33
38
  .map(
34
- (col) =>
39
+ ([colKey]) =>
35
40
  `<td style="
36
41
  font-weight: bold;
37
42
  white-space: nowrap;
38
43
  ">
39
44
  ${
40
- col.footer
41
- ? col.footer(rowsToCopy, rowsToCopy, [])
42
- : ''
45
+ footerFunctions?.[colKey]?.(
46
+ rowsToCopy,
47
+ rowsToCopy,
48
+ []
49
+ ) ?? ''
43
50
  }
44
51
  </td>`
45
52
  )
46
53
  .join('\n')}
47
54
  </tr>`;
48
55
  },
49
- [columns]
56
+ [footerFunctions, visibleColumns]
50
57
  );
51
58
 
52
59
  const generateCellText = useCallback((col: DataGridColumn<R>, value: any) => {
@@ -76,8 +83,8 @@ export const useDataGridCopy = <R>(
76
83
  .map(
77
84
  (row) =>
78
85
  `<tr>
79
- ${Object.values(columns ?? {})
80
- .map((col) => {
86
+ ${visibleColumns
87
+ .map(([, col]) => {
81
88
  const value: any =
82
89
  col.getter && row ? col.getter(row) : '';
83
90
  return generateCellHtml(col, value);
@@ -90,24 +97,22 @@ export const useDataGridCopy = <R>(
90
97
  </table>
91
98
  `;
92
99
  },
93
- [columns, generateCellHtml, generateFootersHtml, generateHeadersHtml]
100
+ [visibleColumns, generateCellHtml, generateFootersHtml, generateHeadersHtml]
94
101
  );
95
102
 
96
103
  const generateHeadersText = useCallback(() => {
97
- return Object.values(columns ?? {})
98
- .map((col) => col.name)
99
- .join('\t');
100
- }, [columns]);
104
+ return visibleColumns.map(([, col]) => col.name).join('\t');
105
+ }, [visibleColumns]);
101
106
 
102
107
  const generateFootersText = useCallback(
103
108
  (rowsToCopy: R[]) => {
104
- return Object.values(columns ?? {})
105
- .map((col) =>
106
- col.footer ? col.footer(rowsToCopy, rowsToCopy, []) : ''
109
+ return visibleColumns
110
+ .map(
111
+ ([colKey]) => footerFunctions?.[colKey]?.(rowsToCopy, [], []) ?? ''
107
112
  )
108
113
  .join('\t');
109
114
  },
110
- [columns]
115
+ [footerFunctions, visibleColumns]
111
116
  );
112
117
 
113
118
  const generateCopyText = useCallback(
@@ -115,8 +120,8 @@ export const useDataGridCopy = <R>(
115
120
  return [
116
121
  includeHeaders ? generateHeadersText() : '',
117
122
  ...(rowsToCopy || []).map((row) =>
118
- Object.values(columns ?? {})
119
- .map((col) => {
123
+ visibleColumns
124
+ .map(([, col]) => {
120
125
  const value: any = col.getter && row ? col.getter(row) : '';
121
126
  return col.excelValue
122
127
  ? col.excelValue(value)
@@ -131,12 +136,12 @@ export const useDataGridCopy = <R>(
131
136
  .filter((s) => s != null)
132
137
  .join('\n');
133
138
  },
134
- [columns, generateFootersText, generateHeadersText]
139
+ [visibleColumns, generateFootersText, generateHeadersText]
135
140
  );
136
141
 
137
142
  const copyTable = useCallback(
138
143
  async (includeHeaders = true, includeFooters = true) => {
139
- const rowsToCopy = loadCopyRows ? await loadCopyRows() : rows;
144
+ const rowsToCopy = await (loadCopyRows ?? (async () => rows))();
140
145
 
141
146
  const copyHtml = generateCopyHtml(
142
147
  rowsToCopy,