es-grid-template 1.3.0 → 1.3.2

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 (51) hide show
  1. package/assets/index.css +16 -0
  2. package/assets/index.scss +37 -3
  3. package/es/grid-component/CheckboxFilter.js +4 -0
  4. package/es/grid-component/CheckboxFilter2.d.ts +20 -0
  5. package/es/grid-component/CheckboxFilter2.js +248 -0
  6. package/es/grid-component/ColumnsGroup/ColumnsGroup.js +4 -4
  7. package/es/grid-component/ContextMenu.js +1 -0
  8. package/es/grid-component/ConvertColumnTable.js +1 -0
  9. package/es/grid-component/EditableCell.js +11 -8
  10. package/es/grid-component/InternalTable.js +47 -11
  11. package/es/grid-component/TableGrid.d.ts +3 -0
  12. package/es/grid-component/TableGrid.js +71 -7
  13. package/es/grid-component/hooks/columns/index.js +14 -45
  14. package/es/grid-component/hooks/content/HeaderContent.js +54 -58
  15. package/es/grid-component/hooks/useColumns.d.ts +4 -2
  16. package/es/grid-component/hooks/useColumns.js +32 -13
  17. package/es/grid-component/hooks/utils.d.ts +9 -0
  18. package/es/grid-component/hooks/utils.js +278 -1
  19. package/es/grid-component/number-range/index.d.ts +10 -0
  20. package/es/grid-component/number-range/index.js +59 -0
  21. package/es/grid-component/styles.scss +24 -0
  22. package/es/grid-component/table/Grid.d.ts +3 -0
  23. package/es/grid-component/table/GridEdit.js +360 -106
  24. package/es/grid-component/table/Group.d.ts +1 -0
  25. package/es/grid-component/table/Group.js +1 -1
  26. package/es/grid-component/type.d.ts +2 -1
  27. package/lib/grid-component/CheckboxFilter.js +4 -0
  28. package/lib/grid-component/CheckboxFilter2.d.ts +20 -0
  29. package/lib/grid-component/CheckboxFilter2.js +257 -0
  30. package/lib/grid-component/ColumnsGroup/ColumnsGroup.js +4 -4
  31. package/lib/grid-component/ContextMenu.js +1 -0
  32. package/lib/grid-component/ConvertColumnTable.js +1 -0
  33. package/lib/grid-component/EditableCell.js +11 -8
  34. package/lib/grid-component/InternalTable.js +41 -10
  35. package/lib/grid-component/TableGrid.d.ts +3 -0
  36. package/lib/grid-component/TableGrid.js +68 -7
  37. package/lib/grid-component/hooks/columns/index.js +14 -45
  38. package/lib/grid-component/hooks/content/HeaderContent.js +53 -55
  39. package/lib/grid-component/hooks/useColumns.d.ts +4 -2
  40. package/lib/grid-component/hooks/useColumns.js +31 -12
  41. package/lib/grid-component/hooks/utils.d.ts +9 -0
  42. package/lib/grid-component/hooks/utils.js +293 -4
  43. package/lib/grid-component/number-range/index.d.ts +10 -0
  44. package/lib/grid-component/number-range/index.js +67 -0
  45. package/lib/grid-component/styles.scss +24 -0
  46. package/lib/grid-component/table/Grid.d.ts +3 -0
  47. package/lib/grid-component/table/GridEdit.js +358 -104
  48. package/lib/grid-component/table/Group.d.ts +1 -0
  49. package/lib/grid-component/table/Group.js +1 -1
  50. package/lib/grid-component/type.d.ts +2 -1
  51. package/package.json +109 -108
@@ -1,5 +1,5 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import React, { Fragment, useEffect, useMemo, useRef, useState } from 'react';
2
+ import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import customParseFormat from 'dayjs/plugin/customParseFormat';
4
4
  import classNames from "classnames";
5
5
  import { Button, Dropdown, Form } from "antd";
@@ -13,19 +13,22 @@ import dayjs from "dayjs";
13
13
  import 'dayjs/locale/es';
14
14
  import 'dayjs/locale/vi';
15
15
  import TableGrid from "../TableGrid";
16
- import { addRows8, checkChild, editAbleColumns, findAllChildrenKeys, findItemByKey, flattenArray, flattenData, getDefaultValue, getEditType, getFirstSelectCell, getLastSelectCell, getRowNumber, getRowsPasteIndex, isEditable, isObjEmpty, newGuid, totalFixedWidth, updateArrayByKey } from "../hooks";
16
+ import { addRows8, checkChild, editAbleColumns, findAllChildrenKeys, findItemByKey, findItemPath, flattenArray, flattenData, getDefaultValue, getEditType, getFirstSelectCell, getLastSelectCell, getRowNumber, getRowsPasteIndex, isEditable, isObjEmpty, newGuid, totalFixedWidth, updateArrayByKey } from "../hooks";
17
17
  import Message from "../../Message/Message";
18
18
  // import Command from "../Command";
19
19
 
20
20
  import { Toolbar, ConfigProvider } from "rc-master-ui";
21
21
  import classnames from "classnames";
22
22
  import useMergedState from "rc-util/es/hooks/useMergedState";
