es-grid-template 1.9.79 → 1.9.83

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.
@@ -1,10 +1,11 @@
1
+ import { nonActionColumn } from "../../grid-component/hooks";
1
2
  export function convertColumnsToTreeData(columns, groupColumns, t) {
2
3
  if (!columns) {
3
4
  return [];
4
5
  }
5
6
  return columns.filter(col => {
6
7
  const inGroup = groupColumns ? groupColumns.includes(String(col.field)) : false;
7
- if (col.showInColumnChoose === false) return false;
8
+ if (col.showInColumnChoose === false || nonActionColumn.includes(col.field)) return false;
8
9
  if (inGroup && !('children' in col && Array.isArray(col.children))) {
9
10
  return false;
10
11
  }
@@ -76,6 +76,8 @@ export type Locale = {
76
76
  export type PaginationConfig = Omit<TablePaginationConfig, 'locale' | 'current'> & {
77
77
  currentPage?: number;
78
78
  locale?: PagingLocale;
79
+ /** Chế độ phân trang. Mặc định là client để giữ tương thích với hành vi hiện tại. */
80
+ mode?: 'client' | 'server';
79
81
  };
80
82
  export type AnyObject = Record<PropertyKey, any>;
81
83
  export type IFormat = {
@@ -2023,7 +2023,25 @@ const TableContainerEdit = props => {
2023
2023
  }
2024
2024
  contextMenuClick?.(args);
2025
2025
  };
2026
+
2027
+ // Chống fire onCellClick trùng lặp: double-click = 2 lần mousedown nên callback sẽ bị gọi 2 lần.
2028
+ // Chỉ bỏ qua khi click LIÊN TIẾP cùng 1 cell trong khoảng thời gian rất ngắn.
2029
+ const lastCellClickRef = React.useRef({
2030
+ key: '',
2031
+ time: 0
2032
+ });
2026
2033
  const handleCellClick = (rowNumber, record, column, rowId, cellValue) => {
2034
+ const clickKey = `${rowId}::${column.field ?? ''}`;
2035
+ const now = Date.now();
2036
+
2037
+ // cùng cell && trong vòng 300ms => coi là double-click, bỏ qua lần lặp
2038
+ if (lastCellClickRef.current.key === clickKey && now - lastCellClickRef.current.time < 300) {
2039
+ return;
2040
+ }
2041
+ lastCellClickRef.current = {
2042
+ key: clickKey,
2043
+ time: now
2044
+ };
2027
2045
  const cellClickCallback = newOptions => {
2028
2046
  if (newOptions) {
2029
2047
  const newElem = {
@@ -1260,6 +1260,11 @@ const TableBodyCellEdit = props => {
1260
1260
  }
1261
1261
  } else {
1262
1262
  handleMouseDown(cell.row.id, cell.column.id);
1263
+
1264
+ // fire onCellClick ngay lần click đầu (trước đây chỉ fire khi cell đã ở trạng thái editing)
1265
+ if (canEdit) {
1266
+ handleCellClick?.(rowNumber, record, columnMeta, record[rowKey], record[columnMeta.field ?? '']);
1267
+ }
1263
1268
  if (editingKey) {
1264
1269
  setTimeout(() => {
1265
1270
  setEditingKey?.('');
@@ -196,10 +196,10 @@ export declare const fixColumnsLeft: <RecordType>(columns: ColumnTable<RecordTyp
196
196
  value: any;
197
197
  rowData: RecordType;
198
198
  }) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode);
199
- onCellStyles?: Omit<CSSProperties, "position" | "left" | "right" | "display" | "width" | "minWidth"> | ((cellValue: any, cell: import("@tanstack/react-table").Cell<RecordType, unknown>) => Omit<CSSProperties, "position" | "left" | "right" | "display" | "width" | "minWidth">);
200
- onCellHeaderStyles?: Omit<CSSProperties, "position" | "left" | "right" | "display" | "width" | "minWidth"> | ((cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "position" | "left" | "right" | "display" | "width" | "minWidth">);
199
+ onCellStyles?: Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width"> | ((cellValue: any, cell: import("@tanstack/react-table").Cell<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width">);
200
+ onCellHeaderStyles?: Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width"> | ((cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width">);
201
201
  onCell?: (rowData: RecordType, index: number) => import("react").TdHTMLAttributes<HTMLTableCellElement>;
202
- onCellFooterStyles?: Omit<CSSProperties, "position" | "left" | "right" | "display" | "width" | "minWidth"> | ((cellValue: any, cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "position" | "left" | "right" | "display" | "width" | "minWidth">);
202
+ onCellFooterStyles?: Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width"> | ((cellValue: any, cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width">);
203
203
  getValue?: (row: any, rowIndex: number) => any;
204
204
  getCellProps?: (value: any, row: any, rowIndex: number) => import("./../../grid-component/type").CellProps;
205
205
  headerCellProps?: import("./../../grid-component/type").CellProps;
@@ -1,3 +1,4 @@
1
+ import { nonActionColumn } from "./../../grid-component/hooks";
1
2
  import { v4 as uuidv4 } from 'uuid';
2
3
  import { presetPalettes } from "@ant-design/colors";
3
4
  import dayjs from "dayjs";
@@ -5,7 +6,6 @@ import moment from "moment";
5
6
  export const newGuid = () => {
6
7
  for (let i = 0; i < 20; i++) {
7
8
  // @ts-ignore
8
- // const id = crypto.randomUUID()
9
9
  return uuidv4();
10
10
  }
11
11
  };
@@ -1916,8 +1916,8 @@ export function convertColumnsToTreeData(columns, groupColumns) {
1916
1916
 
1917
1917
  // Điều kiện filter:
1918
1918
  // - Nếu meta.showInColumnChoose = false => loại bỏ
1919
- // - Nếu không nằm trong groupColumns và không phải column group => loại bỏ
1920
- if (meta.showInColumnChoose === false) return false;
1919
+ // - Nếu là column đặc biệt (selection_column, #, command...) => loại bỏ
1920
+ if (meta.showInColumnChoose === false || nonActionColumn.includes(col.id)) return false;
1921
1921
  if (inGroup && !('columns' in col && Array.isArray(col.columns))) {
1922
1922
  return false;
1923
1923
  }
@@ -1948,6 +1948,15 @@ export const updateColumns1 = (columns, includes) => {
1948
1948
  if (!column.field) {
1949
1949
  return column;
1950
1950
  }
1951
+
1952
+ // Bỏ qua column đặc biệt (selection_column, #, command, drag-handle) — giữ nguyên visible
1953
+ // nhưng vẫn phải đệ quy children để không bỏ sót column con
1954
+ if (nonActionColumn.includes(newColumn.field)) {
1955
+ if (newColumn.children) {
1956
+ newColumn.children = updateColumns1(newColumn.children, includes);
1957
+ }
1958
+ return newColumn;
1959
+ }
1951
1960
  if (newColumn.children) {
1952
1961
  newColumn.children = updateColumns1(newColumn.children, includes);
1953
1962
  hasVisibleChild = newColumn.children.some(child => !child.hidden);
@@ -2078,7 +2078,25 @@ const TableContainerEdit = props => {
2078
2078
  }
2079
2079
  contextMenuClick?.(args);
2080
2080
  };
2081
+
2082
+ // Chống fire onCellClick trùng lặp: double-click = 2 lần mousedown nên callback sẽ bị gọi 2 lần.
2083
+ // Chỉ bỏ qua khi click LIÊN TIẾP cùng 1 cell trong khoảng thời gian rất ngắn.
2084
+ const lastCellClickRef = React.useRef({
2085
+ key: '',
2086
+ time: 0
2087
+ });
2081
2088
  const handleCellClick = (rowNumber, record, column, rowId, cellValue) => {
2089
+ const clickKey = `${rowId}::${column.field ?? ''}`;
2090
+ const now = Date.now();
2091
+
2092
+ // cùng cell && trong vòng 300ms => coi là double-click, bỏ qua lần lặp
2093
+ if (lastCellClickRef.current.key === clickKey && now - lastCellClickRef.current.time < 300) {
2094
+ return;
2095
+ }
2096
+ lastCellClickRef.current = {
2097
+ key: clickKey,
2098
+ time: now
2099
+ };
2082
2100
  const cellClickCallback = newOptions => {
2083
2101
  if (newOptions) {
2084
2102
  const newElem = {
@@ -1344,6 +1344,11 @@ const TableBodyCellEdit = props => {
1344
1344
  }
1345
1345
  } else {
1346
1346
  handleMouseDown(cell.row.id, cell.column.id);
1347
+
1348
+ // fire onCellClick ngay lần click đầu (trước đây chỉ fire khi cell đã ở trạng thái editing)
1349
+ if (canEdit) {
1350
+ handleCellClick?.(rowNumber, record, columnMeta, record[rowKey], record[columnMeta.field ?? '']);
1351
+ }
1347
1352
  if (editingKey) {
1348
1353
  setTimeout(() => {
1349
1354
  setEditingKey?.('');
@@ -6,7 +6,6 @@ import { nonActionColumn } from "../../grid-component/hooks";
6
6
  export const newGuid = () => {
7
7
  for (let i = 0; i < 20; i++) {
8
8
  // @ts-ignore
9
- // const id = crypto.randomUUID()
10
9
  return uuidv4();
11
10
  }
12
11
  };
@@ -2481,9 +2480,8 @@ export function convertColumnsToTreeData(columns, groupColumns) {
2481
2480
 
2482
2481
  // Điều kiện filter:
2483
2482
  // - Nếu meta.showInColumnChoose = false => loại bỏ
2484
- // - Nếu không nằm trong groupColumns và không phải column group => loại bỏ
2485
- // if (meta.showInColumnChoose === false || col.id === "selection_column") return false
2486
- if (meta.showInColumnChoose === false) return false;
2483
+ // - Nếu là column đặc biệt (selection_column, #, command...) => loại bỏ
2484
+ if (meta.showInColumnChoose === false || nonActionColumn.includes(col.id)) return false;
2487
2485
  // if (inGroup && !('columns' in col && Array.isArray((col as any).columns))) {
2488
2486
  if (inGroup && !('columns' in col && Array.isArray(col.columns))) {
2489
2487
  return false;
@@ -2515,6 +2513,15 @@ export const updateColumns1 = (columns, includes) => {
2515
2513
  if (!column.field) {
2516
2514
  return column;
2517
2515
  }
2516
+
2517
+ // Bỏ qua column đặc biệt (selection_column, #, command, drag-handle) — giữ nguyên visible
2518
+ // nhưng vẫn phải đệ quy children để không bỏ sót column con
2519
+ if (nonActionColumn.includes(newColumn.field)) {
2520
+ if (newColumn.children) {
2521
+ newColumn.children = updateColumns1(newColumn.children, includes);
2522
+ }
2523
+ return newColumn;
2524
+ }
2518
2525
  if (newColumn.children) {
2519
2526
  newColumn.children = updateColumns1(newColumn.children, includes);
2520
2527
  hasVisibleChild = newColumn.children.some(child => !child.hidden);
@@ -89,6 +89,8 @@ const InternalTable = props => {
89
89
  pageIndex: pagination && pagination.currentPage ? pagination.currentPage - 1 : 0,
90
90
  pageSize: pagination && pagination.pageSize ? pagination.pageSize : 20
91
91
  });
92
+ const isServerPagination = Boolean(pagination && pagination.mode === 'server');
93
+ const shouldUseClientPagination = Boolean(pagination) && !infiniteScroll && !isServerPagination;
92
94
  const [columnSizing, setColumnSizing] = React.useState({});
93
95
  const [columnSizingInfo, setColumnSizingInfo] = React.useState({});
94
96
 
@@ -264,7 +266,10 @@ const InternalTable = props => {
264
266
  getGroupedRowModel: getGroupedRowModel(),
265
267
  // onExpandedChange: setExpanded,
266
268
  getExpandedRowModel: getExpandedRowModel(),
267
- getPaginationRowModel: pagination && !infiniteScroll ? getPaginationRowModel() : undefined,
269
+ manualPagination: isServerPagination,
270
+ // Chỉ để TanStack tự phân trang khi có pagination, không dùng infinite scroll và đang ở chế độ client.
271
+ // Với server pagination, dữ liệu đã được BE phân trang nên không chạy getPaginationRowModel() để tránh phân trang lần 2.
272
+ getPaginationRowModel: shouldUseClientPagination ? getPaginationRowModel() : undefined,
268
273
  onPaginationChange: setPagination,
269
274
  onColumnVisibilityChange: setColumnVisibility
270
275
  // onColumnPinningChange,
@@ -1,3 +1,4 @@
1
+ import { nonActionColumn } from "../../grid-component/hooks";
1
2
  import { SELECTION_COLUMN } from "rc-master-ui/es/table/hooks/useSelection";
2
3
  import { v4 as uuidv4 } from 'uuid';
3
4
  import { presetPalettes } from "@ant-design/colors";
@@ -1888,8 +1889,8 @@ export function convertColumnsToTreeData(columns, groupColumns) {
1888
1889
 
1889
1890
  // Điều kiện filter:
1890
1891
  // - Nếu meta.showInColumnChoose = false => loại bỏ
1891
- // - Nếu không nằm trong groupColumns và không phải column group => loại bỏ
1892
- if (meta.showInColumnChoose === false) return false;
1892
+ // - Nếu là column đặc biệt (selection_column, #, command...) => loại bỏ
1893
+ if (meta.showInColumnChoose === false || nonActionColumn.includes(col.id)) return false;
1893
1894
  if (inGroup && !('columns' in col && Array.isArray(col.columns))) {
1894
1895
  return false;
1895
1896
  }
@@ -1920,6 +1921,15 @@ export const updateColumns1 = (columns, includes) => {
1920
1921
  if (!column.field) {
1921
1922
  return column;
1922
1923
  }
1924
+
1925
+ // Bỏ qua column đặc biệt (selection_column, #, command, drag-handle) — giữ nguyên visible
1926
+ // nhưng vẫn phải đệ quy children để không bỏ sót column con
1927
+ if (nonActionColumn.includes(newColumn.field)) {
1928
+ if (newColumn.children) {
1929
+ newColumn.children = updateColumns1(newColumn.children, includes);
1930
+ }
1931
+ return newColumn;
1932
+ }
1923
1933
  if (newColumn.children) {
1924
1934
  newColumn.children = updateColumns1(newColumn.children, includes);
1925
1935
  hasVisibleChild = newColumn.children.some(child => !child.hidden);
@@ -79,6 +79,16 @@ const TableContainer = props => {
79
79
  } = props;
80
80
  const [paginationLocal] = useLocale('Pagination');
81
81
  const [tableLocal] = useLocale('Table');
82
+ const paginationProps = React.useMemo(() => {
83
+ if (!pagination) {
84
+ return undefined;
85
+ }
86
+ const paginationConfig = {
87
+ ...pagination
88
+ };
89
+ delete paginationConfig.mode;
90
+ return paginationConfig;
91
+ }, [pagination]);
82
92
  const tableContainerRef = React.useRef(null);
83
93
  const containerRef = React.useRef(null);
84
94
  const bottomToolbarRef = React.useRef(null);
@@ -210,7 +220,7 @@ const TableContainer = props => {
210
220
  showTotal: (totalItems, range) =>
211
221
  // @ts-ignore
212
222
  `${range[0]}-${range[1]} / ${totalItems} ${t ? t(pagination?.locale?.items ?? 'items') : 'items'}`
213
- }, pagination)), typeof actionTemplate === 'function' ? actionTemplate() : actionTemplate, toolbarItemTopRight && /*#__PURE__*/React.createElement("div", {
223
+ }, paginationProps)), typeof actionTemplate === 'function' ? actionTemplate() : actionTemplate, toolbarItemTopRight && /*#__PURE__*/React.createElement("div", {
214
224
  style: {
215
225
  flex: 1,
216
226
  overflow: 'hidden'
@@ -299,7 +309,7 @@ const TableContainer = props => {
299
309
  })} / ${numericFormatter((totalItems ?? 0).toString(), {
300
310
  thousandSeparator: '.'
301
311
  })} ${pagination?.locale?.items || paginationLocal?.items || ''}`
302
- }, pagination, {
312
+ }, paginationProps, {
303
313
  onChange: (page, pageSize1) => {
304
314
  if (pagination.onChange) {
305
315
  pagination.onChange(page, pageSize1);
@@ -6,13 +6,14 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.convertColumnsToTreeData = convertColumnsToTreeData;
7
7
  exports.filterColumnsByField = filterColumnsByField;
8
8
  exports.filterVisibleColumns = filterVisibleColumns;
9
+ var _hooks = require("../../grid-component/hooks");
9
10
  function convertColumnsToTreeData(columns, groupColumns, t) {
10
11
  if (!columns) {
11
12
  return [];
12
13
  }
13
14
  return columns.filter(col => {
14
15
  const inGroup = groupColumns ? groupColumns.includes(String(col.field)) : false;
15
- if (col.showInColumnChoose === false) return false;
16
+ if (col.showInColumnChoose === false || _hooks.nonActionColumn.includes(col.field)) return false;
16
17
  if (inGroup && !('children' in col && Array.isArray(col.children))) {
17
18
  return false;
18
19
  }
@@ -76,6 +76,8 @@ export type Locale = {
76
76
  export type PaginationConfig = Omit<TablePaginationConfig, 'locale' | 'current'> & {
77
77
  currentPage?: number;
78
78
  locale?: PagingLocale;
79
+ /** Chế độ phân trang. Mặc định là client để giữ tương thích với hành vi hiện tại. */
80
+ mode?: 'client' | 'server';
79
81
  };
80
82
  export type AnyObject = Record<PropertyKey, any>;
81
83
  export type IFormat = {
@@ -2031,7 +2031,25 @@ const TableContainerEdit = props => {
2031
2031
  }
2032
2032
  contextMenuClick?.(args);
2033
2033
  };
2034
+
2035
+ // Chống fire onCellClick trùng lặp: double-click = 2 lần mousedown nên callback sẽ bị gọi 2 lần.
2036
+ // Chỉ bỏ qua khi click LIÊN TIẾP cùng 1 cell trong khoảng thời gian rất ngắn.
2037
+ const lastCellClickRef = _react.default.useRef({
2038
+ key: '',
2039
+ time: 0
2040
+ });
2034
2041
  const handleCellClick = (rowNumber, record, column, rowId, cellValue) => {
2042
+ const clickKey = `${rowId}::${column.field ?? ''}`;
2043
+ const now = Date.now();
2044
+
2045
+ // cùng cell && trong vòng 300ms => coi là double-click, bỏ qua lần lặp
2046
+ if (lastCellClickRef.current.key === clickKey && now - lastCellClickRef.current.time < 300) {
2047
+ return;
2048
+ }
2049
+ lastCellClickRef.current = {
2050
+ key: clickKey,
2051
+ time: now
2052
+ };
2035
2053
  const cellClickCallback = newOptions => {
2036
2054
  if (newOptions) {
2037
2055
  const newElem = {
@@ -1267,6 +1267,11 @@ const TableBodyCellEdit = props => {
1267
1267
  }
1268
1268
  } else {
1269
1269
  handleMouseDown(cell.row.id, cell.column.id);
1270
+
1271
+ // fire onCellClick ngay lần click đầu (trước đây chỉ fire khi cell đã ở trạng thái editing)
1272
+ if (canEdit) {
1273
+ handleCellClick?.(rowNumber, record, columnMeta, record[rowKey], record[columnMeta.field ?? '']);
1274
+ }
1270
1275
  if (editingKey) {
1271
1276
  setTimeout(() => {
1272
1277
  setEditingKey?.('');
@@ -167,7 +167,7 @@ export declare const fixColumnsLeft: <RecordType>(columns: ColumnTable<RecordTyp
167
167
  haveSum?: boolean;
168
168
  isSummary?: boolean;
169
169
  sumGroup?: boolean;
170
- summaryTemplate?: (data: number, key: string) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode;
170
+ summaryTemplate?: (data: number, key: string) => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
171
171
  sorter?: boolean;
172
172
  allowFiltering?: boolean;
173
173
  allowSortering?: boolean;
@@ -179,27 +179,27 @@ export declare const fixColumnsLeft: <RecordType>(columns: ColumnTable<RecordTyp
179
179
  showFilterSearch?: boolean;
180
180
  hidden?: boolean;
181
181
  visible?: boolean;
182
- headerTooltip?: string | boolean | (() => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode);
182
+ headerTooltip?: string | boolean | (() => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>);
183
183
  columnGroupText?: string;
184
184
  headerTextAlign?: import("./../../grid-component/type").ITextAlign;
185
- headerTemplate?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode | ((column: ColumnTable<RecordType>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode);
185
+ headerTemplate?: import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | ((column: ColumnTable<RecordType>) => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>);
186
186
  fixedType?: import("./../../grid-component/type").FixedType;
187
187
  headerTextWrap?: boolean;
188
188
  ellipsis?: boolean;
189
189
  allowResizing?: boolean;
190
190
  align?: import("./../../grid-component/type").ITextAlign;
191
191
  textAlign?: import("./../../grid-component/type").ITextAlign;
192
- template?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode | ((args: import("./../../grid-component/type").ColumnTemplate<RecordType>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode);
193
- linkTemplate?: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode | ((args: import("./../../grid-component/type").ColumnTemplate<RecordType>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode);
192
+ template?: import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | ((args: import("./../../grid-component/type").ColumnTemplate<RecordType>) => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>);
193
+ linkTemplate?: import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | ((args: import("./../../grid-component/type").ColumnTemplate<RecordType>) => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>);
194
194
  showTooltip?: boolean;
195
195
  tooltipDescription?: string | ((args: {
196
196
  value: any;
197
197
  rowData: RecordType;
198
- }) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode);
199
- onCellStyles?: Omit<CSSProperties, "width" | "minWidth" | "left" | "right" | "position" | "display"> | ((cellValue: any, cell: import("@tanstack/react-table").Cell<RecordType, unknown>) => Omit<CSSProperties, "width" | "minWidth" | "left" | "right" | "position" | "display">);
200
- onCellHeaderStyles?: Omit<CSSProperties, "width" | "minWidth" | "left" | "right" | "position" | "display"> | ((cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "width" | "minWidth" | "left" | "right" | "position" | "display">);
198
+ }) => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>);
199
+ onCellStyles?: Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width"> | ((cellValue: any, cell: import("@tanstack/react-table").Cell<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width">);
200
+ onCellHeaderStyles?: Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width"> | ((cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width">);
201
201
  onCell?: (rowData: RecordType, index: number) => import("react").TdHTMLAttributes<HTMLTableCellElement>;
202
- onCellFooterStyles?: Omit<CSSProperties, "width" | "minWidth" | "left" | "right" | "position" | "display"> | ((cellValue: any, cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "width" | "minWidth" | "left" | "right" | "position" | "display">);
202
+ onCellFooterStyles?: Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width"> | ((cellValue: any, cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "display" | "minWidth" | "position" | "width">);
203
203
  getValue?: (row: any, rowIndex: number) => any;
204
204
  getCellProps?: (value: any, row: any, rowIndex: number) => import("./../../grid-component/type").CellProps;
205
205
  headerCellProps?: import("./../../grid-component/type").CellProps;
@@ -60,6 +60,7 @@ exports.updateColumnWidthsRecursive = updateColumnWidthsRecursive;
60
60
  exports.updateColumnsByGroup = exports.updateColumns1 = void 0;
61
61
  exports.updateOrInsert = updateOrInsert;
62
62
  exports.updateWidthsByOther = updateWidthsByOther;
63
+ var _hooks = require("./../../grid-component/hooks");
63
64
  var _uuid = require("uuid");
64
65
  var _colors = require("@ant-design/colors");
65
66
  var _dayjs = _interopRequireDefault(require("dayjs"));
@@ -67,7 +68,6 @@ var _moment = _interopRequireDefault(require("moment"));
67
68
  const newGuid = () => {
68
69
  for (let i = 0; i < 20; i++) {
69
70
  // @ts-ignore
70
- // const id = crypto.randomUUID()
71
71
  return (0, _uuid.v4)();
72
72
  }
73
73
  };
@@ -2030,8 +2030,8 @@ function convertColumnsToTreeData(columns, groupColumns) {
2030
2030
 
2031
2031
  // Điều kiện filter:
2032
2032
  // - Nếu meta.showInColumnChoose = false => loại bỏ
2033
- // - Nếu không nằm trong groupColumns và không phải column group => loại bỏ
2034
- if (meta.showInColumnChoose === false) return false;
2033
+ // - Nếu là column đặc biệt (selection_column, #, command...) => loại bỏ
2034
+ if (meta.showInColumnChoose === false || _hooks.nonActionColumn.includes(col.id)) return false;
2035
2035
  if (inGroup && !('columns' in col && Array.isArray(col.columns))) {
2036
2036
  return false;
2037
2037
  }
@@ -2062,6 +2062,15 @@ const updateColumns1 = (columns, includes) => {
2062
2062
  if (!column.field) {
2063
2063
  return column;
2064
2064
  }
2065
+
2066
+ // Bỏ qua column đặc biệt (selection_column, #, command, drag-handle) — giữ nguyên visible
2067
+ // nhưng vẫn phải đệ quy children để không bỏ sót column con
2068
+ if (_hooks.nonActionColumn.includes(newColumn.field)) {
2069
+ if (newColumn.children) {
2070
+ newColumn.children = updateColumns1(newColumn.children, includes);
2071
+ }
2072
+ return newColumn;
2073
+ }
2065
2074
  if (newColumn.children) {
2066
2075
  newColumn.children = updateColumns1(newColumn.children, includes);
2067
2076
  hasVisibleChild = newColumn.children.some(child => !child.hidden);
@@ -2077,7 +2077,25 @@ const TableContainerEdit = props => {
2077
2077
  }
2078
2078
  contextMenuClick?.(args);
2079
2079
  };
2080
+
2081
+ // Chống fire onCellClick trùng lặp: double-click = 2 lần mousedown nên callback sẽ bị gọi 2 lần.
2082
+ // Chỉ bỏ qua khi click LIÊN TIẾP cùng 1 cell trong khoảng thời gian rất ngắn.
2083
+ const lastCellClickRef = _react.default.useRef({
2084
+ key: '',
2085
+ time: 0
2086
+ });
2080
2087
  const handleCellClick = (rowNumber, record, column, rowId, cellValue) => {
2088
+ const clickKey = `${rowId}::${column.field ?? ''}`;
2089
+ const now = Date.now();
2090
+
2091
+ // cùng cell && trong vòng 300ms => coi là double-click, bỏ qua lần lặp
2092
+ if (lastCellClickRef.current.key === clickKey && now - lastCellClickRef.current.time < 300) {
2093
+ return;
2094
+ }
2095
+ lastCellClickRef.current = {
2096
+ key: clickKey,
2097
+ time: now
2098
+ };
2081
2099
  const cellClickCallback = newOptions => {
2082
2100
  if (newOptions) {
2083
2101
  const newElem = {
@@ -1349,6 +1349,11 @@ const TableBodyCellEdit = props => {
1349
1349
  }
1350
1350
  } else {
1351
1351
  handleMouseDown(cell.row.id, cell.column.id);
1352
+
1353
+ // fire onCellClick ngay lần click đầu (trước đây chỉ fire khi cell đã ở trạng thái editing)
1354
+ if (canEdit) {
1355
+ handleCellClick?.(rowNumber, record, columnMeta, record[rowKey], record[columnMeta.field ?? '']);
1356
+ }
1352
1357
  if (editingKey) {
1353
1358
  setTimeout(() => {
1354
1359
  setEditingKey?.('');
@@ -86,7 +86,6 @@ var _hooks = require("../../grid-component/hooks");
86
86
  const newGuid = () => {
87
87
  for (let i = 0; i < 20; i++) {
88
88
  // @ts-ignore
89
- // const id = crypto.randomUUID()
90
89
  return (0, _uuid.v4)();
91
90
  }
92
91
  };
@@ -2625,9 +2624,8 @@ function convertColumnsToTreeData(columns, groupColumns) {
2625
2624
 
2626
2625
  // Điều kiện filter:
2627
2626
  // - Nếu meta.showInColumnChoose = false => loại bỏ
2628
- // - Nếu không nằm trong groupColumns và không phải column group => loại bỏ
2629
- // if (meta.showInColumnChoose === false || col.id === "selection_column") return false
2630
- if (meta.showInColumnChoose === false) return false;
2627
+ // - Nếu là column đặc biệt (selection_column, #, command...) => loại bỏ
2628
+ if (meta.showInColumnChoose === false || _hooks.nonActionColumn.includes(col.id)) return false;
2631
2629
  // if (inGroup && !('columns' in col && Array.isArray((col as any).columns))) {
2632
2630
  if (inGroup && !('columns' in col && Array.isArray(col.columns))) {
2633
2631
  return false;
@@ -2659,6 +2657,15 @@ const updateColumns1 = (columns, includes) => {
2659
2657
  if (!column.field) {
2660
2658
  return column;
2661
2659
  }
2660
+
2661
+ // Bỏ qua column đặc biệt (selection_column, #, command, drag-handle) — giữ nguyên visible
2662
+ // nhưng vẫn phải đệ quy children để không bỏ sót column con
2663
+ if (_hooks.nonActionColumn.includes(newColumn.field)) {
2664
+ if (newColumn.children) {
2665
+ newColumn.children = updateColumns1(newColumn.children, includes);
2666
+ }
2667
+ return newColumn;
2668
+ }
2662
2669
  if (newColumn.children) {
2663
2670
  newColumn.children = updateColumns1(newColumn.children, includes);
2664
2671
  hasVisibleChild = newColumn.children.some(child => !child.hidden);
@@ -99,6 +99,8 @@ const InternalTable = props => {
99
99
  pageIndex: pagination && pagination.currentPage ? pagination.currentPage - 1 : 0,
100
100
  pageSize: pagination && pagination.pageSize ? pagination.pageSize : 20
101
101
  });
102
+ const isServerPagination = Boolean(pagination && pagination.mode === 'server');
103
+ const shouldUseClientPagination = Boolean(pagination) && !infiniteScroll && !isServerPagination;
102
104
  const [columnSizing, setColumnSizing] = _react.default.useState({});
103
105
  const [columnSizingInfo, setColumnSizingInfo] = _react.default.useState({});
104
106
 
@@ -274,7 +276,10 @@ const InternalTable = props => {
274
276
  getGroupedRowModel: (0, _reactTable.getGroupedRowModel)(),
275
277
  // onExpandedChange: setExpanded,
276
278
  getExpandedRowModel: (0, _reactTable.getExpandedRowModel)(),
277
- getPaginationRowModel: pagination && !infiniteScroll ? (0, _reactTable.getPaginationRowModel)() : undefined,
279
+ manualPagination: isServerPagination,
280
+ // Chỉ để TanStack tự phân trang khi có pagination, không dùng infinite scroll và đang ở chế độ client.
281
+ // Với server pagination, dữ liệu đã được BE phân trang nên không chạy getPaginationRowModel() để tránh phân trang lần 2.
282
+ getPaginationRowModel: shouldUseClientPagination ? (0, _reactTable.getPaginationRowModel)() : undefined,
278
283
  onPaginationChange: setPagination,
279
284
  onColumnVisibilityChange: setColumnVisibility
280
285
  // onColumnPinningChange,
@@ -66,6 +66,7 @@ exports.updateColumnWidthsRecursive = updateColumnWidthsRecursive;
66
66
  exports.updateColumnsByGroup = exports.updateColumns1 = void 0;
67
67
  exports.updateOrInsert = updateOrInsert;
68
68
  exports.updateWidthsByOther = updateWidthsByOther;
69
+ var _hooks = require("../../grid-component/hooks");
69
70
  var _useSelection = require("rc-master-ui/es/table/hooks/useSelection");
70
71
  var _uuid = require("uuid");
71
72
  var _colors = require("@ant-design/colors");
@@ -2010,8 +2011,8 @@ function convertColumnsToTreeData(columns, groupColumns) {
2010
2011
 
2011
2012
  // Điều kiện filter:
2012
2013
  // - Nếu meta.showInColumnChoose = false => loại bỏ
2013
- // - Nếu không nằm trong groupColumns và không phải column group => loại bỏ
2014
- if (meta.showInColumnChoose === false) return false;
2014
+ // - Nếu là column đặc biệt (selection_column, #, command...) => loại bỏ
2015
+ if (meta.showInColumnChoose === false || _hooks.nonActionColumn.includes(col.id)) return false;
2015
2016
  if (inGroup && !('columns' in col && Array.isArray(col.columns))) {
2016
2017
  return false;
2017
2018
  }
@@ -2042,6 +2043,15 @@ const updateColumns1 = (columns, includes) => {
2042
2043
  if (!column.field) {
2043
2044
  return column;
2044
2045
  }
2046
+
2047
+ // Bỏ qua column đặc biệt (selection_column, #, command, drag-handle) — giữ nguyên visible
2048
+ // nhưng vẫn phải đệ quy children để không bỏ sót column con
2049
+ if (_hooks.nonActionColumn.includes(newColumn.field)) {
2050
+ if (newColumn.children) {
2051
+ newColumn.children = updateColumns1(newColumn.children, includes);
2052
+ }
2053
+ return newColumn;
2054
+ }
2045
2055
  if (newColumn.children) {
2046
2056
  newColumn.children = updateColumns1(newColumn.children, includes);
2047
2057
  hasVisibleChild = newColumn.children.some(child => !child.hidden);
@@ -87,6 +87,16 @@ const TableContainer = props => {
87
87
  } = props;
88
88
  const [paginationLocal] = (0, _locale.useLocale)('Pagination');
89
89
  const [tableLocal] = (0, _locale.useLocale)('Table');
90
+ const paginationProps = _react.default.useMemo(() => {
91
+ if (!pagination) {
92
+ return undefined;
93
+ }
94
+ const paginationConfig = {
95
+ ...pagination
96
+ };
97
+ delete paginationConfig.mode;
98
+ return paginationConfig;
99
+ }, [pagination]);
90
100
  const tableContainerRef = _react.default.useRef(null);
91
101
  const containerRef = _react.default.useRef(null);
92
102
  const bottomToolbarRef = _react.default.useRef(null);
@@ -218,7 +228,7 @@ const TableContainer = props => {
218
228
  showTotal: (totalItems, range) =>
219
229
  // @ts-ignore
220
230
  `${range[0]}-${range[1]} / ${totalItems} ${t ? t(pagination?.locale?.items ?? 'items') : 'items'}`
221
- }, pagination)), typeof actionTemplate === 'function' ? actionTemplate() : actionTemplate, toolbarItemTopRight && /*#__PURE__*/_react.default.createElement("div", {
231
+ }, paginationProps)), typeof actionTemplate === 'function' ? actionTemplate() : actionTemplate, toolbarItemTopRight && /*#__PURE__*/_react.default.createElement("div", {
222
232
  style: {
223
233
  flex: 1,
224
234
  overflow: 'hidden'
@@ -307,7 +317,7 @@ const TableContainer = props => {
307
317
  })} / ${(0, _reactNumericComponent.numericFormatter)((totalItems ?? 0).toString(), {
308
318
  thousandSeparator: '.'
309
319
  })} ${pagination?.locale?.items || paginationLocal?.items || ''}`
310
- }, pagination, {
320
+ }, paginationProps, {
311
321
  onChange: (page, pageSize1) => {
312
322
  if (pagination.onChange) {
313
323
  pagination.onChange(page, pageSize1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "es-grid-template",
3
- "version": "1.9.79",
3
+ "version": "1.9.83",
4
4
  "description": "es-grid-template",
5
5
  "keywords": [
6
6
  "react",