es-grid-template 1.4.0 → 1.4.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 (33) hide show
  1. package/es/grid-component/EditableCell.js +46 -15
  2. package/es/grid-component/InternalTable.d.ts +1 -0
  3. package/es/grid-component/InternalTable.js +469 -113
  4. package/es/grid-component/TableGrid.js +46 -48
  5. package/es/grid-component/hooks/columns/index.d.ts +1 -1
  6. package/es/grid-component/hooks/columns/index.js +3 -13
  7. package/es/grid-component/hooks/useColumns.js +5 -2
  8. package/es/grid-component/hooks/utils.d.ts +17 -2
  9. package/es/grid-component/hooks/utils.js +24 -5
  10. package/es/grid-component/styles.scss +1186 -1170
  11. package/es/grid-component/table/Grid.d.ts +1 -0
  12. package/es/grid-component/table/GridEdit.d.ts +1 -0
  13. package/es/grid-component/table/GridEdit.js +190 -140
  14. package/es/grid-component/table/Group.d.ts +1 -0
  15. package/es/grid-component/type.d.ts +7 -2
  16. package/es/grid-component/useContext.d.ts +1 -0
  17. package/lib/grid-component/EditableCell.js +46 -15
  18. package/lib/grid-component/InternalTable.d.ts +1 -0
  19. package/lib/grid-component/InternalTable.js +469 -102
  20. package/lib/grid-component/TableGrid.js +45 -47
  21. package/lib/grid-component/hooks/columns/index.d.ts +1 -1
  22. package/lib/grid-component/hooks/columns/index.js +5 -15
  23. package/lib/grid-component/hooks/useColumns.js +4 -1
  24. package/lib/grid-component/hooks/utils.d.ts +17 -2
  25. package/lib/grid-component/hooks/utils.js +26 -6
  26. package/lib/grid-component/styles.scss +1186 -1170
  27. package/lib/grid-component/table/Grid.d.ts +1 -0
  28. package/lib/grid-component/table/GridEdit.d.ts +1 -0
  29. package/lib/grid-component/table/GridEdit.js +189 -139
  30. package/lib/grid-component/table/Group.d.ts +1 -0
  31. package/lib/grid-component/type.d.ts +7 -2
  32. package/lib/grid-component/useContext.d.ts +1 -0
  33. package/package.json +5 -5
@@ -5,6 +5,7 @@ import classNames from "classnames";
5
5
  import { Button, Dropdown, Form, Modal, Typography } from "antd";
6
6
  import { useForm } from 'react-hook-form';
7
7
  import { Toaster } from "react-hot-toast";
8
+ import { yupResolver } from "@hookform/resolvers/yup";
8
9
  import { flatColumns2, getValueCell, renderContent } from "../hooks/columns";
9
10
  import EditableCell from "../EditableCell";
10
11
  import { GridStyle } from "../GridStyle";
@@ -13,19 +14,19 @@ import dayjs from "dayjs";
13
14
  import 'dayjs/locale/es';
14
15
  import 'dayjs/locale/vi';
15
16
  import TableGrid from "../TableGrid";
16
- import { addClassBorderPasteCell, addClassCellIndexSelected, addRows8, addRowsUp, checkChild, editAbleColumns, findAllChildrenKeys, findItemByKey, findItemPath, flattenArray, flattenData, getDefaultValue, getEditType, getFirstSelectCell, getLastSelectCell, getRowNumber, getRowsPasteIndex, hideDraggingPoint, isEditable, isEqualSet, isObjEmpty, newGuid, onAddBorderSelectedCell, onAddBgSelectedCell, onRemoveBorderSelectedCell, onRemoveBgSelectedCell, removeClassBorderPasteCell, removeClassCellIndexSelected, showDraggingPoint, sortedSetASC, totalFixedWidth, updateArrayByKey } from "../hooks";
17
+ import { addClassBorderPasteCell, addClassCellIndexSelected, addRows8, addRowsUp, checkChild, editAbleColumns, findAllChildrenKeys, findItemByKey, findItemPath, flattenArray, flattenData, getDefaultValue, getEditType, getFirstSelectCell, getLastSelectCell, getRowNumber, getRowsPasteIndex, hideDraggingPoint, isEditable, isEqualSet, isObjEmpty, newGuid, onAddBorderSelectedCell, onAddBgSelectedCell, onRemoveBorderSelectedCell, onRemoveBgSelectedCell, removeClassBorderPasteCell, removeClassCellIndexSelected, showDraggingPoint, sortedSetASC, totalFixedWidth, updateArrayByKey, getFormat } from "../hooks";
17
18
  import Message from "../../Message/Message";
18
19
  import { Toolbar, ConfigProvider, InputNumber } from "rc-master-ui";
19
20
  import classnames from "classnames";
