react-table-edit 1.4.23 → 1.4.24

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,13 +1,16 @@
1
1
  import { Dispatch, SetStateAction } from 'react';
2
- import { IHeaderColumnTable } from "../type";
2
+ import { IFFilterTable, IFOrderTable, IFTableEditFormat, IHeaderColumnTable } from "../type";
3
3
  import 'react-resizable/css/styles.css';
4
4
  type IFDataProps = {
5
+ idTable: string;
5
6
  selectEnable: boolean;
6
7
  dataSource: any[];
7
8
  setSelectedRows: Dispatch<SetStateAction<any[]>>;
8
9
  col: IHeaderColumnTable;
9
- column: IHeaderColumnTable[];
10
- setColumn: Dispatch<SetStateAction<IHeaderColumnTable[]>>;
10
+ columns: IHeaderColumnTable[];
11
+ setColumns?: (columns: IHeaderColumnTable[]) => void;
12
+ changeFilter: (data: IFFilterTable[]) => void;
13
+ changeOrder: (data: IFOrderTable[]) => void;
11
14
  indexCol: number;
12
15
  indexParent: number;
13
16
  objWidthFixLeft: any;
@@ -17,6 +20,13 @@ type IFDataProps = {
17
20
  fisrtObjWidthFixRight: number;
18
21
  selectedRows: any[];
19
22
  isMulti: boolean;
23
+ allowFilter?: boolean;
24
+ allowOrder?: boolean;
25
+ filterBy: IFFilterTable[];
26
+ orderBy: IFOrderTable[];
27
+ container: any;
28
+ optionsFilter: any;
29
+ formatSetting?: IFTableEditFormat;
20
30
  };
21
31
  declare const HeaderTableCol: (props: IFDataProps) => import("react/jsx-runtime").JSX.Element;
22
32
  export default HeaderTableCol;
@@ -23,6 +23,9 @@ export type IFTableEditProps = {
23
23
  searchSetting?: IFTableEditSearchSetting;
24
24
  selectedItem?: any;
25
25
  setDataSource?: any;
26
+ allowFilter?: boolean;
27
+ allowOrder?: boolean;
28
+ optionsFilter?: any;
26
29
  setSelectedItem?: Dispatch<SetStateAction<any>>;
27
30
  commandClick?: (data: any) => void;
28
31
  handleSelect?: (data: any) => void;
@@ -159,6 +159,10 @@ export type IColumnTable = {
159
159
  columns?: IColumnTable[];
160
160
  /** Không cho phép dán giá trị */
161
161
  disablePaste?: boolean;
162
+ /** Kiểu lọc cột */
163
+ filterType?: IFilterType;
164
+ /** Cho phép lọc cột */
165
+ allowFilter?: boolean;
162
166
  /**Giá trị trường callback khi copy xuống các dòng dưới */
163
167
  callbackValue?: (row: any) => any;
164
168
  /** Validate giá trị */
@@ -284,8 +288,16 @@ export type IHeaderColumnTable = {
284
288
  columns?: IColumnTable[];
285
289
  /** Căn lề */
286
290
  textAlign?: ITextAlign;
291
+ /** Kiểu lọc cột */
292
+ filterType?: IFilterType;
293
+ /** Cho phép lọc cột */
294
+ allowFilter?: boolean;
287
295
  /** Cố định trái/phải */
288
296
  fixedType?: 'left' | 'right' | undefined;
297
+ /** Cấu hình cho kiểu numeric */
298
+ numericSettings?: ISettingNumericElement;
299
+ /** Kiểu chỉnh sửa */
300
+ editType?: IEditType;
289
301
  /** Thứ tự cột */
290
302
  index?: number;
291
303
  };
@@ -45,4 +45,6 @@ export declare const calculateTableStructure: (columns: any[]) => {
45
45
  objWidthFixRight: Record<number, number>;
46
46
  lastObjWidthFixLeft: number;
47
47
  fisrtObjWidthFixRight: number;
48
+ firstEdit: any;
49
+ lastEdit: any;
48
50
  };
@@ -12,11 +12,11 @@ type VirtualTableProps = {
12
12
  formatSetting?: IFTableEditFormat;
13
13
  allowFilter?: boolean;
14
14
  allowOrder?: boolean;
15
+ optionsFilter?: any;
15
16
  pagingSetting?: IFTableEditPaging;
16
17
  toolbarSetting?: IFTableEditToolbar;
17
18
  searchSetting?: IFTableEditSearchSetting;
18
19
  columnsAggregate?: IColumnsVirtualizedAgg[];
19
- optionsFilter?: any;
20
20
  setColumns?: (columns: IColumnVirtualizedTable[]) => void;
21
21
  commandClick?: (data: any) => void;
22
22
  changeFilter?: (data: IFFilterTable[]) => void;
package/dist/index.d.ts CHANGED
@@ -163,6 +163,10 @@ type IColumnTable = {
163
163
  columns?: IColumnTable[];
164
164
  /** Không cho phép dán giá trị */
165
165
  disablePaste?: boolean;
166
+ /** Kiểu lọc cột */
167
+ filterType?: IFilterType;
168
+ /** Cho phép lọc cột */
169
+ allowFilter?: boolean;
166
170
  /**Giá trị trường callback khi copy xuống các dòng dưới */
167
171
  callbackValue?: (row: any) => any;
168
172
  /** Validate giá trị */
@@ -288,8 +292,16 @@ type IHeaderColumnTable = {
288
292
  columns?: IColumnTable[];
289
293
  /** Căn lề */
290
294
  textAlign?: ITextAlign;
295
+ /** Kiểu lọc cột */
296
+ filterType?: IFilterType;
297
+ /** Cho phép lọc cột */
298
+ allowFilter?: boolean;
291
299
  /** Cố định trái/phải */
292
300
  fixedType?: 'left' | 'right' | undefined;
301
+ /** Cấu hình cho kiểu numeric */
302
+ numericSettings?: ISettingNumericElement;
303
+ /** Kiểu chỉnh sửa */
304
+ editType?: IEditType;
293
305
  /** Thứ tự cột */
294
306
  index?: number;
295
307
  };
@@ -433,6 +445,9 @@ type IFTableEditProps = {
433
445
  searchSetting?: IFTableEditSearchSetting;
434
446
  selectedItem?: any;
435
447
  setDataSource?: any;
448
+ allowFilter?: boolean;
449
+ allowOrder?: boolean;
450
+ optionsFilter?: any;
436
451
  setSelectedItem?: Dispatch<SetStateAction<any>>;
437
452
  commandClick?: (data: any) => void;
438
453
  handleSelect?: (data: any) => void;
@@ -501,6 +516,8 @@ declare const calculateTableStructure: (columns: any[]) => {
501
516
  objWidthFixRight: Record<number, number>;
502
517
  lastObjWidthFixLeft: number;
503
518
  fisrtObjWidthFixRight: number;
519
+ firstEdit: any;
520
+ lastEdit: any;
504
521
  };
505
522
 
506
523
  type IFDataProps$1 = {
@@ -722,11 +739,11 @@ type VirtualTableProps = {
722
739
  formatSetting?: IFTableEditFormat;
723
740
  allowFilter?: boolean;
724
741
  allowOrder?: boolean;
742
+ optionsFilter?: any;
725
743
  pagingSetting?: IFTableEditPaging;
726
744
  toolbarSetting?: IFTableEditToolbar;
727
745
  searchSetting?: IFTableEditSearchSetting;
728
746
  columnsAggregate?: IColumnsVirtualizedAgg[];
729
- optionsFilter?: any;
730
747
  setColumns?: (columns: IColumnVirtualizedTable[]) => void;
731
748
  commandClick?: (data: any) => void;
732
749
  changeFilter?: (data: IFFilterTable[]) => void;
package/dist/index.js CHANGED
@@ -19358,6 +19358,9 @@ const calculateTableStructure = (columns) => {
19358
19358
  const flatVisble = flat.filter((e) => e.visible !== false);
19359
19359
  const lastObjWidthFixLeft = Math.max(...Object.keys(objWidthFixLeft).map(Number), 0);
19360
19360
  const fisrtObjWidthFixRight = Math.min(...Object.keys(objWidthFixRight).map(Number), flat.length);
19361
+ const editableColumns = flat.filter(item => item.editEnable && item.visible !== false && !item.disabledCondition);
19362
+ const firstEdit = editableColumns[0];
19363
+ const lastEdit = editableColumns[editableColumns.length - 1];
19361
19364
  return {
19362
19365
  levels,
19363
19366
  flat,
@@ -19365,7 +19368,9 @@ const calculateTableStructure = (columns) => {
19365
19368
  objWidthFixLeft,
19366
19369
  objWidthFixRight,
19367
19370
  lastObjWidthFixLeft,
19368
- fisrtObjWidthFixRight
19371
+ fisrtObjWidthFixRight,
19372
+ firstEdit,
19373
+ lastEdit
19369
19374
  };
19370
19375
  };
19371
19376
 
@@ -41811,31 +41816,51 @@ var css_248z$1 = ".react-resizable {\n position: relative;\n}\n.react-resizable
41811
41816
  styleInject(css_248z$1);
41812
41817
 
41813
41818
  const HeaderTableCol$1 = (props) => {
41814
- const { selectEnable, dataSource, setSelectedRows, col, indexCol, indexParent, objWidthFixLeft, objWidthFixRight, totalCount, selectedRows, column, setColumn, fisrtObjWidthFixRight, lastObjWidthFixLeft, isMulti } = props;
41819
+ const { selectEnable, dataSource, setSelectedRows, col, indexCol, indexParent, objWidthFixLeft, objWidthFixRight, totalCount, selectedRows, columns, setColumns, orderBy, changeFilter, filterBy, changeOrder, allowFilter, allowOrder, container, fisrtObjWidthFixRight, lastObjWidthFixLeft, formatSetting, optionsFilter, idTable, isMulti } = props;
41815
41820
  const { t } = reactI18next.useTranslation();
41821
+ const headerRef = React$5.useRef(null);
41822
+ const order = orderBy.find((item) => item.key === col.field);
41823
+ const [openFilter, setOpenFilter] = React$5.useState(false);
41824
+ const filter = filterBy.find((item) => item.key === col.field);
41816
41825
  const handleResize = (e, { size }) => {
41817
41826
  // Update the column width here
41818
41827
  // You might need to update the state or call a callback to update the width
41819
41828
  if (size.width > 50) {
41820
- const newColumns = [...column];
41829
+ const newColumns = [...columns];
41821
41830
  newColumns[indexCol].width = size.width;
41822
- if ((column[indexCol]?.maxWidth ?? 0) < size.width) {
41831
+ if ((columns[indexCol]?.maxWidth ?? 0) < size.width) {
41823
41832
  newColumns[indexCol].maxWidth = size.width;
41824
41833
  }
41825
- if ((column[indexCol]?.minWidth ?? 0) > size.width) {
41834
+ if ((columns[indexCol]?.minWidth ?? 0) > size.width) {
41826
41835
  newColumns[indexCol].minWidth = size.width;
41827
41836
  }
41828
- setColumn(newColumns);
41837
+ if (setColumns) {
41838
+ setColumns(newColumns);
41839
+ }
41829
41840
  }
41830
41841
  };
41831
- return (jsxRuntime.jsx(React$5.Fragment, { children: col.visible !== false && (jsxRuntime.jsx(Resizable, { className: "r-resize", width: typeof col.width === 'number' ? col.width : Number((col.width ?? "").replaceAll(new RegExp(`[^0-9]`, "g"), '')), height: 0, onResize: handleResize, draggableOpts: { enableUserSelectHack: false }, children: jsxRuntime.jsx("th", { rowSpan: col.rowspan !== 1 ? col.rowspan : undefined, colSpan: col.columns?.filter(x => x.visible !== false)?.length ?? 1, className: classNames$1(`r-headercell fix-${col.fixedType}`, { 'fixed-last': (col.fixedType === 'left' && indexCol === lastObjWidthFixLeft) || (col.fixedType === 'right' && indexCol === fisrtObjWidthFixRight) }, { 'cell-fixed': col.fixedType }), style: {
41842
+ const checkOverflow = () => {
41843
+ return headerRef.current && headerRef.current.scrollHeight > headerRef.current.clientHeight;
41844
+ };
41845
+ return (jsxRuntime.jsx(React$5.Fragment, { children: col.visible !== false && (jsxRuntime.jsx(Resizable, { className: "r-resize", width: typeof col.width === 'number' ? col.width : Number((col.width ?? "").replaceAll(new RegExp(`[^0-9]`, "g"), '')), height: 0, onResize: handleResize, draggableOpts: { enableUserSelectHack: false }, children: jsxRuntime.jsx("th", { rowSpan: col.rowspan !== 1 ? col.rowspan : 1, colSpan: col.columns?.filter(x => x.visible !== false)?.length ?? 1, className: classNames$1(`r-headercell fix-${col.fixedType}`, { 'fixed-last': (col.fixedType === 'left' && indexCol === lastObjWidthFixLeft) || (col.fixedType === 'right' && indexCol === fisrtObjWidthFixRight) }, { 'cell-fixed': col.fixedType }), style: {
41832
41846
  top: `${indexParent * 42}px`,
41833
- left: col.fixedType === 'left' ? objWidthFixLeft[col.index ?? 0] : undefined,
41834
- right: col.fixedType === 'right' ? objWidthFixRight[col.index ?? 0] : undefined,
41835
- width: col.width ? typeof col.width === 'number' ? col.width : col.width?.includes('px') || col.width?.includes('%') ? col.width : `${col.width}px` : 'auto',
41836
- minWidth: col.fixedType ? col.width : col.minWidth ? typeof col.minWidth === 'number' ? col.minWidth : col.minWidth?.includes('px') || col.minWidth?.includes('%') ? col.minWidth : `${col.minWidth}px` : 'auto',
41837
- maxWidth: col.fixedType ? col.width : col.maxWidth ? typeof col.maxWidth === 'number' ? col.maxWidth : col.maxWidth?.includes('px') || col.maxWidth?.includes('%') ? col.maxWidth : `${col.maxWidth}px` : 'auto'
41838
- }, children: jsxRuntime.jsxs("div", { style: { justifyContent: col.textAlign ?? 'left' }, className: classNames$1('r-headercell-div'), children: [col.field === 'checkbox' && (jsxRuntime.jsx(Input$1, { checked: !!(totalCount > 0 && selectedRows?.length >= totalCount), type: "checkbox", className: classNames$1('cursor-pointer', { 'd-none': !isMulti }), style: { textAlign: col.textAlign ?? 'left', marginTop: 6 }, onChange: (e) => {
41847
+ left: col.fixedType === 'left' ? objWidthFixLeft[indexCol ?? 0] : undefined,
41848
+ right: col.fixedType === 'right' ? objWidthFixRight[indexCol ?? 0] : undefined
41849
+ }, children: jsxRuntime.jsxs("div", { style: { justifyContent: 'space-between' }, onClick: () => {
41850
+ if (order) {
41851
+ if (order.direction === 'asc') {
41852
+ order.direction = 'desc';
41853
+ changeOrder(orderBy);
41854
+ }
41855
+ else {
41856
+ changeOrder(orderBy.filter((x) => x.key !== col.field));
41857
+ }
41858
+ }
41859
+ else {
41860
+ orderBy.push({ direction: 'asc', key: col.field });
41861
+ changeOrder(orderBy);
41862
+ }
41863
+ }, className: classNames$1('r-headercell-div', { 'cursor-pointer': allowOrder }), children: [col.field === 'checkbox' && (jsxRuntime.jsx(Input$1, { checked: !!(totalCount > 0 && selectedRows?.length >= totalCount), type: "checkbox", className: classNames$1('cursor-pointer', { 'd-none': !isMulti }), style: { textAlign: col.textAlign ?? 'left', marginTop: 6 }, onChange: (e) => {
41839
41864
  if (selectEnable) {
41840
41865
  if (e.target.checked) {
41841
41866
  setSelectedRows(dataSource.map((item) => { return item; }));
@@ -41844,7 +41869,89 @@ const HeaderTableCol$1 = (props) => {
41844
41869
  setSelectedRows([]);
41845
41870
  }
41846
41871
  }
41847
- } })), col.field !== 'checkbox' && jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx("span", { className: 'header-content', children: t(col.headerText ?? '') }) })] }) }) })) }, `header-${indexCol}`));
41872
+ } })), col.field !== 'checkbox' && jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: 'header-content', style: { justifyContent: col.textAlign ?? 'left' }, children: [jsxRuntime.jsx("span", { id: `header-${idTable}-${indexParent}-${indexCol}`, ref: headerRef, className: 'text-content', children: t(col.headerText ?? '') }), checkOverflow() && jsxRuntime.jsx(UncontrolledTooltip, { className: "r-tooltip", autohide: false, target: `header-${idTable}-${indexParent}-${indexCol}`, children: t(col.headerText ?? '') })] }), col.field !== '#' && col.field !== 'command' && jsxRuntime.jsxs("div", { className: 'd-flex', children: [allowOrder && order?.direction === 'asc' && jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", className: 'ms-25', width: "10", height: "10", viewBox: "0 0 16 18", fill: "none", children: [jsxRuntime.jsx("g", { "clip-path": "url(#clip0_520_6)", children: jsxRuntime.jsx("path", { d: "M8.70711 0.292893C8.31658 -0.0976311 7.68342 -0.0976311 7.29289 0.292893L0.928932 6.65685C0.538408 7.04738 0.538408 7.68054 0.928932 8.07107C1.31946 8.46159 1.95262 8.46159 2.34315 8.07107L8 2.41421L13.6569 8.07107C14.0474 8.46159 14.6805 8.46159 15.0711 8.07107C15.4616 7.68054 15.4616 7.04738 15.0711 6.65685L8.70711 0.292893ZM8 18H9L9 1H8H7L7 18H8Z", fill: "black" }) }), jsxRuntime.jsx("defs", { children: jsxRuntime.jsx("clipPath", { id: "clip0_520_6", children: jsxRuntime.jsx("rect", { width: "16", height: "18", fill: "white" }) }) })] }), allowOrder && order?.direction === 'desc' && jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", className: 'ms-25', width: "10", height: "10", viewBox: "0 0 16 18", fill: "none", children: [jsxRuntime.jsx("g", { "clip-path": "url(#clip0_520_2)", children: jsxRuntime.jsx("path", { d: "M7.29289 17.7071C7.68342 18.0976 8.31658 18.0976 8.70711 17.7071L15.0711 11.3431C15.4616 10.9526 15.4616 10.3195 15.0711 9.92893C14.6805 9.53841 14.0474 9.53841 13.6569 9.92893L8 15.5858L2.34315 9.92893C1.95262 9.53841 1.31946 9.53841 0.928932 9.92893C0.538408 10.3195 0.538408 10.9526 0.928932 11.3431L7.29289 17.7071ZM8 0L7 0L7 17H8H9L9 0L8 0Z", fill: "black" }) }), jsxRuntime.jsx("defs", { children: jsxRuntime.jsx("clipPath", { id: "clip0_520_2", children: jsxRuntime.jsx("rect", { width: "16", height: "18", fill: "white" }) }) })] }), allowFilter && jsxRuntime.jsxs(Dropdown$1, { isOpen: openFilter, toggle: (e) => {
41873
+ setOpenFilter(!openFilter);
41874
+ e.stopPropagation();
41875
+ }, onClick: (e) => {
41876
+ e.stopPropagation();
41877
+ }, children: [jsxRuntime.jsx(DropdownToggle$1, { tag: 'div', className: 'p-0 r-filter', children: jsxRuntime.jsxs("svg", { className: classNames$1('cursor-pointer ms-25', { 'active': filter }), width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", "stroke-width": "1.5", "font-size": "12", children: [jsxRuntime.jsx("path", { d: "M14.7 11.998v10.506c.052.4-.08.826-.381 1.106a1.306 1.306 0 0 1-.925.39 1.289 1.289 0 0 1-.926-.39l-2.637-2.68a1.323 1.323 0 0 1-.38-1.106v-7.826h-.04L1.85 2.16A1.348 1.348 0 0 1 2.076.293C2.325.107 2.6 0 2.888 0h18.373c.289 0 .564.107.814.293a1.348 1.348 0 0 1 .223 1.866L14.738 12H14.7Z", fill: "currentColor" }), " "] }) }), jsxRuntime.jsx(DropdownMenu$1, { container: container, className: 'formula-dropdown icon-dropdown p-0', style: {
41878
+ borderRadius: 8,
41879
+ zIndex: 1056
41880
+ }, children: jsxRuntime.jsx(DropdownItem$1, { className: 'p-1', style: { borderRadius: '6px' }, tag: 'div', header: true, children: jsxRuntime.jsx(RenderFilterElement$1, { setOpenFilter: setOpenFilter, filter: filter, filterBy: filterBy, optionsFilter: optionsFilter, formatSetting: formatSetting, changeFilter: changeFilter, column: col }) }) })] })] })] })] }) }) })) }, `header-${indexCol}`));
41881
+ };
41882
+ const RenderFilterElement$1 = ({ filter, optionsFilter, formatSetting, filterBy, setOpenFilter, changeFilter, column }) => {
41883
+ const { t } = reactI18next.useTranslation();
41884
+ const [operator, setOperator] = React$5.useState(filter?.ope ?? ((!column.filterType && column.editType === 'numeric') || column.filterType === 'select' ? 'equal' : 'contains'));
41885
+ const [valueFilter, setValueFilter] = React$5.useState(filter?.value ?? '');
41886
+ const RenderStringFilter = () => {
41887
+ const options = [
41888
+ { label: 'Bắt đầu bởi', value: 'startswith' },
41889
+ { label: 'Kết thúc bởi', value: 'endswith' },
41890
+ { label: 'Chứa', value: 'contains' },
41891
+ { label: 'Bằng', value: 'equal' },
41892
+ { label: 'Không bằng', value: 'notequal' }
41893
+ ];
41894
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(SelectTable, { value: options.find((x) => x.value === (operator)), options: options, onChange: (val) => {
41895
+ setOperator(val.value);
41896
+ }, placeholder: 'Select' }), jsxRuntime.jsx(Input$1, { className: 'my-1', value: valueFilter, onChange: (val) => {
41897
+ setValueFilter(val.target.value);
41898
+ } })] }));
41899
+ };
41900
+ const RenderNumberFilter = () => {
41901
+ const options = [
41902
+ { label: 'Lớn hơn', value: 'greaterthan' },
41903
+ { label: 'Lớn hơn hoặc bằng', value: 'greaterthanorequal' },
41904
+ { label: 'Bằng', value: 'equal' },
41905
+ { label: 'Bé hơn', value: 'lessthan' },
41906
+ { label: 'Bé hơn hoặc bằng', value: 'lessthanorequal' }
41907
+ ];
41908
+ const numericFormatProps = {
41909
+ value: !isNullOrUndefined$1(valueFilter) ? valueFilter.toString() : '',
41910
+ thousandSeparator: checkThousandSeparator(formatSetting?.thousandSeparator, formatSetting?.decimalSeparator),
41911
+ decimalSeparator: checkDecimalSeparator(formatSetting?.thousandSeparator, formatSetting?.decimalSeparator),
41912
+ allowNegative: column.numericSettings?.allowNegative ?? false,
41913
+ decimalScale: column.numericSettings?.fraction ?? 0
41914
+ };
41915
+ let floatValue = parseFloat(valueFilter ?? '0');
41916
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(SelectTable, { value: options.find((x) => x.value === (operator)), options: options, onChange: (val) => {
41917
+ setOperator(val.value);
41918
+ }, placeholder: t('Select') }), jsxRuntime.jsx(NumericFormat, { style: { textAlign: column.textAlign, height: 29 }, ...numericFormatProps, defaultValue: formartNumberic(valueFilter, formatSetting?.decimalSeparator ?? ',', formatSetting?.thousandSeparator ?? '.', column.numericSettings?.fraction), className: classNames$1('form-control my-1 input-numeric'), onValueChange: (values) => {
41919
+ floatValue = values?.floatValue;
41920
+ }, onFocus: (e) => {
41921
+ e.target.setSelectionRange(0, e.target.innerText.length - 1);
41922
+ }, onBlur: () => {
41923
+ if (floatValue !== valueFilter) {
41924
+ setValueFilter(!isNaN(floatValue) ? floatValue : 0);
41925
+ }
41926
+ } })] }));
41927
+ };
41928
+ const RenderSelectFilter = () => {
41929
+ return (jsxRuntime.jsx("div", { className: 'mb-1', children: jsxRuntime.jsx(SelectTable, { value: optionsFilter ? optionsFilter[column.field]?.find((x) => x.value === valueFilter) : undefined, options: (optionsFilter && optionsFilter[column.field]) ?? [], isClearable: true, onChange: (val) => {
41930
+ setValueFilter(val?.value);
41931
+ }, placeholder: t('Select') }) }));
41932
+ };
41933
+ const handleSave = () => {
41934
+ if (filter) {
41935
+ filter.ope = operator;
41936
+ filter.value = valueFilter ?? '';
41937
+ }
41938
+ else {
41939
+ filterBy.push({ key: column.field, ope: operator, value: valueFilter ?? '' });
41940
+ }
41941
+ changeFilter([...filterBy]);
41942
+ setOpenFilter(false);
41943
+ };
41944
+ return (jsxRuntime.jsxs("div", { className: 'r-filter-popup', onKeyDown: (e) => {
41945
+ if (e.code === 'Enter' || e.code === 'NumpadEnter') {
41946
+ handleSave();
41947
+ e.stopPropagation();
41948
+ }
41949
+ }, children: [((!column.filterType && column.editType === 'numeric') || column.filterType === 'numeric') ? jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [RenderNumberFilter(), " "] }) : (column.filterType === 'select' ? jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [RenderSelectFilter(), " "] }) : RenderStringFilter()), jsxRuntime.jsxs("div", { className: 'd-flex justify-content-end', children: [jsxRuntime.jsx(Button$1, { color: 'primary', style: { borderRadius: 3 }, className: 'me-50 py-25 px-50 fw-bold', onClick: handleSave, children: t('Filter') }), jsxRuntime.jsx(Button$1, { className: 'py-25 px-50 fw-bold', outline: true, style: { borderRadius: 3 }, onClick: () => {
41950
+ if (filterBy) {
41951
+ changeFilter(filterBy.filter((x) => x.key !== column.field));
41952
+ }
41953
+ setOpenFilter(false);
41954
+ }, children: t('Clear') })] })] }));
41848
41955
  };
