aio-table 13.0.0 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/filter.css +100 -63
  2. package/index.css +7 -28
  3. package/index.d.ts +131 -83
  4. package/index.js +392 -358
  5. package/package.json +1 -1
package/index.js CHANGED
@@ -8,8 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
11
- import { createContext, createRef, Fragment, useContext, useEffect, useRef, useState } from "react";
12
- import AIOInput, { AICheckbox, AIFormInput, AINumber, AIRadio, AISelect, AIText, AITime, SuggestionInput, useForm } from "aio-input";
11
+ import { createContext, createRef, Fragment, useContext, useEffect, useMemo, useRef, useState } from "react";
12
+ import AIOInput, { AICheckbox, AIFormInput, AINumber, AIRadio, AISelect, AIText, AITime } from "aio-input";
13
13
  import * as UT from 'aio-utils';
14
14
  import usePopup from "aio-popup";
15
15
  import AIODate from "aio-date";
@@ -21,45 +21,70 @@ const AIOTable = (props) => {
21
21
  const popup = usePopup();
22
22
  const fileClass = new UT.FileClass();
23
23
  let [searchValue, setSearchValue] = useState('');
24
- const [searchColumns, setSearchColumns] = useState([]);
25
- const [excelColumns, setExcelColumns] = useState([]);
26
- const [filterColumns, setFilterColumns] = useState([]);
27
- const [toggleColumns, setToggleColumns] = useState([]);
28
- const filterColumnsRef = useRef(filterColumns);
29
- filterColumnsRef.current = filterColumns;
30
- const rowsIndexDicRef = useRef({});
31
- const setRowsIndexDic = (rowsIndexDic) => rowsIndexDicRef.current = rowsIndexDic;
32
- const getRowsIndexDic = () => rowsIndexDicRef.current;
33
24
  const propsRef = useRef(props);
34
25
  propsRef.current = props;
35
26
  const pagingHook = usePaging({ rows: props.value, paging: props.paging, onChange: props.onChangePaging });
36
- const getColumnOption = (key, cellDetails) => {
37
- if (key === 'id') {
38
- return cellDetails.column.id;
39
- }
40
- const columnValue = cellDetails.column[key];
41
- if (columnValue !== undefined) {
42
- const { getValue = {} } = props;
43
- if (getValue[columnValue]) {
44
- return getValue[columnValue](cellDetails);
27
+ // const getColumnOption: I_getColumnOption<any> = (key, cellDetails) => {
28
+ // if (key === 'id') { return cellDetails.column.id }
29
+ // const columnValue = cellDetails.column[key]
30
+ // if (columnValue !== undefined) {
31
+ // const { getValue = {} } = props
32
+ // if (getValue[columnValue]) { return getValue[columnValue](cellDetails) }
33
+ // return cellDetails.column[key]
34
+ // }
35
+ // const { columnOption } = props;
36
+ // const fn = (columnOption || {})[key] || (() => { })
37
+ // const res = fn(cellDetails);
38
+ // if (res !== undefined) { return res }
39
+ // if (key === 'value') {
40
+ // return cellDetails.row[cellDetails.column.id]
41
+ // }
42
+ // const defaults: { [key in keyof I_table_column<any>]?: any } = { show: true, title: '', justify: false, titleAttrs: {} }
43
+ // return defaults[key]
44
+ // }
45
+ const tableHook = useTable(() => propsRef.current, () => props.paging);
46
+ const getColumn = (col) => {
47
+ const { columnOption = {} } = props;
48
+ const column = Object.assign({}, col);
49
+ for (let prop in columnOption) {
50
+ if (prop !== 'value') {
51
+ const fn = columnOption[prop];
52
+ if (fn) {
53
+ const res = fn({ column, row: undefined, rowIndex: 0 });
54
+ if (res !== undefined) {
55
+ column[prop] = res;
56
+ }
57
+ }
45
58
  }
46
- return cellDetails.column[key];
47
- }
48
- const { columnOption } = props;
49
- const fn = (columnOption || {})[key] || (() => { });
50
- const res = fn(cellDetails);
51
- if (res !== undefined) {
52
- return res;
53
59
  }
54
- if (key === 'value') {
55
- return cellDetails.row[cellDetails.column.id];
56
- }
57
- const defaults = { show: true, title: '', justify: false, titleAttrs: {} };
58
- return defaults[key];
60
+ return Object.assign(Object.assign({}, column), col);
61
+ };
62
+ const getColumns = () => {
63
+ let { columns = [] } = props;
64
+ let searchColumns = [], excelColumns = [], filterColumns = [], toggleColumns = [];
65
+ let updatedColumns = columns.map((col, i) => {
66
+ const column = getColumn(col);
67
+ const { filter, search, excel, toggle, id, show = true } = column;
68
+ if (id === undefined) {
69
+ console.error(`aio-table error => missing column id in props.columns[${i}]`);
70
+ }
71
+ const fixedColumn = Object.assign(Object.assign({}, column), { show });
72
+ if (search) {
73
+ searchColumns.push(fixedColumn);
74
+ }
75
+ if (excel) {
76
+ excelColumns.push(fixedColumn);
77
+ }
78
+ if (filter) {
79
+ filterColumns.push(fixedColumn);
80
+ }
81
+ if (toggle) {
82
+ toggleColumns.push(fixedColumn);
83
+ }
84
+ return fixedColumn;
85
+ });
86
+ return { columns: updatedColumns, searchColumns, excelColumns, filterColumns, toggleColumns };
59
87
  };
60
- const tableHook = useTable(() => propsRef.current, () => props.paging, getColumnOption);
61
- const getIconRef = useRef(new UT.GetSvg());
62
- const getIcon = getIconRef.current.getIcon;
63
88
  const DragColumns = UT.useDrag((dragIndex, dropIndex, reOrder) => {
64
89
  const newColumns = reOrder(props.columns || [], dragIndex, dropIndex);
65
90
  if (props.onChangeColumns) {
@@ -71,11 +96,9 @@ const AIOTable = (props) => {
71
96
  return sort.getValue;
72
97
  }
73
98
  return (row) => {
74
- const cellDetail = tableHook.getCellDetail({ column, row });
75
- const type = getColumnOption('type', cellDetail) || 'text';
76
- const value = getColumnOption('value', cellDetail);
77
- const cellValue = tableHook.getCellValue(cellDetail, value);
78
- if (type === 'date') {
99
+ const { type = 'text' } = column;
100
+ const cellValue = tableHook.getCellValue({ row, column, rowIndex: 0 });
101
+ if (type === 'date' || type === 'jalaliDate') {
79
102
  const DATE = new AIODate();
80
103
  try {
81
104
  return DATE.getTime(cellValue);
@@ -91,15 +114,14 @@ const AIOTable = (props) => {
91
114
  let sorts = [];
92
115
  for (let i = 0; i < columns.length; i++) {
93
116
  const column = columns[i];
94
- const cellDetail = tableHook.getCellDetail({ column });
95
- const columnId = getColumnOption('id', cellDetail);
96
- const sortValue = getColumnOption('sort', cellDetail);
117
+ const columnId = column.id;
118
+ const sortValue = column.sort;
97
119
  const sort = sortValue === true ? { sortId: columnId } : sortValue;
98
120
  if (!sort) {
99
121
  continue;
100
122
  }
101
123
  let { active = false, dir = 'dec', sortId } = sort;
102
- let sortItem = { dir, title: sort.title || getColumnOption('title', cellDetail), sortId, active, getValue: getGetValue(sort, column) };
124
+ let sortItem = { dir, title: sort.title || column.title, sortId, active, getValue: getGetValue(sort, column) };
103
125
  sorts.push(sortItem);
104
126
  }
105
127
  return sorts;
@@ -111,41 +133,7 @@ const AIOTable = (props) => {
111
133
  onChangeRows: props.onChange,
112
134
  onChangeSort: props.onChangeSort,
113
135
  });
114
- function getColumns() {
115
- let { columns = [] } = props;
116
- let searchColumns = [], excelColumns = [], filterColumns = [], toggleColumns = [];
117
- let updatedColumns = columns.map((column, i) => {
118
- const cellDetail = tableHook.getCellDetail({ column });
119
- const filter = getColumnOption('filter', cellDetail);
120
- const search = getColumnOption('search', cellDetail);
121
- const excel = getColumnOption('excel', cellDetail);
122
- const toggle = getColumnOption('toggle', cellDetail);
123
- const id = getColumnOption('id', cellDetail);
124
- if (id === undefined) {
125
- console.error(`aio-table error => missing column id in props.columns[${i}]`);
126
- }
127
- if (search) {
128
- searchColumns.push(column);
129
- }
130
- if (excel) {
131
- excelColumns.push(column);
132
- }
133
- if (filter) {
134
- filterColumns.push(column);
135
- }
136
- if (toggle) {
137
- toggleColumns.push(column);
138
- }
139
- return column;
140
- });
141
- setSearchColumns(searchColumns);
142
- setExcelColumns(excelColumns);
143
- setFilterColumns(filterColumns);
144
- setToggleColumns(toggleColumns);
145
- return updatedColumns;
146
- }
147
136
  useEffect(() => {
148
- const columns = getColumns();
149
137
  sortHook.setSorts(getSorts(columns));
150
138
  }, []);
151
139
  useEffect(() => {
@@ -182,16 +170,12 @@ const AIOTable = (props) => {
182
170
  }
183
171
  else {
184
172
  for (let rowIndex = 0; rowIndex < props.value.length; rowIndex++) {
185
- const isFirst = rowIndex === 0;
186
- const isLast = rowIndex === props.value.length - 1;
187
173
  let row = props.value[rowIndex], json = {};
188
174
  for (let j = 0; j < excelColumns.length; j++) {
189
175
  const column = excelColumns[j];
190
- const cellDetail = tableHook.getCellDetail({ row, rowIndex, isFirst, isLast, column });
191
- const excel = getColumnOption('excel', cellDetail);
176
+ const { excel, title } = column;
192
177
  let key = '';
193
178
  if (excel === true) {
194
- const title = getColumnOption('title', cellDetail);
195
179
  if (typeof title === 'string') {
196
180
  key = title;
197
181
  }
@@ -205,8 +189,7 @@ const AIOTable = (props) => {
205
189
  else {
206
190
  continue;
207
191
  }
208
- const value = getColumnOption('value', cellDetail);
209
- json[key] = tableHook.getCellValue(cellDetail, value, '');
192
+ json[key] = tableHook.getCellValue({ row, rowIndex, column });
210
193
  }
211
194
  list.push(json);
212
195
  }
@@ -220,15 +203,11 @@ const AIOTable = (props) => {
220
203
  if (!searchColumns.length || !searchValue) {
221
204
  return rows;
222
205
  }
223
- const rowsIndexDic = getRowsIndexDic();
224
- return UT.Search(rows, searchValue, (row) => {
225
- const { isFirst, isLast, rowIndex } = rowsIndexDic[(row)._id];
206
+ return UT.Search(rows, searchValue, (row, rowIndex) => {
226
207
  let str = '';
227
208
  for (let i = 0; i < searchColumns.length; i++) {
228
209
  let column = searchColumns[i];
229
- const cellDetail = tableHook.getCellDetail({ row, rowIndex, isFirst, isLast, column });
230
- const value = getColumnOption('value', cellDetail);
231
- let cellValue = tableHook.getCellValue(cellDetail, value, '');
210
+ let cellValue = tableHook.getCellValue({ row, rowIndex, column });
232
211
  if (cellValue) {
233
212
  str += cellValue + ' ';
234
213
  }
@@ -238,11 +217,6 @@ const AIOTable = (props) => {
238
217
  }
239
218
  function getRows() {
240
219
  const rows = props.value;
241
- const rowsIndexDic = {};
242
- for (let i = 0; i < props.value.length; i++) {
243
- rowsIndexDic[props.value[i]._id] = { rowIndex: i, isFirst: i === 0, isLast: i === rows.length - 1 };
244
- }
245
- setRowsIndexDic(rowsIndexDic);
246
220
  let searchedRows = getSearchedRows(rows);
247
221
  let sortedRows = sortHook.getSortedRows(searchedRows);
248
222
  let pagedRows = pagingHook.getPagedRows(sortedRows);
@@ -257,21 +231,22 @@ const AIOTable = (props) => {
257
231
  }
258
232
  }
259
233
  let ROWS = getRows();
234
+ const { columns, searchColumns, excelColumns, filterColumns, toggleColumns } = useMemo(() => getColumns(), [props.columns]);
260
235
  const context = {
261
236
  rootProps: props, excelColumns, filterColumns, tableHook, sortHook, ROWS, toggleColumns, pagingHook,
262
- getRowsIndexDic, add, remove, search, exportToExcel, DragColumns, getIcon, popup, getColumnOption
237
+ add, remove, search, exportToExcel, DragColumns, popup, columns
263
238
  };
264
239
  return (_jsxs(Provider, { value: context, children: [_jsx(AIOTableComponent, Object.assign({}, props)), popup.render()] }));
265
240
  };
266
241
  export default AIOTable;
267
242
  const AIOTableComponent = (props) => {
268
243
  const { pagingHook, rootProps } = useProvider();
269
- const { formFilter, columnsFilter } = rootProps;
244
+ const { filter } = rootProps;
270
245
  let [dom] = useState(createRef());
271
- const { gap = [0, 1] } = props;
246
+ const { gap = [] } = props;
272
247
  let attrs = UT.AddToAttrs(props.attrs, { className: ['aio-table', props.className], style: Object.assign({ gap: gap[1] }, props.style), attrs: { ref: dom } });
273
248
  const filterHook = useFilter();
274
- return (_jsxs("div", Object.assign({}, attrs, { children: [_jsx(TableToolbar, { filterHook: filterHook }), (!!formFilter || !!columnsFilter) && filterHook.renderTags(), _jsxs("div", { className: 'aio-table-unit aio-table-scroll', style: { gap: gap[1] }, children: [_jsx(TableHeader, {}), _jsx(TableRows, {})] }), pagingHook.render()] })));
249
+ return (_jsxs("div", Object.assign({}, attrs, { children: [_jsx(TableToolbar, { filterHook: filterHook }), !!filter && filterHook.renderTags(), _jsxs("div", { className: 'aio-table-unit aio-table-scroll', style: { gap: gap[1] }, children: [_jsx(TableHeader, {}), _jsx(TableRows, {})] }), pagingHook.render()] })));
275
250
  };
276
251
  const TableRows = () => {
277
252
  let { ROWS, rootProps } = useProvider();
@@ -286,11 +261,7 @@ const TableRows = () => {
286
261
  content = rows.map((o, i) => {
287
262
  let { id = 'ailr' + Math.round(Math.random() * 10000000) } = o;
288
263
  o._id = o._id === undefined ? id : o._id;
289
- const rowDetail = {
290
- row: o, rowIndex: i,
291
- isFirst: i === 0,
292
- isLast: i === rows.length - 1
293
- };
264
+ const rowDetail = { row: o, rowIndex: i };
294
265
  let Row;
295
266
  if (rowTemplate) {
296
267
  Row = rowTemplate(rowDetail);
@@ -307,54 +278,53 @@ const TableRows = () => {
307
278
  else {
308
279
  return null;
309
280
  }
310
- const { gap = [0, 1] } = rootProps;
281
+ const { gap = [] } = rootProps;
311
282
  return _jsx("div", { className: 'aio-table-rows', style: { gap: gap[1] }, children: content });
312
283
  };
313
284
  const TableToolbar = ({ filterHook }) => {
314
- let { add, exportToExcel, search, rootProps, excelColumns, toggleColumns, getIcon, sortHook, getColumnOption, tableHook } = useProvider();
315
- let { toolbarAttrs, toolbar, onAdd, onSearch, value, onChangeColumns, columns = [], fa, formFilter, columnsFilter } = rootProps;
285
+ let { add, exportToExcel, search, rootProps, excelColumns, toggleColumns, sortHook, columns } = useProvider();
286
+ let { toolbarAttrs, toolbar, onAdd, onSearch, value, onChangeColumns, fa, filter, inlineSort } = rootProps;
316
287
  const columnsRef = useRef(columns);
317
288
  columnsRef.current = columns;
318
289
  toolbarAttrs = UT.AddToAttrs(toolbarAttrs, { className: 'aio-table-toolbar' });
319
- if (!onAdd && !toolbar && !onSearch && !sortHook.sorts.length && !excelColumns.length && !toggleColumns.length && !rootProps.columnsFilter && !rootProps.formFilter) {
290
+ if (!onAdd && !toolbar && !onSearch && !sortHook.sorts.length && !excelColumns.length && !toggleColumns.length && !filter) {
320
291
  return null;
321
292
  }
322
293
  function getAddText() {
323
294
  let { addText } = rootProps;
324
295
  if (!rootProps.addText) {
325
- return getIcon('mdiPlusThick', 0.8);
296
+ return new UT.GetSvg('em').getIcon('mdiPlusThick', 0.8);
326
297
  }
327
298
  return typeof addText === 'function' ? addText(value) : addText;
328
299
  }
329
- const getColumnOptionWrapper = (columnId, key) => {
330
- const columns = columnsRef.current || [];
331
- const column = columns.find((o) => o.id === columnId);
332
- return getColumnOption(key, tableHook.getCellDetail({ column }));
333
- };
334
- return (_jsxs("div", Object.assign({}, toolbarAttrs, { children: [toolbar && _jsx("div", { className: 'aio-table-toolbar-content', children: typeof toolbar === 'function' ? toolbar() : toolbar }), (!!formFilter || !!columnsFilter) && filterHook.renderButton({ className: 'aio-table-toolbar-button' }), !!onSearch && _jsx(AIOInput, { type: 'text', className: 'aio-table-search', onChange: (value) => search(value), after: getIcon('mdiMagnify', 0.7) }), !!sortHook.sorts.length && sortHook.renderSortButton({ className: 'aio-table-toolbar-button aio-table-sort-button' }), !!excelColumns.length && _jsx("div", { className: 'aio-table-toolbar-button aio-table-excel-button', onClick: () => exportToExcel(), children: getIcon('mdiFileExcel', 0.8) }), !!toggleColumns.length &&
300
+ return (_jsxs("div", Object.assign({}, toolbarAttrs, { children: [toolbar && _jsx("div", { className: 'aio-table-toolbar-content', children: typeof toolbar === 'function' ? toolbar() : toolbar }), !!filter && filterHook.renderButton(), !!onSearch && _jsx(AIOInput, { type: 'text', className: 'aio-table-search', onChange: (value) => search(value), after: new UT.GetSvg('em').getIcon('mdiMagnify', 0.7) }), !!sortHook.sorts.length && !inlineSort && sortHook.renderSortButton({ className: 'aio-table-toolbar-button aio-table-sort-button' }), !!excelColumns.length && _jsx("div", { className: 'aio-table-toolbar-button aio-table-excel-button', onClick: () => exportToExcel(), children: new UT.GetSvg('em').getIcon('mdiFileExcel', 0.8) }), !!toggleColumns.length &&
335
301
  _jsx(AISelect, { popover: {
336
302
  header: { title: fa ? 'نمایش ستون ها' : 'Show Columns', onClose: false },
337
303
  headerAttrs: { className: 'aio-table-dropdown-header' },
338
304
  limitTo: '.aio-table'
339
- }, className: 'aio-table-toolbar-button aio-table-toggle-button', text: getIcon('mdiEye', 0.8), justify: true, hideTags: true, options: toggleColumns.map((o) => (Object.assign(Object.assign({}, o), { show: true }))), caret: false, option: {
340
- text: (column) => getColumnOptionWrapper(column.id, 'title'),
341
- checked: (column) => getColumnOptionWrapper(column.id, 'show'),
305
+ }, className: 'aio-table-toolbar-button aio-table-toggle-button', text: new UT.GetSvg('em').getIcon('mdiEye', 0.8), justify: true, hideTags: true, options: toggleColumns.map((o) => (Object.assign({}, o))), caret: false, option: {
306
+ text: (column) => column.title,
307
+ checked: (column) => !!column.show,
342
308
  onClick: (column) => {
309
+ console.log(toggleColumns);
343
310
  if (!onChangeColumns) {
344
311
  return;
345
312
  }
346
313
  const columns = columnsRef.current || [];
347
- onChangeColumns(columns.map((o) => column.id === o.id ? Object.assign(Object.assign({}, o), { show: !getColumnOptionWrapper(o.id, 'show') }) : o));
314
+ const newColumns = columns.map((o) => column.id === o.id ? Object.assign(Object.assign({}, o), { show: !o.show }) : o);
315
+ onChangeColumns(newColumns);
348
316
  },
317
+ show: () => true,
318
+ justify: () => false,
349
319
  close: () => false
350
320
  } }), !!onAdd && _jsx("div", { className: 'aio-table-toolbar-button aio-table-add-button', onClick: () => add(), children: getAddText() })] })));
351
321
  };
352
322
  const TableHeader = () => {
353
- let { rootProps, getColumnOption, tableHook } = useProvider();
354
- let { headerAttrs, onRemove, gap = [0, 1], columns = [] } = rootProps;
323
+ let { rootProps, columns } = useProvider();
324
+ let { headerAttrs, onRemove, gap = [] } = rootProps;
355
325
  headerAttrs = UT.AddToAttrs(headerAttrs, { className: 'aio-table-header', style: { gap: gap[0] } });
356
326
  let Titles = columns.map((column, i) => {
357
- const columnId = getColumnOption('id', tableHook.getCellDetail({ column }));
327
+ const columnId = column.id;
358
328
  return _jsx(TableTitle, { column: column, isLast: i === columns.length - 1, colIndex: i }, columnId);
359
329
  });
360
330
  let RemoveTitle = !onRemove ? null : _jsx("div", { className: 'aio-table-remove-title' });
@@ -362,90 +332,91 @@ const TableHeader = () => {
362
332
  };
363
333
  const TableTitle = (p) => {
364
334
  const { column, colIndex } = p;
365
- let { tableHook, DragColumns, getColumnOption } = useProvider();
366
- const cellDetails = tableHook.getCellDetail({ column });
367
- if (!getColumnOption('show', cellDetails)) {
335
+ let { tableHook, DragColumns, sortHook, rootProps } = useProvider();
336
+ const { show = true, title } = column;
337
+ if (!show) {
368
338
  return null;
369
339
  }
370
- const title = getColumnOption('title', cellDetails);
371
340
  const attrs = Object.assign(Object.assign(Object.assign({}, tableHook.getTitleAttrs(column)), DragColumns.getDragAttrs(colIndex)), DragColumns.getDropAttrs(colIndex));
372
- return _jsx("div", Object.assign({}, attrs, { children: title }));
341
+ return (_jsxs("div", Object.assign({}, attrs, { children: [title, !!rootProps.inlineSort && sortHook.renderSortArrow(sortHook.getSortByColumn(column), true)] })));
373
342
  };
374
343
  const TableRow = (props) => {
375
344
  const { rowDetail } = props;
376
345
  const { row, rowIndex } = rowDetail;
377
346
  const rowId = row._id;
378
- let { remove, rootProps, tableHook, getIcon, getColumnOption } = useProvider();
379
- const { columns = [] } = rootProps;
380
- const isOdd = rowIndex % 2 === 0;
347
+ let { remove, rootProps, tableHook, columns } = useProvider();
381
348
  function getCells() {
382
349
  return columns.map((column) => {
383
- if (!getColumnOption('show', tableHook.getCellDetail(Object.assign(Object.assign({}, rowDetail), { column })))) {
350
+ const { show = true } = column;
351
+ if (!show) {
384
352
  return null;
385
353
  }
386
- const cellDetail = tableHook.getCellDetail(Object.assign(Object.assign({}, rowDetail), { column, change: (v) => tableHook.changeCell(tableHook.getCellDetail(Object.assign(Object.assign({}, rowDetail), { column })), v) }));
387
- const columnId = getColumnOption('id', cellDetail);
354
+ const columnId = column.id;
388
355
  const key = rowId + ' ' + columnId;
389
- const value = getColumnOption('value', cellDetail);
390
- const cellValue = tableHook.getCellValue(cellDetail, value);
391
- return (_jsx(TableCell, { cellDetail: cellDetail, cellValue: cellValue, isOdd: isOdd }, key));
356
+ return (_jsx(TableCell, { row: row, rowIndex: rowIndex, column: column }, key));
392
357
  });
393
358
  }
394
359
  let { onRemove } = rootProps;
395
- return (_jsx(_Fragment, { children: _jsxs("div", Object.assign({}, tableHook.getRowAttrs(props.rowDetail, isOdd), { children: [getCells(), onRemove ? _jsx("button", { className: 'aio-table-remove', onClick: () => remove(row, rowIndex), children: getIcon('mdiClose', 0.8) }) : null] }), rowId) }));
360
+ return (_jsx(_Fragment, { children: _jsxs("div", Object.assign({}, tableHook.getRowAttrs({ row, rowIndex }), { children: [getCells(), onRemove ? _jsx("button", { className: 'aio-table-remove', onClick: () => remove(row, rowIndex), children: new UT.GetSvg('em').getIcon('mdiClose', 0.8) }) : null] }), rowId) }));
396
361
  };
397
362
  const TableCell = (props) => {
398
- let { cellDetail, cellValue, isOdd } = props;
399
- const { row, column } = cellDetail;
400
- const { tableHook, rootProps, getColumnOption } = useProvider();
401
- const { columnOption } = rootProps;
402
- const type = getColumnOption('type', cellDetail);
403
- if (type === 'number') {
404
- cellValue = UT.SplitNumber(cellValue);
363
+ var _a, _b;
364
+ let { row, column, rowIndex } = props;
365
+ const { tableHook, rootProps } = useProvider();
366
+ const { templates } = rootProps;
367
+ const { type = 'text', id } = column;
368
+ let cellValue = tableHook.getCellValue({ row, rowIndex, column });
369
+ if (type === 'date') {
370
+ cellValue = new AIODate().toObject(cellValue);
371
+ }
372
+ else if (type === 'jalaliDate') {
373
+ cellValue = new AIODate().toObject(cellValue, true);
405
374
  }
406
- const before = getColumnOption('before', cellDetail);
407
- const after = getColumnOption('after', cellDetail);
408
- const subtext = getColumnOption('subtext', cellDetail);
409
375
  const rowId = row._id;
410
- const colId = getColumnOption('id', cellDetail);
376
+ const colId = id;
411
377
  const getTemplateValue = () => {
412
- const { getValue = {} } = rootProps;
413
- if (typeof column.template === 'function') {
414
- return column.template(cellDetail);
415
- }
416
- if (typeof column.template === 'string' && getValue[column.template]) {
417
- return getValue[column.template](cellDetail);
418
- }
419
- if ((columnOption || {}).template) {
420
- return columnOption.template(cellDetail);
421
- }
422
- const pattern = getColumnOption('pattern', cellDetail);
423
- if (pattern && cellValue) {
378
+ if (column.type === 'date') {
424
379
  try {
425
- if (type === 'date') {
426
- return new AIODate().getDateByPattern(cellValue, pattern);
427
- }
428
- else {
429
- return pattern.replace('{value}', cellValue);
430
- }
380
+ cellValue = new AIODate().toObject(cellValue);
431
381
  }
432
382
  catch (_a) { }
433
383
  }
384
+ else if (column.type === 'jalaliDate') {
385
+ try {
386
+ cellValue = new AIODate().toObject(cellValue, true);
387
+ }
388
+ catch (_b) { }
389
+ }
390
+ const cellTemplateValue = tableHook.getCellTemplateValue({ row, column, rowIndex, key: 'template' });
391
+ if (cellTemplateValue !== undefined) {
392
+ return cellTemplateValue;
393
+ }
394
+ return tableHook.getCellPatternValue({ row, column, rowIndex });
434
395
  };
435
396
  const templateValue = getTemplateValue();
436
- const beforeValue = tableHook.getCellValue(cellDetail, before, undefined);
437
- const afterValue = tableHook.getCellValue(cellDetail, after, undefined);
438
- const subtextValue = tableHook.getCellValue(cellDetail, subtext, undefined);
397
+ const before = tableHook.getCellTemplateValue({ row, column, rowIndex, key: 'before' });
398
+ const after = tableHook.getCellTemplateValue({ row, column, rowIndex, key: 'after' });
399
+ const subtext = tableHook.getCellTemplateValue({ row, column, rowIndex, key: 'subtext' });
439
400
  let content;
401
+ if (column.template) {
402
+ content = tableHook.getCellTemplateValue({ row, column, rowIndex, key: 'template' });
403
+ }
404
+ else if (column.pattern) {
405
+ content = tableHook.getCellPatternValue({ row, column, rowIndex });
406
+ }
440
407
  if (templateValue !== undefined) {
441
408
  content = templateValue;
442
409
  }
410
+ else if (column.type === 'number') {
411
+ content = UT.SplitNumber(cellValue);
412
+ }
443
413
  else {
444
414
  content = cellValue;
445
415
  }
446
- return (_jsx(Fragment, { children: _jsxs("div", Object.assign({}, tableHook.getCellAttrs(props.cellDetail, cellValue, isOdd, rootProps.striped), { children: [beforeValue !== undefined && _jsx("div", { className: "aio-table-cell-before", children: beforeValue }), _jsx("div", { className: `aio-table-cell-value${subtext !== undefined ? ' has-subtext' : ''}`, "data-subtext": subtextValue, children: content }), afterValue !== undefined && _jsx("div", { className: "aio-table-cell-after", children: afterValue })] })) }, rowId + ' ' + colId));
416
+ content = content !== undefined && content !== null && content !== '' ? _jsxs(_Fragment, { children: [(_a = column.prefix) !== null && _a !== void 0 ? _a : null, content, (_b = column.affix) !== null && _b !== void 0 ? _b : null] }) : content;
417
+ return (_jsx(Fragment, { children: _jsxs("div", Object.assign({}, tableHook.getCellAttrs({ row, column, rowIndex }), { children: [before !== undefined && _jsx("div", { className: "aio-table-cell-before", children: before }), _jsx("div", { className: `aio-table-cell-value${subtext !== undefined ? ' has-subtext' : ''}`, "data-subtext": subtext, children: content }), after !== undefined && _jsx("div", { className: "aio-table-cell-after", children: after })] })) }, rowId + ' ' + colId));
447
418
  };
448
- const useTable = (getProps, getPaging, getColumnOption) => {
419
+ const useTable = (getProps, getPaging) => {
449
420
  const DragRows = UT.useDrag((dragIndex, dropIndex, reOrder) => {
450
421
  const { onSwap, onChange, value: rows } = getProps();
451
422
  const newRows = reOrder(rows, dragIndex, dropIndex);
@@ -458,101 +429,147 @@ const useTable = (getProps, getPaging, getColumnOption) => {
458
429
  onChange(newRows);
459
430
  }
460
431
  }, 'aio-table-row');
461
- const getCellValue = (cellDetail, cellValue, def) => {
462
- const { getValue = {} } = getProps();
432
+ const fixIndexByPaging = (rowIndex) => {
463
433
  const paging = getPaging();
464
434
  if (paging) {
465
435
  let { number, size } = paging;
466
- cellDetail = Object.assign(Object.assign({}, cellDetail), { rowIndex: cellDetail.rowIndex + ((number - 1) * size) });
467
- }
468
- let type = typeof cellValue;
469
- if (type === 'string') {
470
- const { row } = cellDetail;
471
- if (row) { }
472
- let result = cellValue;
473
- if (getValue[cellValue]) {
474
- result = getValue[cellValue](cellDetail);
475
- }
476
- else if (cellValue.indexOf('row.') !== -1) {
436
+ return rowIndex + ((number - 1) * size);
437
+ }
438
+ return rowIndex;
439
+ };
440
+ const getCellValue = (p) => {
441
+ let { row, column, rowIndex } = p;
442
+ if (typeof column.value === 'string') {
443
+ let result = column.value;
444
+ if (result.indexOf('row.') !== -1) {
477
445
  try {
478
- eval(`result = ${cellValue}`);
479
- }
480
- catch (_a) {
481
- result = '';
446
+ eval(`result = ${result}`);
482
447
  }
448
+ catch (_a) { }
483
449
  }
484
- return result === undefined ? def : result;
450
+ return result;
451
+ }
452
+ if (typeof column.value === 'function') {
453
+ return column.value({ row, rowIndex, column });
485
454
  }
486
- if (type === 'undefined') {
487
- return def;
455
+ if (typeof column.value === 'undefined') {
456
+ const { columnOption } = getProps();
457
+ if (columnOption === null || columnOption === void 0 ? void 0 : columnOption.value) {
458
+ return columnOption.value({ row, column, rowIndex: fixIndexByPaging(rowIndex) });
459
+ }
460
+ }
461
+ };
462
+ const getTemplateParam = (p) => {
463
+ const value = getCellValue(p);
464
+ let dateObject = { year: 0, month: 0, day: 0, hour: 0, minute: 0, second: 0 };
465
+ if (p.column.type === 'date') {
466
+ try {
467
+ dateObject = new AIODate().toObject(value);
468
+ }
469
+ catch (_a) { }
488
470
  }
489
- if (type === 'function') {
490
- return cellValue(cellDetail);
471
+ else if (p.column.type === 'jalaliDate') {
472
+ try {
473
+ dateObject = new AIODate().toObject(value, true);
474
+ }
475
+ catch (_b) { }
491
476
  }
492
- return cellValue === undefined ? def : cellValue;
477
+ const rowIndex = fixIndexByPaging(p.rowIndex);
478
+ const change = (newRow) => changeCell(p.row, newRow);
479
+ return { value, dateObject, rowIndex, row: p.row, column: p.column, change };
493
480
  };
494
- function changeCell(cellDetail, newRow) {
481
+ const getCellTemplateValue = (p) => {
482
+ let { row, rowIndex, column, key } = p;
483
+ const { templates } = getProps();
484
+ if (!column[key]) {
485
+ return;
486
+ }
487
+ const templateParam = getTemplateParam({ row, column, rowIndex });
488
+ if (typeof column[key] === 'function') {
489
+ const fn = column[key];
490
+ return fn(templateParam);
491
+ }
492
+ if (typeof column[key] === 'string') {
493
+ if (templates && templates[column[key]]) {
494
+ const fn = templates[column[key]];
495
+ return fn(templateParam);
496
+ }
497
+ else {
498
+ return column[key];
499
+ }
500
+ }
501
+ };
502
+ const getCellPatternValue = (p) => {
503
+ let { row, rowIndex, column } = p;
504
+ const cellValue = getCellValue({ row, column, rowIndex });
505
+ const { pattern } = column;
506
+ if (pattern && cellValue !== undefined) {
507
+ try {
508
+ if (column.type === 'date') {
509
+ return new AIODate().getDateByPattern(cellValue, pattern);
510
+ }
511
+ else if (column.type === 'jalaliDate') {
512
+ return new AIODate().getDateByPattern(cellValue, pattern, true);
513
+ }
514
+ else {
515
+ return pattern.replace('{value}', cellValue);
516
+ }
517
+ }
518
+ catch (_a) { }
519
+ }
520
+ };
521
+ function changeCell(row, newRow) {
495
522
  if (newRow) { }
496
523
  const { onChange, value: propsValue } = getProps();
497
524
  if (!onChange) {
498
525
  return;
499
526
  }
500
- const rowId = cellDetail.row._id;
527
+ const rowId = row._id;
501
528
  onChange(propsValue.map((o) => o._id !== rowId ? o : newRow));
502
529
  }
503
- function getCellDetail(v) {
504
- const res = Object.assign({ column: {}, row: {}, rowIndex: 0, isFirst: false, isLast: false, date: [], change: () => { } }, v);
505
- const value = getColumnOption('value', res);
506
- const jalali = getColumnOption('jalali', res);
507
- const date = res.column.type === 'date' ? new AIODate().toArray(getCellValue(res, value, jalali)) : [];
508
- return Object.assign(Object.assign(Object.assign({}, res), { date }), v);
509
- }
510
- const getCellAttrs = (cellDetail, cellValue, isOdd, striped) => {
511
- const { column } = cellDetail;
512
- const attrs = getCellValue(cellDetail, column.attrs, {});
513
- const justify = getColumnOption('justify', cellDetail);
514
- const width = getColumnOption('width', cellDetail);
515
- const minWidth = getColumnOption('minWidth', cellDetail);
530
+ const getCellAttrs = (p) => {
531
+ const { row, rowIndex, column } = p;
532
+ const { cellAttrs } = getProps();
533
+ const cellValue = getCellValue({ row, column, rowIndex });
534
+ const attrs = cellAttrs ? cellAttrs({ row, rowIndex: fixIndexByPaging(rowIndex), column, value: cellValue }) : {};
535
+ const { justify, width, minWidth } = column;
516
536
  const className = `aio-table-cell` + (justify ? ` aio-table-cell-justify` : '');
517
537
  let isNumber = false;
518
538
  try {
519
- if (!isNaN(+cellValue)) {
539
+ if (typeof cellValue === 'number' || column.type === 'number') {
540
+ isNumber = true;
541
+ }
542
+ else if (typeof cellValue === 'string' && !isNaN(+cellValue)) {
520
543
  isNumber = true;
521
544
  }
522
545
  }
523
546
  catch (_a) { }
524
547
  const style = { width, minWidth, flex: width ? undefined : 1, direction: isNumber ? 'ltr' : undefined };
525
- if (striped) {
526
- style.background = isOdd ? striped[0] : striped[1];
527
- }
528
- return UT.AddToAttrs(attrs, { className: [className, isOdd ? 'aio-table-cell-odd' : 'aio-table-cell-even'], style, attrs: { title: typeof cellValue === 'string' ? cellValue : undefined } });
548
+ return UT.AddToAttrs(attrs, { className: [className, rowIndex % 2 === 0 ? 'aio-table-cell-odd' : 'aio-table-cell-even'], style, attrs: { title: typeof cellValue === 'string' ? cellValue : undefined } });
529
549
  };
530
550
  const getTitleAttrs = (column) => {
531
- const cellDetail = getCellDetail({ column });
532
- const attrs = getColumnOption('titleAttrs', cellDetail);
533
- const justify = getColumnOption('justify', cellDetail);
534
- const width = getColumnOption('width', cellDetail);
535
- const minWidth = getColumnOption('minWidth', cellDetail);
551
+ const { justify, width, minWidth, title } = column;
552
+ const { titleAttrs } = getProps();
553
+ const attrs = titleAttrs ? titleAttrs(column) : {};
536
554
  const className = `aio-table-title` + (justify ? ` aio-table-title-justify` : '');
537
555
  const style = { width, minWidth, flex: width ? undefined : 1 };
538
- const title = getColumnOption('title', cellDetail);
539
556
  return UT.AddToAttrs(attrs, { className, style, attrs: { title: typeof title === 'string' ? title : undefined } });
540
557
  };
541
- const getRowAttrs = (rowDetail, isOdd) => {
542
- const { rowOption = {}, onSwap, gap = [0, 1] } = getProps();
558
+ const getRowAttrs = (p) => {
559
+ const { row, rowIndex } = p;
560
+ const { rowOption = {}, onSwap, gap = [] } = getProps();
543
561
  const { attrs: rowAttrs } = rowOption;
544
- const attrs = rowAttrs ? rowAttrs(rowDetail) : {};
545
- let obj = UT.AddToAttrs(attrs, { className: ['aio-table-row', isOdd ? 'aio-table-row-odd' : 'aio-table-row-even'], style: { gap: gap[0] } });
562
+ const attrs = rowAttrs ? rowAttrs({ row, rowIndex }) : {};
563
+ let obj = UT.AddToAttrs(attrs, { className: ['aio-table-row', rowIndex % 2 === 0 ? 'aio-table-row-odd' : 'aio-table-row-even'], style: { gap: gap[0] } });
546
564
  if (onSwap) {
547
- obj = Object.assign(Object.assign(Object.assign({}, obj), DragRows.getDragAttrs(rowDetail.rowIndex)), DragRows.getDropAttrs(rowDetail.rowIndex));
565
+ obj = Object.assign(Object.assign(Object.assign({}, obj), DragRows.getDragAttrs(rowIndex)), DragRows.getDropAttrs(rowIndex));
548
566
  }
549
567
  return obj;
550
568
  };
551
- return { getCellValue, getCellAttrs, getTitleAttrs, getRowAttrs, changeCell, getCellDetail };
569
+ return { getCellValue, getCellTemplateValue, getCellPatternValue, getCellAttrs, getTitleAttrs, getRowAttrs, changeCell };
552
570
  };
553
571
  export const useSort = (p) => {
554
572
  let [sorts, setSorts] = useState(p.sorts);
555
- const getIconRef = useRef(new UT.GetSvg().getIcon);
556
573
  const isInitSortExecutedRef = useRef(false);
557
574
  const getSortedRows = (rows) => {
558
575
  if (isInitSortExecutedRef.current) {
@@ -624,15 +641,50 @@ export const useSort = (p) => {
624
641
  }
625
642
  }
626
643
  });
627
- const renderSortArrow = (option) => {
628
- let { dir = 'dec', sortId } = option;
644
+ const renderSortArrow = (option, inline) => {
645
+ if (option === false) {
646
+ return null;
647
+ }
648
+ let { dir = 'dec', sortId, active } = option;
649
+ let path = dir === 'dec' ? 'mdiArrowDown' : 'mdiArrowUp';
650
+ if (inline && !active) {
651
+ path = 'mdiSortVariantOff';
652
+ }
629
653
  return (_jsx("div", { className: 'aio-sort-arrow', onClick: (e) => {
630
654
  e.stopPropagation();
631
655
  if (!sortId) {
632
656
  return;
633
657
  }
634
- changeSort(sortId, { dir: dir === 'dec' ? 'inc' : 'dec' });
635
- }, children: getIconRef.current(dir === 'dec' ? 'mdiArrowDown' : 'mdiArrowUp', 0.8) }));
658
+ let newActive = active, newDir = dir;
659
+ if (inline) {
660
+ if (active) {
661
+ if (dir === 'inc') {
662
+ newDir = 'dec';
663
+ newActive = true;
664
+ }
665
+ else {
666
+ newActive = false;
667
+ }
668
+ }
669
+ else {
670
+ newDir = 'inc';
671
+ newActive = true;
672
+ }
673
+ }
674
+ else {
675
+ newDir = dir === 'dec' ? 'inc' : 'dec';
676
+ }
677
+ changeSort(sortId, { dir: newDir, active: newActive });
678
+ }, children: new UT.GetSvg('em').getIcon(path, 0.8) }));
679
+ };
680
+ const getSortByColumn = (column) => {
681
+ const sort = column.sort;
682
+ if (!sort) {
683
+ return false;
684
+ }
685
+ const sortId = sort === true ? column.id : (sort.sortId === undefined ? column.id : sort.sortId);
686
+ const res = sorts.find((o) => o.sortId === sortId);
687
+ return res === undefined ? false : res;
636
688
  };
637
689
  const renderSortButton = (attrs, limitTo) => {
638
690
  if (!sorts.length) {
@@ -647,11 +699,11 @@ export const useSort = (p) => {
647
699
  header: { title: p.fa ? 'مرتب سازی' : 'Sort', onClose: false },
648
700
  headerAttrs: { className: 'aio-sort-header' },
649
701
  limitTo: limitTo || '.aio-table'
650
- }, attrs: Attrs, text: getIconRef.current('mdiSort', 0.7), onSwap: (newSorts) => changeSorts(newSorts) }, 'sortbutton'));
702
+ }, attrs: Attrs, text: new UT.GetSvg('em').getIcon('mdiSort', 0.7), onSwap: (newSorts) => changeSorts(newSorts) }, 'sortbutton'));
651
703
  };
652
- return { sorts, setSorts, renderSortButton, getSortedRows, changeSort, changeSorts };
704
+ return { sorts, setSorts, renderSortButton, getSortedRows, changeSort, changeSorts, renderSortArrow, getSortByColumn };
653
705
  };
654
- export const usePaging = (p) => {
706
+ const usePaging = (p) => {
655
707
  const timeoutRef = useRef(undefined);
656
708
  const startRef = useRef(undefined);
657
709
  const endRef = useRef(undefined);
@@ -754,8 +806,8 @@ const FilterContextProvider = (props) => _jsx(FilterContext.Provider, { value: p
754
806
  const useFilterContext = () => useContext(FilterContext);
755
807
  const useFilter = () => {
756
808
  const { rootProps } = useProvider();
757
- const { formFilter, columnsFilter } = rootProps;
758
- const { value = {}, items = [], onChange = () => { } } = formFilter || {};
809
+ const { filter } = rootProps;
810
+ const { onChange } = filter || {};
759
811
  const trans = (key) => {
760
812
  const { fa } = rootProps;
761
813
  const dic = {
@@ -788,39 +840,34 @@ const useFilter = () => {
788
840
  };
789
841
  const popup = usePopup({ rtl: !!rootProps.fa });
790
842
  const filterDataHook = useFilterData(popup, trans);
791
- const type = columnsFilter ? 'columns' : 'form';
792
- const form = useForm({
793
- initData: value, onChange, getLayout: () => ({
794
- v: items.map((o) => ({
795
- input: Object.assign(Object.assign({}, o), { deSelect: true })
796
- }))
797
- })
798
- });
799
843
  const renderButton = (attrs) => {
800
- return (_jsxs(FilterContextProvider, { value: { trans, popup, filterDataHook, form, type }, children: [_jsx(FilterButton, { attrs: attrs }), popup.render()] }));
844
+ return (_jsxs(FilterContextProvider, { value: { trans, popup, filterDataHook, rootProps }, children: [_jsx(FilterButton, { attrs: attrs }), popup.render()] }));
801
845
  };
802
846
  const renderTags = () => {
803
- return (_jsxs(FilterContextProvider, { value: { trans, popup, filterDataHook, form, type }, children: [type === 'columns' && _jsx(FilterColumnsTags, { filterItems: filterDataHook.getData(), remove: true }), type === 'form' && _jsx(FilterFormTags, {}), popup.render()] }));
847
+ return (_jsxs(FilterContextProvider, { value: { trans, popup, filterDataHook, rootProps }, children: [_jsx(FilterColumnsTags, { filterItems: filterDataHook.getData(), remove: true }), popup.render()] }));
804
848
  };
805
849
  return { renderButton, renderTags };
806
850
  };
807
851
  const FilterButton = ({ attrs }) => {
808
- const { popup, trans } = useFilterContext();
852
+ const { popup, trans, rootProps } = useFilterContext();
853
+ const { filter = {} } = rootProps;
854
+ const { modalAttrs } = filter;
809
855
  const openModal = () => {
810
856
  popup.addModal({
811
857
  header: { title: trans('filters') },
812
858
  position: 'fullscreen', body: _jsx(FilterModal, {}),
813
- backdropAttrs: { className: 'aio-filter-modal aio-filter-modal-size' }
859
+ backdropAttrs: { className: 'aio-table-filter-modal aio-table-filter-modal-size' },
860
+ modalAttrs
814
861
  });
815
862
  };
816
- const Attrs = UT.AddToAttrs(attrs, { className: 'aio-filter-icon-button aio-filter-filter-button', attrs: { onClick: openModal } });
817
- return (_jsx("button", Object.assign({}, Attrs, { children: new UT.GetSvg().getIcon('mdiFilter', 0.7) })));
863
+ const Attrs = UT.AddToAttrs(attrs, { className: 'aio-table-toolbar-button', attrs: { onClick: openModal } });
864
+ return (_jsx("button", Object.assign({}, Attrs, { children: new UT.GetSvg('em').getIcon('mdiFilter', 0.7) })));
818
865
  };
819
- const FilterColumnsTags = ({ filterItems, remove, wrap }) => {
866
+ const FilterColumnsTags = ({ filterItems, remove }) => {
820
867
  const { filterDataHook } = useFilterContext();
821
868
  const { filterColumns } = useProvider();
822
869
  const getTags = () => {
823
- var _a, _b, _c;
870
+ var _a, _b;
824
871
  const res = [];
825
872
  for (let i = 0; i < filterItems.length; i++) {
826
873
  const filterItem = filterItems[i];
@@ -846,9 +893,9 @@ const FilterColumnsTags = ({ filterItems, remove, wrap }) => {
846
893
  const option = options.find((o) => o.value === value);
847
894
  valuePresent = (option === null || option === void 0 ? void 0 : option.text) || '';
848
895
  }
849
- else if (type === 'date') {
896
+ else if (type === 'date' || type === 'jalaliDate') {
850
897
  const dateUnit = ((_b = column.filterInput) === null || _b === void 0 ? void 0 : _b.dateUnit) || { year: true, month: true, day: true };
851
- const jalali = (_c = column.filterInput) === null || _c === void 0 ? void 0 : _c.jalali;
898
+ const jalali = column.type === 'jalaliDate';
852
899
  if (dateUnit === 'month') {
853
900
  valuePresent = new AIODate().getDateByPattern(value, '{year}/{month}', jalali);
854
901
  }
@@ -875,88 +922,65 @@ const FilterColumnsTags = ({ filterItems, remove, wrap }) => {
875
922
  if (!filterItems.length) {
876
923
  return null;
877
924
  }
878
- return (_jsx("div", { className: "aio-filter-tags", children: getTags() }));
879
- };
880
- const FilterFormTags = () => {
881
- const { form } = useFilterContext();
882
- return (_jsx(_Fragment, { children: form.renderTags }));
925
+ return (_jsx("div", { className: "aio-table-filter-tags", children: getTags() }));
883
926
  };
884
927
  const FilterTag = ({ filterItem, valuePresent, column, onRemove }) => {
885
928
  var _a;
886
929
  const { trans } = useFilterContext();
887
930
  const { operator } = filterItem;
888
- return (_jsxs("div", { className: "aio-filter-tag", onClick: onRemove, children: [_jsx("div", { className: "aio-filter-tag-column", children: ((_a = column.filterInput) === null || _a === void 0 ? void 0 : _a.label) || column.title || '' }), !!operator && _jsx("div", { className: "aio-filter-tag-operator", children: trans(operator) }), _jsx("div", { className: "aio-filter-tag-value", children: valuePresent }), !!onRemove && new UT.GetSvg().getIcon('mdiClose', 0.6)] }));
931
+ return (_jsxs("div", { className: "aio-table-filter-tag", onClick: onRemove, children: [_jsx("div", { className: "aio-table-filter-tag-column", children: ((_a = column.filterInput) === null || _a === void 0 ? void 0 : _a.label) || column.title || '' }), !!operator && _jsx("div", { className: "aio-table-filter-tag-operator", children: trans(operator) }), _jsx("div", { className: "aio-table-filter-tag-value", children: valuePresent }), !!onRemove && new UT.GetSvg('em').getIcon('mdiClose', 0.6)] }));
889
932
  };
890
933
  const SaveConfirm = ({ onSubmit }) => {
891
934
  const { popup, filterDataHook, trans } = useFilterContext();
892
- const [name, setName] = useState(filterDataHook.activeName || '');
893
- const getOptions = (text) => __awaiter(void 0, void 0, void 0, function* () {
894
- const filtered = filterDataHook.getSaves().filter((collection) => {
895
- if (!collection.name) {
896
- return false;
897
- }
898
- if (!text) {
899
- return true;
900
- }
901
- return collection.name.indexOf(text) !== -1;
902
- });
903
- const res = filtered.map((collection) => ({ text: collection.name, value: collection.name }));
904
- return res;
905
- });
906
- return (_jsxs("div", { className: "aio-filter-save-modal", children: [_jsx(AIFormInput, { label: trans('inter filter name'), input: (_jsx(SuggestionInput, { value: name, onChange: (newName) => setName(newName), getOptions: getOptions })) }), _jsxs("div", { className: "aio-filter-save-modal-footer", children: [_jsx("button", { className: "aio-filter-button aio-filter-active-button", disabled: !name, onClick: () => onSubmit(name), children: trans(name === filterDataHook.activeName ? 'edit' : 'save') }), _jsx("button", { className: "aio-filter-button", onClick: () => popup.removeModal(), children: trans('cansel') })] })] }));
935
+ const [name, setName] = useState('');
936
+ return (_jsxs("div", { className: "aio-table-filter-save-modal", children: [_jsx(AIFormInput, { label: trans('inter filter name'), input: (_jsx(AIText, { options: filterDataHook.getSaves(), option: { text: (o) => o.name, value: (o) => o.name, onClick: (o) => setName(o) }, onChange: (newName, option) => setName(option ? option.text : newName) })) }), _jsxs("div", { className: "aio-table-filter-save-modal-footer", children: [_jsx("button", { className: "aio-table-filter-button aio-table-filter-active-button", disabled: !name, onClick: () => onSubmit(name), children: trans(name === filterDataHook.activeName ? 'edit' : 'save') }), _jsx("button", { className: "aio-table-filter-button", onClick: () => popup.removeModal(), children: trans('cansel') })] })] }));
907
937
  };
908
- const FilterSaves = () => {
938
+ const FilterSaveds = () => {
909
939
  const { trans, filterDataHook } = useFilterContext();
910
940
  const saves = filterDataHook.getSaves();
911
941
  if (!saves.length) {
912
- return (_jsx("div", { className: "af-collections-empty", children: trans('saved empty') }));
942
+ return (_jsx("div", { className: "aio-table-saved-filters-empty", children: trans('saved empty') }));
913
943
  }
914
- return (_jsx("div", { className: "af-filter-collections", children: saves.map((o) => _jsx(FilterSave, { item: o }, o.name)) }));
944
+ return (_jsx("div", { className: "aio-table-saved-filters", children: saves.map((o) => _jsx(FilterSaved, { item: o }, o.name)) }));
915
945
  };
916
- const FilterSave = ({ item }) => {
946
+ const FilterSaved = ({ item }) => {
917
947
  const { rootProps } = useProvider();
918
- const { trans, filterDataHook, type } = useFilterContext();
948
+ const { trans, filterDataHook } = useFilterContext();
919
949
  const { fa } = rootProps;
920
950
  if (!item.name) {
921
951
  return null;
922
952
  }
923
- const header_layout = () => _jsxs("div", { className: "af-collection-header", children: [" ", name_layout(), " ", remove_layout(), " ", activate_layout()] });
924
- const name_layout = () => _jsx("div", { className: "af-collection-name", children: item.name });
953
+ const header_layout = () => _jsxs("div", { className: "aio-table-saved-filter-header", children: [" ", name_layout(), " ", remove_layout(), " ", activate_layout()] });
954
+ const name_layout = () => _jsx("div", { className: "aio-table-saved-filter-name", children: item.name });
925
955
  const remove_layout = () => {
926
- const attrs = { className: "af-collection-remove", onClick: () => filterDataHook.removeSave(item), style: { [fa ? 'right' : 'left']: -4 } };
956
+ const attrs = { className: "aio-table-filter-remove-button", onClick: () => filterDataHook.removeSave(item), style: { [fa ? 'right' : 'left']: -4 } };
927
957
  return (_jsx("div", Object.assign({}, attrs, { children: _jsx(FilterRemoveIcon, {}) })));
928
958
  };
929
959
  const activate_layout = () => {
930
- return (_jsxs("div", { className: "aio-filter-add-button", onClick: () => filterDataHook.activeSave(item), children: [_jsx(FilterActiveIcon, {}), " ", trans('activate')] }));
960
+ return (_jsxs("div", { className: "aio-table-filter-button", onClick: () => filterDataHook.activeSave(item), children: [_jsx(FilterActiveIcon, {}), " ", trans('activate')] }));
931
961
  };
932
962
  const body_layout = () => {
933
- if (type === 'columns') {
934
- return _jsx("div", { className: "af-collection-body", children: _jsx(FilterColumnsTags, { filterItems: item.data.filter((o) => o.value !== undefined && o.value !== '') }) });
935
- }
936
- else {
937
- return _jsx("div", { className: "af-collection-body", children: _jsx(FilterFormTags, {}) });
938
- }
963
+ return _jsx("div", { className: "aio-table-saved-filter-body", children: _jsx(FilterColumnsTags, { filterItems: item.data.filter((o) => o.value !== undefined && o.value !== '') }) });
939
964
  };
940
- return (_jsxs("div", { className: "af-collection", children: [header_layout(), " ", body_layout()] }));
965
+ return (_jsxs("div", { className: "aio-table-saved-filter", children: [header_layout(), " ", body_layout()] }));
941
966
  };
942
967
  const FilterModal = () => {
943
968
  const { rootProps } = useProvider();
944
969
  const { trans } = useFilterContext();
945
- const { fa, columnsFilter, formFilter } = rootProps;
946
- const { getSavedItems } = columnsFilter || formFilter || {};
970
+ const { fa, filter } = rootProps;
971
+ const { getSavedItems } = filter || {};
947
972
  const collections_layout = () => {
948
- return (_jsxs("div", { className: "aio-filter-panel", children: [_jsx("div", { className: "aio-filter-panel-header", children: _jsx("div", { className: "aio-filter-panel-label", children: trans('saved filters') }) }), _jsx(FilterSaves, {})] }));
973
+ return (_jsxs("div", { className: "aio-table-filter-panel", children: [_jsx("div", { className: "aio-table-filter-panel-header", children: _jsx("div", { className: "aio-table-filter-panel-label", children: trans('saved filters') }) }), _jsx(FilterSaveds, {})] }));
949
974
  };
950
- return (_jsxs("div", { className: `aio-filter-body aio-filter-body-${fa ? 'rtl' : 'ltr'}`, children: [_jsx(CurrentFilters, {}), !!(columnsFilter === null || columnsFilter === void 0 ? void 0 : columnsFilter.after) && columnsFilter.after(), !!getSavedItems && collections_layout()] }));
975
+ return (_jsxs("div", { className: `aio-table-filter-body aio-table-filter-body-${fa ? 'rtl' : 'ltr'}`, children: [_jsx(CurrentFilters, {}), !!getSavedItems && collections_layout()] }));
951
976
  };
952
977
  const CurrentFilters = () => {
953
978
  const { rootProps } = useProvider();
954
- const { filterDataHook, trans, form, type } = useFilterContext();
955
- const { columnsFilter, formFilter } = rootProps;
956
- const canSave = (!!columnsFilter && !!columnsFilter.setSavedItems) || (!!formFilter && !!formFilter.setSavedItems);
979
+ const { filterDataHook, trans } = useFilterContext();
980
+ const { filter } = rootProps;
981
+ const canSave = (!!filter && !!filter.setSavedItems);
957
982
  const data = filterDataHook.getData();
958
- return (_jsxs("div", { className: "aio-filter-panel", children: [_jsxs("div", { className: "aio-filter-panel-header", children: [_jsx("div", { className: "aio-filter-panel-label", children: trans('current filters') }), !!columnsFilter && _jsxs("button", { className: "aio-filter-add-button", onClick: filterDataHook.addColumnsFilterItem, children: [_jsx(FilterAddIcon, {}), " ", trans('add')] }), type === 'columns' && canSave && !!data.length && _jsxs("button", { className: "aio-filter-add-button", onClick: filterDataHook.save, children: [_jsx(FilterSaveIcon, {}), " ", trans('save')] }), type === 'form' && canSave && !form.errors.hasError() && _jsxs("button", { className: "aio-filter-add-button", onClick: filterDataHook.save, children: [_jsx(FilterSaveIcon, {}), " ", trans('save')] })] }), type === 'columns' &&
959
- _jsx("div", { className: "af-current-filters", children: data.map((columnsFilterItem) => _jsx(CurrentFilter, { filterItem: columnsFilterItem }, columnsFilterItem.id)) }), !!formFilter && form.renderLayout] }));
983
+ return (_jsxs("div", { className: "aio-table-filter-panel", children: [_jsxs("div", { className: "aio-table-filter-panel-header", children: [_jsx("div", { className: "aio-table-filter-panel-label", children: trans('current filters') }), _jsxs("button", { className: "aio-table-filter-button", onClick: filterDataHook.addColumnsFilterItem, children: [_jsx(FilterAddIcon, {}), " ", trans('add')] }), !!canSave && !!data.length && _jsxs("button", { className: "aio-table-filter-button", onClick: filterDataHook.save, children: [_jsx(FilterSaveIcon, {}), " ", trans('save')] })] }), _jsx("div", { className: "aio-table-current-filters", children: data.map((columnsFilterItem) => _jsx(CurrentFilter, { filterItem: columnsFilterItem }, columnsFilterItem.id)) })] }));
960
984
  };
961
985
  const CurrentFilter = ({ filterItem }) => {
962
986
  const { operator, columnId, value } = filterItem;
@@ -978,6 +1002,7 @@ const CurrentFilter = ({ filterItem }) => {
978
1002
  text: { contain: true, notContain: true, equal: true, notEqual: true },
979
1003
  number: { less: true, more: true, lessequal: true, moreequal: true, equal: true, notEqual: true },
980
1004
  date: { less: true, more: true, lessequal: true, moreequal: true, equal: true, notEqual: true },
1005
+ jalaliDate: { less: true, more: true, lessequal: true, moreequal: true, equal: true, notEqual: true },
981
1006
  select: { equal: true, notEqual: true },
982
1007
  multiSelect: { contain: true, notContain: true },
983
1008
  checkbox: {}
@@ -995,12 +1020,13 @@ const CurrentFilter = ({ filterItem }) => {
995
1020
  filterDataHook.changeColumnsFilterItem({ filterItem: filterItem, key: 'value', value: newValue, column });
996
1021
  };
997
1022
  const getValueInput = () => {
1023
+ var _a, _b;
998
1024
  if (!column) {
999
1025
  return null;
1000
1026
  }
1001
- let { type = 'text' } = column;
1027
+ const type = ((_a = column.filterInput) === null || _a === void 0 ? void 0 : _a.type) || column.type || 'text';
1002
1028
  if (type === 'select') {
1003
- return (_jsx(AISelect, Object.assign({}, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true })));
1029
+ return (_jsx(AISelect, Object.assign({}, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true, popover: Object.assign({ fitHorizontal: true }, (_b = column.filterInput) === null || _b === void 0 ? void 0 : _b.popover) })));
1004
1030
  }
1005
1031
  if (type === 'multiSelect') {
1006
1032
  return (_jsx(AIRadio, Object.assign({ multiple: true }, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true })));
@@ -1014,16 +1040,15 @@ const CurrentFilter = ({ filterItem }) => {
1014
1040
  if (type === 'number') {
1015
1041
  return _jsx(AINumber, Object.assign({}, column.filterInput, { value: value, onChange: (value) => changeValue(value), deSelect: true, inputAttrs: { style: { letterSpacing: 4 } }, justify: true }));
1016
1042
  }
1017
- if (type === 'date') {
1018
- return _jsx(TimeInput, Object.assign({}, column.filterInput, { filterItem: filterItem, onChange: (value) => changeValue(value), column: column }));
1043
+ if (type === 'date' || type === 'jalaliDate') {
1044
+ return _jsx(TimeInput, Object.assign({}, column.filterInput, { filterItem: filterItem, onChange: (value) => changeValue(value), column: column, jalali: type === 'jalaliDate' }));
1019
1045
  }
1020
1046
  };
1021
- return (_jsx(_Fragment, { children: _jsxs("div", { className: "aio-filter-row", children: [!!column &&
1022
- _jsx(AISelect, { options: filterColumns, value: columnId, option: { text: (column) => column.title, value: (column) => column.id }, onChange: (columnId) => filterDataHook.changeColumnsFilterItem({ filterItem: filterItem, key: 'columnId', value: columnId, column }), popover: { fitHorizontal: true } }), !!column && !!operators.length &&
1023
- _jsx(AISelect, { className: 'aio-filter-operator-select', options: operators, value: operator, option: { text: (operator) => trans(operator), value: (operator) => operator }, onChange: (operator) => filterDataHook.changeColumnsFilterItem({ filterItem: filterItem, key: 'operator', value: operator, column }), popover: { fitHorizontal: true } }), getValueInput(), _jsx("div", { className: "aio-filter-icon-button aio-filter-remove-button", onClick: () => filterDataHook.removeFilterItem(filterItem), children: _jsx(FilterRemoveIcon, {}) })] }) }));
1047
+ return (_jsx(_Fragment, { children: _jsxs("div", { className: "aio-table-filter-row", children: [!!column &&
1048
+ _jsx(AISelect, { className: 'msf', options: filterColumns.map((o) => ({ text: o.title, value: o.id })), value: columnId, onChange: (columnId) => filterDataHook.changeColumnsFilterItem({ filterItem: filterItem, key: 'columnId', value: columnId, column }), popover: { fitHorizontal: true } }), !!column && !!operators.length &&
1049
+ _jsx(AISelect, { className: 'aio-table-filter-operator-select', options: operators, value: operator, option: { text: (operator) => trans(operator), value: (operator) => operator }, onChange: (operator) => filterDataHook.changeColumnsFilterItem({ filterItem: filterItem, key: 'operator', value: operator, column }), popover: { fitHorizontal: true } }), getValueInput(), _jsx("div", { className: "aio-table-filter-remove-button", onClick: () => filterDataHook.removeFilterItem(filterItem), children: _jsx(FilterRemoveIcon, {}) })] }) }));
1024
1050
  };
1025
- const TimeInput = ({ filterItem, onChange, column }) => {
1026
- var _a;
1051
+ const TimeInput = ({ filterItem, onChange, column, jalali }) => {
1027
1052
  const [unit] = useState(getUnit);
1028
1053
  function getUnit() {
1029
1054
  const { dateUnit = 'day' } = column.filterInput || {};
@@ -1040,42 +1065,40 @@ const TimeInput = ({ filterItem, onChange, column }) => {
1040
1065
  return res;
1041
1066
  }
1042
1067
  const DATE = new AIODate();
1043
- const jalali = column.jalali || ((_a = column.filterInput) === null || _a === void 0 ? void 0 : _a.jalali);
1044
1068
  return (_jsx(AITime, { jalali: jalali, timeUnit: unit, value: filterItem.value, deSelect: true, onChange: (value) => onChange(value ? DATE.getTime(value) : undefined) }));
1045
1069
  };
1046
- const FilterSaveIcon = () => new UT.GetSvg().getIcon('mdiSaveContent', 0.8);
1047
- const FilterRemoveIcon = () => new UT.GetSvg().getIcon('mdiClose', 0.6);
1048
- const FilterActiveIcon = () => new UT.GetSvg().getIcon('mdiCheckBold', 0.6);
1049
- const FilterAddIcon = () => new UT.GetSvg().getIcon('mdiPlusThick', 0.7);
1070
+ const FilterSaveIcon = () => new UT.GetSvg('em').getIcon('mdiSaveContent', 0.8);
1071
+ const FilterRemoveIcon = () => new UT.GetSvg('em').getIcon('mdiClose', 0.6);
1072
+ const FilterActiveIcon = () => new UT.GetSvg('em').getIcon('mdiCheckBold', 0.6);
1073
+ const FilterAddIcon = () => new UT.GetSvg('em').getIcon('mdiPlusThick', 0.7);
1050
1074
  const useFilterData = (popup, trans) => {
1051
1075
  const [activeName, setActiveName] = useState();
1052
1076
  const { filterColumns, rootProps } = useProvider();
1053
- const { columnsFilter, formFilter } = rootProps;
1077
+ const { filter = {} } = rootProps;
1054
1078
  const [saves, setSaves] = useState([]);
1055
1079
  const savesRef = useRef(saves);
1056
1080
  savesRef.current = saves;
1057
1081
  const getSaves = () => savesRef.current;
1058
1082
  const [data, setData] = useState(getInitialData);
1059
1083
  function getInitialData() {
1060
- if (columnsFilter) {
1061
- return columnsFilter.items || [];
1084
+ if (filter.cache) {
1085
+ const storage = new UT.Storage(filter.cache);
1086
+ const data = storage.load('columnsFilterData', filter.items || []);
1087
+ if (filter.onChange) {
1088
+ filter.onChange(data);
1089
+ }
1090
+ return data;
1062
1091
  }
1063
- if (formFilter) {
1064
- return {};
1092
+ else {
1093
+ return filter.items || [];
1065
1094
  }
1066
1095
  }
1067
1096
  const getData = () => dataRef.current;
1068
1097
  const dataRef = useRef(data);
1069
1098
  dataRef.current = data;
1070
1099
  const changeData = (newData) => __awaiter(void 0, void 0, void 0, function* () {
1071
- if (columnsFilter && columnsFilter.onChange) {
1072
- const res = yield columnsFilter.onChange(newData);
1073
- if (res === false) {
1074
- return false;
1075
- }
1076
- }
1077
- if (formFilter && formFilter.onChange) {
1078
- const res = yield formFilter.onChange(newData);
1100
+ if (filter.onChange) {
1101
+ const res = yield filter.onChange(newData);
1079
1102
  if (res === false) {
1080
1103
  return false;
1081
1104
  }
@@ -1084,7 +1107,7 @@ const useFilterData = (popup, trans) => {
1084
1107
  return true;
1085
1108
  });
1086
1109
  const changeSaves = (newSaves) => __awaiter(void 0, void 0, void 0, function* () {
1087
- const { setSavedItems } = columnsFilter || formFilter || {};
1110
+ const { setSavedItems } = filter;
1088
1111
  if (!setSavedItems) {
1089
1112
  return false;
1090
1113
  }
@@ -1118,7 +1141,7 @@ const useFilterData = (popup, trans) => {
1118
1141
  popup.removeModal();
1119
1142
  }
1120
1143
  }) })),
1121
- backdropAttrs: { className: 'aio-filter-modal' }
1144
+ backdropAttrs: { className: 'aio-table-filter-modal' }
1122
1145
  });
1123
1146
  };
1124
1147
  const removeSave = (saveItem) => {
@@ -1127,37 +1150,21 @@ const useFilterData = (popup, trans) => {
1127
1150
  text: trans('remove confirm'),
1128
1151
  submitText: trans('remove'),
1129
1152
  canselText: trans('cansel'),
1130
- backdropAttrs: { className: 'aio-filter-modal' },
1131
- submitAttrs: { className: 'aio-filter-button aio-filter-active-button' },
1132
- canselAttrs: { className: 'aio-filter-button' },
1153
+ backdropAttrs: { className: 'aio-table-filter-modal' },
1154
+ submitAttrs: { className: 'aio-table-filter-button aio-table-filter-active-button' },
1155
+ canselAttrs: { className: 'aio-table-filter-button' },
1133
1156
  onSubmit: () => __awaiter(void 0, void 0, void 0, function* () { return yield changeSaves(savesRef.current.filter((o) => o.name !== saveItem.name)); })
1134
1157
  });
1135
1158
  };
1136
- const activeSave = (saveItem) => {
1137
- popup.addConfirm({
1138
- title: trans('activate saved filter'),
1139
- text: trans('activate confirm'),
1140
- submitText: trans('activate'),
1141
- canselText: trans('cansel'),
1142
- backdropAttrs: { className: 'aio-filter-modal' },
1143
- submitAttrs: { className: 'aio-filter-button aio-filter-active-button' },
1144
- canselAttrs: { className: 'aio-filter-button' },
1145
- onSubmit: () => __awaiter(void 0, void 0, void 0, function* () {
1146
- const { onChange } = columnsFilter || formFilter || {};
1147
- if (!onChange) {
1148
- return false;
1149
- }
1150
- const res = yield changeData(saveItem.data);
1151
- if (res) {
1152
- setActiveName(saveItem.name);
1153
- popup.removeModal('savedItems');
1154
- }
1155
- return !!res;
1156
- })
1157
- });
1158
- };
1159
+ const activeSave = (saveItem) => __awaiter(void 0, void 0, void 0, function* () {
1160
+ const { onChange } = filter;
1161
+ if (!onChange) {
1162
+ return false;
1163
+ }
1164
+ changeData(saveItem.data);
1165
+ });
1159
1166
  const fetchSaves = () => __awaiter(void 0, void 0, void 0, function* () {
1160
- const { getSavedItems } = columnsFilter || formFilter || {};
1167
+ const { getSavedItems } = filter;
1161
1168
  if (!getSavedItems) {
1162
1169
  return;
1163
1170
  }
@@ -1175,7 +1182,7 @@ const useFilterData = (popup, trans) => {
1175
1182
  value = options[0].value;
1176
1183
  }
1177
1184
  const operatorDic = {
1178
- text: 'contain', number: 'equal', date: 'equal', select: 'equal', multiSelect: 'contain', checkbox: false
1185
+ text: 'contain', number: 'equal', date: 'equal', jalaliDate: 'equal', select: 'equal', multiSelect: 'contain', checkbox: false
1179
1186
  };
1180
1187
  const operator = column ? (operatorDic[type] === false ? undefined : operatorDic[type]) : undefined;
1181
1188
  return { value, operator, columnId: column === null || column === void 0 ? void 0 : column.id, id: 'a' + UT.GetRandomNumber(10000000, 99999999) };
@@ -1215,3 +1222,30 @@ const useFilterData = (popup, trans) => {
1215
1222
  };
1216
1223
  return { getSaves, getData, save, removeSave, removeFilterItem, changeColumnsFilterItem, activeName, activeSave, addColumnsFilterItem };
1217
1224
  };
1225
+ export function sortRows(rows, sorts) {
1226
+ if (!rows) {
1227
+ return [];
1228
+ }
1229
+ if (!sorts || !sorts.length) {
1230
+ return rows;
1231
+ }
1232
+ return rows.sort((a, b) => {
1233
+ for (let i = 0; i < sorts.length; i++) {
1234
+ let { dir, getValue } = sorts[i];
1235
+ if (!getValue) {
1236
+ return 0;
1237
+ }
1238
+ let aValue = getValue(a), bValue = getValue(b);
1239
+ if (aValue < bValue) {
1240
+ return -1 * (dir === 'dec' ? -1 : 1);
1241
+ }
1242
+ if (aValue > bValue) {
1243
+ return 1 * (dir === 'dec' ? -1 : 1);
1244
+ }
1245
+ if (i === sorts.length - 1) {
1246
+ return 0;
1247
+ }
1248
+ }
1249
+ return 0;
1250
+ });
1251
+ }