20
21
  import { Plus, Trash2 } from "becoxy-icons";
21
22
  import { faker } from "@faker-js/faker";
23
+ import { SELECTION_COLUMN } from "../InternalTable";
22
24
  const {
23
25
  Paragraph,
24
26
  Title
25
27
  } = Typography;
26
28
  dayjs.extend(customParseFormat);
27
29
  const toast = 'top-right';
28
- // const defaultContext: ContextMenuItem[] = [
29
30
  const defaultContext = [{
30
31
  key: 'INSERT_BEFORE',
31
32
  label: 'Thêm dòng bên trên',
@@ -88,6 +89,44 @@ const defaultContext = [{
88
89
  key: 'INSERT_AFTER_ADV',
89
90
  label: 'Tùy chỉnh'
90
91
  }]
92
+ }, {
93
+ key: 'INSERT_CHILDREN',
94
+ // label: 'Insert item children',
95
+ label: 'Thêm cấp con',
96
+ icon: /*#__PURE__*/React.createElement(Plus, {
97
+ fontSize: 14
98
+ })
99
+ // children: [
100
+ // {
101
+ // parentKey: 'INSERT_AFTER',
102
+ // key: 'INSERT_AFTER_1',
103
+ // label: 'Thêm 1 dòng',
104
+ // row: 1
105
+ // },
106
+ // {
107
+ // parentKey: 'INSERT_AFTER',
108
+ // key: 'INSERT_AFTER_10',
109
+ // label: 'Thêm 10 dòng',
110
+ // row: 10
111
+ // },
112
+ // {
113
+ // parentKey: 'INSERT_AFTER',
114
+ // key: 'INSERT_AFTER_50',
115
+ // label: 'Thêm 50 dòng',
116
+ // row: 50
117
+ // },
118
+ // {
119
+ // parentKey: 'INSERT_AFTER',
120
+ // key: 'INSERT_AFTER_100',
121
+ // label: 'Thêm 100 dòng',
122
+ // row: 100
123
+ // },
124
+ // {
125
+ // parentKey: 'INSERT_AFTER',
126
+ // key: 'INSERT_AFTER_ADV',
127
+ // label: 'Tùy chỉnh'
128
+ // }
129
+ // ]
91
130
  }, {
92
131
  key: 'DELETE_CONTENT',
93
132
  label: 'Xóa nội dung',
@@ -101,6 +140,37 @@ const defaultContext = [{
101
140
  fontSize: 14
102
141
  })
103
142
  }];