41849
41956
 
41850
41957
  const defaultMaxHeight = 250;
@@ -42616,9 +42723,15 @@ const EditFormInline = React$5.forwardRef((props, ref) => {
42616
42723
  }) })] }));
42617
42724
  });
42618
42725
 
42726
+ const RenderColGroup = ({ contentColumns }) => (jsxRuntime.jsx("colgroup", { children: contentColumns.map((col, index) => (jsxRuntime.jsx("col", { style: {
42727
+ width: typeof col.width === 'number' ? `${col.width}px` : col.width || undefined,
42728
+ minWidth: typeof col.minWidth === 'number' ? `${col.minWidth}px` : col.minWidth || undefined,
42729
+ maxWidth: typeof col.maxWidth === 'number' ? `${col.maxWidth}px` : col.maxWidth || undefined
42730
+ } }, index))) }));
42731
+
42619
42732
  const TableEdit = React$5.forwardRef((props, ref) => {
42620
42733
  const { t } = reactI18next.useTranslation();
42621
- const { idTable, dataSource, columns, commandClick, dataSourceChange, rowChange, pagingSetting, setDataSource, height, maxHeight, minHeight, defaultValue, toolbarSetting, searchSetting, setSelectedItem, selectedItem, selectEnable, editDisable, addDisable, buttonSetting, formatSetting, handleSelect, haveSum, isMulti, disableAutoKey, onDuplicate } = props;
42734
+ const { idTable, dataSource, columns, commandClick, dataSourceChange, rowChange, pagingSetting, setDataSource, height, maxHeight, minHeight, defaultValue, toolbarSetting, searchSetting, setSelectedItem, selectedItem, selectEnable, editDisable, addDisable, buttonSetting, formatSetting, handleSelect, haveSum, isMulti, disableAutoKey, onDuplicate, allowFilter = true, allowOrder, optionsFilter } = props;
42622
42735
  React$5.useImperativeHandle(ref, () => {
42623
42736
  return {
42624
42737
  refeshFocusRow: handleRefeshRow
@@ -42627,17 +42740,11 @@ const TableEdit = React$5.forwardRef((props, ref) => {
42627
42740
  const [refreshRow, setRefreshRow] = React$5.useState(false);
42628
42741
  const [indexFocus, setIndexFocus] = React$5.useState(-1);
42629
42742
  const [selectedRows, setSelectedRows] = React$5.useState([]);
42630
- const [headerColumns, setHeaderColumns] = React$5.useState([[]]);
42631
42743
  const [contentColumns, setContentColumns] = React$5.useState([]);
42632
- const [levelCol, setLevelCol] = React$5.useState(0);
42633
- const [columnFistEdit, setColumnFistEdit] = React$5.useState(0);
42634
- const [columnLastEdit, setColumnlastEdit] = React$5.useState(0);
42635
- const [objWidthFixRight, setObjWidthFixRight] = React$5.useState({});
42636
- const [objWidthFixLeft, setObjWidthFixLeft] = React$5.useState({});
42637
- const [lastObjWidthFixLeft, setLastObjWidthFixLeft] = React$5.useState(0);
42638
- const [fisrtObjWidthFixRight, setFisrtObjWidthFixRight] = React$5.useState(0);
42639
42744
  const [openPopupSetupColumn, setOpenPopupSetupColumn] = React$5.useState(false);
42640
42745
  const [searchTerm, setSearchTerm] = React$5.useState('');
42746
+ const [orderBy, setOrderBy] = React$5.useState([]);
42747
+ const [filterBy, setFilterBy] = React$5.useState([]);
42641
42748
  const tableElement = React$5.useRef(null);
42642
42749
  const gridRef = React$5.useRef(null);
42643
42750
  const totalCount = dataSource.length;
@@ -42650,95 +42757,11 @@ const TableEdit = React$5.forwardRef((props, ref) => {
42650
42757
  pagingSetting.setCurrentPage(1);
42651
42758
  }
42652
42759
  }, [dataSource]);
42653
- React$5.useEffect(() => {
42654
- let indexFirst = -1;
42655
- let indexlast = -1;
42656
- let letfWidthFix = 0;
42657
- let rightWidthFix = 0;
42658
- contentColumns.forEach((item, index) => {
42659
- if (levelCol === 1) {
42660
- headerColumns[0][index].width = item.width;
42661
- headerColumns[0][index].visible = item.visible;
42662
- headerColumns[0][index].fixedType = item.fixedType;
42663
- }
42664
- if (item.fixedType === 'left' && item.visible !== false) {
42665
- setLastObjWidthFixLeft(index);
42666
- objWidthFixLeft[index] = letfWidthFix;
42667
- letfWidthFix += Number(item.width ?? 40);
42668
- }
42669
- const lasColumn = contentColumns[contentColumns.length - 1 - index];
42670
- if (lasColumn.fixedType === 'right' && lasColumn.visible !== false) {
42671
- setFisrtObjWidthFixRight(contentColumns.length - 1 - index);
42672
- objWidthFixRight[contentColumns.length - 1 - index] = rightWidthFix;
42673
- rightWidthFix += Number(lasColumn.width ?? 40);
42674
- }
42675
- if (item.editEnable && (item.visible !== false) && (!item.disabledCondition)) {
42676
- if (indexFirst === -1) {
42677
- indexFirst = index;
42678
- }
42679
- indexlast = index;
42680
- }
42681
- });
42682
- if (levelCol === 1) {
42683
- setHeaderColumns([...headerColumns]);
42684
- }
42685
- setObjWidthFixLeft(objWidthFixLeft);
42686
- setObjWidthFixRight(objWidthFixRight);
42687
- setColumnFistEdit(indexFirst + 1);
42688
- setColumnlastEdit(indexlast + 1);
42689
- }, [contentColumns]);
42690
- React$5.useEffect(() => {
42691
- const arrHeaderColumns = [];
42692
- const arrContentColumns = [];
42693
- let headerLevelRow = 0;
42694
- if (levelCol) {
42695
- headerLevelRow = levelCol;
42696
- }
42697
- else {
42698
- headerLevelRow = stretchColumn(columns, 0);
42699
- setLevelCol(headerLevelRow);
42700
- }
42701
- for (let i = 0; i < headerLevelRow; i++) {
42702
- arrHeaderColumns.push([]);
42703
- }
42704
- getNestedChildren(columns, arrHeaderColumns, arrContentColumns, 0, headerLevelRow);
42705
- setHeaderColumns(arrHeaderColumns);
42706
- setContentColumns(arrContentColumns);
42760
+ const { levels: headerColumns, flatVisble, objWidthFixLeft, objWidthFixRight, lastObjWidthFixLeft, fisrtObjWidthFixRight, firstEdit: columnFirstEdit, lastEdit: columnLastEdit } = React$5.useMemo(() => {
42761
+ const obj = calculateTableStructure(columns);
42762
+ setContentColumns(obj.flat);
42763
+ return obj;
42707
42764
  }, [columns]);
42708
- const getNestedChildren = (array, arrHeaderColumns, arrContentColumns, level, maxLevelRow) => {
42709
- array.forEach((item) => {
42710
- const ele = { ...item, visible: item.visible, rowspan: 1, index: 0 };
42711
- if (item.columns && item.columns?.length > 0) {
42712
- const countLevel = getNestedChildren(item.columns, arrHeaderColumns, arrContentColumns, level + 1, maxLevelRow);
42713
- arrHeaderColumns[(maxLevelRow - 1) - countLevel].push(ele);
42714
- }
42715
- else {
42716
- ele.rowspan = maxLevelRow - level;
42717
- ele.index = arrContentColumns.length;
42718
- if (maxLevelRow === 1) {
42719
- ele.visible = (item.invisibleDisable ? item.visible : (contentColumns[arrContentColumns.length]?.visible ?? item.visible));
42720
- ele.width = (contentColumns[arrContentColumns.length]?.width ?? item.width);
42721
- ele.maxWidth = (contentColumns[arrContentColumns.length]?.maxWidth ?? item.maxWidth);
42722
- ele.minWidth = (contentColumns[arrContentColumns.length]?.minWidth ?? item.minWidth);
42723
- }
42724
- arrHeaderColumns[level].push(ele);
42725
- arrContentColumns.push(ele);
42726
- }
42727
- });
42728
- return level;
42729
- };
42730
- const stretchColumn = (subColumns, headerLevelRow) => {
42731
- let count = headerLevelRow + 1;
42732
- subColumns.map((item) => {
42733
- if (item.columns && item.columns.length > 0) {
42734
- const newCount = stretchColumn(item.columns, headerLevelRow + 1);
42735
- if (newCount > count) {
42736
- count = newCount;
42737
- }
42738
- }
42739
- });
42740
- return count;
42741
- };
42742
42765
  const handleRefeshRow = () => {
42743
42766
  setRefreshRow(true);
42744
42767
  setTimeout(() => {
@@ -43068,7 +43091,7 @@ const TableEdit = React$5.forwardRef((props, ref) => {
43068
43091
  }
43069
43092
  if (tableElement) {
43070
43093
  setIndexFocus(totalCount);
43071
- focusNewElement(columnFistEdit, totalCount + 1, true);
43094
+ focusNewElement(columnFirstEdit, totalCount + 1, true);
43072
43095
  }
43073
43096
  };
43074
43097
  const checkKeyDown = (e, row, col, indexRow, indexCol) => {
@@ -43304,14 +43327,6 @@ const TableEdit = React$5.forwardRef((props, ref) => {
43304
43327
  };
43305
43328
  const changeDataSource = (data, numberOfRows) => {
43306
43329
  if (!editDisable && setDataSource) {
43307
- if ((searchSetting?.searchTerm !== undefined ? searchSetting?.searchTerm : searchTerm)) {
43308
- if (searchSetting?.setSearchTerm) {
43309
- searchSetting?.setSearchTerm('');
43310
- }
43311
- else {
43312
- setSearchTerm('');
43313
- }
43314
- }
43315
43330
  if (numberOfRows && !addDisable) {
43316
43331
  for (let index = 0; index < numberOfRows; index++) {
43317
43332
  data.push(defaultValue ? { ...defaultValue, [fieldKey]: disableAutoKey ? undefined : generateUUID() } : {});
@@ -43512,22 +43527,52 @@ const TableEdit = React$5.forwardRef((props, ref) => {
43512
43527
  textAlign: col.textAlign ? col.textAlign : 'left'
43513
43528
  }, children: jsxRuntime.jsxs("div", { className: "r-footer-div", children: [col.haveSum === true && col.editType === "numeric" && (Number(sumValue) >= 0) && jsxRuntime.jsx(jsxRuntime.Fragment, { children: formartNumberic(sumValue, formatSetting?.decimalSeparator ?? ',', formatSetting?.thousandSeparator ?? '.', col.numericSettings?.fraction, true, false) }), col.haveSum === true && col.editType === "numeric" && (Number(sumValue) < 0) && jsxRuntime.jsxs("div", { style: { color: formatSetting?.colorNegative ?? 'red' }, children: [" ", `${formatSetting?.prefixNegative ?? '-'}${formartNumberic(sumValue, formatSetting?.decimalSeparator ?? ',', formatSetting?.thousandSeparator ?? '.', col.numericSettings?.fraction, true, false)}${formatSetting?.suffixNegative ?? ''}`] })] }) }) }, `summarycell-${indexCol}`));
43514
43529
  };
43515
- const checkSearch = (keyword, data, fieldKey) => {
43516
- if (!keyword || fieldKey.length === 0) {
43517
- return true;
43518
- }
43519
- for (let index = 0; index < fieldKey.length; index++) {
43520
- const key = fieldKey[index].trim();
43521
- if (data[key] && data[key].toString().trim().toLowerCase().includes(keyword.trim().toLowerCase())) {
43522
- return true;
43530
+ /**
43531
+ * Kiểm tra row thỏa mãn tất cả filter và chứa từ khóa tìm kiếm hay không
43532
+ */
43533
+ function checkRowMatch(row, filters, keyword, searchKeys) {
43534
+ if ((!filters || filters.length === 0) && (!keyword || !searchClient))
43535
+ return true; // Không có filter thì mặc định là match
43536
+ const isFilterMatch = filters.every(filter => {
43537
+ const { key, value, ope } = filter;
43538
+ const rowValue = row[key];
43539
+ if (rowValue === undefined || rowValue === null || value === undefined || value === null)
43540
+ return false;
43541
+ const valStr = String(rowValue).toLowerCase();
43542
+ const filterStr = String(value).toLowerCase();
43543
+ switch (ope) {
43544
+ case 'startswith':
43545
+ return valStr.startsWith(filterStr);
43546
+ case 'endswith':
43547
+ return valStr.endsWith(filterStr);
43548
+ case 'contains':
43549
+ return valStr.includes(filterStr);
43550
+ case 'equal':
43551
+ return rowValue == value;
43552
+ case 'notequal':
43553
+ return rowValue != value;
43554
+ case 'greaterthan':
43555
+ return rowValue > value;
43556
+ case 'greaterthanorequal':
43557
+ return rowValue >= value;
43558
+ case 'lessthan':
43559
+ return rowValue < value;
43560
+ case 'lessthanorequal':
43561
+ return rowValue <= value;
43562
+ default:
43563
+ return false;
43523
43564
  }
43524
- }
43525
- return false;
43526
- };
43565
+ });
43566
+ const isSearchMatch = !keyword || searchKeys.some(key => {
43567
+ const val = row[key];
43568
+ return val?.toString().toLowerCase().includes(keyword.trim().toLowerCase());
43569
+ });
43570
+ return isFilterMatch && isSearchMatch;
43571
+ }
43527
43572
  const renderData = () => {
43528
43573
  return (dataSource.map((row, indexRow) => {
43529
43574
  const isSelected = selectedRows?.some((x) => x[fieldKey] === row[fieldKey]);
43530
- const flagSearch = !searchClient || checkSearch(searchSetting?.searchTerm !== undefined ? searchSetting?.searchTerm : searchTerm, row, searchSetting?.keyField ?? []);
43575
+ const flagSearch = checkRowMatch(row, filterBy, searchSetting?.searchTerm !== undefined ? searchSetting?.searchTerm : searchTerm, searchSetting?.keyField ?? []);
43531
43576
  if (flagSearch) {
43532
43577
  const flagDisplay = !pagingClient || ((indexRow + 1) > ((pagingSetting.pageSize ?? 0) * ((pagingSetting.currentPage ?? 0) - 1)) && (indexRow + 1) <= ((pagingSetting.pageSize ?? 0) * ((pagingSetting.currentPage ?? 0))));
43533
43578
  return (flagDisplay && jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx("tr", { className: classNames$1('r-row'), children: contentColumns.map((col, indexCol) => renderContentCol(col, row, indexRow, indexCol, isSelected)) }, `row-${indexRow}`) }));
@@ -43539,14 +43584,18 @@ const TableEdit = React$5.forwardRef((props, ref) => {
43539
43584
  pagingSetting?.setCurrentPage(1);
43540
43585
  }
43541
43586
  }, [searchTerm, searchSetting?.searchTerm]);
43542
- return (jsxRuntime.jsxs(React$5.Fragment, { children: [jsxRuntime.jsxs("div", { className: "react-table-edit", children: [jsxRuntime.jsxs("div", { className: 'r-grid', ref: gridRef, children: [toolbarSetting?.showTopToolbar && jsxRuntime.jsx(RenderToolbarTop, { toolbarTopOption: toolbarTopOption }), jsxRuntime.jsx("div", { ref: tableElement, className: "r-gridtable", style: { height: `${height ? `${height}px` : 'auto'}`, minHeight: `${minHeight ? `${minHeight}px` : ''}`, maxHeight: `${maxHeight ? `${maxHeight}px` : '400px'}` }, children: jsxRuntime.jsxs("table", { style: { width: '100%' }, children: [jsxRuntime.jsx("thead", { className: 'r-gridheader', children: headerColumns.map((element, indexParent) => {
43587
+ return (jsxRuntime.jsxs(React$5.Fragment, { children: [jsxRuntime.jsxs("div", { className: "react-table-edit", children: [jsxRuntime.jsxs("div", { className: 'r-grid', ref: gridRef, children: [toolbarSetting?.showTopToolbar && jsxRuntime.jsx(RenderToolbarTop, { toolbarTopOption: toolbarTopOption }), jsxRuntime.jsx("div", { ref: tableElement, className: "r-gridtable", style: { height: `${height ? `${height}px` : 'auto'}`, minHeight: `${minHeight ? `${minHeight}px` : ''}`, maxHeight: `${maxHeight ? `${maxHeight}px` : '400px'}` }, children: jsxRuntime.jsxs("table", { style: { width: '100%' }, children: [jsxRuntime.jsx(RenderColGroup, { contentColumns: flatVisble }), jsxRuntime.jsx("thead", { className: 'r-gridheader', children: headerColumns.map((element, indexParent) => {
43543
43588
  return (jsxRuntime.jsx("tr", { className: "r-row", role: "row", children: element?.map((col, index) => {
43544
- return (jsxRuntime.jsx(HeaderTableCol$1, { col: col, dataSource: dataSource, indexCol: index, indexParent: indexParent, isMulti: isMulti ?? false, objWidthFixLeft: objWidthFixLeft, objWidthFixRight: objWidthFixRight, selectEnable: selectEnable ?? false, selectedRows: selectedRows, setSelectedRows: setSelectedRows, column: contentColumns, setColumn: setContentColumns, fisrtObjWidthFixRight: fisrtObjWidthFixRight, lastObjWidthFixLeft: lastObjWidthFixLeft, totalCount: totalCount }, `header-${indexParent}-${index}`));
43589
+ return (jsxRuntime.jsx(HeaderTableCol$1, { col: col, idTable: idTable ?? '', dataSource: dataSource, indexCol: index, indexParent: indexParent, isMulti: isMulti ?? false, objWidthFixLeft: objWidthFixLeft, objWidthFixRight: objWidthFixRight, selectEnable: selectEnable ?? false, selectedRows: selectedRows, setSelectedRows: setSelectedRows, container: tableElement, filterBy: filterBy, orderBy: orderBy, optionsFilter: optionsFilter, allowFilter: allowFilter, allowOrder: allowOrder, formatSetting: formatSetting, changeFilter: (val) => {
43590
+ setFilterBy([...val]);
43591
+ }, changeOrder: (val) => {
43592
+ setOrderBy([...val]);
43593
+ }, columns: contentColumns, setColumns: setContentColumns, fisrtObjWidthFixRight: fisrtObjWidthFixRight, lastObjWidthFixLeft: lastObjWidthFixLeft, totalCount: totalCount }, `header-${indexParent}-${index}`));
43545
43594
  }) }, `header-${-indexParent}`));
43546
43595
  }) }), jsxRuntime.jsx("tbody", { className: 'r-gridcontent', children: renderData() }), jsxRuntime.jsx("tfoot", { className: "r-gridfoot", children: haveSum == true ? jsxRuntime.jsx("tr", { className: 'r-row', children: contentColumns.map((col, index) => {
43547
43596
  return (renderFooterCol(col, index));
43548
43597
  }) }) : jsxRuntime.jsx(jsxRuntime.Fragment, {}) })] }) }), toolbarSetting?.showBottomToolbar && jsxRuntime.jsx(ToolbarBottom, { handleAdd: (numberOfRows) => {
43549
- handleAdd(dataSource, tableElement.current, columnFistEdit, changeDataSource, pagingSetting, setIndexFocus, focusNewElement, numberOfRows);
43598
+ handleAdd(dataSource, tableElement.current, columnFirstEdit, changeDataSource, pagingSetting, setIndexFocus, focusNewElement, numberOfRows);
43550
43599
  }, handleDuplicate: () => {
43551
43600
  handleDuplicate(dataSource, indexFocus, fieldKey, defaultValue, fieldUniKey, changeDataSource, tableElement, totalCount, toolbarSetting, buttonSetting, editDisable, addDisable, onDuplicate);
43552
43601
  }, handleInsertAfter: () => {
@@ -65662,12 +65711,6 @@ const RenderContentCol = (props) => {
65662
65711
  }, children: RenderElement() }, `col-${indexRow}-${indexCol}`));
65663
65712
  };
65664
65713
 
65665
- const RenderColGroup = ({ contentColumns }) => (jsxRuntime.jsx("colgroup", { children: contentColumns.map((col, index) => (jsxRuntime.jsx("col", { style: {
65666
- width: typeof col.width === 'number' ? `${col.width}px` : col.width || undefined,
65667
- minWidth: typeof col.minWidth === 'number' ? `${col.minWidth}px` : col.minWidth || undefined,
65668
- maxWidth: typeof col.maxWidth === 'number' ? `${col.maxWidth}px` : col.maxWidth || undefined
65669
- } }, index))) }));
65670
-
65671
65714
  const VirtualTable = ({ idTable, dataSource, rowHeight = 33, height = 400, columns, isMutil, isLoading, selectEnable, formatSetting, commandClick, allowFilter, allowOrder, setColumns, pagingSetting, changeFilter, changeOrder, searchSetting, columnsAggregate, toolbarSetting, optionsFilter }) => {
65672
65715
  const gridRef = React$5.useRef(null);
65673
65716
  const [startIndex, setStartIndex] = React$5.useState(0);