es-grid-template 1.9.18 → 1.9.20

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.
@@ -35,6 +35,7 @@ const Grid = /*#__PURE__*/React.forwardRef((props, ref) => {
35
35
  locale,
36
36
  fullScreen,
37
37
  actionTemplate,
38
+ bottom,
38
39
  theme,
39
40
  height,
40
41
  minHeight,
@@ -292,7 +293,7 @@ const Grid = /*#__PURE__*/React.forwardRef((props, ref) => {
292
293
  },
293
294
  theme: theme,
294
295
  footerDataSource: footerDataSource
295
- })), pagination && !infiniteScroll && /*#__PURE__*/React.createElement(Pagination, _extends({
296
+ })), bottom, pagination && !infiniteScroll && /*#__PURE__*/React.createElement(Pagination, _extends({
296
297
  pageSizeOptions: pageSizeOptions,
297
298
  rootClassName: 'pagination-template',
298
299
  showSizeChanger: true,
@@ -42,16 +42,12 @@ $prefix: 'ui-rc' !default;
42
42
  .ui-rc-grid-table-wrapper.dark {
43
43
 
44
44
  .ui-rc-grid-horizontal-scroll-container {
45
-
46
-
47
- &::-webkit-scrollbar-thumb {
48
- background: rgba(255, 255, 255, 0.3);
49
- }
50
- &::-webkit-scrollbar-thumb:hover {
51
- background: rgba(255, 255, 255, 0.5);
52
- }
45
+ &::-webkit-scrollbar-thumb {
46
+ background: rgba(255, 255, 255, 0.3);
47
+ }
48
+ &::-webkit-scrollbar-thumb:hover {
49
+ background: rgba(255, 255, 255, 0.5);
50
+ }
53
51
  }
54
-
55
52
 
56
-
57
53
  }
@@ -4,7 +4,7 @@ import type { Cell, Header, OnChangeFn } from '@tanstack/react-table';
4
4
  import type { CSSProperties, ReactElement, ReactNode } from 'react';
5
5
  import type { TableLocale } from "rc-master-ui/lib/table/interface";
6
6
  import type { PaginationLocale } from 'rc-master-ui/lib/pagination/Pagination';
7
- import { BaseTableCSSVariables } from '../ali-table/base-table/styles';
7
+ import type { BaseTableCSSVariables } from '../ali-table/base-table/styles';
8
8
  declare module "@tanstack/table-core" {
9
9
  interface ColumnMeta<any, any> extends ColumnTable {
10
10
  rowSpan?: number;
@@ -135,95 +135,175 @@ export interface SpanRect {
135
135
  right: number;
136
136
  }
137
137
  export type ColumnTable<RecordType = AnyObject> = {
138
+ /** Field key dùng để mapping dữ liệu */
138
139
  field: string;
140
+ /** Text hiển thị ở header */
141
+ headerText?: string;
142
+ /** Field gốc trước khi transform */
139
143
  fieldOriginal?: string;
144
+ /** Độ rộng column */
140
145
  width?: number;
146
+ /** Độ rộng tối đa */
141
147
  maxWidth?: number;
148
+ /** Độ rộng tối thiểu */
142
149
  minWidth?: number;
150
+ /** Hiển thị trong popup chọn column */
151
+ showInColumnChoose?: boolean;
152
+ /** Kiểu dữ liệu của column */
143
153
  type?: IColumnType;
154
+ /** Format hiển thị dữ liệu column type = number */
155
+ format?: IFormat | ((rowData: any) => IFormat);
156
+ /**
157
+ * @deprecated Please use `isSummary` instead.
158
+ * @since 1.7.25
159
+ */
144
160
  haveSum?: boolean;
161
+ /** Có tính tổng column type = number hay không
162
+ *
163
+ * Mặc định = true
164
+ */
145
165
  isSummary?: boolean;
166
+ /** Có tính tổng theo group */
167
+ sumGroup?: boolean;
168
+ /** Template custom cho ô summary */
146
169
  summaryTemplate?: (data: number, key: string) => ReactElement | ReactNode;
147
- /** Custom method to get cell props */
148
- format?: IFormat | ((rowData: any) => IFormat);
149
- allowFiltering?: boolean;
150
170
  /**
151
171
  * @deprecated Please use `allowSortering` instead.
152
172
  * @since 1.7.25
153
173
  */
154
174
  sorter?: boolean;
175
+ /** Cho phép filter
176
+ *
177
+ * Mặc định = true
178
+ */
179
+ allowFiltering?: boolean;
180
+ /** Cho phép sort dữ liệu
181
+ *
182
+ * Mặc định = true
183
+ * */
155
184
  allowSortering?: boolean;
185
+ /** Kiểu filter */
186
+ typeFilter?: TypeFilter;
187
+ /** Toán tử filter mặc định */
156
188
  operator?: FilterOperator;
189
+ /** Ẩn phần chọn toán tử filter
190
+ * mặc đinh = false
191
+ */
157
192
  hideOperator?: boolean;
193
+ /** Custom Placeholder cho input/ Select/ Date.... filter */
158
194
  placeholder?: string;
159
- showInColumnChoose?: boolean;
160
- typeFilter?: TypeFilter;
195
+ /** Data source cho select/filter */
161
196
  source?: any[];
197
+ /** Hiển thị ô search trong select filter */
162
198
  showFilterSearch?: boolean;
163
- headerText?: string;
164
199
  /**
165
200
  * @deprecated Please use `visible` instead.
166
201
  * @since 1.7.33
167
202
  */
168
203
  hidden?: boolean;
204
+ /** Hiển thị / ẩn column
205
+ * mặc định = true
206
+ * */
169
207
  visible?: boolean;
208
+ /** Tooltip cho header */
170
209
  headerTooltip?: boolean | string | (() => ReactNode | ReactElement);
210
+ /** Tên group header */
171
211
  columnGroupText?: string;
172
- /**
173
- * @deprecated Please use `textAlign` instead.
174
- * @since 1.7.34
175
- */
176
- align?: ITextAlign;
177
- textAlign?: ITextAlign;
212
+ /** Canh lề nội dung header */
178
213
  headerTextAlign?: ITextAlign;
179
- template?: ReactNode | ReactElement | ((args: ColumnTemplate<RecordType>) => ReactNode | ReactElement);
180
- showTooltip?: boolean;
181
- tooltipDescription?: string | ((args: {
182
- value: any;
183
- rowData: RecordType;
184
- }) => ReactNode | ReactElement);
214
+ /** Template custom render header */
185
215
  headerTemplate?: React.ReactNode | React.ReactElement | ((column: ColumnTable<RecordType>) => React.ReactNode | React.ReactElement);
186
- commandItems?: CommandItem[];
187
- children?: ColumnTable<RecordType>[];
188
- editType?: EditType | ((rowData?: RecordType) => EditType);
189
- disable?: boolean | ((rowData: any) => boolean);
190
- editEnable?: boolean | ((rowData: any) => boolean);
191
- isClearable?: boolean;
192
- maxDate?: any;
193
- minDate?: any;
194
- maxTime?: any;
195
- minTime?: any;
196
- max?: number;
197
- min?: number;
198
- editSelectSettings?: IEditSelectSettings;
199
- editFromSettings?: IEditFromSettings;
200
216
  /**
201
217
  * @deprecated Please use `fixed` instead.
202
218
  * @since 1.7.25
203
219
  */
204
220
  fixedType?: FixedType;
221
+ /** Fixed column trái/phải */
205
222
  fixed?: FixedType;
206
223
  /**
207
- * @deprecated Please use `wrapSettings` instead.
224
+ * @deprecated Please use `wrapSettings` on Table instead.
208
225
  * @since 1.7.34
209
226
  */
210
227
  headerTextWrap?: boolean;
228
+ /** Hiển thị dấu ... khi text overflow */
211
229
  ellipsis?: boolean;
230
+ /** Cho phép resize column
231
+ *
232
+ * Mặc định = true
233
+ */
212
234
  allowResizing?: boolean;
213
- allowSelection?: boolean | ((rowData: RecordType) => boolean);
235
+ /**
236
+ * @deprecated Please use `textAlign` instead.
237
+ * @since 1.7.34
238
+ */
239
+ align?: ITextAlign;
240
+ /** Canh lề nội dung cell */
241
+ textAlign?: ITextAlign;
242
+ /** Template custom render cell */
243
+ template?: ReactNode | ReactElement | ((args: ColumnTemplate<RecordType>) => ReactNode | ReactElement);
244
+ /** Hiển thị tooltip cell */
245
+ showTooltip?: boolean;
246
+ /** Nội dung tooltip của cell */
247
+ tooltipDescription?: string | ((args: {
248
+ value: any;
249
+ rowData: RecordType;
250
+ }) => ReactNode | ReactElement);
251
+ /**
252
+ * @deprecated Please use `getCellProps` instead.
253
+ * @since 1.7.34
254
+ */
214
255
  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'>);
256
+ /**
257
+ * @deprecated Please use `headerCellProps` instead.
258
+ * @since 1.7.34
259
+ */
215
260
  onCellHeaderStyles?: Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'> | ((cell: Header<RecordType, unknown>) => Omit<React.CSSProperties, 'display' | 'width' | 'minWidth' | 'left' | 'right' | 'position'>);
261
+ /**
262
+ * @deprecated Please use `getCellProps` instead.
263
+ * @since 1.7.34
264
+ */
265
+ onCell?: (rowData: RecordType, index: number) => React.TdHTMLAttributes<HTMLTableCellElement>;
216
266
  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'>);
217
- sumGroup?: boolean;
218
267
  /** Custom data retrieval method */
268
+ /** Custom method lấy value cell */
219
269
  getValue?: (row: any, rowIndex: number) => any;
220
- /** Custom render method */
221
270
  /** Custom method to get cell props */
222
271
  getCellProps?: (value: any, row: any, rowIndex: number) => CellProps;
223
272
  /** Props for the header cell */
224
273
  headerCellProps?: CellProps;
225
274
  /** Custom method to get cell SpanRect */
275
+ /** Custom merge cell */
226
276
  getSpanRect?: (value: any, row: any, rowIndex: number) => SpanRect;
277
+ /** Kiểu editor khi edit cell */
278
+ editType?: EditType | ((rowData?: RecordType) => EditType);
279
+ /** Disable editor */
280
+ disable?: boolean | ((rowData: any) => boolean);
281
+ /** Cho phép edit */
282
+ editEnable?: boolean | ((rowData: any) => boolean);
283
+ /** Cho phép clear value khi edit */
284
+ isClearable?: boolean;
285
+ /** Ngày lớn nhất cho date picker */
286
+ maxDate?: any;
287
+ /** Ngày nhỏ nhất cho date picker */
288
+ minDate?: any;
289
+ /** Thời gian lớn nhất */
290
+ maxTime?: any;
291
+ /** Thời gian nhỏ nhất */
292
+ minTime?: any;
293
+ /** Giá trị số lớn nhất khi editType : number */
294
+ max?: number;
295
+ /** Giá trị số nhỏ nhất khi editType : number */
296
+ min?: number;
297
+ /** Config select editor */
298
+ editSelectSettings?: IEditSelectSettings;
299
+ /** Config form editor */
300
+ editFromSettings?: IEditFromSettings;
301
+ /** Cho phép select column */
302
+ allowSelection?: boolean | ((rowData: RecordType) => boolean);
303
+ /** Danh sách command/action trong column type = command */
304
+ commandItems?: CommandItem[];
305
+ /** Column con (multi header/group column) */
306
+ children?: ColumnTable<RecordType>[];
227
307
  };
228
308
  export type ColumnsTable<RecordType = AnyObject> = ColumnTable<RecordType>[];
229
309
  export type IFTheme = {
@@ -315,6 +395,7 @@ export type TableProps<RecordType = AnyObject> = {
315
395
  }) => void;
316
396
  expandable?: ExpandableConfig<RecordType>;
317
397
  actionTemplate?: ReactNode | ReactElement | (() => ReactNode | ReactElement);
398
+ bottom?: ReactNode;
318
399
  rowClassName?: string | RowClassName<RecordType>;
319
400
  onRowStyles?: CSSProperties | ((data: RecordType) => CSSProperties);
320
401
  onRowHeaderStyles?: Omit<React.CSSProperties, 'display' | 'transform' | 'gridTemplateColumns' | 'height' | 'minHeight'> | (() => Omit<React.CSSProperties, 'display' | 'transform' | 'gridTemplateColumns' | 'height' | 'minHeight'>);
@@ -155,42 +155,53 @@ export declare const removeColumns: <RecordType>(columns: ColumnTable<RecordType
155
155
  export declare const fixColumnsLeft: <RecordType>(columns: ColumnTable<RecordType>[], fixedFields: string[]) => {
156
156
  fixed: string;
157
157
  field: string;
158
+ headerText?: string;
158
159
  fieldOriginal?: string;
159
160
  width?: number;
160
161
  maxWidth?: number;
161
162
  minWidth?: number;
163
+ showInColumnChoose?: boolean;
162
164
  type?: IColumnType;
165
+ format?: IFormat | ((rowData: any) => IFormat);
163
166
  haveSum?: boolean;
164
167
  isSummary?: boolean;
165
- summaryTemplate?: (data: number, key: string) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode;
166
- format?: IFormat | ((rowData: any) => IFormat);
167
- allowFiltering?: boolean;
168
+ sumGroup?: boolean;
169
+ summaryTemplate?: (data: number, key: string) => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
168
170
  sorter?: boolean;
171
+ allowFiltering?: boolean;
169
172
  allowSortering?: boolean;
173
+ typeFilter?: TypeFilter;
170
174
  operator?: FilterOperator;
171
175
  hideOperator?: boolean;
172
176
  placeholder?: string;
173
- showInColumnChoose?: boolean;
174
- typeFilter?: TypeFilter;
175
177
  source?: any[];
176
178
  showFilterSearch?: boolean;
177
- headerText?: string;
178
179
  hidden?: boolean;
179
180
  visible?: boolean;
180
- headerTooltip?: string | boolean | (() => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode);
181
+ headerTooltip?: string | boolean | (() => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>);
181
182
  columnGroupText?: string;
183
+ headerTextAlign?: import("./../../grid-component/type").ITextAlign;
184
+ 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>>);
185
+ fixedType?: import("./../../grid-component/type").FixedType;
186
+ headerTextWrap?: boolean;
187
+ ellipsis?: boolean;
188
+ allowResizing?: boolean;
182
189
  align?: import("./../../grid-component/type").ITextAlign;
183
190
  textAlign?: import("./../../grid-component/type").ITextAlign;
184
- headerTextAlign?: import("./../../grid-component/type").ITextAlign;
185
- 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);
191
+ 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>>);
186
192
  showTooltip?: boolean;
187
193
  tooltipDescription?: string | ((args: {
188
194
  value: any;
189
195
  rowData: RecordType;
190
- }) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactNode);
191
- 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);
192
- commandItems?: import("./../../grid-component/type").CommandItem[];
193
- children?: ColumnTable<RecordType>[];
196
+ }) => import("react").ReactNode | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>);
197
+ 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">);
198
+ 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">);
199
+ onCell?: (rowData: RecordType, index: number) => import("react").TdHTMLAttributes<HTMLTableCellElement>;
200
+ 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">);
201
+ getValue?: (row: any, rowIndex: number) => any;
202
+ getCellProps?: (value: any, row: any, rowIndex: number) => import("./../../grid-component/type").CellProps;
203
+ headerCellProps?: import("./../../grid-component/type").CellProps;
204
+ getSpanRect?: (value: any, row: any, rowIndex: number) => import("./../../grid-component/type").SpanRect;
194
205
  editType?: EditType | ((rowData?: RecordType) => EditType);