143
+ const validateData = async (data, formSchema) => {
144
+ if (!formSchema) {
145
+ return [];
146
+ } else {
147
+ const errors = [];
148
+ for (let i = 0; i < data.length; i++) {
149
+ try {
150
+ await formSchema.validate(data[i], {
151
+ abortEarly: false
152
+ });
153
+ } catch (error) {
154
+ errors.push(error.inner.reduce((acc, err) => {
155
+ acc[err.path] = {
156
+ field: err.path,
157
+ index: i,
158
+ message: err.message,
159
+ type: err.type,
160
+ ref: {
161
+ name: err.path
162
+ }
163
+ };
164
+ return {
165
+ ...acc,
166
+ index: i
167
+ };
168
+ }, {}));
169
+ }
170
+ }
171
+ return errors;
172
+ }
173
+ };
104
174
  const GridEdit = props => {
105
175
  const {
106
176
  id: tableId,
@@ -129,6 +199,8 @@ const GridEdit = props => {
129
199
  rowEditable,
130
200
  contextMenuItems: propsContext,
131
201
  showDefaultContext,
202
+ validate,
203
+ setTooltipContent,
132
204
  ...rest
133
205
  } = props;
134
206
  const ref = useRef(null);
@@ -149,6 +221,9 @@ const GridEdit = props => {
149
221
  // quét vùng được paste - tiếp tục hiển thị con trỏ crosshair
150
222
  // const isPasteDragging = useRef(false);
151
223
 
224
+ const visibleCols = React.useMemo(() => {
225
+ return flatColumns2(columns.filter(it => it.visible !== false));
226
+ }, [columns]);
152
227
  const id = React.useMemo(() => {
153
228
  return tableId ?? faker.string.alpha(20);
154
229
  // return tableId ?? newGuid()
@@ -165,33 +240,17 @@ const GridEdit = props => {
165
240
  }];
166
241
  const [form] = Form.useForm();
167
242
  const [editingKey, setEditingKey] = useState('');
243
+ const [dataErrors, setDataErrors] = useState([]);
168
244
  const [isFilter, setIsFilter] = React.useState(false);
169
245
  const [rangeCells, setRangeCells] = useState(new Set());
170
-
171
- // const [pasteCells, setPasteCells] = useState(new Set())
172
-
173
- // const defaultModalPaste = {open: false, rowIndex: -1, colIndex: -1, record: {}, rowsPasted: []}
174
-
175
- // const [isCtrlDown, setIsCtrlDown] = useState(false)
176
-
177
- // const [ctrlCells, setCtrlCells] = useState<any>([])
178
- // const [currentCtrlCells, setCurrentCtrlCells] = useState<any>(new Set())
179
-
180
246
  const [openModalAddRow, setOpenModalAddRow] = useState({
181
247
  open: false,
182
248
  type: ''
183
249
  });
184
250
  const [rowsAdd, setRowsAdd] = useState(1);
185
251
  const [cellEditing, setCellEditing] = useState(null);
186
-
187
- // const [isSelectDragging, setSelectIsDragging] = useState(false)
188
-
189
252
  const [isPasteDragging, setIsPasteDragging] = useState(false); // isPasteDragging == tiếp tục hiển thị con trỏ crosshair
190
253
 
191
- // const [rowsSelected, setRowsSelected] = useState(new Set())
192
-
193
- // const [startSelectedCells, setStartSelectedCell] = useState<{ row: number; col: number } | null>(null)
194
-
195
254
  const [innerExpandedKeys, setInnerExpandedKeys] = React.useState(() => {
196
255
  // if (defaultExpandedRowKeys) {
197
256
  // return defaultExpandedRowKeys;
@@ -202,6 +261,16 @@ const GridEdit = props => {
202
261
  // return [];
203
262
  });
204
263
  const mergedExpandedKeys = React.useMemo(() => new Set(innerExpandedKeys || []), [innerExpandedKeys]);
264
+ React.useEffect(() => {
265
+ if (validate && dataSource && dataSource.length) {
266
+ validateData(dataSource, validate).then(error => {
267
+ setDataErrors([...error]);
268
+ // if (getErrors) {
269
+ // getErrors([...error])
270
+ // }
271
+ });
272
+ }
273
+ }, [validate, dataSource]);
205
274
  const rowsFocus = React.useMemo(() => {
206
275
  return [...new Set(Array.from(rangeCells).map(item => parseInt(item.split('-')[0])))] ?? [];
207
276
  }, [rangeCells]);
@@ -223,8 +292,11 @@ const GridEdit = props => {
223
292
  newExpandedKeys = [...mergedExpandedKeys, key];
224
293
  }
225
294
  setInnerExpandedKeys(newExpandedKeys);
226
- }, [getRowKey, mergedExpandedKeys, dataSource]);
227
- const handleAddSingle = item => {
295
+ //
296
+ // onAddBgSelectedCell(rangeCells, id)
297
+ // onAddBorderSelectedCell(rangeCells, id)
298
+ }, [getRowKey, dataSource, mergedExpandedKeys]);
299
+ const handleAddSingle = React.useCallback(item => {
228
300
  const defaultRowValue = getDefaultValue(defaultValue);
229
301
  const rowId = defaultRowValue && defaultRowValue.id ? defaultRowValue.id : newGuid();
230
302
  if (item && item.onClick) {
@@ -242,8 +314,8 @@ const GridEdit = props => {
242
314
  }];
243
315
  triggerChangeData?.(newData, 'Add');
244
316
  }
245
- };
246
- const handleAddMulti = (item, e) => {
317
+ }, [dataSource, defaultValue, triggerChangeData]);
318
+ const handleAddMulti = React.useCallback((item, e) => {
247
319
  if (item.onClick) {
248
320
  item.onClick({
249
321
  toolbar: item
@@ -263,8 +335,8 @@ const GridEdit = props => {
263
335
  const newData = dataSource.concat(newRows);
264
336
  triggerChangeData?.(newData, 'Add');
265
337
  }
266
- };
267
- const handleDuplicate = () => {
338
+ }, [dataSource, defaultValue, triggerChangeData]);
339
+ const handleDuplicate = React.useCallback(() => {
268
340
  // không tính tree
269
341
 
270
342
  // Cập nhật data mới
@@ -280,10 +352,10 @@ const GridEdit = props => {
280
352
  const insertAfter = Math.max(...rowsFocus);
281
353
  const rs = [...newData.slice(0, insertAfter + 1), ...duplicatedItems, ...newData.slice(insertAfter + 1)];
282
354
  triggerChangeData?.(rs, 'DUPLICATE');
283
- };
355
+ }, [dataSource, rowsFocus, triggerChangeData]);
284
356
 
285
357
  // thêm n dòng bên trên
286
- const handleInsertBefore = (item, n) => {
358
+ const handleInsertBefore = React.useCallback((item, n) => {
287
359
  //
288
360
  onRemoveBgSelectedCell(selectedCells.current, id);
289
361
  onRemoveBorderSelectedCell(selectedCells.current, id);
@@ -362,10 +434,10 @@ const GridEdit = props => {
362
434
  triggerChangeData?.(newDataSource, 'INSERT_BEFORE');
363
435
  }
364
436
  }
365
- };
437
+ }, [dataSource, defaultValue, id, isFilter, rowKey, rowsFocus, triggerChangeData]);
366
438
 
367
439
  //thêm 1 dòng bên dưới
368
- const handleInsertAfter = (item, n) => {
440
+ const handleInsertAfter = React.useCallback((item, n) => {
369
441
  const defaultRowValue = getDefaultValue(defaultValue);
370
442
  const record = flattenData(childrenColumnName, dataSource)[rowsFocus[rowsFocus.length - 1]];
371
443
 
@@ -436,8 +508,8 @@ const GridEdit = props => {
436
508
  triggerChangeData?.(newDataSource, 'INSERT_BEFORE');
437
509
  }
438
510
  }
439
- };
440
- const handleInsertChild = item => {
511
+ }, [dataSource, defaultValue, isFilter, rowKey, rowsFocus, triggerChangeData]);
512
+ const handleInsertChild = React.useCallback(item => {
441
513
  const defaultRowValue = getDefaultValue(defaultValue);
442
514
  const rowId = defaultRowValue && defaultRowValue.id ? defaultRowValue.id : newGuid();
443
515
  const record = flattenData(childrenColumnName, dataSource)[rowsFocus[rowsFocus.length - 1]];
@@ -478,8 +550,8 @@ const GridEdit = props => {
478
550
  const newExpandedKeys = [...mergedExpandedKeys, key];
479
551
  setInnerExpandedKeys(newExpandedKeys);
480
552
  }
481
- };
482
- const handleDeleteRows = item => {
553
+ }, [dataSource, defaultValue, getRowKey, mergedExpandedKeys, rowKey, rowsFocus, triggerChangeData]);
554
+ const handleDeleteRows = React.useCallback(item => {
483
555
  setTimeout(() => {
484
556
  onAddBgSelectedCell(selectedCells.current, id);
485
557
  onAddBorderSelectedCell(selectedCells.current, id);
@@ -498,16 +570,16 @@ const GridEdit = props => {
498
570
  });
499
571
  triggerChangeData?.([...newData], 'DELETE_ROWS');
500
572
  }
501
- };
502
- const handleDeleteAll = () => {
573
+ }, [dataSource, id, rowsFocus, triggerChangeData]);
574
+ const handleDeleteAll = React.useCallback(() => {
503
575
  triggerChangeData?.([], 'INSERT_BEFORE');
504
- };
505
- const handleDeleteContent = () => {
576
+ }, [triggerChangeData]);
577
+ const handleDeleteContent = React.useCallback(() => {
506
578
  if (selectedCells.current.size > 0) {
507
579
  const newData = [...dataSource];
508
580
 
509
581
  // colIndex => field
510
- const colIndexToField = flatColumns2(columns).map(col => col.field);
582
+ const colIndexToField = flatColumns2(visibleCols).map(col => col.field);
511
583
 
512
584
  // Duyệt qua mỗi ô cần xóa
513
585
  for (const cell of selectedCells.current) {
@@ -522,7 +594,7 @@ const GridEdit = props => {
522
594
  }
523
595
  triggerChangeData?.([...newData], 'DELETE_CONTENT');
524
596
  }
525
- };
597
+ }, [dataSource, triggerChangeData, visibleCols]);
526
598
  const toolbarItemsBottom = useMemo(() => {
527
599
  if (!rowsFocus || rowsFocus.length === 0) {
528
600
  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 => {
@@ -687,7 +759,7 @@ const GridEdit = props => {
687
759
  variant: 'outlined',
688
760
  onClick: () => handleInsertChild(item),
689
761
  className: "d-flex toolbar-button"
690
- }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item after') : 'Insert item after')));
762
+ }, item.label ? t ? t(item.label) : item.label : t ? t('Insert item children') : 'Insert item children')));
691
763
  }
692
764
  };
693
765
  }
