es-grid-template 1.9.72 → 1.9.74

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 (39) hide show
  1. package/es/ali-table/Grid.js +0 -1
  2. package/es/ali-table/InternalTable.js +169 -29
  3. package/es/ali-table/base-table/html-table.js +1 -1
  4. package/es/ali-table/base-table/styles.d.ts +1 -0
  5. package/es/ali-table/base-table/styles.js +2 -1
  6. package/es/ali-table/pipeline/features/columnCustom.d.ts +1 -0
  7. package/es/ali-table/pipeline/features/columnCustom.js +143 -10
  8. package/es/ali-table/utils/utility.d.ts +11 -0
  9. package/es/ali-table/utils/utility.js +52 -0
  10. package/es/grid-component/hooks/constant.js +4 -0
  11. package/es/group-component/hook/useColumns.js +2 -2
  12. package/es/group-component/hook/utils.js +3 -0
  13. package/es/table-component/ColumnsConfig.js +6 -4
  14. package/es/table-component/TableContainer.js +1 -0
  15. package/es/table-component/TableContainerEdit.js +1 -0
  16. package/es/table-component/hook/utils.js +3 -0
  17. package/es/table-component/table/Grid.js +2 -2
  18. package/es/table-component/table/TableWrapper.js +97 -33
  19. package/es/table-virtuoso/hook/utils.js +3 -0
  20. package/lib/ali-table/Grid.js +0 -1
  21. package/lib/ali-table/InternalTable.js +167 -27
  22. package/lib/ali-table/base-table/html-table.js +1 -1
  23. package/lib/ali-table/base-table/styles.d.ts +1 -0
  24. package/lib/ali-table/base-table/styles.js +2 -1
  25. package/lib/ali-table/pipeline/features/columnCustom.d.ts +1 -0
  26. package/lib/ali-table/pipeline/features/columnCustom.js +144 -12
  27. package/lib/ali-table/utils/utility.d.ts +11 -0
  28. package/lib/ali-table/utils/utility.js +58 -3
  29. package/lib/grid-component/hooks/constant.js +4 -0
  30. package/lib/group-component/hook/useColumns.js +2 -2
  31. package/lib/group-component/hook/utils.js +3 -0
  32. package/lib/table-component/ColumnsConfig.js +6 -4
  33. package/lib/table-component/TableContainer.js +1 -0
  34. package/lib/table-component/TableContainerEdit.js +1 -0
  35. package/lib/table-component/hook/utils.js +3 -0
  36. package/lib/table-component/table/Grid.js +2 -2
  37. package/lib/table-component/table/TableWrapper.js +97 -33
  38. package/lib/table-virtuoso/hook/utils.js +3 -0
  39. package/package.json +2 -2
@@ -9,12 +9,13 @@ import { booleanOperator, findItemPath, isEditable, isObjEmpty, nonActionColumn,
9
9
  import classNames from 'classnames';
10
10
  import { Dropdown, Select, Space, Button } from 'rc-master-ui';
11
11
  import { addRowsDown, addRowsDownWithCtrl, addRowsUp, addRowsUpWithCtrl, convertFilters, extendsObject,
12
+ // findFirst,
12
13
  // flattenArray,
13
14
  flattenData, getColIdsBetween1, getDefaultOperator, getDragRightData, getEditType, getKeys, getNextColumn, getNextColumn1, getPrevColumn, getRowIdsBetween3,
14
15
  // getRowIndexMap,
15
16
  getSelectedCellMatrix1, getTypeFilter,
16
17
  // isObjEqual,
17
- newGuid } from "../../../table-component/hook/utils";
18
+ newGuid, unFlattenData, updateOrInsert } from "../../../table-component/hook/utils";
18
19
  import { renderFilter } from "../../base-table/renderFilter";
19
20
  import { renderValueCell } from "../../../table-component/hook/useColumns";
20
21
  import EditCell from "../../base-table/cell/EditCell";