195
206
  disable?: boolean | ((rowData: any) => boolean);
196
207
  editEnable?: boolean | ((rowData: any) => boolean);
@@ -203,18 +214,8 @@ export declare const fixColumnsLeft: <RecordType>(columns: ColumnTable<RecordTyp
203
214
  min?: number;
204
215
  editSelectSettings?: import("./../../grid-component/type").IEditSelectSettings;
205
216
  editFromSettings?: import("./../../grid-component/type").IEditFromSettings;
206
- fixedType?: import("./../../grid-component/type").FixedType;
207
- headerTextWrap?: boolean;
208
- ellipsis?: boolean;
209
- allowResizing?: boolean;
210
217
  allowSelection?: boolean | ((rowData: RecordType) => boolean);
211
- onCellStyles?: Omit<CSSProperties, "left" | "right" | "position" | "display" | "minWidth" | "width"> | ((cellValue: any, cell: import("@tanstack/react-table").Cell<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "position" | "display" | "minWidth" | "width">);
212
- onCellHeaderStyles?: Omit<CSSProperties, "left" | "right" | "position" | "display" | "minWidth" | "width"> | ((cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "position" | "display" | "minWidth" | "width">);
213
- onCellFooterStyles?: Omit<CSSProperties, "left" | "right" | "position" | "display" | "minWidth" | "width"> | ((cellValue: any, cell: import("@tanstack/react-table").Header<RecordType, unknown>) => Omit<CSSProperties, "left" | "right" | "position" | "display" | "minWidth" | "width">);
214
- sumGroup?: boolean;
215
- getValue?: (row: any, rowIndex: number) => any;
216
- getCellProps?: (value: any, row: any, rowIndex: number) => import("./../../grid-component/type").CellProps;
217
- headerCellProps?: import("./../../grid-component/type").CellProps;
218
- getSpanRect?: (value: any, row: any, rowIndex: number) => import("./../../grid-component/type").SpanRect;
218
+ commandItems?: import("./../../grid-component/type").CommandItem[];
219
+ children?: ColumnTable<RecordType>[];
219
220
  }[];
220
221
  export declare function sortColumnsByField<T extends ColumnTable>(columns: T[], priorityFields: string[]): T[];
@@ -194,7 +194,9 @@ const TableHeadCell2 = props => {
194
194
  doFilter,
195
195
  format,
196
196
  dataSourceFilter,
197
- tableLocal
197
+ tableLocal,
198
+ prevFilterValue: column.getFilterValue(),
199
+ triggerVisible
198
200
  })), /*#__PURE__*/React.createElement(Space, {
199
201
  style: {
200
202
  justifyContent: 'end',
@@ -16,6 +16,8 @@ type RenderFilterProps<RecordType> = {
16
16
  dateRangeLocale?: any;
17
17
  doFilter?: (type: boolean) => void;
18
18
  tableLocal: any;
19
+ prevFilterValue?: string[];
20
+ triggerVisible?: (visible: boolean) => void;
19
21
  };
20
22
  export declare const renderFilter: <RecordType>(args: RenderFilterProps<RecordType>) => React.JSX.Element;
21
23
  export {};
@@ -10,6 +10,16 @@ import { convertDateToDayjs, convertDayjsToDate, convertFormat, getDatepickerFor
10
10
  import NumberInput from "../components/number";
11
11
  import NumberRange from "../components/number-range";
12
12
  import CheckboxFilter from "../components/checkbox-filter/CheckboxFilter";
13
+ const isEqualDateArray = (arr1, arr2) => {
14
+ if (arr1?.length !== arr2?.length) {
15
+ return false;
16
+ }
17
+ return arr1?.every((item, index) => {
18
+ const date1 = new Date(item).getTime();
19
+ const date2 = new Date(arr2?.[index]).getTime();
20
+ return date1 === date2;
21
+ });
22
+ };
13
23
  export const renderFilter = args => {
14
24
  const {
15
25
  column,
@@ -20,7 +30,9 @@ export const renderFilter = args => {
20
30
  dataSourceFilter,
21
31
  format,
22
32
  doFilter,
23
- tableLocal
33
+ tableLocal,
34
+ prevFilterValue,
35
+ triggerVisible
24
36
  } = args;
25
37
  const {
26
38
  format: columnFormat,
@@ -97,10 +109,26 @@ export const renderFilter = args => {
97
109
  onChange: value => {
98
110
  const newDateRangeValue = value ? [value[0] ? moment(value[0]).format() : '', value[1] ? moment(value[1]).format() : ''] : [];
99
111
  setSelectedKeys(newDateRangeValue);
100
- }
112
+ },
113
+ onOk: value => {
114
+ const newDateRangeValue = value ? [value[0] ? moment(value[0]).format() : '', value[1] ? moment(value[1]).format() : ''] : [];
115
+ setSelectedKeys(newDateRangeValue);
116
+ },
117
+ onExit: () => {
118
+ // clear nhưng chưa ấn OK
119
+ if (!dateRangeValue) {
120
+ return;
121
+ }
101
122
 
102
- // onSelect={(val) => {
103
- // }}
123
+ // Click ok
124
+ if (!isEqualDateArray(dateRangeValue, prevFilterValue)) {
125
+ // giá trị khác nhau
126
+ doFilter?.(true);
127
+ } else {
128
+ // giá trị = nhau
129
+ triggerVisible?.(false);
130
+ }
131
+ }
104
132
 
105
133
  // menuClassName="rc-menu-popup"
106
134
  ,
@@ -67,6 +67,8 @@ export declare const detectSeparators: (str: string) => {
67
67
  thousandSeparator: string;
68
68
  decimalSeparator: string;
69
69
  };
70
+ export declare const isDateValue: (value: any) => boolean;
71
+ export declare const convertFomatedDateToDate: (value: string) => Date | null;
70
72
  export declare function isDateString(str: any): boolean;
71
73
  export declare function compareDates(date1: any, date2: any): boolean;
72
74
  export declare function compareDate(itemValue: any, value: any): boolean;
@@ -727,6 +727,172 @@ export const detectSeparators = str => {
727
727
  // Không có dấu hoặc không hợp lệ
728
728
  return null;
729
729
  };
730
+ export const isDateValue = value => {
731
+ if (value === null || value === undefined) {
732
+ return false;
733
+ }
734
+
735
+ // Date object
736
+ if (value instanceof Date) {
737
+ return !isNaN(value.getTime());
738
+ }
739
+
740
+ // number timestamp
741
+ if (typeof value === 'number') {
742
+ const date = new Date(value);
743
+ return !isNaN(date.getTime());
744
+ }
745
+ if (typeof value !== 'string') return false;
746
+ const str = value.trim();
747
+ if (!str) {
748
+ return false;
749
+ }
750
+
751
+ // Các format date phổ biến
752
+ const patterns = [
753
+ // dd/MM/yyyy
754
+ /^\d{2}\/\d{2}\/\d{4}$/,
755
+ // d/M/yyyy
756
+ /^\d{1,2}\/\d{1,2}\/\d{4}$/,
757
+ // yyyy/MM/dd
758
+ /^\d{4}\/\d{2}\/\d{2}$/,
759
+ // yyyy/M/d
760
+ /^\d{4}\/\d{1,2}\/\d{1,2}$/,
761
+ // MM/yyyy
762
+ /^\d{2}\/\d{4}$/,
763
+ // M/yyyy
764
+ /^\d{1,2}\/\d{4}$/,
765
+ // yyyy/MM
766
+ /^\d{4}\/\d{2}$/,
767
+ // yyyy/M
768
+ /^\d{4}\/\d{1,2}$/,
769
+ // dd-MM-yyyy
770
+ /^\d{2}-\d{2}-\d{4}$/,
771
+ // yyyy-MM-dd
772
+ /^\d{4}-\d{2}-\d{2}$/,
773
+ // yyyy-M-d
774
+ /^\d{4}-\d{1,2}-\d{1,2}$/,
775
+ // ISO datetime
776
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/,
777
+ // ISO datetime milliseconds
778
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z?$/,
779
+ // yyyyMMdd
780
+ /^\d{8}$/,
781
+ // dd MMM yyyy
782
+ /^\d{1,2}\s[A-Za-z]{3}\s\d{4}$/,
783
+ // MMM dd, yyyy
784
+ /^[A-Za-z]{3}\s\d{1,2},\s\d{4}$/,
785
+ // full text date
786
+ /^[A-Za-z]+,\s[A-Za-z]+\s\d{1,2},\s\d{4}$/];
787
+ const matched = patterns.some(regex => regex.test(str));
788
+ if (matched) {
789
+ return true;
790
+ }
791
+
792
+ // fallback:
793
+ // nếu regex không match nhưng Date parse được
794
+ if (!matched) {
795
+ const fallbackDate = new Date(str);
796
+ return !isNaN(fallbackDate.getTime());
797
+ }
798
+
799
+ // validate real date
800
+ const date = new Date(str);
801
+ return !isNaN(date.getTime());
802
+ };
803
+ export const convertFomatedDateToDate = value => {
804
+ const monthMap = {
805
+ Jan: 0,
806
+ Feb: 1,
807
+ Mar: 2,
808
+ Apr: 3,
809
+ May: 4,
810
+ Jun: 5,
811
+ Jul: 6,
812
+ Aug: 7,
813
+ Sep: 8,
814
+ Oct: 9,
815
+ Nov: 10,
816
+ Dec: 11
817
+ };
818
+ let date = null;
819
+
820
+ // dd/MM/yyyy | d/M/yyyy
821
+ if (/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(value)) {
822
+ const [d, m, y] = value.split('/').map(Number);
823
+ date = new Date(y, m - 1, d);
824
+ }
825
+
826
+ // yyyy/MM/dd | yyyy/M/d
827
+ else if (/^\d{4}\/\d{1,2}\/\d{1,2}$/.test(value)) {
828
+ const [y, m, d] = value.split('/').map(Number);
829
+ date = new Date(y, m - 1, d);
830
+ }
831
+
832
+ // MM/yyyy | M/yyyy
833
+ else if (/^\d{1,2}\/\d{4}$/.test(value)) {
834
+ const [m, y] = value.split('/').map(Number);
835
+ date = new Date(y, m - 1, 1);
836
+ }
837
+
838
+ // yyyy/MM | yyyy/M
839
+ else if (/^\d{4}\/\d{1,2}$/.test(value)) {
840
+ const [y, m] = value.split('/').map(Number);
841
+ date = new Date(y, m - 1, 1);
842
+ }
843
+
844
+ // dd-MM-yyyy
845
+ else if (/^\d{2}-\d{2}-\d{4}$/.test(value)) {
846
+ const [d, m, y] = value.split('-').map(Number);
847
+ date = new Date(y, m - 1, d);
848
+ }
849
+
850
+ // yyyy-MM-dd | yyyy-M-d
851
+ else if (/^\d{4}-\d{1,2}-\d{1,2}$/.test(value)) {
852
+ const [y, m, d] = value.split('-').map(Number);
853
+ date = new Date(y, m - 1, d);
854
+ }
855
+
856
+ // ISO datetime
857
+ else if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/.test(value)) {
858
+ date = new Date(value);
859
+ }
860
+
861
+ // ISO datetime milliseconds
862
+ else if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z?$/.test(value)) {
863
+ date = new Date(value);
864
+ }
865
+
866
+ // yyyyMMdd
867
+ else if (/^\d{8}$/.test(value)) {
868
+ const y = Number(value.slice(0, 4));
869
+ const m = Number(value.slice(4, 6));
870
+ const d = Number(value.slice(6, 8));
871
+ date = new Date(y, m - 1, d);
872
+ }
873
+
874
+ // dd MMM yyyy
875
+ else if (/^\d{1,2}\s[A-Za-z]{3}\s\d{4}$/.test(value)) {
876
+ const [d, mon, y] = value.split(' ');
877
+ date = new Date(Number(y), monthMap[mon], Number(d));
878
+ }
879
+
880
+ // MMM dd, yyyy
881
+ else if (/^[A-Za-z]{3}\s\d{1,2},\s\d{4}$/.test(value)) {
882
+ const [mon, dayComma, y] = value.split(' ');
883
+ const d = Number(dayComma.replace(',', ''));
884
+ date = new Date(Number(y), monthMap[mon], d);
885
+ }
886
+
887
+ // full text date
888
+ else if (/^[A-Za-z]+,\s[A-Za-z]+\s\d{1,2},\s\d{4}$/.test(value)) {
889
+ date = new Date(value);
890
+ }
891
+ if (!date || isNaN(date.getTime())) {
892
+ return null;
893
+ }
894
+ return date;
895
+ };
730
896
  function isDate(value) {
731
897
  if (value instanceof Date) {
732
898
  return !isNaN(value.getTime());
@@ -786,8 +952,11 @@ export const shouldInclude = (item, queries, ignoreAccents) => {
786
952
  } = query;
787
953
  const itemValue = item[field];
788
954
  let condition = false;
789
- const isDateComparison = isDate(itemValue) || isDateString(value);
790
- const itemDate = isDateComparison ? new Date(itemValue) : null;
955
+
956
+ // const aaa = convertFomatedDateToDate('25/01/2026')
957
+
958
+ const isDateComparison = isDate(itemValue) || isDateString(value) || isDateValue(itemValue) || isDateValue(value);
959
+ const itemDate = isDateComparison ? isNaN(new Date(itemValue).getTime()) ? convertFomatedDateToDate(itemValue) : new Date(itemValue) : null;
791
960
  const queryDate = isDateComparison ? parseToDate(value) : null;
792
961
  const itemStr = removeVietnameseTones(itemValue?.toString().toLowerCase?.() ?? '');
793
962
  const queryStr = removeVietnameseTones(value?.toString().toLowerCase?.() ?? '');
@@ -45,6 +45,7 @@ const Grid = /*#__PURE__*/_react.default.forwardRef((props, ref) => {
45
45
  locale,
46
46
  fullScreen,
47
47
  actionTemplate,
48
+ bottom,
48
49
  theme,
49
50
  height,
50
51
  minHeight,
@@ -302,7 +303,7 @@ const Grid = /*#__PURE__*/_react.default.forwardRef((props, ref) => {
302
303
  },
303
304
  theme: theme,
304
305
  footerDataSource: footerDataSource
305
- })), pagination && !infiniteScroll && /*#__PURE__*/_react.default.createElement(_pagination.default, (0, _extends2.default)({
306
+ })), bottom, pagination && !infiniteScroll && /*#__PURE__*/_react.default.createElement(_pagination.default, (0, _extends2.default)({
306
307
  pageSizeOptions: _hooks.pageSizeOptions,
307
308
  rootClassName: 'pagination-template',
308
309
  showSizeChanger: true,