@@ -731,19 +803,24 @@ const GridEdit = props => {
731
803
  ...item
732
804
  };
733
805
  });
734
- }, [handleAddMulti, handleAddSingle, itemsAdd, rowsFocus.length, t, toolbarItems]);
806
+ }, [handleAddMulti, handleAddSingle, handleDeleteAll, handleDeleteRows, handleDuplicate, handleInsertAfter, handleInsertBefore, handleInsertChild, itemsAdd, rowsFocus, t, toolbarItems]);
735
807
  const {
736
808
  control,
737
809
  handleSubmit,
738
810
  setValue,
739
811
  trigger,
740
812
  getValues,
741
- reset
813
+ reset,
814
+ formState: {
815
+ errors
816
+ }
742
817
  } = useForm({
743
- mode: 'onChange'
744
- // resolver: yupResolver(formSchema)
818
+ mode: 'onChange',
819
+ resolver: yupResolver(validate)
745
820
  });
746
- const isEditing = record => record[rowKey] === editingKey;
821
+ const isEditing = React.useCallback(record => {
822
+ return record[rowKey] === editingKey;
823
+ }, [editingKey, rowKey]);
747
824
  useEffect(() => {
748
825
  const handleClickOutside = event => {
749
826
  const element = event.target;
@@ -788,8 +865,11 @@ const GridEdit = props => {
788
865
  return () => {
789
866
  document.removeEventListener("click", handleClickOutside);
790
867
  };
791
- }, []);
868
+ }, [id]);
792
869
  const handleMouseDown = (record, row, col, e) => {
870
+ if (editingKey && editingKey === record[rowKey]) {
871
+ return;
872
+ }
793
873
  if (e.button === 2) {
794
874
  e.stopPropagation();
795
875
  return;
@@ -845,7 +925,7 @@ const GridEdit = props => {
845
925
  setTimeout(() => {
846
926
  onAddBgSelectedCell(cells, id);
847
927
  onAddBorderSelectedCell(cells, id);
848
- }, 100);
928
+ }, 200);
849
929
  } else {
850
930
  onAddBgSelectedCell(cells, id);
851
931
  onAddBorderSelectedCell(cells, id);
@@ -859,7 +939,9 @@ const GridEdit = props => {
859
939
  };
860
940
  const triggerDragPaste = pastesArray => {
861
941
  const mergedSet = new Set([...selectedCells.current, ...pastesArray]);
862
- const tmpCols = flatColumns2(columns.filter(it => it.visible !== false));
942
+ const tmpCols = {
943
+ ...visibleCols
944
+ };
863
945
  const rowSelectedFirst = getFirstSelectCell(selectedCells.current).row;
864
946
  const rowPasteLast = getLastSelectCell(pasteCells.current).row;
865
947
  const selectedArray = Array.from(selectedCells.current).map(key => {
@@ -990,9 +1072,12 @@ const GridEdit = props => {
990
1072
  // selectedCells.current = sortedSetASC(mergedSet)
991
1073
  hideDraggingPoint(selectedCells.current, id);
992
1074
  selectedCells.current = sortedSetASC(mergedSet);
993
- onAddBgSelectedCell(sortedSetASC(mergedSet), id);
994
- onAddBorderSelectedCell(sortedSetASC(mergedSet), id);
995
- showDraggingPoint(sortedSetASC(mergedSet), id);
1075
+ setRangeCells(sortedSetASC(mergedSet));
1076
+ setTimeout(() => {
1077
+ onAddBgSelectedCell(sortedSetASC(mergedSet), id);
1078
+ onAddBorderSelectedCell(sortedSetASC(mergedSet), id);
1079
+ showDraggingPoint(sortedSetASC(mergedSet), id);
1080
+ }, 50);
996
1081
 
997
1082
  // setPasteCells(new Set())
998
1083
 
@@ -1016,27 +1101,6 @@ const GridEdit = props => {
1016
1101
  hideDraggingPoint(selectedCells.current, id);
1017
1102
  triggerDragPaste(newPasteCells);
1018
1103
  };
1019
-
1020
- // const handleClickCell = (e: any) => {
1021
- //
1022
- // if (e.ctrlKey) {
1023
- //
1024
- // const cell: any = new Set([`${row}-${col}`])
1025
- //
1026
- // const found = ctrlCells.find((s: any) => isEqualSet(s, cell));
1027
- //
1028
- // if (found) {
1029
- // const rs = ctrlCells.filter((s: any) => !isEqualSet(s, cell));
1030
- //
1031
- // setCtrlCells(rs)
1032
- //
1033
- // } else {
1034
- // setCtrlCells([...ctrlCells, cell])
1035
- // }
1036
- //
1037
- // }
1038
- // }
1039
-
1040
1104
  const handleMouseUp = e => {
1041
1105
  isSelecting.current = false;
1042
1106
  startCell.current = null;
@@ -1076,15 +1140,6 @@ const GridEdit = props => {
1076
1140
  showDraggingPoint(selectedCells.current, id);
1077
1141
  }
1078
1142
  };
1079
-
1080
- // const handlePointEnter = () => {
1081
- // isPointEnter.current = true;
1082
- // }
1083
- //
1084
- // const handlePointLeave = () => {
1085
- // isPointEnter.current = false;
1086
- // }
1087
-
1088
1143
  const handleMouseEnter = (row, col, e) => {
1089
1144
  if (!isSelecting.current || !startCell.current) {
1090
1145
  return;
@@ -1190,32 +1245,6 @@ const GridEdit = props => {
1190
1245
  }
1191
1246
  }
1192
1247
  };
1193
-
1194
- // const handleClickRowHeader = (row: any, col: any) => {
1195
- //
1196
- // const newSelectedCells = new Set()
1197
- //
1198
- // const tCols = editAbleColumns(columns)
1199
- //
1200
- // for (let r = Math.min(row, row); r <= Math.max(row, row); r++) {
1201
- // for (let c = Math.min(tCols.length, col) + 1; c <= Math.max(tCols.length, col); c++) {
1202
- // newSelectedCells.add(`${r}-${c}`)
1203
- // }
1204
- // }
1205
- //
1206
- // // setSelectedCells(newSelectedCells)
1207
- //
1208
- // if (selectedCells.current && selectedCells.current.size > 0) {
1209
- // onRemoveBgSelectedCell(selectedCells.current, id)
1210
- // }
1211
- //
1212
- // selectedCells.current = newSelectedCells
1213
- //
1214
- // onAddBgSelectedCell(newSelectedCells, id)
1215
- //
1216
- //
1217
- // };
1218
-
1219
1248
  const handleClickColHeader = (column, indexColumn) => {
1220
1249
  const newSelectedCells = new Set();
1221
1250
  for (let r = Math.min(dataSource.length, 0); r <= Math.max(dataSource.length - 1, 0); r++) {
@@ -1250,7 +1279,7 @@ const GridEdit = props => {
1250
1279
  col
1251
1280
  };
1252
1281
  const newSelectedCells = new Set();
1253
- const tCols = editAbleColumns(columns);
1282
+ const tCols = editAbleColumns(visibleCols);
1254
1283
  for (let r = Math.min(row, row); r <= Math.max(row, row); r++) {
1255
1284
  for (let c = Math.min(tCols.length, col) + 1; c <= Math.max(tCols.length, col); c++) {
1256
1285
  newSelectedCells.add(`${r}-${c}`);
@@ -1270,7 +1299,7 @@ const GridEdit = props => {
1270
1299
  hideDraggingPoint(selectedCells.current, id);
1271
1300
  selectedCells.current = newSelectedCells;
1272
1301
  rowsSelected.current = new Set([`${row}-${col}`]);
1273
- onAddBgSelectedCell(newSelectedCells, id);
1302
+ onAddBgSelectedCell(newSelectedCells, id, false);
1274
1303
  onAddBorderSelectedCell(newSelectedCells, id);
1275
1304
  addClassCellIndexSelected(new Set([`${row}-${col}`]), id);
1276
1305
  };
@@ -1412,13 +1441,13 @@ const GridEdit = props => {
1412
1441
  }
1413
1442
  rowValues.forEach((cellValue, colIndex) => {
1414
1443
  const targetCol = startCol + colIndex;
1415
- if (targetCol >= columns.length) {
1444
+ if (targetCol >= visibleCols.length) {
1416
1445
  // Không vượt quá số cột
1417
1446
  return;
1418
1447
  }
1419
- if (columns[targetCol].editEnable) {
1448
+ if (visibleCols[targetCol].editEnable) {
1420
1449
  // @ts-ignore
1421
- const columnKey = columns[targetCol].field;
1450
+ const columnKey = visibleCols[targetCol].field;
1422
1451
 
1423
1452
  // @ts-ignore
1424
1453
  newData[targetRow] = {
@@ -1461,13 +1490,13 @@ const GridEdit = props => {
1461
1490
  }
1462
1491
  rowValues.forEach((cellValue, colIndex) => {
1463
1492
  const targetCol = startCol + colIndex;
1464
- if (targetCol >= columns.length) {
1493
+ if (targetCol >= visibleCols.length) {
1465
1494
  // Không vượt quá số cột
1466
1495
  return;
1467
1496
  }
1468
- if (columns[targetCol].editEnable) {
1497
+ if (visibleCols[targetCol].editEnable) {
1469
1498
  // @ts-ignore
1470
- const columnKey = columns[targetCol].field;
1499
+ const columnKey = visibleCols[targetCol].field;
1471
1500
 
1472
1501
  // @ts-ignore
1473
1502
  childData[targetRow] = {
@@ -1726,6 +1755,7 @@ const GridEdit = props => {
1726
1755
  }
1727
1756
  };
1728
1757
  const handleEdit = (record, col, editType, e) => {
1758
+ setTooltipContent('');
1729
1759
  // @ts-ignore
1730
1760
  setEditingKey(record[rowKey]);
1731
1761
  setCellEditing({
@@ -1783,7 +1813,7 @@ const GridEdit = props => {
1783
1813
  // }, []);
1784
1814
 
1785
1815
  const scrollToCell = (rowIndex, colIndex, cell, scrollType) => {
1786
- const fixedWidth = totalFixedWidth(columns, 'left', selectionSettings);
1816
+ const fixedWidth = totalFixedWidth(visibleCols, 'left', selectionSettings);
1787
1817
  if (scrollType === 'horizontal') {
1788
1818
  if (tableRef.current) {
1789
1819
  tableRef.current.scrollTo({
@@ -1876,10 +1906,10 @@ const GridEdit = props => {
1876
1906
  }
1877
1907
  };
1878
1908
  const convertColumns = flatColumns2(columns.filter(it => it.visible !== false)).map((column, colIndex) => {
1879
- if (!column?.field && !column?.key) {
1880
- return column;
1909
+ if (column === SELECTION_COLUMN) {
1910
+ return SELECTION_COLUMN;
1881
1911
  }
1882
- if (column.dataIndex === '#' || column.dataIndex === '#') {
1912
+ if (column.field === '#') {
1883
1913
  return {
1884
1914
  ...column,
1885
1915
  className: 'rc-ui-cell-editable rc-ui-cell-index',
@@ -1904,7 +1934,7 @@ const GridEdit = props => {
1904
1934
  setEditingKey('');
1905
1935
  }
1906
1936
  },
1907
- tabIndex: (rowIndex ?? 0) * columns.length + colIndex
1937
+ tabIndex: (rowIndex ?? 0) * visibleCols.length + colIndex
1908
1938
  };
1909
1939
  },
1910
1940
  render: (value, record) => {
@@ -1920,7 +1950,7 @@ const GridEdit = props => {
1920
1950
  }
1921
1951
  };
1922
1952
  }
1923
- if ((column.key || column.field) === 'command') {
1953
+ if (column.field === 'command') {
1924
1954
  return {
1925
1955
  ...column
1926
1956
  };
@@ -1971,14 +2001,16 @@ const GridEdit = props => {
1971
2001
  }
1972
2002
  }
1973
2003
  if (event.key === 'Tab') {
1974
- if (colIndex + 1 !== columns.length) {
1975
- handleFocusCell(rowNumber, colIndex + 1, column, 'horizontal', event);
1976
- } else {
1977
- event.stopPropagation();
1978
- event.preventDefault();
2004
+ if (editingKey) {} else {
2005
+ if (colIndex + 1 !== visibleCols.length) {
2006
+ handleFocusCell(rowNumber, colIndex + 1, column, 'horizontal', event);
2007
+ } else {
2008
+ event.stopPropagation();
2009
+ event.preventDefault();
2010
+ }
1979
2011
  }
1980
2012
  }
1981
- if (event.key === 'ArrowRight' && colIndex + 1 !== columns.length) {
2013
+ if (event.key === 'ArrowRight' && colIndex + 1 !== visibleCols.length) {
1982
2014
  if (editingKey !== '') {} else {
1983
2015
  handleFocusCell(rowNumber, colIndex + 1, column, 'horizontal', event);
1984
2016
  }
@@ -2051,16 +2083,16 @@ const GridEdit = props => {
2051
2083
  rowsSelected.current = new Set();
2052
2084
  }
2053
2085
  },
2054
- // onMouseEnter: () => {
2055
- //
2056
- // },
2057
-
2058
2086
  onClick: () => {
2059
2087
  if (record[rowKey] !== editingKey && editingKey !== '') {
2060
2088
  setEditingKey('');
2089
+ } else {
2090
+ if (editingKey) {
2091
+ handleCellClick(rowNumber, record, column);
2092
+ }
2061
2093
  }
2062
2094
  },
2063
- className: isEditing(record) ? 'rc-ui-cell-editable cell-editing' : `rc-ui-cell-editable cell-editable ${!isEditable(column, record) ? 'disable' : ''}`,
2095
+ className: isEditing(record) ? `rc-ui-cell-editable cell-editing ${!isEditable(column, record) ? 'disable' : ''}` : `rc-ui-cell-editable cell-editable ${!isEditable(column, record) ? 'disable' : ''}`,
2064
2096
  record,
2065
2097
  column: column,
2066
2098
  editType: getEditType(column, record),
@@ -2077,7 +2109,7 @@ const GridEdit = props => {
2077
2109
  editing: isEditing(record) && rowEditable?.(record) !== false && isEditable(column, record),
2078
2110
  cellEditing,
2079
2111
  t,
2080
- tabIndex: (rowIndex ?? 0) * columns.length + colIndex,
2112
+ tabIndex: (rowIndex ?? 0) * visibleCols.length + colIndex,
2081
2113
  style: isPasteDragging ? {
2082
2114
  cursor: "crosshair"
2083
2115
  } : {}
@@ -2108,12 +2140,25 @@ const GridEdit = props => {
2108
2140
  },
2109
2141
  render: (value, record, rowIndex) => {
2110
2142
  const rowNumber = getRowNumber(dataSource, record[rowKey], rowKey);
2143
+ const colFormat = typeof column.format === 'function' ? column.format(record) : column.format;
2144
+ const cellFormat = getFormat(colFormat, format);
2145
+ const rowError = dataErrors.find(it => it.index === rowNumber);
2146
+ const cellError = rowError && column.field && rowError[column.field]?.field === column.field ? rowError[column.field] : null;
2147
+
2148
+ // const aaa = dataErrors.find((it) => column?.field && it[column.field].field === column.field && it.index === rowNumber)
2149
+ // const aaa = column.field && rowError && rowError[column.field]?.field === column?.field
2150
+
2111
2151
  return /*#__PURE__*/React.createElement("div", {
2112
2152
  className: classNames('ui-rc_cell-content', {
2113
2153
  // disable: !isEditable(column as any, record)
2154
+ isValid: column.field && rowError && rowError[column.field]?.field === column?.field
2114
2155
  }),
2115
2156
  onMouseDown: event => handleMouseDown(record, rowNumber, colIndex, event),
2116
- onMouseEnter: event => handleMouseEnter(rowNumber, colIndex, event),
2157
+ onMouseEnter: event => {
2158
+ // setTooltipContent(cellError ? cellError.message : renderContent(column as any, value, record, rowIndex, cellFormat))
2159
+ setTooltipContent(cellError ? cellError.message : '');
2160
+ handleMouseEnter(rowNumber, colIndex, event);
2161
+ },
2117
2162
  onMouseUp: handleMouseUp,
2118
2163
  onMouseMove: () => {
2119
2164
  if (selectedCells && selectedCells.current.size > 0 && isMouseDown.current) {
@@ -2129,7 +2174,7 @@ const GridEdit = props => {
2129
2174
  // }}
2130
2175
  }, /*#__PURE__*/React.createElement("div", {
2131
2176
  className: 'ui-rc_content'
2132
- }, renderContent(column, value, record, rowIndex, column.format ? typeof column.format === 'function' ? column.format(record) : column.format : format)),
2177
+ }, renderContent(column, value, record, rowIndex, cellFormat)),
2133
2178
  // selectedCells.current && selectedCells.current.size > 0 && getLastSelectCell(selectedCells.current).row === rowNumber &&
2134
2179
  // getLastSelectCell(selectedCells.current).col === colIndex &&
2135
2180
  // isEditable(column as any, record) &&
@@ -2153,9 +2198,9 @@ const GridEdit = props => {
2153
2198
  const transformColumns = React.useCallback(cols => {
2154
2199
  // @ts-ignore
2155
2200
  return cols.map(column => {
2156
- const find = convertColumns.find(it => it.key === column.key);
2157
- if (!column?.field && !column?.key) {
2158
- return column;
2201
+ const find = convertColumns.find(it => it?.field === column.field);
2202
+ if (column === SELECTION_COLUMN) {
2203
+ return SELECTION_COLUMN;
2159
2204
  }
2160
2205
  if (find) {
2161
2206
  return {
@@ -2222,6 +2267,10 @@ const GridEdit = props => {
2222
2267
  }
2223
2268
  return;
2224
2269
  }
2270
+ if (args.item.key === 'INSERT_CHILDREN') {
2271
+ handleInsertChild(args.item);
2272
+ return;
2273
+ }
2225
2274
  if (args.item.key === 'DELETE_ROWS') {
2226
2275
  handleDeleteRows(args.item);
2227
2276
  return;
@@ -2264,6 +2313,7 @@ const GridEdit = props => {
2264
2313
  format,
2265
2314
  control,
2266
2315
  trigger,
2316
+ errors,
2267
2317
  getValues,
2268
2318
  handleCellChange,
2269
2319
  getRowKey
@@ -2320,7 +2370,7 @@ const GridEdit = props => {
2320
2370
  },
2321
2371
  rowHoverable: false,
2322
2372
  bottomToolbar: bottomToolbar,
2323
- expandable: {
2373
+ expandable: expandable ? {
2324
2374
  expandIconColumnIndex: checkChild(dataSource) ? 3 : undefined,
2325
2375
  ...expandable,
2326
2376
  expandedRowKeys: innerExpandedKeys,
@@ -2355,7 +2405,7 @@ const GridEdit = props => {
2355
2405
  });
2356
2406
  }
2357
2407
  }
2358
- },
2408
+ } : undefined,
2359
2409
  triggerChangeColumns: triggerChangeColumns,
2360
2410
  clickHeaderToSort: false,
2361
2411
  isFilter: isFilter,