@@ -23,7 +24,7 @@ import { stateKeyResize, stateKeyColumnFilter, stateKeyFilter, stateKeyPaginatio
23
24
  // state For edit
24
25
  stateKeyEndCell, stateKeyEndPasteCell, stateKeyStartCell, stateKeyStartPasteCell, stateKeyFocusedCell, stateKeyEditCellSettings, stateKeyIsEditing, stateKeyIsPasting, stateKeyIsSelecting } from "../../utils/constants";
25
26
  import { getColumnsAtLevel } from "../../base-table/utils";
26
- import { unFlattenData, updateOrInsert } from "../../utils/utility";
27
+ // import { unFlattenData } from '../../utils/utility';
27
28
  // import { getMaxDepth } from '../../utils/utility';
28
29
 
29
30
  function clamp(min, x, max) {
@@ -50,6 +51,7 @@ export function columnCustom(opts) {
50
51
  wrapSettings,
51
52
  // ignoreAccents,
52
53
  dataSource,
54
+ dataFlatten,
53
55
  isDataTree,
54
56
  defaultSorter,
55
57
  defaultFilter,
@@ -440,7 +442,7 @@ export function columnCustom(opts) {
440
442
  }
441
443
 
442
444
  // Cập nhật data mới
443
- const newData = allRows;
445
+ const newData = dataFlatten;
444
446
  const pastedRows = [];
445
447
  if (pasteState.type === 'down' || pasteState.type === 'up') {
446
448
  newRange.addedRows.forEach((rowValues, rowIndex1) => {
@@ -508,7 +510,7 @@ export function columnCustom(opts) {
508
510
  }
509
511
 
510
512
  // const rsFilterData = updateOrInsert(dataSource, newData)
511
- const rsFilterData = updateOrInsert(allRows, newData);
513
+ const rsFilterData = updateOrInsert(dataFlatten, newData);
512
514
  const rs = unFlattenData(rsFilterData);
513
515
  triggerPaste?.(pastedRows, colPasteds, rs, copyRows);
514
516
  pipeline.setStateAtKey(stateKeyEndCell, endPasteCell);
@@ -535,7 +537,7 @@ export function columnCustom(opts) {
535
537
  const newRange = ctrlKey ? addRowsDownWithCtrl(dataSelected, rowsPasteId.length) : addRowsDown(dataSelected, rowsPasteId.length);
536
538
 
537
539
  // Cập nhật data mới
538
- const newData = allRows;
540
+ const newData = dataFlatten;
539
541
  const pastedRows = [];
540
542
  newRange.addedRows.forEach((rowValues, rowIndex1) => {
541
543
  const targetRow = pasteState?.startRowIndex + rowIndex1;
@@ -557,7 +559,7 @@ export function columnCustom(opts) {
557
559
  });
558
560
 
559
561
  // const rsFilterData = updateOrInsert(dataSource, newData)
560
- const rsFilterData = updateOrInsert(dataSource, newData);
562
+ const rsFilterData = updateOrInsert(dataFlatten, newData);
561
563
  const rs = unFlattenData(rsFilterData);
562
564
  triggerPaste?.(pastedRows, colsPastedId, rs, copyRows);
563
565
  };
@@ -1061,6 +1063,73 @@ export function columnCustom(opts) {
1061
1063
  pipeline.setStateAtKey(stateKeyEndCell, cellEnd);
1062
1064
  triggerPointPaste(selectPasteState, cellStart, cellEnd, e.ctrlKey);
1063
1065
  };
1066
+
1067
+ // cell Số thứ tự
1068
+
1069
+ const handleMouseDownIndex = rowId => {
1070
+ // setIsSelecting?.(true);
1071
+ pipeline.setStateAtKey(stateKeyIsSelecting, true);
1072
+ const allColumns = allCols.filter(it => !nonActionColumn.includes(it.field));
1073
+
1074
+ // const firstCOlSpin = findFirst(allColumns)
1075
+
1076
+ const startCol = allColumns[0].field;
1077
+ const endCol = allColumns[allColumns.length - 1].field;
1078
+
1079
+ // setStartCell?.({ rowId, colId: startCol });
1080
+ // setEndCell?.({ rowId, colId: endCol });
1081
+
1082
+ pipeline.setStateAtKey(stateKeyStartCell, {
1083
+ rowId,
1084
+ colId: startCol
1085
+ });
1086
+ pipeline.setStateAtKey(stateKeyEndCell, {
1087
+ rowId,
1088
+ colId: endCol
1089
+ });
1090
+
1091
+ // if (firstCOlSpin) {
1092
+ // setFocusedCell?.({ rowId: cell.row.id, colId: firstCOlSpin.id })
1093
+ // } else {
1094
+ // const firstCOlVisible = allColumns[0]
1095
+ // setFocusedCell?.({ rowId: cell.row.id, colId: firstCOlVisible.id })
1096
+ // }
1097
+ pipeline.setStateAtKey(stateKeyFocusedCell, {
1098
+ rowId,
1099
+ colId: startCol
1100
+ });
1101
+
1102
+ // setRangeState?.(getSelectedCellMatrix(table, { rowId, colId: startCol }, { rowId, colId: endCol }))
1103
+ };
1104
+ const handleMouseEnterIndex = rowId => {
1105
+ if (isSelecting) {
1106
+ const allColumns = allCols.filter(it => !nonActionColumn.includes(it.field));
1107
+
1108
+ // const firstCOl = findFirst(allColumns)
1109
+
1110
+ // const startCol = allColumns[0].id
1111
+ const endCol = allColumns[allColumns.length - 1].field;
1112
+
1113
+ // // setStartCell?.({ rowId, colId: startCol });
1114
+ // setEndCell?.({ rowId, colId: endCol });
1115
+ pipeline.setStateAtKey(stateKeyEndCell, {
1116
+ rowId,
1117
+ colId: endCol
1118
+ });
1119
+ }
1120
+ };
1121
+ const handleMouseUpIndex = () => {
1122
+ // setIsSelecting?.(false);
1123
+
1124
+ pipeline.setStateAtKey(stateKeyIsSelecting, false);
1125
+
1126
+ // const selectState = getSelectedCellMatrix(table, startCell, endCell)
1127
+
1128
+ // if (!isObjEqual(rangeState, selectState)) {
1129
+
1130
+ // setRangeState?.(selectState)
1131
+ // }
1132
+ };
1064
1133
  pipeline.mapColumns(makeRecursiveMapper((col, params) => {
1065
1134
  const {
1066
1135
  startIndex,
@@ -1213,6 +1282,7 @@ export function columnCustom(opts) {
1213
1282
  // cell Index
1214
1283
  if (col.field === '#') {
1215
1284
  const prevContent = col.template;
1285
+ const prevGetCellProps = col?.getCellProps;
1216
1286
  return {
1217
1287
  ...col,
1218
1288
  lock: !!col.fixed,
@@ -1247,7 +1317,73 @@ export function columnCustom(opts) {
1247
1317
  overflow: 'visible',
1248
1318
  position: 'relative'
1249
1319
  }
1250
- })
1320
+ }),
1321
+ getCellProps(value, record, rowIndex) {
1322
+ const prevCellProps = prevGetCellProps?.(value, record, rowIndex);
1323
+
1324
+ // const isCellSelected = (!startCell || !endCell) ? false : selectRowIds.includes(record.rowId) && cols.includes(col.field);
1325
+
1326
+ return mergeCellProps(prevCellProps, {
1327
+ // @ts-ignore
1328
+ 'data-col-key': col.field,
1329
+ ref: el => {
1330
+ if (focusedCell?.rowId === record.rowId && focusedCell?.colId === col.field && !isEditing.editing) {
1331
+ el?.focus({
1332
+ preventScroll: true
1333
+ });
1334
+ }
1335
+ },
1336
+ style: {
1337
+ ...prevCellProps?.style,
1338
+ userSelect: 'none'
1339
+ // padding: cellEditing ? 0 : undefined
1340
+ // ...cellStyles,
1341
+ },
1342
+ className: classNames(prevCellProps?.className, `${prefix}-grid-cell`, {
1343
+ [`${prefix}-grid-cell-ellipsis`]: !wrapSettings || !(wrapSettings && (wrapSettings.wrapMode === 'Both' || wrapSettings.wrapMode === 'Content')),
1344
+ [`${prefix}-grid-cell-wrap`]: wrapSettings && (wrapSettings.wrapMode === 'Both' || wrapSettings.wrapMode === 'Content'),
1345
+ [`${prefix}-grid-cell-text-center`]: col?.textAlign === 'center',
1346
+ [`${prefix}-grid-cell-text-right`]: col?.textAlign === 'right' || col.type === 'number',
1347
+ [`${prefix}-grid-cell-index-selected`]: selectRowIds?.includes(record.rowId),
1348
+ 'no-hover': editAble
1349
+
1350
+ // isValid: !isEditing && rowError && rowError[col.field]?.field === col.field,
1351
+ // [`${prefix}-grid-cell-selected`]: isCellSelected,
1352
+ }),
1353
+ onMouseDown: e => {
1354
+ prevCellProps?.onMouseDown?.(e);
1355
+ if (editAble) {
1356
+ // if (record[rowKey] === editingKey) {
1357
+ if (isEditing.editing) {
1358
+ // setFocusedCell?.({ rowId: cell.row.id, colId: cell.column.id })
1359
+ } else {
1360
+ handleMouseDownIndex(record.rowId);
1361
+ if (isEditing.editing) {
1362
+ setTimeout(() => {
1363
+ // setEditingKey?.('')
1364
+ pipeline.setStateAtKey(stateKeyIsEditing, defaultCellEditing);
1365
+ reset?.();
1366
+ });
1367
+ }
1368
+ }
1369
+ }
1370
+ },
1371
+ onMouseEnter: e => {
1372
+ prevCellProps?.onMouseEnter?.(e);
1373
+ // Edit
1374
+
1375
+ if (editAble) {
1376
+ handleMouseEnterIndex(record.rowId);
1377
+ }
1378
+ },
1379
+ onMouseUp: e => {
1380
+ prevCellProps?.onMouseUp?.(e);
1381
+ if (editAble) {
1382
+ handleMouseUpIndex();
1383
+ }
1384
+ }
1385
+ });
1386
+ }
1251
1387
  };
1252
1388
  }
1253
1389
 
@@ -1514,9 +1650,6 @@ export function columnCustom(opts) {
1514
1650
  }),
1515
1651
  getCellProps(value, record, rowIndex) {
1516
1652
  const prevCellProps = prevGetCellProps?.(value, record, rowIndex);
1517
-
1518
- // console.log('record', record)
1519
-
1520
1653
  const fomatedValue = ['color', 'checkbox', 'field'].includes(col.type ?? '') ? '' : renderValueCell(col, value, record, rowIndex, 0, format, false);
1521
1654
  const tooltipContent = isOpenTooltip === false ? '' : col?.tooltipDescription ? typeof col.tooltipDescription === 'function' ? col.tooltipDescription({
1522
1655
  value,
@@ -25,4 +25,15 @@ export declare function filterVisibleColumns<T extends ColumnTable>(columns: T[]
25
25
  export declare const sortByType: (arr: ColumnTable[], rowDnd?: RowDnd) => ColumnTable[];
26
26
  export declare function getVisibleColumnFields<T extends ColumnTable>(columns: T[]): string[];
27
27
  export declare const getOnlyInA: (a: string[], b: string[]) => string[];
28
+ export declare const buildParentMap: <T extends {
29
+ id: string;
30
+ rowId: string;
31
+ children?: T[];
32
+ }>(tree: T[]) => Map<string, T>;
33
+ export declare const flattenTree: <T extends {
34
+ children?: T[];
35
+ }>(tree: T[]) => T[];
36
+ export declare const flattenTree2: <T extends {
37
+ children?: T[];
38
+ }>(tree: T[]) => Omit<T, 'children'>[];
28
39
  export {};
@@ -94,6 +94,9 @@ export const shouldIncludeOptimized = (item, queries, ignoreAccents = true) => {
94
94
  case 'contains':
95
95
  condition = ignoreAccents === false ? itemValue?.includes(value) : itemStr.includes(compareValue);
96
96
  break;
97
+ case 'notcontains':
98
+ condition = ignoreAccents === false ? !itemValue?.includes(value) : !itemStr.includes(compareValue);
99
+ break;
97
100
  case 'startswith':
98
101
  condition = ignoreAccents === false ? itemValue?.startsWith(value) : itemStr.startsWith(compareValue);
99
102
  break;
@@ -696,4 +699,53 @@ export function getVisibleColumnFields(columns) {
696
699
  export const getOnlyInA = (a, b) => {
697
700
  const setB = new Set(b);
698
701
  return a.filter(item => !setB.has(item));
702
+ };
703
+ export const buildParentMap = tree => {
704
+ const parentMap = new Map();
705
+ const stack = [...tree];
706
+ while (stack.length) {
707
+ const node = stack.pop();
708
+ const children = node.children;
709
+ if (!children?.length) continue;
710
+ for (let i = 0; i < children.length; i++) {
711
+ const child = children[i];
712
+ parentMap.set(child.rowId, node);
713
+ stack.push(child);
714
+ }
715
+ }
716
+ return parentMap;
717
+ };
718
+ export const flattenTree = tree => {
719
+ const result = [];
720
+ const stack = [...tree];
721
+ while (stack.length) {
722
+ const node = stack.pop();
723
+ result.push(node);
724
+ const children = node.children;
725
+ if (children?.length) {
726
+ // Push ngược để giữ nguyên thứ tự tree
727
+ for (let i = children.length - 1; i >= 0; i--) {
728
+ stack.push(children[i]);
729
+ }
730
+ }
731
+ }
732
+ return result;
733
+ };
734
+ export const flattenTree2 = tree => {
735
+ const result = [];
736
+ const stack = [...tree];
737
+ while (stack.length) {
738
+ const node = stack.pop();
739
+ const {
740
+ children,
741
+ ...item
742
+ } = node;
743
+ result.push(item);
744
+ if (children?.length) {
745
+ for (let i = children.length - 1; i >= 0; i--) {
746
+ stack.push(children[i]);
747
+ }
748
+ }
749
+ }
750
+ return result;
699
751
  };
@@ -37,6 +37,10 @@ export const stringOperator = [{
37
37
  value: 'contains',
38
38
  key: '~=',
39
39
  label: 'Contains'
40
+ }, {
41
+ value: 'notcontains',
42
+ key: '!~=',
43
+ label: 'Does not contain'
40
44
  }, {
41
45
  value: 'equal',
42
46
  key: '==',
@@ -204,12 +204,12 @@ export const toggleRowSelection = props => {
204
204
  } else {
205
205
  // chưa selected
206
206
 
207
- const checkedRows = [...prevSelected, row];
207
+ const checkedRows = [...prevSelected, row.original];
208
208
  setIsSelectionChange({
209
209
  isChange: true,
210
210
  type: 'rowSelected',
211
211
  rowData: row.original,
212
- rowsData: selectionSettings?.type === 'single' ? [row] : checkedRows
212
+ rowsData: selectionSettings?.type === 'single' ? [row.original] : checkedRows
213
213
  });
214
214
  }
215
215
  return;
@@ -801,6 +801,9 @@ export const shouldInclude = (item, queries) => {
801
801
  case "contains":
802
802
  condition = itemStr?.includes(queryStr);
803
803
  break;
804
+ case "notcontains":
805
+ condition = !itemStr?.includes(queryStr);
806
+ break;
804
807
  case "startswith":
805
808
  condition = itemStr?.startsWith(queryStr);
806
809
  break;
@@ -60,6 +60,7 @@ export const ColumnsConfig = props => {
60
60
  };
61
61
  const handleAccept = () => {
62
62
  triggerChangeColumns?.(tmpColumn, [], 'columnChoose');
63
+ setCurrentRow('');
63
64
  onClose();
64
65
  };
65
66
  const handleChange = newElemt => {
@@ -109,10 +110,11 @@ export const ColumnsConfig = props => {
109
110
  return /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Input, {
110
111
  defaultValue: value,
111
112
  allowClear: true,
113
+ autoFocus: true,
112
114
  onBlur: e => {
113
115
  const newData = {
114
116
  ...rowData,
115
- visible: e.target.value
117
+ headerText: e.target.value
116
118
  };
117
119
  handleChange(newData);
118
120
  }
@@ -209,7 +211,7 @@ export const ColumnsConfig = props => {
209
211
  } = args;
210
212
  if (currentRow === rowData.field) {
211
213
  return /*#__PURE__*/React.createElement(InputNumber, {
212
- defaultValue: value,
214
+ defaultValue: value ?? 150,
213
215
  style: {
214
216
  width: '100%'
215
217
  },
@@ -217,13 +219,13 @@ export const ColumnsConfig = props => {
217
219
  onBlur: e => {
218
220
  const newData = {
219
221
  ...rowData,
220
- visible: e.target.value
222
+ width: e.target.value ? Number(e.target.value) : 150
221
223
  };
222
224
  handleChange(newData);
223
225
  }
224
226
  });
225
227
  }
226
- return /*#__PURE__*/React.createElement("span", null, value);
228
+ return /*#__PURE__*/React.createElement("span", null, value ?? 150, "px");
227
229
  }
228
230
  }];
229
231
  const handleReset = () => {
@@ -359,6 +359,7 @@ const TableContainer = props => {
359
359
  summary: summary,
360
360
  dataSource: dataSource,
361
361
  infiniteScroll: infiniteScroll,
362
+ pagination: pagination,
362
363
  next: next,
363
364
  loading: loading,
364
365
  columnVirtualizer: columnVirtualizer,
@@ -2274,6 +2274,7 @@ const TableContainerEdit = props => {
2274
2274
  summary: summary,
2275
2275
  dataSource: dataSource,
2276
2276
  infiniteScroll: infiniteScroll,
2277
+ pagination: pagination,
2277
2278
  next: next,
2278
2279
  loading: loading,
2279
2280
  columnVirtualizer: columnVirtualizer,
@@ -1069,6 +1069,9 @@ export const shouldInclude = (item, queries, ignoreAccents) => {
1069
1069
  case "contains":
1070
1070
  condition = ignoreAccents === false ? itemValue?.includes(value) : itemStr?.includes(queryStr);
1071
1071
  break;
1072
+ case "notcontains":
1073
+ condition = ignoreAccents === false ? !itemValue?.includes(value) : !itemStr?.includes(queryStr);
1074
+ break;
1072
1075
  case "startswith":
1073
1076
  condition = ignoreAccents === false ? itemValue?.startsWith(value) : itemStr?.startsWith(queryStr);
1074
1077
  break;
@@ -64,8 +64,8 @@ const Grid = props => {
64
64
  const [columnResizeMode] = React.useState('onChange');
65
65
  const [columnResizeDirection] = React.useState('ltr');
66
66
  const [paginationState, setPagination] = React.useState({
67
- pageIndex: pagination && pagination.currentPage ? pagination.currentPage - 1 : 0,
68
- pageSize: pagination && pagination.pageSize ? pagination.pageSize : 20
67
+ pageIndex: pagination && pagination?.currentPage ? pagination.currentPage - 1 : 0,
68
+ pageSize: pagination && pagination?.pageSize ? pagination.pageSize : 20
69
69
  });
70
70
 
71
71
  // const [rowSelection, setRowSelection] = React.useState<RowSelectionState>({})
@@ -7,7 +7,6 @@ import { Tooltip } from "react-tooltip";
7
7
  import ContextMenu from "../ContextMenu";
8
8
  import React, { useContext } from "react";
9
9
  import { TableContext } from "../useContext";
10
- import { isNullOrUndefined } from "../hook/utils";
11
10
  const TableWrapper = props => {
12
11
  const {
13
12
  id,
@@ -40,6 +39,12 @@ const TableWrapper = props => {
40
39
  const menuRef = React.useRef(null);
41
40
  const loadingRef = React.useRef(false);
42
41
  const hasMoreRef = React.useRef(true);
42
+ const pendingPageRef = React.useRef(null);
43
+ const pendingDataLengthRef = React.useRef(0);
44
+ const sawLoadingRef = React.useRef(false);
45
+ const lastScrollTopRef = React.useRef(0);
46
+ // const directionRef = React.useRef<'up' | 'down' | null>(null);
47
+
43
48
  const {
44
49
  windowSize
45
50
  } = useContext(TableContext);
@@ -48,6 +53,23 @@ const TableWrapper = props => {
48
53
  pageSize,
49
54
  total
50
55
  } = pagination ?? {};
56
+ React.useEffect(() => {
57
+ if (pendingPageRef.current === null) {
58
+ return;
59
+ }
60
+ if (loading) {
61
+ sawLoadingRef.current = true;
62
+ return;
63
+ }
64
+ const pageLoaded = currentPage >= pendingPageRef.current;
65
+ const dataLoaded = dataSource.length !== pendingDataLengthRef.current;
66
+ const requestFinished = sawLoadingRef.current;
67
+ if (pageLoaded || dataLoaded || requestFinished) {
68
+ loadingRef.current = false;
69
+ pendingPageRef.current = null;
70
+ sawLoadingRef.current = false;
71
+ }
72
+ }, [currentPage, dataSource.length, loading]);
51
73
  const [menuVisible, setMenuVisible] = React.useState(false);
52
74
  const [selectedRowData, setSelectedRowData] = React.useState(undefined);
53
75
  const [position, setPosition] = React.useState({
@@ -74,46 +96,88 @@ const TableWrapper = props => {
74
96
  const loadData = page => {
75
97
  if (!hasMoreRef.current || loadingRef.current || loading) return;
76
98
  loadingRef.current = true;
77
- setTimeout(() => {
78
- next?.();
79
- if (page * pageSize >= total) {
80
- hasMoreRef.current = false;
81
- }
82
- loadingRef.current = false;
83
- }, 10);
99
+ pendingPageRef.current = page;
100
+ pendingDataLengthRef.current = dataSource.length;
101
+ next?.();
102
+ if (pageSize && total && page * pageSize >= total) {
103
+ hasMoreRef.current = false;
104
+ }
84
105
  };
85
106
  const handleNext = () => {
86
107
  loadData(currentPage + 1);
87
108
  };
88
109
  const handleScroll = e => {
89
- if (infiniteScroll) {
90
- if (loadingRef.current || loading || dataSource?.length === 0) {
91
- e.stopPropagation();
92
- e.preventDefault();
93
- return;
94
- }
95
- const {
96
- scrollHeight: tbScrollHeight,
97
- scrollTop,
98
- clientHeight
99
- } = e.currentTarget;
100
- const abc = clientHeight * (isNullOrUndefined(onEndReachedThreshold) ? 0.1 : onEndReachedThreshold ?? 0);
110
+ // if (infiniteScroll) {
111
+ // const current = e.currentTarget.scrollTop;
112
+ // const last = lastScrollTopRef.current;
101
113
 
102
- // const isEnd = scrollTop + clientHeight >= tbScrollHeight - 50;
103
- const isEnd = scrollTop + clientHeight >= tbScrollHeight - abc;
104
- if (isEnd && !loadingRef.current && hasMoreRef.current && dataSource?.length > 0) {
105
- handleNext();
106
- }
114
+ // if (loadingRef.current || loading || dataSource?.length === 0 || current === last) {
115
+
116
+ // e.stopPropagation()
117
+ // e.preventDefault()
118
+ // return
119
+ // }
120
+
121
+ // const { scrollHeight: tbScrollHeight, scrollTop, clientHeight } = e.currentTarget;
122
+
123
+ // const abc = clientHeight * (isNullOrUndefined(onEndReachedThreshold) ? 0.1 : onEndReachedThreshold ?? 0)
124
+
125
+ // // const isEnd = scrollTop + clientHeight >= tbScrollHeight - 50;
126
+ // const isEnd = scrollTop + clientHeight >= tbScrollHeight - abc;
127
+
128
+ // if (isEnd && !loadingRef.current && hasMoreRef.current && dataSource?.length > 0) {
129
+
130
+ // handleNext()
131
+
132
+ // }
133
+ // }
134
+
135
+ // if (e.target.scrollLeft >= 0 && e.target.scrollLeft + e.target.clientWidth < e.target.scrollWidth) {
136
+ // e.target.classList.add('ui-rc-table-ping-right')
137
+ // } else {
138
+ // e.target.classList.remove('ui-rc-table-ping-right')
139
+ // }
140
+
141
+ // if ((e.target.scrollLeft ?? 0) > 0) {
142
+ // e.target.classList.add('ui-rc-table-ping-left')
143
+ // } else {
144
+ // e.target.classList.remove('ui-rc-table-ping-left')
145
+ // }
146
+
147
+ const target = e.currentTarget;
148
+
149
+ // Horizontal scroll
150
+ const {
151
+ scrollLeft,
152
+ clientWidth,
153
+ scrollWidth,
154
+ clientHeight
155
+ } = target;
156
+ target.classList.toggle('ui-rc-table-ping-left', scrollLeft > 0);
157
+ target.classList.toggle('ui-rc-table-ping-right', scrollLeft + clientWidth < scrollWidth);
158
+ if (!infiniteScroll) {
159
+ return;
160
+ }
161
+ const {
162
+ scrollTop,
163
+ scrollHeight
164
+ } = target;
165
+ const last = lastScrollTopRef.current;
166
+
167
+ // Update ngay
168
+ lastScrollTopRef.current = scrollTop;
169
+
170
+ // Chỉ xử lý khi scroll DOWN
171
+ if (scrollTop <= last) {
172
+ return;
107
173
  }
108
- if (e.target.scrollLeft >= 0 && e.target.scrollLeft + e.target.clientWidth < e.target.scrollWidth) {
109
- e.target.classList.add('ui-rc-table-ping-right');
110
- } else {
111
- e.target.classList.remove('ui-rc-table-ping-right');
174
+ if (loadingRef.current || loading || !dataSource?.length || !hasMoreRef.current) {
175
+ return;
112
176
  }
113
- if ((e.target.scrollLeft ?? 0) > 0) {
114
- e.target.classList.add('ui-rc-table-ping-left');
115
- } else {
116
- e.target.classList.remove('ui-rc-table-ping-left');
177
+ const thresholdRatio = onEndReachedThreshold ?? 0.1;
178
+ const threshold = clientHeight * thresholdRatio;
179
+ if (scrollTop + clientHeight >= scrollHeight - threshold) {
180
+ handleNext();
117
181
  }
118
182
  };
119
183
  const onContextMenu = args => event => {
@@ -849,6 +849,9 @@ export const shouldInclude = (item, queries) => {
849
849
  case "contains":
850
850
  condition = itemStr?.includes(queryStr);
851
851
  break;
852
+ case "notcontains":
853
+ condition = !itemStr?.includes(queryStr);
854
+ break;
852
855
  case "startswith":
853
856
  condition = itemStr?.startsWith(queryStr);
854
857
  break;
@@ -179,7 +179,6 @@ const Grid = /*#__PURE__*/_react.default.forwardRef((props, ref) => {
179
179
 
180
180
  // setColumns(cols)
181
181
  } else {
182
- console.log('setColumns');
183
182
  setColumns(cols);
184
183
  // pipeline.columns(cols)
185
184