es-grid-template 1.8.68 → 1.8.70

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.
@@ -159,6 +159,8 @@ export type ColumnTable<RecordType = AnyObject> = {
159
159
  onCellStyles?: Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'> | ((cellValue: any, cell: Cell<RecordType, unknown>) => Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'>);
160
160
  onCellHeaderStyles?: Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'> | ((cell: Header<RecordType, unknown>) => Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'>);
161
161
  onCellFooterStyles?: Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'> | ((cellValue: any, cell: Header<RecordType, unknown>) => Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'>);
162
+ sumGroup?: boolean;
163
+ onCell?: (rowData: RecordType, index: number) => React.TdHTMLAttributes<HTMLTableCellElement>;
162
164
  };
163
165
  export type Locale = TableLocale & {
164
166
  ok_btn?: string;
@@ -193,11 +195,13 @@ export type Locale = TableLocale & {
193
195
  };
194
196
  export type ColumnsTable<RecordType = AnyObject> = ColumnTable<RecordType>[];
195
197
  export type TableProps<RecordType = AnyObject> = {
198
+ id?: string;
196
199
  theme?: {
197
200
  theme?: 'dark' | 'light';
198
201
  backgroundColor?: string;
199
202
  color?: string;
200
203
  };
204
+ className?: string;
201
205
  title?: ReactNode | ((data: RecordType) => ReactNode);
202
206
  fullScreenTitle?: ReactNode | (() => ReactNode);
203
207
  editAble?: boolean;
@@ -64,7 +64,7 @@ const CheckboxFilter = props => {
64
64
  prefixCls = 'ui-rc-table-filter',
65
65
  dropdownPrefixCls = 'ui-rc-dropdown',
66
66
  filterMultiple,
67
- selectedKeys,
67
+ selectedKeys: propsSelectedKeys,
68
68
  locale,
69
69
  options,
70
70
  filterMode = 'tree',
@@ -74,6 +74,12 @@ const CheckboxFilter = props => {
74
74
  // setSearchValue,
75
75
  onSelect
76
76
  } = props;
77
+ const selectedKeys = React.useMemo(() => {
78
+ if (propsSelectedKeys) {
79
+ return propsSelectedKeys.map(it => String(it));
80
+ }
81
+ return [];
82
+ }, [propsSelectedKeys]);
77
83
  const [searchValue, setSearchValue] = React.useState('');
78
84
  const [openKeys, setOpenKeys] = React.useState([]);
79
85
 
@@ -129,6 +135,7 @@ const CheckboxFilter = props => {
129
135
  const key = String(filter.value);
130
136
  const item = {
131
137
  title: filter.label,
138
+ id: filter.value !== undefined ? filter.value : index,
132
139
  key: filter.value !== undefined ? key : String(index)
133
140
  };
134
141
  if (filter.children) {
@@ -146,7 +153,7 @@ const CheckboxFilter = props => {
146
153
  });
147
154
  const onCheckAll = e => {
148
155
  if (e.target.checked) {
149
- const allFilterKeys = flattenKeys(options).map(key => String(key));
156
+ const allFilterKeys = flattenKeys(options).map(key => key);
150
157
 
151
158
  // setFilteredKeysSync(allFilterKeys);
152
159
  onSelect?.(allFilterKeys);
@@ -161,10 +168,17 @@ const CheckboxFilter = props => {
161
168
  }) => {
162
169
  if (!filterMultiple) {
163
170
  // onSelectKeys({ selectedKeys: checked && node.key ? [node.key] : [] });
164
- onSelect?.(checked && node.key ? [node.key] : []);
171
+
172
+ onSelect?.(checked && node.key ? [node.id] : []);
165
173
  } else {
174
+ if (!checked) {
175
+ const rs = propsSelectedKeys.filter(it => it !== node.id);
176
+ onSelect?.(rs);
177
+ } else {
178
+ const rs = [...propsSelectedKeys, node.id];
179
+ onSelect?.(rs);
180
+ }
166
181
  // onSelectKeys({ selectedKeys: keys });
167
- onSelect?.(keys);
168
182
  }
169
183
  };
170
184
  if (filterMode === 'tree') {
@@ -137,7 +137,7 @@ const TableHeadCell = props => {
137
137
  minWidth: 275,
138
138
  padding: '8px'
139
139
  }
140
- }, /*#__PURE__*/React.createElement("div", null), column.meta?.showOperator !== false && column.meta?.typeFilter !== 'DateRange' && column.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/React.createElement("div", {
140
+ }, /*#__PURE__*/React.createElement("div", null), column.meta?.hideOperator === true && column.meta?.typeFilter !== 'DateRange' && column.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/React.createElement("div", {
141
141
  className: 'mb-1'
142
142
  }, /*#__PURE__*/React.createElement(Select, {
143
143
  options: translateOption(operatorOptions, t),
@@ -136,7 +136,7 @@ const TableHeadCell2 = props => {
136
136
  minWidth: 275,
137
137
  padding: '8px'
138
138
  }
139
- }, /*#__PURE__*/React.createElement("div", null), column.columnDef?.meta?.showOperator !== false && column.columnDef?.meta?.typeFilter !== 'DateRange' && column.columnDef?.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/React.createElement("div", {
139
+ }, /*#__PURE__*/React.createElement("div", null), column.columnDef?.meta?.hideOperator === true && column.columnDef?.meta?.typeFilter !== 'DateRange' && column.columnDef?.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/React.createElement("div", {
140
140
  className: 'mb-1'
141
141
  }, /*#__PURE__*/React.createElement(Select, {
142
142
  options: translateOption(operatorOptions, t),
@@ -258,7 +258,9 @@ export const renderFilter = args => {
258
258
  }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(CheckboxFilter, {
259
259
  locale: locale,
260
260
  selectedKeys: selectedKeys,
261
- onSelect: setSelectedKeys
261
+ onSelect: val => {
262
+ setSelectedKeys(val);
263
+ }
262
264
  // options={options}
263
265
  ,
264
266
  options: source ? source : options ?? [],
@@ -819,6 +819,89 @@ export const shouldInclude = (item, queries) => {
819
819
  }
820
820
  return result;
821
821
  };
822
+
823
+ // function compareValues(a: any, b: any, order: "ascend" | "descend") {
824
+ // const desc = order === "descend";
825
+
826
+ // if (a == null && b == null) return 0;
827
+ // if (a == null) return desc ? 1 : -1;
828
+ // if (b == null) return desc ? -1 : 1;
829
+
830
+ // // Nếu là số
831
+ // if (typeof a === "number" && typeof b === "number") {
832
+ // return desc ? b - a : a - b;
833
+ // }
834
+
835
+ // // Nếu là ngày hợp lệ
836
+ // const dateA = new Date(a);
837
+ // const dateB = new Date(b);
838
+ // if (!isNaN(dateA.getTime()) && !isNaN(dateB.getTime())) {
839
+ // return desc
840
+ // ? dateB.getTime() - dateA.getTime()
841
+ // : dateA.getTime() - dateB.getTime();
842
+ // }
843
+
844
+ // // Mặc định coi như string
845
+ // return desc
846
+ // ? String(b).localeCompare(String(a))
847
+ // : String(a).localeCompare(String(b));
848
+ // }
849
+
850
+ // export function sortData(data: any[], sorter: Sorter[]): any[] {
851
+ // const sorted = [...data].sort((a, b) => {
852
+ // for (const { field, order } of sorter) {
853
+ // const result = compareValues(a[field], b[field], order);
854
+ // if (result !== 0) return result;
855
+ // }
856
+ // return 0;
857
+ // });
858
+
859
+ // return sorted.map(item => ({
860
+ // ...item,
861
+ // children: item.children
862
+ // ? sortData(item.children, sorter)
863
+ // : undefined
864
+ // }));
865
+ // }
866
+
867
+ // export function filterDataByColumns(data: any[], queries: any[], sorter: Sorter[], keysFilter: string[] | undefined) {
868
+
869
+ // if (!queries || queries.length === 0) {
870
+ // return sorter ? sortData(data, sorter) : data;
871
+ // }
872
+
873
+ // let filtered = data.map(item => {
874
+ // const newItem = { ...item }
875
+
876
+ // if (Array.isArray(item.children)) {
877
+ // newItem.children = filterDataByColumns(item.children, queries, sorter, keysFilter)
878
+ // }
879
+
880
+ // const isSelfMatched = shouldInclude(item, queries) || keysFilter?.includes(newItem?.rowId)
881
+
882
+ // // Nếu chính item thỏa hoặc có con thỏa → giữ lại
883
+ // if (isSelfMatched || (newItem.children && newItem.children.length > 0)) {
884
+ // return newItem
885
+ // }
886
+
887
+ // return null // loại bỏ node không phù hợp
888
+ // })
889
+ // .filter(Boolean) // xóa các null
890
+
891
+ // if (sorter && sorter.length > 0) {
892
+ // filtered = sortData(filtered, sorter);
893
+ // }
894
+
895
+ // return filtered;
896
+ // }
897
+
898
+ function getSortValue(item, field) {
899
+ if (item[field] !== undefined) return item[field];
900
+ if (item.children && item.children.length > 0) {
901
+ return getSortValue(item.children[0], field);
902
+ }
903
+ return undefined;
904
+ }
822
905
  function compareValues(a, b, order) {
823
906
  const desc = order === "descend";
824
907
  if (a == null && b == null) return 0;
@@ -846,7 +929,7 @@ export function sortData(data, sorter) {
846
929
  field,
847
930
  order
848
931
  } of sorter) {
849
- const result = compareValues(a[field], b[field], order);
932
+ const result = compareValues(getSortValue(a, field), getSortValue(b, field), order);
850
933
  if (result !== 0) return result;
851
934
  }
852
935
  return 0;
@@ -55,6 +55,7 @@ const Grid = props => {
55
55
  allowResizing,
56
56
  windowSize,
57
57
  fullScreenTitle,
58
+ className: tableClassNames,
58
59
  ...rest
59
60
  } = props;
60
61
  const [columnResizeMode] = React.useState('onChange');
@@ -258,7 +259,7 @@ const Grid = props => {
258
259
  theme: theme?.theme,
259
260
  ...theme
260
261
  },
261
- className: classNames(`${prefix}-grid`, {
262
+ className: classNames(`${prefix}-grid ${tableClassNames}`, {
262
263
  [`${prefix}-grid-light`]: !theme || theme.theme === 'light',
263
264
  [`${prefix}-grid-dark`]: theme?.theme === 'dark'
264
265
  }),
@@ -337,7 +338,7 @@ const Grid = props => {
337
338
  theme: theme?.theme,
338
339
  ...theme
339
340
  },
340
- className: classNames(`${prefix}-grid`, {
341
+ className: classNames(`${prefix}-grid ${tableClassNames}`, {
341
342
  [`${prefix}-grid-light`]: !theme || theme.theme === 'light',
342
343
  [`${prefix}-grid-dark`]: theme?.theme === 'dark'
343
344
  }),
@@ -144,7 +144,9 @@ const TableBodyCell = props => {
144
144
  table,
145
145
  isEditing,
146
146
  colSpan,
147
+ rowSpan,
147
148
  groupValue
149
+ // ...cellProps
148
150
  } = props;
149
151
  const {
150
152
  id,
@@ -309,6 +311,10 @@ const TableBodyCell = props => {
309
311
  return /*#__PURE__*/React.createElement("td", {
310
312
  key: cell.id,
311
313
  colSpan: colSpan,
314
+ rowSpan: rowSpan
315
+ // {...cellProps}
316
+ ,
317
+
312
318
  ref: el => {
313
319
  if (focusedCell?.rowId === cell.row.id && focusedCell?.colId === cell.column.id && !isEditing) {
314
320
  el?.focus();
@@ -53,12 +53,22 @@ const TableBodyRow = ({
53
53
  }
54
54
  }
55
55
  }), visibleCells.map(cell => {
56
+ const originCol = cell.column.columnDef.meta ?? {};
57
+ const {
58
+ onCell
59
+ } = originCol ?? {};
60
+ const cellAttributes = onCell?.(cell.row.original, cell.row.index) ?? {};
61
+ const {
62
+ colSpan: onCellColSpan,
63
+ rowSpan: onCellRowSpan,
64
+ ...otherCellAttributes
65
+ } = cellAttributes;
56
66
  const nonGroupColumns = visibleCells.filter(col => col.column.id !== 'selection_column' && col.column.id !== '#');
57
67
  const firstNonGroupColumn = nonGroupColumns[0];
58
68
 
59
69
  // const colSpan = row.subRows && cell.column.id === firstNonGroupColumn?.id ? (groupSetting?.groupColumnSpan ?? 2)
60
- const colSpan = row.subRows && row.subRows.length > 0 && cell.column.id === firstNonGroupColumn?.column.id ? 2 : row.subRows && nonGroupColumns[1].column.id === cell.column.id ? 0 : 1;
61
- if (row.subRows && row.subRows.length > 0 && colSpan === 0) {
70
+ const colSpanGroup = row.subRows && row.subRows.length > 0 && cell.column.id === firstNonGroupColumn?.column.id ? 2 : row.subRows && nonGroupColumns[1].column.id === cell.column.id ? 0 : 1;
71
+ if (row.subRows && row.subRows.length > 0 && colSpanGroup === 0 || onCellRowSpan === 0 || onCellColSpan === 0) {
62
72
  return null;
63
73
  }
64
74
 
@@ -87,7 +97,7 @@ const TableBodyRow = ({
87
97
  rowData: row.original,
88
98
  value: cellValue
89
99
  }) : /*#__PURE__*/React.createElement(React.Fragment, null, headertext, headertext ? ': ' : '', " ", cellContent);
90
- return /*#__PURE__*/React.createElement(TableBodyCell, {
100
+ return /*#__PURE__*/React.createElement(TableBodyCell, _extends({
91
101
  table: table,
92
102
  tableId: tableId,
93
103
  key: cell.id,
@@ -95,11 +105,13 @@ const TableBodyRow = ({
95
105
  commandClick: commandClick,
96
106
  virtualRow: virtualRow,
97
107
  isEditing: false,
98
- colSpan: colSpan ?? 1,
108
+ colSpan: colSpanGroup ?? 1,
109
+ rowSpan: 1
110
+ }, otherCellAttributes, {
99
111
  groupValue: groupValue
100
- });
112
+ }));
101
113
  }
102
- return /*#__PURE__*/React.createElement(TableBodyCell, {
114
+ return /*#__PURE__*/React.createElement(TableBodyCell, _extends({
103
115
  table: table,
104
116
  tableId: tableId,
105
117
  key: cell.id,
@@ -107,8 +119,9 @@ const TableBodyRow = ({
107
119
  commandClick: commandClick,
108
120
  virtualRow: virtualRow,
109
121
  isEditing: false,
110
- colSpan: colSpan ?? 1
111
- });
122
+ colSpan: onCellColSpan ?? 1,
123
+ rowSpan: onCellRowSpan ?? 1
124
+ }, otherCellAttributes));
112
125
  }));
113
126
  };
114
127
  export default TableBodyRow;
@@ -122,7 +122,7 @@ const TableHeadCell = props => {
122
122
  minWidth: 275,
123
123
  padding: '8px'
124
124
  }
125
- }, column.meta?.showOperator !== false && column.meta?.typeFilter !== 'DateRange' && column.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/React.createElement("div", {
125
+ }, column.meta?.hideOperator === true && column.meta?.typeFilter !== 'DateRange' && column.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/React.createElement("div", {
126
126
  className: 'mb-1'
127
127
  }, /*#__PURE__*/React.createElement(Select, {
128
128
  options: translateOption(operatorOptions, t),
@@ -52,6 +52,7 @@ const Grid = props => {
52
52
  columnFilters,
53
53
  setColumnOrder,
54
54
  rowSelection,
55
+ className: tableClassNames,
55
56
  ...rest
56
57
  } = props;
57
58
  const [isSelectionChange, setIsSelectionChange] = React.useState({
@@ -153,7 +154,7 @@ const Grid = props => {
153
154
  theme: theme?.theme,
154
155
  ...theme
155
156
  },
156
- className: classNames(`${prefix}-grid`, {
157
+ className: classNames(`${prefix}-grid ${tableClassNames}`, {
157
158
  [`${prefix}-grid-light`]: !theme || theme.theme === 'light',
158
159
  [`${prefix}-grid-dark`]: theme?.theme === 'dark'
159
160
  }),
@@ -159,6 +159,8 @@ export type ColumnTable<RecordType = AnyObject> = {
159
159
  onCellStyles?: Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'> | ((cellValue: any, cell: Cell<RecordType, unknown>) => Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'>);
160
160
  onCellHeaderStyles?: Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'> | ((cell: Header<RecordType, unknown>) => Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'>);
161
161
  onCellFooterStyles?: Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'> | ((cellValue: any, cell: Header<RecordType, unknown>) => Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'>);
162
+ sumGroup?: boolean;
163
+ onCell?: (rowData: RecordType, index: number) => React.TdHTMLAttributes<HTMLTableCellElement>;
162
164
  };
163
165
  export type Locale = TableLocale & {
164
166
  ok_btn?: string;
@@ -193,11 +195,13 @@ export type Locale = TableLocale & {
193
195
  };
194
196
  export type ColumnsTable<RecordType = AnyObject> = ColumnTable<RecordType>[];
195
197
  export type TableProps<RecordType = AnyObject> = {
198
+ id?: string;
196
199
  theme?: {
197
200
  theme?: 'dark' | 'light';
198
201
  backgroundColor?: string;
199
202
  color?: string;
200
203
  };
204
+ className?: string;
201
205
  title?: ReactNode | ((data: RecordType) => ReactNode);
202
206
  fullScreenTitle?: ReactNode | (() => ReactNode);
203
207
  editAble?: boolean;
@@ -73,7 +73,7 @@ const CheckboxFilter = props => {
73
73
  prefixCls = 'ui-rc-table-filter',
74
74
  dropdownPrefixCls = 'ui-rc-dropdown',
75
75
  filterMultiple,
76
- selectedKeys,
76
+ selectedKeys: propsSelectedKeys,
77
77
  locale,
78
78
  options,
79
79
  filterMode = 'tree',
@@ -83,6 +83,12 @@ const CheckboxFilter = props => {
83
83
  // setSearchValue,
84
84
  onSelect
85
85
  } = props;
86
+ const selectedKeys = React.useMemo(() => {
87
+ if (propsSelectedKeys) {
88
+ return propsSelectedKeys.map(it => String(it));
89
+ }
90
+ return [];
91
+ }, [propsSelectedKeys]);
86
92
  const [searchValue, setSearchValue] = React.useState('');
87
93
  const [openKeys, setOpenKeys] = React.useState([]);
88
94
 
@@ -138,6 +144,7 @@ const CheckboxFilter = props => {
138
144
  const key = String(filter.value);
139
145
  const item = {
140
146
  title: filter.label,
147
+ id: filter.value !== undefined ? filter.value : index,
141
148
  key: filter.value !== undefined ? key : String(index)
142
149
  };
143
150
  if (filter.children) {
@@ -155,7 +162,7 @@ const CheckboxFilter = props => {
155
162
  });
156
163
  const onCheckAll = e => {
157
164
  if (e.target.checked) {
158
- const allFilterKeys = (0, _useFilter.flattenKeys)(options).map(key => String(key));
165
+ const allFilterKeys = (0, _useFilter.flattenKeys)(options).map(key => key);
159
166
 
160
167
  // setFilteredKeysSync(allFilterKeys);
161
168
  onSelect?.(allFilterKeys);
@@ -170,10 +177,17 @@ const CheckboxFilter = props => {
170
177
  }) => {
171
178
  if (!filterMultiple) {
172
179
  // onSelectKeys({ selectedKeys: checked && node.key ? [node.key] : [] });
173
- onSelect?.(checked && node.key ? [node.key] : []);
180
+
181
+ onSelect?.(checked && node.key ? [node.id] : []);
174
182
  } else {
183
+ if (!checked) {
184
+ const rs = propsSelectedKeys.filter(it => it !== node.id);
185
+ onSelect?.(rs);
186
+ } else {
187
+ const rs = [...propsSelectedKeys, node.id];
188
+ onSelect?.(rs);
189
+ }
175
190
  // onSelectKeys({ selectedKeys: keys });
176
- onSelect?.(keys);
177
191
  }
178
192
  };
179
193
  if (filterMode === 'tree') {
@@ -146,7 +146,7 @@ const TableHeadCell = props => {
146
146
  minWidth: 275,
147
147
  padding: '8px'
148
148
  }
149
- }, /*#__PURE__*/_react.default.createElement("div", null), column.meta?.showOperator !== false && column.meta?.typeFilter !== 'DateRange' && column.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/_react.default.createElement("div", {
149
+ }, /*#__PURE__*/_react.default.createElement("div", null), column.meta?.hideOperator === true && column.meta?.typeFilter !== 'DateRange' && column.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/_react.default.createElement("div", {
150
150
  className: 'mb-1'
151
151
  }, /*#__PURE__*/_react.default.createElement(_rcMasterUi.Select, {
152
152
  options: (0, _hooks.translateOption)(operatorOptions, t),
@@ -145,7 +145,7 @@ const TableHeadCell2 = props => {
145
145
  minWidth: 275,
146
146
  padding: '8px'
147
147
  }
148
- }, /*#__PURE__*/_react.default.createElement("div", null), column.columnDef?.meta?.showOperator !== false && column.columnDef?.meta?.typeFilter !== 'DateRange' && column.columnDef?.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/_react.default.createElement("div", {
148
+ }, /*#__PURE__*/_react.default.createElement("div", null), column.columnDef?.meta?.hideOperator === true && column.columnDef?.meta?.typeFilter !== 'DateRange' && column.columnDef?.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/_react.default.createElement("div", {
149
149
  className: 'mb-1'
150
150
  }, /*#__PURE__*/_react.default.createElement(_rcMasterUi.Select, {
151
151
  options: (0, _hooks.translateOption)(operatorOptions, t),
@@ -267,7 +267,9 @@ const renderFilter = args => {
267
267
  }, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_CheckboxFilter.default, {
268
268
  locale: locale,
269
269
  selectedKeys: selectedKeys,
270
- onSelect: setSelectedKeys
270
+ onSelect: val => {
271
+ setSelectedKeys(val);
272
+ }
271
273
  // options={options}
272
274
  ,
273
275
  options: source ? source : options ?? [],
@@ -915,7 +915,89 @@ const shouldInclude = (item, queries) => {
915
915
  }
916
916
  return result;
917
917
  };
918
+
919
+ // function compareValues(a: any, b: any, order: "ascend" | "descend") {
920
+ // const desc = order === "descend";
921
+
922
+ // if (a == null && b == null) return 0;
923
+ // if (a == null) return desc ? 1 : -1;
924
+ // if (b == null) return desc ? -1 : 1;
925
+
926
+ // // Nếu là số
927
+ // if (typeof a === "number" && typeof b === "number") {
928
+ // return desc ? b - a : a - b;
929
+ // }
930
+
931
+ // // Nếu là ngày hợp lệ
932
+ // const dateA = new Date(a);
933
+ // const dateB = new Date(b);
934
+ // if (!isNaN(dateA.getTime()) && !isNaN(dateB.getTime())) {
935
+ // return desc
936
+ // ? dateB.getTime() - dateA.getTime()
937
+ // : dateA.getTime() - dateB.getTime();
938
+ // }
939
+
940
+ // // Mặc định coi như string
941
+ // return desc
942
+ // ? String(b).localeCompare(String(a))
943
+ // : String(a).localeCompare(String(b));
944
+ // }
945
+
946
+ // export function sortData(data: any[], sorter: Sorter[]): any[] {
947
+ // const sorted = [...data].sort((a, b) => {
948
+ // for (const { field, order } of sorter) {
949
+ // const result = compareValues(a[field], b[field], order);
950
+ // if (result !== 0) return result;
951
+ // }
952
+ // return 0;
953
+ // });
954
+
955
+ // return sorted.map(item => ({
956
+ // ...item,
957
+ // children: item.children
958
+ // ? sortData(item.children, sorter)
959
+ // : undefined
960
+ // }));
961
+ // }
962
+
963
+ // export function filterDataByColumns(data: any[], queries: any[], sorter: Sorter[], keysFilter: string[] | undefined) {
964
+
965
+ // if (!queries || queries.length === 0) {
966
+ // return sorter ? sortData(data, sorter) : data;
967
+ // }
968
+
969
+ // let filtered = data.map(item => {
970
+ // const newItem = { ...item }
971
+
972
+ // if (Array.isArray(item.children)) {
973
+ // newItem.children = filterDataByColumns(item.children, queries, sorter, keysFilter)
974
+ // }
975
+
976
+ // const isSelfMatched = shouldInclude(item, queries) || keysFilter?.includes(newItem?.rowId)
977
+
978
+ // // Nếu chính item thỏa hoặc có con thỏa → giữ lại
979
+ // if (isSelfMatched || (newItem.children && newItem.children.length > 0)) {
980
+ // return newItem
981
+ // }
982
+
983
+ // return null // loại bỏ node không phù hợp
984
+ // })
985
+ // .filter(Boolean) // xóa các null
986
+
987
+ // if (sorter && sorter.length > 0) {
988
+ // filtered = sortData(filtered, sorter);
989
+ // }
990
+
991
+ // return filtered;
992
+ // }
918
993
  exports.shouldInclude = shouldInclude;
994
+ function getSortValue(item, field) {
995
+ if (item[field] !== undefined) return item[field];
996
+ if (item.children && item.children.length > 0) {
997
+ return getSortValue(item.children[0], field);
998
+ }
999
+ return undefined;
1000
+ }
919
1001
  function compareValues(a, b, order) {
920
1002
  const desc = order === "descend";
921
1003
  if (a == null && b == null) return 0;
@@ -943,7 +1025,7 @@ function sortData(data, sorter) {
943
1025
  field,
944
1026
  order
945
1027
  } of sorter) {
946
- const result = compareValues(a[field], b[field], order);
1028
+ const result = compareValues(getSortValue(a, field), getSortValue(b, field), order);
947
1029
  if (result !== 0) return result;
948
1030
  }
949
1031
  return 0;
@@ -60,6 +60,7 @@ const Grid = props => {
60
60
  allowResizing,
61
61
  windowSize,
62
62
  fullScreenTitle,
63
+ className: tableClassNames,
63
64
  ...rest
64
65
  } = props;
65
66
  const [columnResizeMode] = _react.default.useState('onChange');
@@ -263,7 +264,7 @@ const Grid = props => {
263
264
  theme: theme?.theme,
264
265
  ...theme
265
266
  },
266
- className: (0, _classnames.default)(`${prefix}-grid`, {
267
+ className: (0, _classnames.default)(`${prefix}-grid ${tableClassNames}`, {
267
268
  [`${prefix}-grid-light`]: !theme || theme.theme === 'light',
268
269
  [`${prefix}-grid-dark`]: theme?.theme === 'dark'
269
270
  }),
@@ -342,7 +343,7 @@ const Grid = props => {
342
343
  theme: theme?.theme,
343
344
  ...theme
344
345
  },
345
- className: (0, _classnames.default)(`${prefix}-grid`, {
346
+ className: (0, _classnames.default)(`${prefix}-grid ${tableClassNames}`, {
346
347
  [`${prefix}-grid-light`]: !theme || theme.theme === 'light',
347
348
  [`${prefix}-grid-dark`]: theme?.theme === 'dark'
348
349
  }),
@@ -151,7 +151,9 @@ const TableBodyCell = props => {
151
151
  table,
152
152
  isEditing,
153
153
  colSpan,
154
+ rowSpan,
154
155
  groupValue
156
+ // ...cellProps
155
157
  } = props;
156
158
  const {
157
159
  id,
@@ -316,6 +318,10 @@ const TableBodyCell = props => {
316
318
  return /*#__PURE__*/_react.default.createElement("td", {
317
319
  key: cell.id,
318
320
  colSpan: colSpan,
321
+ rowSpan: rowSpan
322
+ // {...cellProps}
323
+ ,
324
+
319
325
  ref: el => {
320
326
  if (focusedCell?.rowId === cell.row.id && focusedCell?.colId === cell.column.id && !isEditing) {
321
327
  el?.focus();
@@ -60,12 +60,22 @@ const TableBodyRow = ({
60
60
  }
61
61
  }
62
62
  }), visibleCells.map(cell => {
63
+ const originCol = cell.column.columnDef.meta ?? {};
64
+ const {
65
+ onCell
66
+ } = originCol ?? {};
67
+ const cellAttributes = onCell?.(cell.row.original, cell.row.index) ?? {};
68
+ const {
69
+ colSpan: onCellColSpan,
70
+ rowSpan: onCellRowSpan,
71
+ ...otherCellAttributes
72
+ } = cellAttributes;
63
73
  const nonGroupColumns = visibleCells.filter(col => col.column.id !== 'selection_column' && col.column.id !== '#');
64
74
  const firstNonGroupColumn = nonGroupColumns[0];
65
75
 
66
76
  // const colSpan = row.subRows && cell.column.id === firstNonGroupColumn?.id ? (groupSetting?.groupColumnSpan ?? 2)
67
- const colSpan = row.subRows && row.subRows.length > 0 && cell.column.id === firstNonGroupColumn?.column.id ? 2 : row.subRows && nonGroupColumns[1].column.id === cell.column.id ? 0 : 1;
68
- if (row.subRows && row.subRows.length > 0 && colSpan === 0) {
77
+ const colSpanGroup = row.subRows && row.subRows.length > 0 && cell.column.id === firstNonGroupColumn?.column.id ? 2 : row.subRows && nonGroupColumns[1].column.id === cell.column.id ? 0 : 1;
78
+ if (row.subRows && row.subRows.length > 0 && colSpanGroup === 0 || onCellRowSpan === 0 || onCellColSpan === 0) {
69
79
  return null;
70
80
  }
71
81
 
@@ -94,7 +104,7 @@ const TableBodyRow = ({
94
104
  rowData: row.original,
95
105
  value: cellValue
96
106
  }) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, headertext, headertext ? ': ' : '', " ", cellContent);
97
- return /*#__PURE__*/_react.default.createElement(_TableBodyCell.default, {
107
+ return /*#__PURE__*/_react.default.createElement(_TableBodyCell.default, (0, _extends2.default)({
98
108
  table: table,
99
109
  tableId: tableId,
100
110
  key: cell.id,
@@ -102,11 +112,13 @@ const TableBodyRow = ({
102
112
  commandClick: commandClick,
103
113
  virtualRow: virtualRow,
104
114
  isEditing: false,
105
- colSpan: colSpan ?? 1,
115
+ colSpan: colSpanGroup ?? 1,
116
+ rowSpan: 1
117
+ }, otherCellAttributes, {
106
118
  groupValue: groupValue
107
- });
119
+ }));
108
120
  }
109
- return /*#__PURE__*/_react.default.createElement(_TableBodyCell.default, {
121
+ return /*#__PURE__*/_react.default.createElement(_TableBodyCell.default, (0, _extends2.default)({
110
122
  table: table,
111
123
  tableId: tableId,
112
124
  key: cell.id,
@@ -114,8 +126,9 @@ const TableBodyRow = ({
114
126
  commandClick: commandClick,
115
127
  virtualRow: virtualRow,
116
128
  isEditing: false,
117
- colSpan: colSpan ?? 1
118
- });
129
+ colSpan: onCellColSpan ?? 1,
130
+ rowSpan: onCellRowSpan ?? 1
131
+ }, otherCellAttributes));
119
132
  }));
120
133
  };
121
134
  var _default = exports.default = TableBodyRow;
@@ -131,7 +131,7 @@ const TableHeadCell = props => {
131
131
  minWidth: 275,
132
132
  padding: '8px'
133
133
  }
134
- }, column.meta?.showOperator !== false && column.meta?.typeFilter !== 'DateRange' && column.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/_react.default.createElement("div", {
134
+ }, column.meta?.hideOperator === true && column.meta?.typeFilter !== 'DateRange' && column.meta?.typeFilter !== 'NumberRange' && /*#__PURE__*/_react.default.createElement("div", {
135
135
  className: 'mb-1'
136
136
  }, /*#__PURE__*/_react.default.createElement(_rcMasterUi.Select, {
137
137
  options: (0, _hooks.translateOption)(operatorOptions, t),
@@ -61,6 +61,7 @@ const Grid = props => {
61
61
  columnFilters,
62
62
  setColumnOrder,
63
63
  rowSelection,
64
+ className: tableClassNames,
64
65
  ...rest
65
66
  } = props;
66
67
  const [isSelectionChange, setIsSelectionChange] = _react.default.useState({
@@ -162,7 +163,7 @@ const Grid = props => {
162
163
  theme: theme?.theme,
163
164
  ...theme
164
165
  },
165
- className: (0, _classnames.default)(`${prefix}-grid`, {
166
+ className: (0, _classnames.default)(`${prefix}-grid ${tableClassNames}`, {
166
167
  [`${prefix}-grid-light`]: !theme || theme.theme === 'light',
167
168
  [`${prefix}-grid-dark`]: theme?.theme === 'dark'
168
169
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "es-grid-template",
3
- "version": "1.8.68",
3
+ "version": "1.8.70",
4
4
  "description": "es-grid-template",
5
5
  "keywords": [
6
6
  "react",