23
+ import { Plus, Trash2 } from "becoxy-icons";
24
+ // import {ContextInfo, ContextMenuItem} from "../type";
23
25
  // import useLazyKVMap from "rc-master-ui/es/table/hooks/useLazyKVMap";
24
26
 
25
27
  dayjs.extend(customParseFormat);
26
28
  const toast = 'top-right';
27
29
  const GridEdit = props => {
28
30
  const {
31
+ id,
29
32
  tableRef,
30
33
  t,
31
34
  columns,
@@ -60,6 +63,7 @@ const GridEdit = props => {
60
63
  // selectedRowKeys,
61
64
  // defaultSelectedRowKeys
62
65
  } = selectionSettings || {};
66
+ const ref = useRef(null);
63
67
  const isSelecting = useRef(false);
64
68
  const startCell = useRef(null);
65
69
  const childrenColumnName = 'children';
@@ -80,6 +84,7 @@ const GridEdit = props => {
80
84
  }];
81
85
  const [form] = Form.useForm();
82
86
  const [editingKey, setEditingKey] = useState('');
87
+ const [isFilter, setIsFilter] = React.useState(false);
83
88
  const [selectedCells, setSelectedCells] = useState(new Set());
84
89
  const [pasteCells, setPasteCells] = useState(new Set());
85
90
  const [cellEditing, setCellEditing] = useState(null);
@@ -104,6 +109,33 @@ const GridEdit = props => {
104
109
  const rowsFocus = React.useMemo(() => {
105
110
  return [...new Set(Array.from(selectedCells).map(item => parseInt(item.split('-')[0])))] ?? [];
106
111
  }, [selectedCells]);
112
+ const contextMenuItems = React.useMemo(() => {
113
+ return [{
114
+ key: 'INSERT_BEFORE',
115
+ label: 'Thêm dòng bên trên',
116
+ icon: /*#__PURE__*/React.createElement(Plus, {
117
+ fontSize: 14
118
+ })
119
+ }, {
120
+ key: 'INSERT_AFTER',
121
+ label: 'Thêm dòng bên dưới',
122
+ icon: /*#__PURE__*/React.createElement(Plus, {
123
+ fontSize: 14
124
+ })
125
+ }, {
126
+ key: 'DELETE_CONTENT',
127
+ label: 'Xóa nội dung',
128
+ icon: /*#__PURE__*/React.createElement(Trash2, {
129
+ fontSize: 14
130
+ })
131
+ }, {
132
+ key: 'DELETE_ROWS',
133
+ label: 'Xóa dòng',
134
+ icon: /*#__PURE__*/React.createElement(Trash2, {
135
+ fontSize: 14
136
+ })
137
+ }];
138
+ }, []);
107
139
  const onTriggerExpand = React.useCallback(record => {
108
140
  const key = getRowKey(record, dataSource.indexOf(record));
109
141
  let newExpandedKeys;
@@ -173,9 +205,12 @@ const GridEdit = props => {
173
205
  const rs = [...newData.slice(0, insertAfter + 1), ...duplicatedItems, ...newData.slice(insertAfter + 1)];
174
206
  triggerChangeData?.(rs, 'DUPLICATE');
175
207
  };
176
- const handleInsertBefore = item => {
208
+
209
+ // thêm n dòng bên trên
210
+ const handleInsertBefore = (item, n) => {
177
211
  const defaultRowValue = getDefaultValue(defaultValue);
178
- const rowId = defaultRowValue && defaultRowValue.id ? defaultRowValue.id : newGuid();
212
+ // const rowId = defaultRowValue && defaultRowValue.id ? defaultRowValue.id : newGuid()
213
+
179
214
  const record = flattenData(childrenColumnName, dataSource)[rowsFocus[rowsFocus.length - 1]];
180
215
  if (item.onClick) {
181
216
  item.onClick({
@@ -185,27 +220,55 @@ const GridEdit = props => {
185
220
  if (!record?.parentId) {
186
221
  // Cập nhật data mới
187
222
  const newData = [...dataSource];
188
- const index = newData.findIndex(obj => obj[rowKey] === record[rowKey]);
189
- newData.splice(index, 0, {
223
+ const newRows = Array.from({
224
+ length: n
225
+ }).map(() => defaultRowValue ? isFilter ? {
190
226
  ...defaultRowValue,
191
- rowId,
192
- parentId: null,
193
- id: undefined
227
+ id: undefined,
228
+ rowId: newGuid(),
229
+ isFilterState: true
230
+ } : {
231
+ ...defaultRowValue,
232
+ id: undefined,
233
+ rowId: newGuid()
234
+ } : isFilter ? {
235
+ id: undefined,
236
+ rowId: newGuid(),
237
+ isFilterState: true
238
+ } : {
239
+ id: undefined,
240
+ rowId: newGuid()
194
241
  });
242
+ const index = newData.findIndex(obj => obj[rowKey] === record[rowKey]);
243
+ newData.splice(index, 0, ...newRows);
195
244
  triggerChangeData?.(newData, 'INSERT_BEFORE');
196
245
  } else {
197
246
  const newData = [...dataSource];
247
+ const newRows = Array.from({
248
+ length: n
249
+ }).map(() => defaultRowValue ? isFilter ? {
250
+ ...defaultRowValue,
251
+ id: undefined,
252
+ rowId: newGuid(),
253
+ isFilterState: true
254
+ } : {
255
+ ...defaultRowValue,
256
+ id: undefined,
257
+ rowId: newGuid()
258
+ } : isFilter ? {
259
+ id: undefined,
260
+ rowId: newGuid(),
261
+ isFilterState: true
262
+ } : {
263
+ id: undefined,
264
+ rowId: newGuid()
265
+ });
198
266
  const parent = findItemByKey(newData, rowKey, record.parentId);
199
267
 
200
268
  // Cập nhật childData mới
201
269
  const childData = parent?.children ? [...parent.children] : [];
202
270
  const index = childData.findIndex(obj => obj[rowKey] === record[rowKey]);
203
- childData.splice(index, 0, {
204
- ...defaultRowValue,
205
- rowId,
206
- parentId: record.parentId,
207
- id: undefined
208
- });
271
+ childData.splice(index, 0, ...newRows);
209
272
  const newRowData = {
210
273
  ...parent,
211
274
  children: childData
@@ -215,9 +278,13 @@ const GridEdit = props => {
215
278
  }
216
279
  }
217
280
  };
218
- const handleInsertAfter = item => {
281
+
282
+ //thêm 1 dòng bên dưới
283
+ const handleInsertAfter = (item, n) => {
219
284
  const defaultRowValue = getDefaultValue(defaultValue);
220
- const rowId = defaultRowValue && defaultRowValue.id ? defaultRowValue.id : newGuid();
285
+
286
+ // const rowId = defaultRowValue && defaultRowValue.id ? defaultRowValue.id : newGuid()
287
+
221
288
  const record = flattenData(childrenColumnName, dataSource)[rowsFocus[rowsFocus.length - 1]];
222
289
 
223
290
  // const record = getRecordByKey()
@@ -230,25 +297,57 @@ const GridEdit = props => {
230
297
  if (!record?.parentId) {
231
298
  // Cập nhật data mới
232
299
  const newData = [...dataSource];
233
- const index = newData.findIndex(obj => obj[rowKey] === record[rowKey]);
234
- newData.splice(index + 1, 0, {
300
+ const newRows = Array.from({
301
+ length: n
302
+ }).map(() => defaultRowValue ? isFilter ? {
303
+ ...defaultRowValue,
304
+ id: undefined,
305
+ rowId: newGuid(),
306
+ isFilterState: true
307
+ } : {
235
308
  ...defaultRowValue,
236
- rowId,
237
- parentId: null
309
+ id: undefined,
310
+ rowId: newGuid()
311
+ } : isFilter ? {
312
+ id: undefined,
313
+ rowId: newGuid(),
314
+ isFilterState: true
315
+ } : {
316
+ id: undefined,
317
+ rowId: newGuid()
238
318
  });
319
+ const index = newData.findIndex(obj => obj[rowKey] === record[rowKey]);
320
+
321
+ // newData.splice(index + 1, 0, { ...defaultRowValue, rowId, parentId: null })
322
+ newData.splice(index + 1, 0, ...newRows);
239
323
  triggerChangeData?.(newData, 'INSERT_AFTER');
240
324
  } else {
241
325
  const newData = [...dataSource];
326
+ const newRows = Array.from({
327
+ length: n
328
+ }).map(() => defaultRowValue ? isFilter ? {
329
+ ...defaultRowValue,
330
+ id: undefined,
331
+ rowId: newGuid(),
332
+ isFilterState: true
333
+ } : {
334
+ ...defaultRowValue,
335
+ id: undefined,
336
+ rowId: newGuid()
337
+ } : isFilter ? {
338
+ id: undefined,
339
+ rowId: newGuid(),
340
+ isFilterState: true
341
+ } : {
342
+ id: undefined,
343
+ rowId: newGuid()
344
+ });
242
345
  const parent = findItemByKey(newData, rowKey, record.parentId);
243
346
 
244
347
  // Cập nhật childData mới
245
348
  const childData = parent?.children ? [...parent.children] : [];
246
349
  const index = childData.findIndex(obj => obj[rowKey] === record[rowKey]);
247
- childData.splice(index + 1, 0, {
248
- ...defaultRowValue,
249
- rowId,
250
- parentId: record.parentId
251
- });
350
+ childData.splice(index + 1, 0, ...newRows);
252
351
  const newRowData = {
253
352
  ...parent,
254
353
  children: childData
@@ -300,12 +399,49 @@ const GridEdit = props => {
300
399
  setInnerExpandedKeys(newExpandedKeys);
301
400
  }
302
401
  };
402
+ const handleDeleteRows = item => {
403
+ if (item.onClick) {
404
+ item.onClick({
405
+ toolbar: item
406
+ });
407
+ } else {
408
+ const newData = [...dataSource];
409
+ const indexesToDelete = [...rowsFocus];
410
+
411
+ // Sắp xếp giảm dần để xóa từ cuối lên đầu
412
+ indexesToDelete.sort((a, b) => b - a).forEach(index => {
413
+ newData.splice(index, 1);
414
+ });
415
+ triggerChangeData?.([...newData], 'DELETE_ROWS');
416
+ }
417
+ };
303
418
  const handleDeleteAll = () => {
304
419
  triggerChangeData?.([], 'INSERT_BEFORE');
305
420
  };
421
+ const handleDeleteContent = () => {
422
+ if (selectedCells.size > 0) {
423
+ const newData = [...dataSource];
424
+
425
+ // colIndex => field
426
+ const colIndexToField = flatColumns2(columns).map(col => col.field);
427
+
428
+ // Duyệt qua mỗi ô cần xóa
429
+ for (const cell of selectedCells) {
430
+ const [rowIndexStr, colIndexStr] = cell.split("-");
431
+ const rowIndex = Number(rowIndexStr);
432
+ const colIndex = Number(colIndexStr);
433
+ const field = colIndexToField[colIndex];
434
+ if (newData[rowIndex] && field && field in newData[rowIndex]) {
435
+ // @ts-ignore
436
+ newData[rowIndex][field] = '';
437
+ }
438
+ }
439
+ triggerChangeData?.([...newData], 'DELETE_CONTENT');
440
+ }
441
+ };
306
442
  const toolbarItemsBottom = useMemo(() => {
307
443
  if (!rowsFocus || rowsFocus.length === 0) {
308
- return toolbarItems?.filter(it => it.position === 'Bottom' && it.visible !== false && it.key !== 'DUPLICATE' && it.key !== 'INSERT_BEFORE' && it.key !== 'INSERT_AFTER' && it.key !== 'INSERT_CHILDREN').map(item => {
444
+ return toolbarItems?.filter(it => it.position === 'Bottom' && it.visible !== false && it.key !== 'DUPLICATE' && it.key !== 'INSERT_BEFORE' && it.key !== 'INSERT_AFTER' && it.key !== 'DELETE_ROWS' && it.key !== 'INSERT_CHILDREN').map(item => {
309
445
  if (item.key === 'ADD') {
310
446
  return {
311
447
  ...item,
@@ -313,6 +449,7 @@ const GridEdit = props => {
313
449
  return /*#__PURE__*/React.createElement(Fragment, null, item.key === 'ADD' && /*#__PURE__*/React.createElement("div", {
314
450
  className: classnames(`be-toolbar-item`, item?.className)
315
451
  }, /*#__PURE__*/React.createElement(Dropdown.Button, {
452
+ overlayClassName: 'be-popup-container',
316
453
  style: {
317
454
  color: '#28c76f',
318
455
  borderColor: '#28c76f'
@@ -362,6 +499,7 @@ const GridEdit = props => {
362
499
  return /*#__PURE__*/React.createElement(Fragment, null, item.key === 'ADD' && /*#__PURE__*/React.createElement("div", {
363
500
  className: classnames(`be-toolbar-item`, item?.className)
364
501
  }, /*#__PURE__*/React.createElement(Dropdown.Button, {
502
+ overlayClassName: 'be-popup-container',
365
503
  style: {
366
504
  color: '#28c76f',
367
505
  borderColor: '#28c76f'
@@ -402,17 +540,25 @@ const GridEdit = props => {
402
540
  return {
403
541
  ...item,
404
542
  template: () => {
405
- return /*#__PURE__*/React.createElement(Fragment, null, item.key === 'INSERT_BEFORE' && item.visible !== false && rowsFocus.length > 0 && /*#__PURE__*/React.createElement("div", {
543
+ return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
406
544
  className: classnames(`be-toolbar-item`, item?.className)
407
- }, /*#__PURE__*/React.createElement(Button, {
545
+ }, /*#__PURE__*/React.createElement(Dropdown.Button, {
546
+ overlayClassName: 'be-popup-container',
408
547
  style: {
409
548
  color: '#28c76f',
410
549
  borderColor: '#28c76f'
411
550
  },
412
- variant: 'outlined',
413
- onClick: () => handleInsertBefore(item),
414
- className: "d-flex toolbar-button"
415
- }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item before') : 'Insert item before')));
551
+ className: 'toolbar-button toolbar-dropdown-button',
552
+ menu: {
553
+ items: itemsAdd,
554
+ onClick: e => handleInsertBefore(item, Number(e.key))
555
+ }
556
+ }, /*#__PURE__*/React.createElement("span", {
557
+ style: {
558
+ color: '#28c76f'
559
+ },
560
+ onClick: () => handleInsertBefore(item, 1)
561
+ }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item before') : 'Insert item before'))));
416
562
  }
417
563
  };
418
564
  }
@@ -420,17 +566,25 @@ const GridEdit = props => {
420
566
  return {
421
567
  ...item,
422
568
  template: () => {
423
- return /*#__PURE__*/React.createElement(Fragment, null, item.key === 'INSERT_AFTER' && item.visible !== false && rowsFocus.length > 0 && /*#__PURE__*/React.createElement("div", {
569
+ return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
424
570
  className: classnames(`be-toolbar-item`, item?.className)
425
- }, /*#__PURE__*/React.createElement(Button, {
571
+ }, /*#__PURE__*/React.createElement(Dropdown.Button, {
572
+ overlayClassName: 'be-popup-container',
426
573
  style: {
427
574
  color: '#28c76f',
428
575
  borderColor: '#28c76f'
429
576
  },
430
- variant: 'outlined',
431
- onClick: () => handleInsertAfter(item),
432
- className: "d-flex toolbar-button"
433
- }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item after') : 'Insert item after')));
577
+ className: 'toolbar-button toolbar-dropdown-button',
578
+ menu: {
579
+ items: itemsAdd,
580
+ onClick: e => handleInsertAfter(item, Number(e.key))
581
+ }
582
+ }, /*#__PURE__*/React.createElement("span", {
583
+ style: {
584
+ color: '#28c76f'
585
+ },
586
+ onClick: () => handleInsertAfter(item, 1)
587
+ }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item after') : 'Insert item after'))));
434
588
  }
435
589
  };
436
590
  }
@@ -470,6 +624,24 @@ const GridEdit = props => {
470
624
  }
471
625
  };
472
626
  }
627
+ if (item.key === 'DELETE_ROWS') {
628
+ return {
629
+ ...item,
630
+ template: () => {
631
+ return /*#__PURE__*/React.createElement("div", {
632
+ className: classnames(`be-toolbar-item`, item?.className)
633
+ }, /*#__PURE__*/React.createElement(Button, {
634
+ style: {
635
+ color: '#eb4619',
636
+ borderColor: '#eb4619'
637
+ },
638
+ variant: 'outlined',
639
+ onClick: () => handleDeleteRows(item),
640
+ className: "d-flex toolbar-button"
641
+ }, t ? `${t('Delete')} ${rowsFocus.length} ${t('row')}` : `Delete ${rowsFocus.length} item`));
642
+ }
643
+ };
644
+ }
473
645
  return {
474
646
  ...item
475
647
  };
@@ -494,35 +666,55 @@ const GridEdit = props => {
494
666
  useEffect(() => {
495
667
  const handleClickOutside = event => {
496
668
  const element = event.target;
497
- const tableBodies = document.getElementsByClassName("ui-rc-table-tbody");
669
+
670
+ // const tableId = id ? document.getElementById(id) : undefined
671
+ // const tableBodies = document.getElementsByClassName("ui-rc-table-tbody");
498
672
  const container = document.querySelector(".be-popup-container");
673
+ const tableBody = document.querySelector(`#${id} .ui-rc-table-tbody`);
499
674
  // const containerHidden = document.querySelector(".be-popup-container.ant-picker-dropdown-hidden")
500
675
 
501
676
  // const toolbarContainer = document.getElementsByClassName("ui-rc-toolbar");
502
- const itemContainer = document.querySelector(".ui-rc-toolbar-selection-overflow-item");
677
+ const itemContainer = document.querySelector(`#${id} .ui-rc-toolbar-selection-overflow-item`);
678
+ const itemHeader = document.querySelector(`#${id} .ui-rc-table-thead`);
503
679
  const isInsideContainer = element.closest(".be-popup-container") && container;
504
- const isInsideToolbar = element.closest(".ui-rc-toolbar-selection-overflow-item") && itemContainer;
505
- if (isInsideContainer || isInsideToolbar) {
680
+ const isInsideToolbar = element.closest(`.ui-rc-toolbar-selection-overflow-item`) && itemContainer;
681
+ const isInsideHeader = itemHeader && itemHeader.contains(event.target);
682
+ if (isInsideContainer || isInsideToolbar || isInsideHeader) {
506
683
  return;
507
684
  }
508
- if (tableBodies.length > 0) {
509
- const tableBody = tableBodies[0]; // Chọn tbody đầu tiên (nếu có nhiều)
510
-
511
- if (!tableBody.contains(event.target)) {
512
- setEditingKey('');
513
- isSelecting.current = false;
514
- startCell.current = null;
515
- setSelectedCells(new Set());
516
- setRowsSelected(new Set());
517
- } else {}
685
+
686
+ // if (ref.current && !ref.current.contains(event.target)) {
687
+ // if (ref.current && tableId && !tableId.contains(event.target as Node)) {
688
+
689
+ if (ref.current && tableBody && !tableBody.contains(event.target)) {
690
+ setEditingKey('');
691
+ isSelecting.current = false;
692
+ startCell.current = null;
693
+ setSelectedCells(new Set());
694
+ setRowsSelected(new Set());
518
695
  }
696
+
697
+ // if (tableBodies.length > 0) {
698
+ // const tableBody = tableBodies[0]; // Chọn tbody đầu tiên (nếu có nhiều)
699
+ //
700
+ // if (!tableBody.contains(event.target as Node)) {
701
+ // setEditingKey('')
702
+ // isSelecting.current = false;
703
+ // startCell.current = null;
704
+ // setSelectedCells(new Set())
705
+ // setRowsSelected(new Set())
706
+ // } else {
707
+ //
708
+ // }
709
+ // }
519
710
  };
520
711
  document.addEventListener("click", handleClickOutside);
521
712
  return () => {
522
713
  document.removeEventListener("click", handleClickOutside);
523
714
  };
524
715
  }, []);
525
- const handleMouseDown = (record, row, col, e) => {
716
+ const handleMouseDown = useCallback((record, row, col, e) => {
717
+ setEditingKey('');
526
718
  if (e.button === 2) {
527
719
  e.stopPropagation();
528
720
  return;
@@ -559,7 +751,7 @@ const GridEdit = props => {
559
751
  // setSelectedCells(new Set([`${row}-${col}`]));
560
752
  // setRowsSelected(new Set())
561
753
  // }
562
- };
754
+ }, []);
563
755
 
564
756
  // const handlePointEnter = (e: any) => {
565
757
  //
@@ -764,25 +956,15 @@ const GridEdit = props => {
764
956
  }
765
957
  setSelectedCells(newSelectedCells);
766
958
  };
767
-
768
- // const handleClickColHeader = (column: ColumnTable, indexColumn: number) => {
769
- //
770
- // const newSelectedCells = new Set();
771
- //
772
- // for (let r = Math.min(dataSource.length, 0); r <= Math.max(dataSource.length - 1, 0); r++) {
773
- // for (let c = Math.min(indexColumn, indexColumn); c <= Math.max(indexColumn, indexColumn); c++) {
774
- // newSelectedCells.add(`${r}-${c}`)
775
- // }
776
- // }
777
- //
778
- // // console.log('newSelectedCells', newSelectedCells)
779
- // // setSelectedCells(newSelectedCells)
780
- //
781
- // setSelectedCells(new Set(newSelectedCells));
782
- // // forceUpdate();
783
- // setUpdateKey((prev) => prev + 1); // Cập nhật key để trigger re-render
784
- // }
785
-
959
+ const handleClickColHeader = (column, indexColumn) => {
960
+ const newSelectedCells = new Set();
961
+ for (let r = Math.min(dataSource.length, 0); r <= Math.max(dataSource.length - 1, 0); r++) {
962
+ for (let c = Math.min(indexColumn, indexColumn); c <= Math.max(indexColumn, indexColumn); c++) {
963
+ newSelectedCells.add(`${r}-${c}`);
964
+ }
965
+ }
966
+ setSelectedCells(new Set(newSelectedCells));
967
+ };
786
968
  const handleMouseDownColIndex = (row, col, e) => {
787
969
  if (e.button === 2) {
788
970
  e.stopPropagation();
@@ -815,7 +997,7 @@ const GridEdit = props => {
815
997
  }
816
998
  const newSelectedCells = new Set();
817
999
  for (let r = Math.min(startRow, row); r <= Math.max(startRow, row); r++) {
818
- for (let c = Math.min(columns.length, col) + 1; c <= Math.max(columns.length, col); c++) {
1000
+ for (let c = Math.min(editAbleColumns(columns).length, col) + 1; c <= Math.max(editAbleColumns(columns).length, col); c++) {
819
1001
  newSelectedCells.add(`${r}-${c}`);
820
1002
  }
821
1003
  }
@@ -853,7 +1035,7 @@ const GridEdit = props => {
853
1035
  const selectedArray = Array.from(selectedCells).map(key => {
854
1036
  const [row, col] = key.split("-").map(Number);
855
1037
  // @ts-ignore
856
- const columnKey = columns[col].field;
1038
+ const columnKey = editAbleColumns(columns)[col - 1].field;
857
1039
 
858
1040
  // @ts-ignore
859
1041
  return {
@@ -932,16 +1114,17 @@ const GridEdit = props => {
932
1114
  // Không vượt quá số cột
933
1115
  return;
934
1116
  }
935
-
936
- // @ts-ignore
937
- const columnKey = columns[targetCol].field;
938
-
939
- // @ts-ignore
940
- newData[targetRow] = {
941
- ...newData[targetRow],
942
- [columnKey]: cellValue.trim()
943
- };
944
- pastedColumns.add(columnKey);
1117
+ if (columns[targetCol].editEnable) {
1118
+ // @ts-ignore
1119
+ const columnKey = columns[targetCol].field;
1120
+
1121
+ // @ts-ignore
1122
+ newData[targetRow] = {
1123
+ ...newData[targetRow],
1124
+ [columnKey]: cellValue.trim()
1125
+ };
1126
+ pastedColumns.add(columnKey);
1127
+ }
945
1128
  });
946
1129
 
947
1130
  // Lưu dòng được paste
@@ -980,16 +1163,17 @@ const GridEdit = props => {
980
1163
  // Không vượt quá số cột
981
1164
  return;
982
1165
  }
983
-
984
- // @ts-ignore
985
- const columnKey = columns[targetCol].field;
986
-
987
- // @ts-ignore
988
- childData[targetRow] = {
989
- ...childData[targetRow],
990
- [columnKey]: cellValue.trim()
991
- };
992
- pastedColumns.add(columnKey);
1166
+ if (columns[targetCol].editEnable) {
1167
+ // @ts-ignore
1168
+ const columnKey = columns[targetCol].field;
1169
+
1170
+ // @ts-ignore
1171
+ childData[targetRow] = {
1172
+ ...childData[targetRow],
1173
+ [columnKey]: cellValue.trim()
1174
+ };
1175
+ pastedColumns.add(columnKey);
1176
+ }
993
1177
  });
994
1178
 
995
1179
  // Lưu dòng được paste
@@ -1288,7 +1472,7 @@ const GridEdit = props => {
1288
1472
  tabIndex: (rowIndex ?? 0) * columns.length + colIndex
1289
1473
  };
1290
1474
  },
1291
- render: (value, record, rowIndex) => {
1475
+ render: (value, record) => {
1292
1476
  const rowNumber = getRowNumber(dataSource, record[rowKey], rowKey);
1293
1477
  return /*#__PURE__*/React.createElement("div", {
1294
1478
  className: classNames('ui-rc_cell-content ui-rc_cell-content--index', {
@@ -1297,10 +1481,11 @@ const GridEdit = props => {
1297
1481
  }),
1298
1482
  onMouseDown: event => handleMouseDownColIndex(rowNumber, colIndex, event),
1299
1483
  onMouseEnter: event => handleMouseEnterColIndex(rowNumber, colIndex, event),
1300
- onClick: () => handleClickRowHeader(rowNumber, colIndex)
1484
+ onClick: () => handleClickRowHeader(rowNumber, colIndex),
1485
+ onMouseUp: handleMouseUp
1301
1486
  }, /*#__PURE__*/React.createElement("div", {
1302
1487
  className: 'ui-rc_content'
1303
- }, rowIndex + 1));
1488
+ }, findItemPath(dataSource, record, rowKey)));
1304
1489
  }
1305
1490
  };
1306
1491
  }
@@ -1314,6 +1499,10 @@ const GridEdit = props => {
1314
1499
  onCell: (record, rowIndex) => {
1315
1500
  const rowNumber = getRowNumber(dataSource, record[rowKey], rowKey);
1316
1501
  return {
1502
+ // onKeyPress: () => {
1503
+ //
1504
+ // },
1505
+
1317
1506
  onKeyDown: event => {
1318
1507
  const key = getRowKey(record, dataSource.indexOf(record));
1319
1508
  if (event.key.length === 1 && !event.ctrlKey && !event.metaKey || event.key === 'Enter') {
@@ -1379,6 +1568,9 @@ const GridEdit = props => {
1379
1568
  if (event.key === 'ArrowUp' && (rowNumber ?? 0) > 0) {
1380
1569
  handleFocusCell((rowNumber ?? 0) - 1, colIndex, column, 'vertical', event);
1381
1570
  }
1571
+ if (event.key === 'Delete') {
1572
+ handleDeleteContent();
1573
+ }
1382
1574
  },
1383
1575
  onPaste: event => {
1384
1576
  if (editingKey === '') {
@@ -1398,6 +1590,19 @@ const GridEdit = props => {
1398
1590
  handleCellClick(rowNumber, record, column);
1399
1591
  }
1400
1592
  },
1593
+ onContextMenu: () => {
1594
+ // isSelecting.current = true;
1595
+ // startCell.current = { row: rowNumber, col: colIndex };
1596
+
1597
+ if (selectedCells.size === 0) {
1598
+ setStartSelectedCell({
1599
+ row: rowNumber,
1600
+ col: colIndex
1601
+ });
1602
+ setSelectedCells(new Set([`${rowNumber}-${colIndex}`]));
1603
+ setRowsSelected(new Set());
1604
+ }
1605
+ },
1401
1606
  onClick: () => {
1402
1607
  if (record[rowKey] !== editingKey && editingKey !== '') {
1403
1608
  setEditingKey('');
@@ -1422,19 +1627,42 @@ const GridEdit = props => {
1422
1627
  } : {}
1423
1628
  };
1424
1629
  },
1630
+ onHeaderCell: () => {
1631
+ return {
1632
+ onClick: () => {
1633
+ handleClickColHeader(column, colIndex);
1634
+ },
1635
+ onCopy: e => {
1636
+ if (editingKey === '') {
1637
+ handleCopy(e);
1638
+ e.preventDefault();
1639
+ }
1640
+ },
1641
+ onPaste: event => {
1642
+ if (editingKey === '') {
1643
+ handlePaste(dataSource[0], colIndex, 0, event);
1644
+ event.preventDefault();
1645
+ }
1646
+ },
1647
+ style: {
1648
+ userSelect: 'none'
1649
+ }
1650
+ };
1651
+ },
1425
1652
  render: (value, record, rowIndex) => {
1426
1653
  const rowNumber = getRowNumber(dataSource, record[rowKey], rowKey);
1427
1654
  return /*#__PURE__*/React.createElement("div", {
1428
1655
  className: classNames('ui-rc_cell-content', {
1429
1656
  // selected: selectedCells.has(`${record[rowKey]}-${colIndex}`)
1430
- selected: selectedCells.has(`${rowNumber}-${colIndex}`)
1657
+ selected: selectedCells.has(`${rowNumber}-${colIndex}`),
1658
+ disable: !isEditable(column, record)
1431
1659
  }),
1432
1660
  onMouseDown: event => handleMouseDown(record, rowNumber, colIndex, event),
1433
1661
  onMouseEnter: () => handleMouseEnter(rowNumber, colIndex),
1434
1662
  onMouseUp: handleMouseUp
1435
1663
  }, /*#__PURE__*/React.createElement("div", {
1436
1664
  className: 'ui-rc_content'
1437
- }, renderContent(column, value, record, rowIndex, format)), selectedCells && selectedCells.size > 0 && getLastSelectCell(selectedCells).row === rowNumber && getLastSelectCell(selectedCells).col === colIndex && isEditable(column, record) !== false && !isSelectDragging &&
1665
+ }, renderContent(column, value, record, rowIndex, format)), selectedCells && selectedCells.size > 0 && getLastSelectCell(selectedCells).row === rowNumber && getLastSelectCell(selectedCells).col === colIndex && isEditable(column, record) && !isSelectDragging && rowIndex !== dataSource.length - 1 &&
1438
1666
  /*#__PURE__*/
1439
1667
  // showDraggingPoint &&
1440
1668
  React.createElement("div", {
@@ -1495,11 +1723,26 @@ const GridEdit = props => {
1495
1723
  const onSelectChange = keys => {
1496
1724
  setMergedSelectedKeys(keys);
1497
1725
  };
1726
+ const contextMenuClick = args => {
1727
+ if (args.item.key === 'INSERT_BEFORE') {
1728
+ handleInsertAfter(args.item, 1);
1729
+ }
1730
+ if (args.item.key === 'INSERT_AFTER') {
1731
+ handleInsertBefore(args.item, 1);
1732
+ }
1733
+ if (args.item.key === 'DELETE_ROWS') {
1734
+ handleDeleteRows(args.item);
1735
+ }
1736
+ if (args.item.key === 'DELETE_CONTENT') {
1737
+ handleDeleteContent();
1738
+ }
1739
+ };
1498
1740
  return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(GridStyle, {
1499
1741
  heightTable: height,
1500
1742
  style: {
1501
1743
  position: 'relative'
1502
- }
1744
+ },
1745
+ ref: ref
1503
1746
  // onMouseUp={handleMouseUp}
1504
1747
  }, /*#__PURE__*/React.createElement(TableContext.Provider, {
1505
1748
  value: {
@@ -1521,7 +1764,7 @@ const GridEdit = props => {
1521
1764
  rowHoverBg: '#eb461912',
1522
1765
  rowSelectedBg: '#eb4619',
1523
1766
  rowSelectedHoverBg: '#eb4619',
1524
- cellFontSize: 12,
1767
+ // cellFontSize: 12,
1525
1768
  cellFontSizeSM: 13,
1526
1769
  headerBg: '#ffffff',
1527
1770
  cellPaddingBlockSM: 7
@@ -1534,11 +1777,13 @@ const GridEdit = props => {
1534
1777
  }
1535
1778
  }, /*#__PURE__*/React.createElement(TableGrid, _extends({}, rest, {
1536
1779
  t: t,
1780
+ id: id,
1537
1781
  tableRef: tableRef,
1538
1782
  dataSource: dataSource,
1539
1783
  components: {
1540
1784
  ...components,
1541
1785
  body: {
1786
+ // wrapper: () => <div></div>,
1542
1787
  cell: EditableCell
1543
1788
  // cell: () => <EditableCell />,
1544
1789
  }
@@ -1551,11 +1796,15 @@ const GridEdit = props => {
1551
1796
  target: 'sorter-icon'
1552
1797
  },
1553
1798
  format: format,
1554
- toolbarItems: toolbarItems,
1799
+ toolbarItems: toolbarItems
1800
+ // selectionSettings={selectionSettings ? {...selectionSettings, checkboxOnly: true} : undefined}
1801
+ ,
1555
1802
  selectionSettings: selectionSettings ? {
1556
1803
  ...selectionSettings,
1557
1804
  checkboxOnly: true
1558
- } : undefined,
1805
+ } : {
1806
+ checkboxOnly: true
1807
+ },
1559
1808
  rowHoverable: false,
1560
1809
  bottomToolbar: bottomToolbar,
1561
1810
  expandable: {
@@ -1595,13 +1844,18 @@ const GridEdit = props => {
1595
1844
  }
1596
1845
  },
1597
1846
  triggerChangeColumns: triggerChangeColumns,
1847
+ clickHeaderToSort: false,
1598
1848
  rowSelection: columns && columns.length === 0 ? undefined : {
1599
1849
  type: mode === 'checkbox' || type === 'multiple' ? 'checkbox' : "radio",
1600
1850
  columnWidth: !mode ? 0.0000001 : columnWidth ?? 50,
1601
1851
  onChange: onSelectChange,
1602
1852
  selectedRowKeys: mergedSelectedKeys,
1603
1853
  preserveSelectedRowKeys: true
1604
- }
1854
+ },
1855
+ isFilter: isFilter,
1856
+ setIsFilter: setIsFilter,
1857
+ contextMenuItems: contextMenuItems,
1858
+ contextMenuClick: contextMenuClick
1605
1859
  })))))), /*#__PURE__*/React.createElement(Toaster, {
1606
1860
  position: toast,
1607
1861
  toastOptions: {